<commit_before>//! Runtime support needed for testing the stdsimd crate.
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.

#![feature(proc_macro)]
#![cfg_attr(feature = "cargo-clippy",
            allow(missing_docs_in_private_items, print_stdout))]

extern crate assert_instr_macro;
extern crate backtrace;
extern crate cc;
#[macro_use]
extern crate lazy_static;
extern crate rustc_demangle;
extern crate simd_test_macro;

use std::collections::HashMap;
use std::env;
use std::process::Command;
use std::str;

pub use assert_instr_macro::*;
pub use simd_test_macro::*;

lazy_static! {
    static ref DISASSEMBLY: HashMap<String, Vec<Function>>
        = disassemble_myself();
}

struct Function {
    instrs: Vec<Instruction>,
}

struct Instruction {
    parts: Vec<String>,
}

fn disassemble_myself() -> HashMap<String, Vec<Function>> {
    let me = env::current_exe().expect("failed to get current exe");

    if cfg!(target_arch = "x86_64") && cfg!(target_os = "windows")
        && cfg!(target_env = "msvc")
    {
        let mut cmd = cc::windows_registry::find(
            "x86_64-pc-windows-msvc",
            "dumpbin.exe",
        ).expect("failed to find `dumpbin` tool");
        let output = cmd.arg("/DISASM")
            .arg(&me)
            .output()
            .expect("failed to execute dumpbin");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());
        parse_dumpbin(&String::from_utf8_lossy(&output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else if cfg!(target_os = "macos") {
        let output = Command::new("otool")
            .arg("-vt")
            .arg(&me)
            .output()
            .expect("failed to execute otool");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        parse_otool(str::from_utf8(&output.stdout).expect("stdout not utf8"))
    } else {
        let objdump =
            env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string());
        let output = Command::new(objdump)
            .arg("--disassemble")
            .arg(&me)
            .output()
            .expect("failed to execute objdump");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        parse_objdump(str::from_utf8(&output.stdout).expect("stdout not utf8"))
    }
}

fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();
    let expected_len =
        if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") {
            8
        } else {
            2
        };

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    while let Some(header) = lines.next() {
        // symbols should start with `$hex_addr <$name>:`
        if !header.ends_with(">:") {
            continue;
        }
        let start = header.find('<')
            .expect(&format!("\"<\" not found in symbol pattern of the form \"$hex_addr <$name>\": {}", header));
        let symbol = &header[start + 1..header.len() - 2];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.is_empty() {
                break;
            }
            // Each line of instructions should look like:
            //
            //      $rel_offset: ab cd ef 00    $instruction...
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == expected_len
                        && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn parse_otool(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        // symbols should start with `$symbol:`
        if !header.ends_with(':') {
            continue;
        }
        // strip the leading underscore and the trailing colon
        let symbol = &header[1..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(':') {
                cached_header = Some(instruction);
                break;
            }
            // Each line of instructions should look like:
            //
            //      $addr    $instruction...
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn parse_dumpbin(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        // symbols should start with `$symbol:`
        if !header.ends_with(':') {
            continue;
        }
        // strip the trailing colon
        let symbol = &header[..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if !instruction.starts_with("  ") {
                cached_header = Some(instruction);
                break;
            }
            // Each line looks like:
            //
            // >  $addr: ab cd ef     $instr..
            // >         00 12          # this line os optional
            if instruction.starts_with("       ") {
                continue;
            }
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn normalize(symbol: &str) -> String {
    let symbol = rustc_demangle::demangle(symbol).to_string();
    match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(fnptr: usize, fnname: &str, expected: &str) {
    // Translate this function pointer to a symbolic name that we'd have found
    // in the disassembly.
    let mut sym = None;
    backtrace::resolve(fnptr as *mut _, |name| {
        sym = name.name().and_then(|s| s.as_str()).map(normalize);
    });

    let functions =
        if let Some(s) = sym.as_ref().and_then(|s| DISASSEMBLY.get(s)) {
            s
        } else {
            if let Some(sym) = sym {
                println!("assumed symbol name: `{}`", sym);
            }
            println!("maybe related functions");
            for f in DISASSEMBLY.keys().filter(|k| k.contains(fnname)) {
                println!("\t- {}", f);
            }
            panic!("failed to find disassembly of {:#x} ({})", fnptr, fnname);
        };

    assert_eq!(functions.len(), 1);
    let function = &functions[0];

    // Look for `expected` as the first part of any instruction in this
    // function, returning if we do indeed find it.
    let mut found = false;
    for instr in &function.instrs {
        // Gets the first instruction, e.g. tzcntl in tzcntl %rax,%rax
        if let Some(part) = instr.parts.get(0) {
            // Truncates the instruction with the length of the expected
            // instruction: tzcntl => tzcnt and compares that.
            if part.starts_with(expected) {
                found = true;
                break;
            }
        }
    }

    // Look for `call` instructions in the disassembly to detect whether
    // inlining failed: all intrinsics are `#[inline(always)]`, so
    // calling one intrinsic from another should not generate `call`
    // instructions.
    let mut inlining_failed = false;
    for (i, instr) in function.instrs.iter().enumerate() {
        let part = match instr.parts.get(0) {
            Some(part) => part,
            None => continue,
        };
        if !part.contains("call") {
            continue
        }

        // On 32-bit x86 position independent code will call itself and be
        // immediately followed by a `pop` to learn about the current address.
        // Let's not take that into account when considering whether a function
        // failed inlining something.
        let followed_by_pop = function.instrs.get(i + 1)
            .and_then(|i| i.parts.get(0))
            .map(|s| s.contains("pop"))
            .unwrap_or(false);
        if followed_by_pop && cfg!(target_arch = "x86") {
            continue
        }

        inlining_failed = true;
        break;
    }

    let instruction_limit = match expected {
        // cpuid returns a pretty big aggregate structure so excempt it from the
        // slightly more restrictive 20 instructions below
        "cpuid" => 30,
        _ => 20,
    };
    let probably_only_one_instruction =
        function.instrs.len() < instruction_limit;

    if found && probably_only_one_instruction && !inlining_failed {
        return;
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!(
        "disassembly for {}: ",
        sym.as_ref().expect("symbol not found")
    );
    for (i, instr) in function.instrs.iter().enumerate() {
        print!("\t{:2}: ", i);
        for part in &instr.parts {
            print!("{} ", part);
        }
        println!();
    }

    if !found {
        panic!(
            "failed to find instruction `{}` in the disassembly",
            expected
        );
    } else if !probably_only_one_instruction {
        panic!("instruction found, but the disassembly contains too many \
                instructions: #instructions = {} >= {} (limit)",
               function.instrs.len(), instruction_limit);
    } else if inlining_failed {
        panic!("instruction found, but the disassembly contains `call` \
                instructions, which hint that inlining failed");
    }
}

pub fn assert_skip_test_ok(name: &str) {
    if env::var("STDSIMD_TEST_EVERYTHING").is_err() {
        return;
    }
    panic!("skipped test `{}` when it shouldn't be skipped", name);
}
<commit_msg>Add an exception for vzeroall/vzeroupper on Windows<commit_after>//! Runtime support needed for testing the stdsimd crate.
//!
//! This basically just disassembles the current executable and then parses the
//! output once globally and then provides the `assert` function which makes
//! assertions about the disassembly of a function.

#![feature(proc_macro)]
#![cfg_attr(feature = "cargo-clippy",
            allow(missing_docs_in_private_items, print_stdout))]

extern crate assert_instr_macro;
extern crate backtrace;
extern crate cc;
#[macro_use]
extern crate lazy_static;
extern crate rustc_demangle;
extern crate simd_test_macro;

use std::collections::HashMap;
use std::env;
use std::process::Command;
use std::str;

pub use assert_instr_macro::*;
pub use simd_test_macro::*;

lazy_static! {
    static ref DISASSEMBLY: HashMap<String, Vec<Function>>
        = disassemble_myself();
}

struct Function {
    instrs: Vec<Instruction>,
}

struct Instruction {
    parts: Vec<String>,
}

fn disassemble_myself() -> HashMap<String, Vec<Function>> {
    let me = env::current_exe().expect("failed to get current exe");

    if cfg!(target_arch = "x86_64") && cfg!(target_os = "windows")
        && cfg!(target_env = "msvc")
    {
        let mut cmd = cc::windows_registry::find(
            "x86_64-pc-windows-msvc",
            "dumpbin.exe",
        ).expect("failed to find `dumpbin` tool");
        let output = cmd.arg("/DISASM")
            .arg(&me)
            .output()
            .expect("failed to execute dumpbin");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());
        parse_dumpbin(&String::from_utf8_lossy(&output.stdout))
    } else if cfg!(target_os = "windows") {
        panic!("disassembly unimplemented")
    } else if cfg!(target_os = "macos") {
        let output = Command::new("otool")
            .arg("-vt")
            .arg(&me)
            .output()
            .expect("failed to execute otool");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        parse_otool(str::from_utf8(&output.stdout).expect("stdout not utf8"))
    } else {
        let objdump =
            env::var("OBJDUMP").unwrap_or_else(|_| "objdump".to_string());
        let output = Command::new(objdump)
            .arg("--disassemble")
            .arg(&me)
            .output()
            .expect("failed to execute objdump");
        println!(
            "{}\n{}",
            output.status,
            String::from_utf8_lossy(&output.stderr)
        );
        assert!(output.status.success());

        parse_objdump(str::from_utf8(&output.stdout).expect("stdout not utf8"))
    }
}

fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();
    let expected_len =
        if cfg!(target_arch = "arm") || cfg!(target_arch = "aarch64") {
            8
        } else {
            2
        };

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    while let Some(header) = lines.next() {
        // symbols should start with `$hex_addr <$name>:`
        if !header.ends_with(">:") {
            continue;
        }
        let start = header.find('<')
            .expect(&format!("\"<\" not found in symbol pattern of the form \"$hex_addr <$name>\": {}", header));
        let symbol = &header[start + 1..header.len() - 2];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.is_empty() {
                break;
            }
            // Each line of instructions should look like:
            //
            //      $rel_offset: ab cd ef 00    $instruction...
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == expected_len
                        && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn parse_otool(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        // symbols should start with `$symbol:`
        if !header.ends_with(':') {
            continue;
        }
        // strip the leading underscore and the trailing colon
        let symbol = &header[1..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if instruction.ends_with(':') {
                cached_header = Some(instruction);
                break;
            }
            // Each line of instructions should look like:
            //
            //      $addr    $instruction...
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn parse_dumpbin(output: &str) -> HashMap<String, Vec<Function>> {
    let mut lines = output.lines();

    for line in output.lines().take(100) {
        println!("{}", line);
    }

    let mut ret = HashMap::new();
    let mut cached_header = None;
    while let Some(header) = cached_header.take().or_else(|| lines.next()) {
        // symbols should start with `$symbol:`
        if !header.ends_with(':') {
            continue;
        }
        // strip the trailing colon
        let symbol = &header[..header.len() - 1];

        let mut instructions = Vec::new();
        while let Some(instruction) = lines.next() {
            if !instruction.starts_with("  ") {
                cached_header = Some(instruction);
                break;
            }
            // Each line looks like:
            //
            // >  $addr: ab cd ef     $instr..
            // >         00 12          # this line os optional
            if instruction.starts_with("       ") {
                continue;
            }
            let parts = instruction
                .split_whitespace()
                .skip(1)
                .skip_while(|s| {
                    s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
                })
                .map(|s| s.to_string())
                .collect::<Vec<String>>();
            instructions.push(Instruction { parts });
        }

        ret.entry(normalize(symbol))
            .or_insert_with(Vec::new)
            .push(Function {
                instrs: instructions,
            });
    }

    ret
}

fn normalize(symbol: &str) -> String {
    let symbol = rustc_demangle::demangle(symbol).to_string();
    match symbol.rfind("::h") {
        Some(i) => symbol[..i].to_string(),
        None => symbol.to_string(),
    }
}

/// Main entry point for this crate, called by the `#[assert_instr]` macro.
///
/// This asserts that the function at `fnptr` contains the instruction
/// `expected` provided.
pub fn assert(fnptr: usize, fnname: &str, expected: &str) {
    // Translate this function pointer to a symbolic name that we'd have found
    // in the disassembly.
    let mut sym = None;
    backtrace::resolve(fnptr as *mut _, |name| {
        sym = name.name().and_then(|s| s.as_str()).map(normalize);
    });

    let functions =
        if let Some(s) = sym.as_ref().and_then(|s| DISASSEMBLY.get(s)) {
            s
        } else {
            if let Some(sym) = sym {
                println!("assumed symbol name: `{}`", sym);
            }
            println!("maybe related functions");
            for f in DISASSEMBLY.keys().filter(|k| k.contains(fnname)) {
                println!("\t- {}", f);
            }
            panic!("failed to find disassembly of {:#x} ({})", fnptr, fnname);
        };

    assert_eq!(functions.len(), 1);
    let function = &functions[0];

    // Look for `expected` as the first part of any instruction in this
    // function, returning if we do indeed find it.
    let mut found = false;
    for instr in &function.instrs {
        // Gets the first instruction, e.g. tzcntl in tzcntl %rax,%rax
        if let Some(part) = instr.parts.get(0) {
            // Truncates the instruction with the length of the expected
            // instruction: tzcntl => tzcnt and compares that.
            if part.starts_with(expected) {
                found = true;
                break;
            }
        }
    }

    // Look for `call` instructions in the disassembly to detect whether
    // inlining failed: all intrinsics are `#[inline(always)]`, so
    // calling one intrinsic from another should not generate `call`
    // instructions.
    let mut inlining_failed = false;
    for (i, instr) in function.instrs.iter().enumerate() {
        let part = match instr.parts.get(0) {
            Some(part) => part,
            None => continue,
        };
        if !part.contains("call") {
            continue
        }

        // On 32-bit x86 position independent code will call itself and be
        // immediately followed by a `pop` to learn about the current address.
        // Let's not take that into account when considering whether a function
        // failed inlining something.
        let followed_by_pop = function.instrs.get(i + 1)
            .and_then(|i| i.parts.get(0))
            .map(|s| s.contains("pop"))
            .unwrap_or(false);
        if followed_by_pop && cfg!(target_arch = "x86") {
            continue
        }

        inlining_failed = true;
        break;
    }

    let instruction_limit = match expected {
        // cpuid returns a pretty big aggregate structure so excempt it from the
        // slightly more restrictive 20 instructions below
        "cpuid" => 30,

        // Apparently on Windows LLVM generates a bunch of saves/restores of xmm
        // registers around these intstructions which blows the 20 limit
        // below. As it seems dictates by Windows's abi (I guess?) we probably
        // can't do much about it...
        "vzeroall" | "vzeroupper" if cfg!(windows) => 30,

        _ => 20,
    };
    let probably_only_one_instruction =
        function.instrs.len() < instruction_limit;

    if found && probably_only_one_instruction && !inlining_failed {
        return;
    }

    // Help debug by printing out the found disassembly, and then panic as we
    // didn't find the instruction.
    println!(
        "disassembly for {}: ",
        sym.as_ref().expect("symbol not found")
    );
    for (i, instr) in function.instrs.iter().enumerate() {
        print!("\t{:2}: ", i);
        for part in &instr.parts {
            print!("{} ", part);
        }
        println!();
    }

    if !found {
        panic!(
            "failed to find instruction `{}` in the disassembly",
            expected
        );
    } else if !probably_only_one_instruction {
        panic!("instruction found, but the disassembly contains too many \
                instructions: #instructions = {} >= {} (limit)",
               function.instrs.len(), instruction_limit);
    } else if inlining_failed {
        panic!("instruction found, but the disassembly contains `call` \
                instructions, which hint that inlining failed");
    }
}

pub fn assert_skip_test_ok(name: &str) {
    if env::var("STDSIMD_TEST_EVERYTHING").is_err() {
        return;
    }
    panic!("skipped test `{}` when it shouldn't be skipped", name);
}
<|endoftext|>


<commit_before>use std::thread;

static NTHREADS: i32 = 10;

// This is the `main` thread
fn main() {
    let mut thread_vec: Vec<_> = Vec::new();

    for i in 0..NTHREADS {
        // Spawn up another thread
        let child = thread::spawn(move || {
            println!("this is thread number {}", i)
        });
        thread_vec.push(child);
    }

    for handle in thread_vec {
        // .unwrap() will propagate a panic from the child thread to the whole program
        handle.join().unwrap();
    }
}<commit_msg>added comment<commit_after>use std::thread;

static NTHREADS: i32 = 10;

// This is the `main` thread
fn main() {
    let mut thread_vec: Vec<_> = Vec::new();

    for i in 0..NTHREADS {
        // Spawn up another thread
        let child = thread::spawn(move || {
            println!("this is thread number {}", i)
        });
        thread_vec.push(child);
    }

    for handle in thread_vec {
        // .unwrap() will propagate a panic from the child thread to the whole program
        // .unwrap() just panics on None/Err(e)
        // And returns the value from Some(x)/Ok(x)

        handle.join().unwrap();
    }
}<|endoftext|>


<commit_before>//
// base32.rs - base32 implementation
//
// The Base32 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 A             9 J            18 S            27 3
//     1 B            10 K            19 T            28 4
//     2 C            11 L            20 U            29 5
//     3 D            12 M            21 V            30 6
//     4 E            13 N            22 W            31 7
//     5 F            14 O            23 X
//     6 G            15 P            24 Y         (pad) =
//     7 H            16 Q            25 Z
//     8 I            17 R            26 2
//
// The "Extended Hex" Base 32 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 0             9 9            18 I            27 R
//     1 1            10 A            19 J            28 S
//     2 2            11 B            20 K            29 T
//     3 3            12 C            21 L            30 U
//     4 4            13 D            22 M            31 V
//     5 5            14 E            23 N
//     6 6            15 F            24 O         (pad) =
//     7 7            16 G            25 P
//     8 8            17 H            26 Q
//

use std;

export mk;

const padd: u8 = 61u8;

iface base32 {
    fn encode(src: [u8]) -> [u8];
    fn decode(src: [u8]) -> [u8];
    fn hex_encode(src: [u8]) -> [u8];
    fn hex_decode(src: [u8]) -> [u8];
}

fn mk() -> base32 {
    type _base32 = {table: [u8], table_hex: [u8]};

    impl of base32 for _base32 {
        fn encode(src: [u8]) -> [u8] {
            b32encode(self.table, src)
        }
        fn decode(src: [u8]) -> [u8] {
            b32decode(self.table, src)
        }
        fn hex_encode(src: [u8]) -> [u8] {
            b32encode(self.table_hex, src)
        }
        fn hex_decode(src: [u8]) -> [u8] {
            b32decode(self.table_hex, src)
        }
    }

    let table = vec::init_elt_mut(32u, 0u8), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(50u8, 56u8)  { |j| table[i] = j; i += 1u8; }

    let table_hex = vec::init_elt_mut(32u, 0u8), i = 0u8;
    u8::range(48u8, 58u8)  { |j| table_hex[i] = j; i += 1u8; }
    u8::range(65u8, 87u8)  { |j| table_hex[i] = j; i += 1u8; }

    {table: vec::from_mut(table),
     table_hex: vec::from_mut(table_hex)} as base32
}

fn b32encode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);
    let targ = if srclen % 5u == 0u {
        vec::init_elt_mut(srclen / 5u * 8u, 0u8)
    } else {
        vec::init_elt_mut((srclen / 5u + 1u) * 8u, 0u8)
    };
    let input = vec::init_elt_mut(5u, 0u8);
    let output = vec::init_elt_mut(8u, 0u8);
    let curr = 0u, src_curr = 0u;

    while srclen > 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];
        input[4] = src[src_curr + 4u];
        srclen -= 5u; src_curr += 5u;

        output[0] = input[0] >> 3u8;
        output[1] = (input[0] & 0x07_u8) << 2u8 | input[1] >> 6u8;
        output[2] = (input[1] & 0x3f_u8) >> 1u8;
        output[3] = (input[1] & 0x01_u8) << 4u8 | input[2] >> 4u8;
        output[4] = (input[2] & 0x0f_u8) << 1u8 | input[3] >> 7u8;
        output[5] = (input[3] & 0x7f_u8) >> 2u8;
        output[6] = (input[3] & 0x03_u8) << 3u8 | input[4] >> 5u8;
        output[7] = input[4] & 0x1f_u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = table[output[2]]; curr += 1u;
        targ[curr] = table[output[3]]; curr += 1u;
        targ[curr] = table[output[4]]; curr += 1u;
        targ[curr] = table[output[5]]; curr += 1u;
        targ[curr] = table[output[6]]; curr += 1u;
        targ[curr] = table[output[7]]; curr += 1u;
    }

    if srclen != 0u {
        input[0] = 0u8; input[1] = 0u8; input[2] = 0u8;
        input[3] = 0u8; input[4] = 0u8;

        alt srclen {
          1u {input[0] = src[src_curr];}
          2u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];}
          3u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];
              input[2] = src[src_curr + 2u];}
          4u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];
              input[2] = src[src_curr + 2u];
              input[3] = src[src_curr + 3u];}
          _ { }
        }

        output[0] = input[0] >> 3u8;
        output[1] = (input[0] & 0x07_u8) << 2u8 | input[1] >> 6u8;
        output[2] = (input[1] & 0x3f_u8) >> 1u8;
        output[3] = (input[1] & 0x01_u8) << 4u8 | input[2] >> 4u8;
        output[4] = (input[2] & 0x0f_u8) << 1u8 | input[3] >> 7u8;
        output[5] = (input[3] & 0x7f_u8) >> 2u8;
        output[6] = (input[3] & 0x03_u8) << 3u8 | input[4] >> 5u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] =
            if srclen > 1u { table[output[2]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 1u { table[output[3]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 2u { table[output[4]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 3u { table[output[5]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 3u { table[output[6]] } else { padd }; curr += 1u;
        targ[curr] = padd;
    }

    vec::from_mut(targ)
}

fn b32decode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);

    if srclen % 8u != 0u { fail "malformed base32 string"; }
    if srclen == 0u { ret []; }

    []
}

mod tests {
    import std::map;
    import core::str::{bytes, from_bytes};
    enum mode {
        t_encode,
        t_decode,
        t_hex_encode,
        t_hex_decode,
    }
    fn setup(t: mode) -> map::hashmap<str, str> {
        let m = map::new_str_hash::<str>();
        alt t {
          t_decode { }
          t_encode {
            m.insert("fooba", "MZXW6YTB");
            m.insert("foob",  "MZXW6YQ=");
            m.insert("foo",   "MZXW6===");
            m.insert("fo",    "MZXQ====");
            m.insert("f",     "MY======");
          }
          t_hex_decode { }
          t_hex_encode {
            m.insert("fooba", "CPNMUOJ1");
            m.insert("foob",  "CPNMUOG=");
            m.insert("foo",   "CPNMU===");
            m.insert("fo",    "CPNG====");
            m.insert("f",     "CO======");
          }
        }
        m.insert("", "");
        m
    }
    fn do_test(t: mode) {
        let b32 = mk();
        let m = setup(t);
        m.keys { |k|
            let expected = m.get(k);
            let actual = alt t {
              t_decode { from_bytes(b32.decode(bytes(k))) }
              t_encode { from_bytes(b32.encode(bytes(k))) }
              t_hex_decode { from_bytes(b32.hex_decode(bytes(k))) }
              t_hex_encode { from_bytes(b32.hex_encode(bytes(k))) }
            };
            #debug("expected: %s", expected);
            #debug("actual:   %s", actual);
            assert expected == actual;
        }
    }
    #[test]
    fn encode() { do_test(t_encode); }
    #[test]
    fn hex_encode() { do_test(t_hex_encode); }
    #[test]
    fn decode() { do_test(t_decode); }
    #[test]
    fn hex_decode() { do_test(t_hex_decode); }
}
<commit_msg>wip: base32.rs<commit_after>//
// base32.rs - base32 implementation
//
// The Base32 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 A             9 J            18 S            27 3
//     1 B            10 K            19 T            28 4
//     2 C            11 L            20 U            29 5
//     3 D            12 M            21 V            30 6
//     4 E            13 N            22 W            31 7
//     5 F            14 O            23 X
//     6 G            15 P            24 Y         (pad) =
//     7 H            16 Q            25 Z
//     8 I            17 R            26 2
//
// The "Extended Hex" Base 32 Alphabet
//
// Value Encoding  Value Encoding  Value Encoding  Value Encoding
//     0 0             9 9            18 I            27 R
//     1 1            10 A            19 J            28 S
//     2 2            11 B            20 K            29 T
//     3 3            12 C            21 L            30 U
//     4 4            13 D            22 M            31 V
//     5 5            14 E            23 N
//     6 6            15 F            24 O         (pad) =
//     7 7            16 G            25 P
//     8 8            17 H            26 Q
//

use std;

export base32, mk;

const padd: u8 = 61u8;

iface base32 {
    fn encode(src: [u8]) -> [u8];
    fn decode(src: [u8]) -> [u8];
    fn hex_encode(src: [u8]) -> [u8];
    fn hex_decode(src: [u8]) -> [u8];
}

fn mk() -> base32 {
    type _base32 = {table: [u8], table_hex: [u8]};

    impl of base32 for _base32 {
        fn encode(src: [u8]) -> [u8] {
            b32encode(self.table, src)
        }
        fn decode(src: [u8]) -> [u8] {
            b32decode(self.table, src)
        }
        fn hex_encode(src: [u8]) -> [u8] {
            b32encode(self.table_hex, src)
        }
        fn hex_decode(src: [u8]) -> [u8] {
            b32decode(self.table_hex, src)
        }
    }

    let table = vec::init_elt_mut(32u, 0u8), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(50u8, 56u8)  { |j| table[i] = j; i += 1u8; }

    let table_hex = vec::init_elt_mut(32u, 0u8), i = 0u8;
    u8::range(48u8, 58u8)  { |j| table_hex[i] = j; i += 1u8; }
    u8::range(65u8, 87u8)  { |j| table_hex[i] = j; i += 1u8; }

    {table: vec::from_mut(table),
     table_hex: vec::from_mut(table_hex)} as base32
}

fn b32encode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);
    let targ = if srclen % 5u == 0u {
        vec::init_elt_mut(srclen / 5u * 8u, 0u8)
    } else {
        vec::init_elt_mut((srclen / 5u + 1u) * 8u, 0u8)
    };
    let input = vec::init_elt_mut(5u, 0u8);
    let output = vec::init_elt_mut(8u, 0u8);
    let curr = 0u, src_curr = 0u;

    while srclen > 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];
        input[4] = src[src_curr + 4u];
        srclen -= 5u; src_curr += 5u;

        output[0] = input[0] >> 3u8;
        output[1] = (input[0] & 0x07_u8) << 2u8 | input[1] >> 6u8;
        output[2] = (input[1] & 0x3f_u8) >> 1u8;
        output[3] = (input[1] & 0x01_u8) << 4u8 | input[2] >> 4u8;
        output[4] = (input[2] & 0x0f_u8) << 1u8 | input[3] >> 7u8;
        output[5] = (input[3] & 0x7f_u8) >> 2u8;
        output[6] = (input[3] & 0x03_u8) << 3u8 | input[4] >> 5u8;
        output[7] = input[4] & 0x1f_u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = table[output[2]]; curr += 1u;
        targ[curr] = table[output[3]]; curr += 1u;
        targ[curr] = table[output[4]]; curr += 1u;
        targ[curr] = table[output[5]]; curr += 1u;
        targ[curr] = table[output[6]]; curr += 1u;
        targ[curr] = table[output[7]]; curr += 1u;
    }

    if srclen != 0u {
        input[0] = 0u8; input[1] = 0u8; input[2] = 0u8;
        input[3] = 0u8; input[4] = 0u8;

        alt srclen {
          1u {input[0] = src[src_curr];}
          2u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];}
          3u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];
              input[2] = src[src_curr + 2u];}
          4u {input[0] = src[src_curr];
              input[1] = src[src_curr + 1u];
              input[2] = src[src_curr + 2u];
              input[3] = src[src_curr + 3u];}
          _ { }
        }

        output[0] = input[0] >> 3u8;
        output[1] = (input[0] & 0x07_u8) << 2u8 | input[1] >> 6u8;
        output[2] = (input[1] & 0x3f_u8) >> 1u8;
        output[3] = (input[1] & 0x01_u8) << 4u8 | input[2] >> 4u8;
        output[4] = (input[2] & 0x0f_u8) << 1u8 | input[3] >> 7u8;
        output[5] = (input[3] & 0x7f_u8) >> 2u8;
        output[6] = (input[3] & 0x03_u8) << 3u8 | input[4] >> 5u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] =
            if srclen > 1u { table[output[2]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 1u { table[output[3]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 2u { table[output[4]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 3u { table[output[5]] } else { padd }; curr += 1u;
        targ[curr] =
            if srclen > 3u { table[output[6]] } else { padd }; curr += 1u;
        targ[curr] = padd;
    }

    vec::from_mut(targ)
}

fn b32decode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);

    if srclen % 8u != 0u { fail "malformed base32 string"; }
    if srclen == 0u { ret []; }

    []
}

mod tests {
    import std::map;
    import core::str::{bytes, from_bytes};
    enum mode {
        t_encode,
        t_decode,
        t_hex_encode,
        t_hex_decode,
    }
    fn setup(t: mode) -> map::hashmap<str, str> {
        let m = map::new_str_hash::<str>();
        alt t {
          t_decode { }
          t_encode {
            m.insert("fooba", "MZXW6YTB");
            m.insert("foob",  "MZXW6YQ=");
            m.insert("foo",   "MZXW6===");
            m.insert("fo",    "MZXQ====");
            m.insert("f",     "MY======");
          }
          t_hex_decode { }
          t_hex_encode {
            m.insert("fooba", "CPNMUOJ1");
            m.insert("foob",  "CPNMUOG=");
            m.insert("foo",   "CPNMU===");
            m.insert("fo",    "CPNG====");
            m.insert("f",     "CO======");
          }
        }
        m.insert("", "");
        m
    }
    fn do_test(t: mode) {
        let b32 = mk();
        let m = setup(t);
        m.keys { |k|
            let expected = m.get(k);
            let actual = alt t {
              t_decode { from_bytes(b32.decode(bytes(k))) }
              t_encode { from_bytes(b32.encode(bytes(k))) }
              t_hex_decode { from_bytes(b32.hex_decode(bytes(k))) }
              t_hex_encode { from_bytes(b32.hex_encode(bytes(k))) }
            };
            #debug("expected: %s", expected);
            #debug("actual:   %s", actual);
            assert expected == actual;
        }
    }
    #[test]
    fn encode() { do_test(t_encode); }
    #[test]
    fn hex_encode() { do_test(t_hex_encode); }
    #[test]
    fn decode() { do_test(t_decode); }
    #[test]
    fn hex_decode() { do_test(t_hex_decode); }
}
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc_hir::{PatKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};

declare_clippy_lint! {
    /// **What it does:** Checks for `let _ = <expr>`
    /// where expr is #[must_use]
    ///
    /// **Why is this bad?** It's better to explicitly
    /// handle the value of a #[must_use] expr
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn f() -> Result<u32, u32> {
    ///     Ok(0)
    /// }
    ///
    /// let _ = f();
    /// // is_ok() is marked #[must_use]
    /// let _ = f().is_ok();
    /// ```
    pub LET_UNDERSCORE_MUST_USE,
    restriction,
    "non-binding let on a `#[must_use]` expression"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `let _ = sync_lock`
    ///
    /// **Why is this bad?** This statement immediately drops the lock instead of
    /// extending it's lifetime to the end of the scope, which is often not intended.
    /// To extend lock lifetime to the end of the scope, use an underscore-prefixed
    /// name instead (i.e. _lock). If you want to explicitly drop the lock,
    /// `std::mem::drop` conveys your intention better and is less error-prone.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// Bad:
    /// ```rust,ignore
    /// let _ = mutex.lock();
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// let _lock = mutex.lock();
    /// ```
    pub LET_UNDERSCORE_LOCK,
    correctness,
    "non-binding let on a synchronization lock"
}

declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);

const SYNC_GUARD_PATHS: [&[&str]; 3] = [
    &paths::MUTEX_GUARD,
    &paths::RWLOCK_READ_GUARD,
    &paths::RWLOCK_WRITE_GUARD,
];

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
    fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) {
        if in_external_macro(cx.tcx.sess, stmt.span) {
            return;
        }

        if_chain! {
            if let StmtKind::Local(ref local) = stmt.kind;
            if let PatKind::Wild = local.pat.kind;
            if let Some(ref init) = local.init;
            then {
                let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path));
                if cx.tables.expr_ty(init).walk().any(check_ty) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_LOCK,
                        stmt.span,
                        "non-binding let on a synchronization lock",
                        "consider using an underscore-prefixed named \
                            binding or dropping explicitly with `std::mem::drop`"
                    )
                } else if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_MUST_USE,
                        stmt.span,
                        "non-binding let on an expression with `#[must_use]` type",
                        "consider explicitly using expression value"
                    )
                } else if is_must_use_func_call(cx, init) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_MUST_USE,
                        stmt.span,
                        "non-binding let on a result of a `#[must_use]` function",
                        "consider explicitly using function result"
                    )
                }
            }
        }
    }
}
<commit_msg>Allow let_underscore<commit_after>use if_chain::if_chain;
use rustc_hir::{Local, PatKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help};

declare_clippy_lint! {
    /// **What it does:** Checks for `let _ = <expr>`
    /// where expr is #[must_use]
    ///
    /// **Why is this bad?** It's better to explicitly
    /// handle the value of a #[must_use] expr
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// fn f() -> Result<u32, u32> {
    ///     Ok(0)
    /// }
    ///
    /// let _ = f();
    /// // is_ok() is marked #[must_use]
    /// let _ = f().is_ok();
    /// ```
    pub LET_UNDERSCORE_MUST_USE,
    restriction,
    "non-binding let on a `#[must_use]` expression"
}

declare_clippy_lint! {
    /// **What it does:** Checks for `let _ = sync_lock`
    ///
    /// **Why is this bad?** This statement immediately drops the lock instead of
    /// extending it's lifetime to the end of the scope, which is often not intended.
    /// To extend lock lifetime to the end of the scope, use an underscore-prefixed
    /// name instead (i.e. _lock). If you want to explicitly drop the lock,
    /// `std::mem::drop` conveys your intention better and is less error-prone.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// Bad:
    /// ```rust,ignore
    /// let _ = mutex.lock();
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// let _lock = mutex.lock();
    /// ```
    pub LET_UNDERSCORE_LOCK,
    correctness,
    "non-binding let on a synchronization lock"
}

declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK]);

const SYNC_GUARD_PATHS: [&[&str]; 3] = [
    &paths::MUTEX_GUARD,
    &paths::RWLOCK_READ_GUARD,
    &paths::RWLOCK_WRITE_GUARD,
];

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore {
    fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local<'_>) {
        if in_external_macro(cx.tcx.sess, local.span) {
            return;
        }

        if_chain! {
            if let PatKind::Wild = local.pat.kind;
            if let Some(ref init) = local.init;
            then {
                let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path));
                if cx.tables.expr_ty(init).walk().any(check_ty) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_LOCK,
                        local.span,
                        "non-binding let on a synchronization lock",
                        "consider using an underscore-prefixed named \
                            binding or dropping explicitly with `std::mem::drop`"
                    )
                } else if is_must_use_ty(cx, cx.tables.expr_ty(init)) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_MUST_USE,
                        local.span,
                        "non-binding let on an expression with `#[must_use]` type",
                        "consider explicitly using expression value"
                    )
                } else if is_must_use_func_call(cx, init) {
                    span_lint_and_help(
                        cx,
                        LET_UNDERSCORE_MUST_USE,
                        local.span,
                        "non-binding let on a result of a `#[must_use]` function",
                        "consider explicitly using function result"
                    )
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Procedurally generating the game world.

use world::{Chunk, ChunkIndex, ChunkProvider, HeightType, HexPillar};
use world::{CHUNK_SIZE, GroundMaterial, PILLAR_STEP_HEIGHT, PillarSection, Prop, PropType};
use rand::Rand;
use gen::PlantGenerator;
use noise::{PermutationTable, open_simplex2, open_simplex3};
use gen::seeded_rng;

enum Biome {
    GrassLand,
    Desert,
    Snow,
    Forest,
    RainForest,
    Savanna,
    Stone,
    WeihnachtsmannLand,
}

/// Land "fill noise" scaling in x, y, and z direction.
const LAND_NOISE_SCALE: (f32, f32, f32) = (0.03, 0.03, 0.05);

/// Main type to generate the game world. Implements the `ChunkProvider` trait
/// (TODO, see #8).
pub struct WorldGenerator {
    seed: u64,
    terrain_table: PermutationTable,
    plant_table: PermutationTable,
    temperature_table: PermutationTable,
    humidity_table: PermutationTable,
}

impl WorldGenerator {
    /// Creates the generator with the given seed.
    pub fn with_seed(seed: u64) -> Self {
        let mut terrain_rng = seeded_rng(seed, 0, ());
        let mut plant_rng = seeded_rng(seed, 1, ());
        let mut temperature_rng = seeded_rng(seed, 2, ());
        let mut humidity_rng = seeded_rng(seed, 3, ());

        WorldGenerator {
            seed: seed,
            terrain_table: PermutationTable::rand(&mut terrain_rng),
            plant_table: PermutationTable::rand(&mut plant_rng),
            temperature_table: PermutationTable::rand(&mut temperature_rng),
            humidity_table: PermutationTable::rand(&mut humidity_rng),
        }
    }

    /// Returns the seed of this world generator.
    pub fn seed(&self) -> u64 {
        self.seed
    }

    fn biome_from_climate(temperature: f32, humidity: f32) -> Biome {
        match (temperature, humidity) {
            (0.0...0.2, 0.0...0.2) => Biome::Stone,
            (0.0...0.2, 0.2...0.4) => Biome::Snow,
            (0.0...0.2, 0.4...1.0) => Biome::Snow,
            (0.2...0.4, 0.0...0.2) => Biome::GrassLand,
            (0.2...0.4, 0.2...0.4) => Biome::GrassLand,
            (0.2...0.4, 0.4...1.0) => Biome::Forest,
            (0.4...1.0, 0.0...0.2) => Biome::Desert,
            (0.4...1.0, 0.2...0.4) => Biome::Savanna,
            (0.4...1.0, 0.4...1.0) => Biome::RainForest,
            _ => Biome::WeihnachtsmannLand,

        }
    }

    fn plant_threshold_from_biome(biome: &Biome) -> f32 {
        0.05 +
        match *biome {
            Biome::GrassLand => 0.3,
            Biome::Desert => 0.46,
            Biome::Snow => 0.35,
            Biome::Forest => 0.25,
            Biome::RainForest => 0.2,
            Biome::Savanna => 0.375,
            Biome::Stone => 0.45,
            Biome::WeihnachtsmannLand => 1.0,
        }
    }

    /// trying aproximate the
    /// steepvalues       10   20   60  200
    /// for temperature  0.0  0.2  0.4  1.0
    fn steepness_from_temperature(temperature: f32) -> f32 {
        120.0 * temperature * temperature + 72.0 * temperature + 3.5
    }

    fn material_from_biome(biome: &Biome) -> GroundMaterial {
        match *biome {
            Biome::GrassLand => GroundMaterial::Grass,
            Biome::Desert => GroundMaterial::Sand,
            Biome::Snow => GroundMaterial::Snow,
            Biome::Forest => GroundMaterial::Mulch,
            Biome::RainForest => GroundMaterial::Jungle,
            Biome::Savanna => GroundMaterial::Dirt,
            Biome::Stone => GroundMaterial::Stone,
            Biome::WeihnachtsmannLand => GroundMaterial::Color(1.0, 0.0, 0.0),
        }
    }
}

impl ChunkProvider for WorldGenerator {
    fn load_chunk(&self, index: ChunkIndex) -> Option<Chunk> {
        const WORLDGEN_HEIGHT: usize = 256;
        // Create a 3D-Array of booleans indicating which pillar sections to fill
        // (Map height is unlimited in theory, but we'll limit worldgen to 64 height
        // units)
        let mut fill = [[[false; WORLDGEN_HEIGHT]; CHUNK_SIZE as usize]; CHUNK_SIZE as usize];

        Some(Chunk::with_pillars(index, |pos| {

            let real_pos = pos.to_real();
            let x = real_pos.x;
            let y = real_pos.y;
            // Pillar pos relative to first pillar
            let rel_q = pos.q - index.0.q * CHUNK_SIZE as i32;
            let rel_r = pos.r - index.0.r * CHUNK_SIZE as i32;

            // noises
            let mut temperature_noise = (open_simplex2::<f32>(&self.temperature_table,
                                                              &[(x as f32) * 0.0015,
                                                                (y as f32) * 0.0015]) +
                                         0.6) / 2.0;
            temperature_noise += 0.035 *
                                 open_simplex2::<f32>(&self.temperature_table,
                                                      &[(x as f32) * 0.15, (y as f32) * 0.15]);

            let mut humidity_noise = (open_simplex2::<f32>(&self.humidity_table,
                                                           &[(x as f32) * 0.0015,
                                                             (y as f32) * 0.0015]) +
                                      0.6) / 2.0;
            humidity_noise += 0.035 *
                              open_simplex2::<f32>(&self.humidity_table,
                                                   &[(x as f32) * 0.15, (y as f32) * 0.15]);

            let current_biome = WorldGenerator::biome_from_climate(temperature_noise,
                                                                   humidity_noise);

            for i in 0..WORLDGEN_HEIGHT {
                if i == 0 {
                    fill[rel_q as usize][rel_r as usize][i as usize] = true;
                    continue;
                }

                let z = i as f32 * PILLAR_STEP_HEIGHT;
                let fill_noise = open_simplex3::<f32>(&self.terrain_table,
                                                      &[x * LAND_NOISE_SCALE.0,
                                                        y * LAND_NOISE_SCALE.1,
                                                        z * LAND_NOISE_SCALE.2]);

                // The noise is (theoretically) in the range -1..1
                // Map the noise to a range of 0..1
                let fill_noise = (fill_noise + 1.0) / 2.0;

                // Calculate threshold to fill this "block". The lower the threshold, the more
                // likely this voxel is filled, so it should increase with height.
                let height_pct = i as f32 / WORLDGEN_HEIGHT as f32;

                // The threshold is calculated using a sigmoid function. These are the
                // parameters used:

                /// Minimum threshold to prevent threshold to reach 0,
                /// needed to have any caves at all
                const MIN_THRESH: f32 = 0.6;
                /// Threshold at half value (max. steepness, avg. terrain
                /// height)
                const THRESH_MID: f32 = 0.5;

                // "Steepness" of the sigmoid function.
                let thresh_steepness: f32 =
                    WorldGenerator::steepness_from_temperature(temperature_noise);

                let sig_thresh = 1.0 /
                                 (1.0 + f32::exp(-thresh_steepness * (height_pct - THRESH_MID)));

                let threshold = (sig_thresh + MIN_THRESH) / (1.0 + MIN_THRESH);

                fill[rel_q as usize][rel_r as usize][i as usize] = fill_noise > threshold;
            }

            let column = &fill[rel_q as usize][rel_r as usize];

            // Create sections for all connected `true`s in the array
            let mut sections = Vec::new();
            let mut low = 0;
            let mut height = None;
            for i in 0..WORLDGEN_HEIGHT {
                let material = WorldGenerator::material_from_biome(&current_biome);

                match (height, column[i]) {

                    (Some(h), true) => {
                        // Next one's still solid, increase section height
                        height = Some(h + 1);
                    }
                    (Some(h), false) => {
                        // Create a section of height `h` and start over
                        sections.push(PillarSection::new(material,
                                                         HeightType::from_units(low),
                                                         HeightType::from_units(low + h)));
                        height = None;
                    }
                    (None, true) => {
                        low = i as u16;
                        height = Some(1);
                    }
                    (None, false) => {}
                };
            }

            if let Some(h) = height {
                // Create the topmost pillar
                sections.push(PillarSection::new(GroundMaterial::Dirt,
                                                 HeightType::from_units(low),
                                                 HeightType::from_units(low + h)));
            }

            let mut props = Vec::new();

            // plants
            let plant_noise = open_simplex2::<f32>(&self.plant_table,
                                                   &[(x as f32) * 0.25, (y as f32) * 0.25]);

            if plant_noise > WorldGenerator::plant_threshold_from_biome(&current_biome) {
                let mut rng = super::seeded_rng(self.seed, "TREE", (pos.q, pos.r));
                let gen = PlantGenerator::rand(&mut rng);

                // put the tree at the highest position
                let height = match sections.last() {
                    Some(section) => section.top,
                    None => HeightType::from_units(0),
                };

                props.push(Prop {
                    baseline: height,
                    prop: PropType::Plant(gen.generate(&mut rng)),
                });
            }

            HexPillar::new(sections, props)
        }))
    }

    fn is_chunk_loadable(&self, _: ChunkIndex) -> bool {
        // All chunks can be generated from nothing
        true
    }
}
<commit_msg>corrections according to comments<commit_after>//! Procedurally generating the game world.

use world::{Chunk, ChunkIndex, ChunkProvider, HeightType, HexPillar};
use world::{CHUNK_SIZE, GroundMaterial, PILLAR_STEP_HEIGHT, PillarSection, Prop, PropType};
use rand::Rand;
use gen::PlantGenerator;
use noise::{PermutationTable, open_simplex2, open_simplex3};
use gen::seeded_rng;

enum Biome {
    GrassLand,
    Desert,
    Snow,
    Forest,
    RainForest,
    Savanna,
    Stone,
    WeihnachtsmannLand,
}

/// Land "fill noise" scaling in x, y, and z direction.
const LAND_NOISE_SCALE: (f32, f32, f32) = (0.03, 0.03, 0.05);

/// Main type to generate the game world. Implements the `ChunkProvider` trait
/// (TODO, see #8).
pub struct WorldGenerator {
    seed: u64,
    terrain_table: PermutationTable,
    plant_table: PermutationTable,
    temperature_table: PermutationTable,
    humidity_table: PermutationTable,
}

impl WorldGenerator {
    /// Creates the generator with the given seed.
    pub fn with_seed(seed: u64) -> Self {
        let mut terrain_rng = seeded_rng(seed, 0, ());
        let mut plant_rng = seeded_rng(seed, 1, ());
        let mut temperature_rng = seeded_rng(seed, 2, ());
        let mut humidity_rng = seeded_rng(seed, 3, ());

        WorldGenerator {
            seed: seed,
            terrain_table: PermutationTable::rand(&mut terrain_rng),
            plant_table: PermutationTable::rand(&mut plant_rng),
            temperature_table: PermutationTable::rand(&mut temperature_rng),
            humidity_table: PermutationTable::rand(&mut humidity_rng),
        }
    }

    /// Returns the seed of this world generator.
    pub fn seed(&self) -> u64 {
        self.seed
    }

    fn biome_from_climate(temperature: f32, humidity: f32) -> Biome {
        match (temperature, humidity) {
            (0.0...0.2, 0.0...0.2) => Biome::Stone,
            (0.0...0.2, 0.2...0.4) => Biome::Snow,
            (0.0...0.2, 0.4...1.0) => Biome::Snow,
            (0.2...0.4, 0.0...0.2) => Biome::GrassLand,
            (0.2...0.4, 0.2...0.4) => Biome::GrassLand,
            (0.2...0.4, 0.4...1.0) => Biome::Forest,
            (0.4...1.0, 0.0...0.2) => Biome::Desert,
            (0.4...1.0, 0.2...0.4) => Biome::Savanna,
            (0.4...1.0, 0.4...1.0) => Biome::RainForest,
            _ => Biome::WeihnachtsmannLand,

        }
    }

    fn plant_threshold_from_biome(biome: &Biome) -> f32 {
        0.05 +
        match *biome {
            Biome::GrassLand => 0.3,
            Biome::Desert => 0.46,
            Biome::Snow => 0.35,
            Biome::Forest => 0.25,
            Biome::RainForest => 0.2,
            Biome::Savanna => 0.375,
            Biome::Stone => 0.45,
            Biome::WeihnachtsmannLand => 1.0,
        }
    }

    /// trying aproximate the
    /// steepvalues       10   20   60  200
    /// for temperature  0.0  0.2  0.4  1.0
    fn steepness_from_temperature(temperature: f32) -> f32 {
        120.0 * temperature * temperature + 72.0 * temperature + 3.5
    }

    fn material_from_biome(biome: &Biome) -> GroundMaterial {
        match *biome {
            Biome::GrassLand => GroundMaterial::Grass,
            Biome::Desert => GroundMaterial::Sand,
            Biome::Snow => GroundMaterial::Snow,
            Biome::Forest => GroundMaterial::Mulch,
            Biome::RainForest => GroundMaterial::Jungle,
            Biome::Savanna => GroundMaterial::Dirt,
            Biome::Stone => GroundMaterial::Stone,
            Biome::WeihnachtsmannLand => GroundMaterial::Color(1.0, 0.0, 0.0),
        }
    }
}

impl ChunkProvider for WorldGenerator {
    fn load_chunk(&self, index: ChunkIndex) -> Option<Chunk> {
        const WORLDGEN_HEIGHT: usize = 256;
        // Create a 3D-Array of booleans indicating which pillar sections to fill
        // (Map height is unlimited in theory, but we'll limit worldgen to 64 height
        // units)
        let mut fill = [[[false; WORLDGEN_HEIGHT]; CHUNK_SIZE as usize]; CHUNK_SIZE as usize];

        Some(Chunk::with_pillars(index, |pos| {

            let real_pos = pos.to_real();
            let x = real_pos.x;
            let y = real_pos.y;
            // Pillar pos relative to first pillar
            let rel_pos = pos - index.0 * CHUNK_SIZE as i32;

            // noises
            let mut temperature_noise = (open_simplex2::<f32>(&self.temperature_table,
                                                              &[(x as f32) * 0.0015,
                                                                (y as f32) * 0.0015]) +
                                         0.6) / 2.0;
            temperature_noise += 0.035 *
                                 open_simplex2::<f32>(&self.temperature_table,
                                                      &[(x as f32) * 0.15, (y as f32) * 0.15]);

            let mut humidity_noise = (open_simplex2::<f32>(&self.humidity_table,
                                                           &[(x as f32) * 0.0015,
                                                             (y as f32) * 0.0015]) +
                                      0.6) / 2.0;
            humidity_noise += 0.035 *
                              open_simplex2::<f32>(&self.humidity_table,
                                                   &[(x as f32) * 0.15, (y as f32) * 0.15]);

            let current_biome = WorldGenerator::biome_from_climate(temperature_noise,
                                                                   humidity_noise);

            for i in 0..WORLDGEN_HEIGHT {
                if i == 0 {
                    fill[rel_pos.q as usize][rel_pos.r as usize][i as usize] = true;
                    continue;
                }

                let z = i as f32 * PILLAR_STEP_HEIGHT;
                let fill_noise = open_simplex3::<f32>(&self.terrain_table,
                                                      &[x * LAND_NOISE_SCALE.0,
                                                        y * LAND_NOISE_SCALE.1,
                                                        z * LAND_NOISE_SCALE.2]);

                // The noise is (theoretically) in the range -1..1
                // Map the noise to a range of 0..1
                let fill_noise = (fill_noise + 1.0) / 2.0;

                // Calculate threshold to fill this "block". The lower the threshold, the more
                // likely this voxel is filled, so it should increase with height.
                let height_pct = i as f32 / WORLDGEN_HEIGHT as f32;

                // The threshold is calculated using a sigmoid function. These are the
                // parameters used:

                /// Minimum threshold to prevent threshold to reach 0,
                /// needed to have any caves at all
                const MIN_THRESH: f32 = 0.6;
                /// Threshold at half value (max. steepness, avg. terrain
                /// height)
                const THRESH_MID: f32 = 0.5;

                // "Steepness" of the sigmoid function.
                let thresh_steepness: f32 =
                    WorldGenerator::steepness_from_temperature(temperature_noise);

                let sig_thresh = 1.0 /
                                 (1.0 + f32::exp(-thresh_steepness * (height_pct - THRESH_MID)));

                let threshold = (sig_thresh + MIN_THRESH) / (1.0 + MIN_THRESH);

                fill[rel_pos.q as usize][rel_pos.r as usize][i as usize] = fill_noise > threshold;
            }

            let column = &fill[rel_pos.q as usize][rel_pos.r as usize];

            // Create sections for all connected `true`s in the array
            let mut sections = Vec::new();
            let mut low = 0;
            let mut height = None;
            for i in 0..WORLDGEN_HEIGHT {
                let material = WorldGenerator::material_from_biome(&current_biome);

                match (height, column[i]) {

                    (Some(h), true) => {
                        // Next one's still solid, increase section height
                        height = Some(h + 1);
                    }
                    (Some(h), false) => {
                        // Create a section of height `h` and start over
                        sections.push(PillarSection::new(material,
                                                         HeightType::from_units(low),
                                                         HeightType::from_units(low + h)));
                        height = None;
                    }
                    (None, true) => {
                        low = i as u16;
                        height = Some(1);
                    }
                    (None, false) => {}
                };
            }

            if let Some(h) = height {
                // Create the topmost pillar
                sections.push(PillarSection::new(GroundMaterial::Dirt,
                                                 HeightType::from_units(low),
                                                 HeightType::from_units(low + h)));
            }

            let mut props = Vec::new();

            // plants
            let plant_noise = open_simplex2::<f32>(&self.plant_table,
                                                   &[(x as f32) * 0.25, (y as f32) * 0.25]);

            if plant_noise > WorldGenerator::plant_threshold_from_biome(&current_biome) {
                let mut rng = super::seeded_rng(self.seed, "TREE", (pos.q, pos.r));
                let gen = PlantGenerator::rand(&mut rng);

                // put the tree at the highest position
                let height = match sections.last() {
                    Some(section) => section.top,
                    None => HeightType::from_units(0),
                };

                props.push(Prop {
                    baseline: height,
                    prop: PropType::Plant(gen.generate(&mut rng)),
                });
            }

            HexPillar::new(sections, props)
        }))
    }

    fn is_chunk_loadable(&self, _: ChunkIndex) -> bool {
        // All chunks can be generated from nothing
        true
    }
}
<|endoftext|>


<commit_before>/// A legacy 16/16 version encoding

/// Packed 32-bit value with major and minor version numbers.
///
/// This is a legacy type with an unusual representation. See [the spec][] for
/// additional details.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version16Dot16(u32);

/// A type representing a major, minor version pair.
///
/// This is not part of the spec, but versions in the spec are frequently
/// represented as a `major_version`, `minor_version` pair. This type encodes
/// those as a single type, which is useful for some of the generated code that
/// parses out a version.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MajorMinor {
    /// The major version number
    pub major: u16,
    /// The minor version number
    pub minor: u16,
}

/// A trait for determining whether versions are compatible.
pub trait Compatible: Sized {
    /// return `true` if this version is field-compatible with `other`.
    ///
    /// This is kind of poorly defined, but basically means 'same major version,
    /// greater than or equal minor version'.
    fn compatible(&self, other: Self) -> bool;
}

impl Version16Dot16 {
    /// Version 0.5
    pub const VERSION_0_5: Version16Dot16 = Version16Dot16::new(0, 5);
    /// Version 1.0
    pub const VERSION_1_0: Version16Dot16 = Version16Dot16::new(1, 0);
    /// Version 2.0
    pub const VERSION_2_0: Version16Dot16 = Version16Dot16::new(2, 0);
    /// Version 2.5
    pub const VERSION_2_5: Version16Dot16 = Version16Dot16::new(2, 5);
    /// Version 3.0
    pub const VERSION_3_0: Version16Dot16 = Version16Dot16::new(3, 0);

    /// Create a new version with the provided major and minor parts.
    ///
    /// The minor version must be in the range 0..=9.
    ///
    /// # Panics
    ///
    /// Panics if `minor > 9`.
    pub const fn new(major: u16, minor: u16) -> Self {
        assert!(minor < 10, "minor version must be in the range [0, 9)");
        let version = (major as u32) << 16 | (minor as u32) << 12;
        Version16Dot16(version)
    }

    /// Return the separate major & minor version numbers.
    pub const fn to_major_minor(self) -> (u16, u16) {
        let major = (self.0 >> 16) as u16;
        let minor = ((self.0 & 0xFFFF) >> 12) as u16;
        (major, minor)
    }

    /// The representation of this version as a big-endian byte array.
    #[inline]
    pub fn to_be_bytes(self) -> [u8; 4] {
        self.0.to_be_bytes()
    }
}

crate::newtype_scalar!(Version16Dot16, [u8; 4]);

impl MajorMinor {
    /// Version 1.0
    pub const VERSION_1_0: MajorMinor = MajorMinor::new(1, 0);
    /// Version 1.1
    pub const VERSION_1_1: MajorMinor = MajorMinor::new(1, 1);
    /// Version 1.2
    pub const VERSION_1_2: MajorMinor = MajorMinor::new(1, 2);
    /// Version 1.3
    pub const VERSION_1_3: MajorMinor = MajorMinor::new(1, 3);

    /// Create a new version with major and minor parts.
    #[inline]
    pub const fn new(major: u16, minor: u16) -> Self {
        MajorMinor { major, minor }
    }

    /// The representation of this version as a big-endian byte array.
    #[inline]
    pub fn to_be_bytes(self) -> [u8; 4] {
        let [a, b] = self.major.to_be_bytes();
        let [c, d] = self.minor.to_be_bytes();
        [a, b, c, d]
    }
}

impl crate::Scalar for MajorMinor {
    type Raw = [u8; 4];

    fn from_raw(raw: Self::Raw) -> Self {
        let major = u16::from_be_bytes([raw[0], raw[1]]);
        let minor = u16::from_be_bytes([raw[2], raw[3]]);
        Self { major, minor }
    }

    fn to_raw(self) -> Self::Raw {
        self.to_be_bytes()
    }
}

impl Compatible for Version16Dot16 {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        let (self_major, self_minor) = self.to_major_minor();
        let (other_major, other_minor) = other.to_major_minor();
        self_major == other_major && self_minor >= other_minor
    }
}

impl Compatible for MajorMinor {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        self.major == other.major && self.minor >= other.minor
    }
}

impl Compatible for u16 {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        *self >= other
    }
}

impl std::fmt::Debug for Version16Dot16 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Version16Dot16({:08x})", self.0)
    }
}

impl std::fmt::Display for Version16Dot16 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let (major, minor) = self.to_major_minor();
        write!(f, "{major}.{minor}")
    }
}

impl std::fmt::Display for MajorMinor {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let MajorMinor { major, minor } = self;
        write!(f, "{major}.{minor}")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn version_smoke_test() {
        assert_eq!(Version16Dot16(0x00005000).to_major_minor(), (0, 5));
        assert_eq!(Version16Dot16(0x00011000).to_major_minor(), (1, 1));
        assert_eq!(Version16Dot16::new(0, 5).0, 0x00005000);
        assert_eq!(Version16Dot16::new(1, 1).0, 0x00011000);
    }
}
<commit_msg>Make the 'rhs' of the Compatible trait be generic<commit_after>/// A legacy 16/16 version encoding

/// Packed 32-bit value with major and minor version numbers.
///
/// This is a legacy type with an unusual representation. See [the spec][] for
/// additional details.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Version16Dot16(u32);

/// A type representing a major, minor version pair.
///
/// This is not part of the spec, but versions in the spec are frequently
/// represented as a `major_version`, `minor_version` pair. This type encodes
/// those as a single type, which is useful for some of the generated code that
/// parses out a version.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct MajorMinor {
    /// The major version number
    pub major: u16,
    /// The minor version number
    pub minor: u16,
}

/// A trait for determining whether versions are compatible.
pub trait Compatible<Rhs = Self>: Sized {
    /// return `true` if this version is field-compatible with `other`.
    ///
    /// This is kind of poorly defined, but basically means 'same major version,
    /// greater than or equal minor version'.
    fn compatible(&self, other: Rhs) -> bool;
}

impl Version16Dot16 {
    /// Version 0.5
    pub const VERSION_0_5: Version16Dot16 = Version16Dot16::new(0, 5);
    /// Version 1.0
    pub const VERSION_1_0: Version16Dot16 = Version16Dot16::new(1, 0);
    /// Version 2.0
    pub const VERSION_2_0: Version16Dot16 = Version16Dot16::new(2, 0);
    /// Version 2.5
    pub const VERSION_2_5: Version16Dot16 = Version16Dot16::new(2, 5);
    /// Version 3.0
    pub const VERSION_3_0: Version16Dot16 = Version16Dot16::new(3, 0);

    /// Create a new version with the provided major and minor parts.
    ///
    /// The minor version must be in the range 0..=9.
    ///
    /// # Panics
    ///
    /// Panics if `minor > 9`.
    pub const fn new(major: u16, minor: u16) -> Self {
        assert!(minor < 10, "minor version must be in the range [0, 9)");
        let version = (major as u32) << 16 | (minor as u32) << 12;
        Version16Dot16(version)
    }

    /// Return the separate major & minor version numbers.
    pub const fn to_major_minor(self) -> (u16, u16) {
        let major = (self.0 >> 16) as u16;
        let minor = ((self.0 & 0xFFFF) >> 12) as u16;
        (major, minor)
    }

    /// The representation of this version as a big-endian byte array.
    #[inline]
    pub fn to_be_bytes(self) -> [u8; 4] {
        self.0.to_be_bytes()
    }
}

crate::newtype_scalar!(Version16Dot16, [u8; 4]);

impl MajorMinor {
    /// Version 1.0
    pub const VERSION_1_0: MajorMinor = MajorMinor::new(1, 0);
    /// Version 1.1
    pub const VERSION_1_1: MajorMinor = MajorMinor::new(1, 1);
    /// Version 1.2
    pub const VERSION_1_2: MajorMinor = MajorMinor::new(1, 2);
    /// Version 1.3
    pub const VERSION_1_3: MajorMinor = MajorMinor::new(1, 3);

    /// Create a new version with major and minor parts.
    #[inline]
    pub const fn new(major: u16, minor: u16) -> Self {
        MajorMinor { major, minor }
    }

    /// The representation of this version as a big-endian byte array.
    #[inline]
    pub fn to_be_bytes(self) -> [u8; 4] {
        let [a, b] = self.major.to_be_bytes();
        let [c, d] = self.minor.to_be_bytes();
        [a, b, c, d]
    }
}

impl crate::Scalar for MajorMinor {
    type Raw = [u8; 4];

    fn from_raw(raw: Self::Raw) -> Self {
        let major = u16::from_be_bytes([raw[0], raw[1]]);
        let minor = u16::from_be_bytes([raw[2], raw[3]]);
        Self { major, minor }
    }

    fn to_raw(self) -> Self::Raw {
        self.to_be_bytes()
    }
}

impl Compatible for Version16Dot16 {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        let (self_major, self_minor) = self.to_major_minor();
        let (other_major, other_minor) = other.to_major_minor();
        self_major == other_major && self_minor >= other_minor
    }
}

impl Compatible for MajorMinor {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        self.major == other.major && self.minor >= other.minor
    }
}

impl Compatible for u16 {
    #[inline]
    fn compatible(&self, other: Self) -> bool {
        *self >= other
    }
}

impl std::fmt::Debug for Version16Dot16 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Version16Dot16({:08x})", self.0)
    }
}

impl std::fmt::Display for Version16Dot16 {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let (major, minor) = self.to_major_minor();
        write!(f, "{major}.{minor}")
    }
}

impl std::fmt::Display for MajorMinor {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let MajorMinor { major, minor } = self;
        write!(f, "{major}.{minor}")
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn version_smoke_test() {
        assert_eq!(Version16Dot16(0x00005000).to_major_minor(), (0, 5));
        assert_eq!(Version16Dot16(0x00011000).to_major_minor(), (1, 1));
        assert_eq!(Version16Dot16::new(0, 5).0, 0x00005000);
        assert_eq!(Version16Dot16::new(1, 1).0, 0x00011000);
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

#[macro_export]
macro_rules! msg_send(
	($obj:expr $name:ident) => ({
		use runtime::Messageable;
		let sel_name = stringify!($name);
		let sel = ::runtime::Sel::register(sel_name);
		::runtime::objc_msgSend($obj.as_ptr(), sel)
	});
	($obj:expr $($name:ident : $arg:expr)+) => ({
		use runtime::Messageable;
		let sel_name = concat!($(stringify!($name), ':'),+);
		let sel = ::runtime::Sel::register(sel_name);
		::runtime::objc_msgSend($obj.as_ptr(), sel $(,$arg)+)
	});
)

#[macro_export]
macro_rules! object_struct(
	($name:ident<$($t:ident),+>) => (
		object_struct!($name, $($t),+)
	);
	($name:ident $(,$t:ident)*) => (
		pub enum $name<$($t),*> { }

		impl<$($t),*> ::runtime::Messageable for $name<$($t),*> {
			fn as_ptr(&self) -> *::runtime::Object {
				(self as *$name<$($t),*>) as *::runtime::Object
			}
		}

		impl<$($t),*> ::foundation::INSObject for $name<$($t),*> {
			fn class_name() -> ::id::ClassName<$name<$($t),*>> {
				::id::ClassName::from_str(stringify!($name))
			}
		}

		impl<$($t),*> ::std::cmp::PartialEq for $name<$($t),*> {
			fn eq(&self, other: &$name<$($t),*>) -> bool {
				use foundation::INSObject;
				self.is_equal(other)
			}
		}

		impl<$($t),*> ::std::cmp::Eq for $name<$($t),*> { }

		impl<$($t,)* S: ::std::hash::Writer> ::std::hash::Hash<S> for $name<$($t),*> {
			fn hash(&self, state: &mut S) {
				use foundation::INSObject;
				self.hash_code().hash(state);
			}
		}

		impl<$($t),*> ::std::fmt::Show for $name<$($t),*> {
			fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
				use foundation::{INSObject, INSString};
				self.description().as_str().fmt(f)
			}
		}
	);
)
<commit_msg>Made objects not copyable.<commit_after>#![macro_escape]

#[macro_export]
macro_rules! msg_send(
	($obj:expr $name:ident) => ({
		use runtime::Messageable;
		let sel_name = stringify!($name);
		let sel = ::runtime::Sel::register(sel_name);
		::runtime::objc_msgSend($obj.as_ptr(), sel)
	});
	($obj:expr $($name:ident : $arg:expr)+) => ({
		use runtime::Messageable;
		let sel_name = concat!($(stringify!($name), ':'),+);
		let sel = ::runtime::Sel::register(sel_name);
		::runtime::objc_msgSend($obj.as_ptr(), sel $(,$arg)+)
	});
)

#[macro_export]
macro_rules! object_struct(
	($name:ident<$($t:ident),+>) => (
		object_struct!($name, $($t),+)
	);
	($name:ident $(,$t:ident)*) => (
		pub struct $name<$($t),*> {
			nocopy: ::std::kinds::marker::NoCopy,
		}

		impl<$($t),*> ::runtime::Messageable for $name<$($t),*> {
			fn as_ptr(&self) -> *::runtime::Object {
				(self as *$name<$($t),*>) as *::runtime::Object
			}
		}

		impl<$($t),*> ::foundation::INSObject for $name<$($t),*> {
			fn class_name() -> ::id::ClassName<$name<$($t),*>> {
				::id::ClassName::from_str(stringify!($name))
			}
		}

		impl<$($t),*> ::std::cmp::PartialEq for $name<$($t),*> {
			fn eq(&self, other: &$name<$($t),*>) -> bool {
				use foundation::INSObject;
				self.is_equal(other)
			}
		}

		impl<$($t),*> ::std::cmp::Eq for $name<$($t),*> { }

		impl<$($t,)* S: ::std::hash::Writer> ::std::hash::Hash<S> for $name<$($t),*> {
			fn hash(&self, state: &mut S) {
				use foundation::INSObject;
				self.hash_code().hash(state);
			}
		}

		impl<$($t),*> ::std::fmt::Show for $name<$($t),*> {
			fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
				use foundation::{INSObject, INSString};
				self.description().as_str().fmt(f)
			}
		}
	);
)
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use futures::Stream;
use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::os::unix::io::{AsRawFd};
use std::pin::Pin;
use std::task::{Context, Poll};

use libc::{EWOULDBLOCK, O_NONBLOCK};

use sys_util::{self, add_fd_flags};

use cros_async::fd_executor::{self, add_read_waker};

/// Errors generated while polling for events.
#[derive(Debug)]
pub enum Error {
    /// An error occurred attempting to register a waker with the executor.
    AddingWaker(fd_executor::Error),
    /// Failure creating the event FD.
    EventFdCreate(sys_util::Error),
    /// An error occurred when reading the event FD.
    EventFdRead(sys_util::Error),
    /// An error occurred when setting the event FD non-blocking.
    SettingNonBlocking(sys_util::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            AddingWaker(e) => write!(
                f,
                "An error occurred attempting to register a waker with the executor: {}.",
                e
            ),
            EventFdCreate(e) => write!(f, "An error occurred when creating the event FD: {}.", e),
            EventFdRead(e) => write!(f, "An error occurred when reading the event FD: {}.", e),
            SettingNonBlocking(e) => {
                write!(f, "An error occurred setting the FD non-blocking: {}.", e)
            }
        }
    }
}

/// Asynchronous version of `sys_util::EventFd`. Provides an implementation of `futures::Stream` so
/// that events can be consumed in an async context.
///
/// # Example
///
/// ```
/// use std::convert::TryInto;
///
/// use async_core::{EventFd };
/// use futures::StreamExt;
/// use sys_util::{self};
///
/// async fn process_events() -> std::result::Result<(), Box<dyn std::error::Error>> {
///     let mut async_events: EventFd = sys_util::EventFd::new()?.try_into()?;
///     while let Some(e) = async_events.next().await {
///         // Handle event here.
///     }
///     Ok(())
/// }
/// ```
pub struct EventFd {
    inner: sys_util::EventFd,
    done: bool,
}

impl EventFd {
    pub fn new() -> Result<EventFd> {
        Self::try_from(sys_util::EventFd::new().map_err(Error::EventFdCreate)?)
    }
}

impl TryFrom<sys_util::EventFd> for EventFd {
    type Error = crate::eventfd::Error;

    fn try_from(eventfd: sys_util::EventFd) -> Result<EventFd> {
        let fd = eventfd.as_raw_fd();
        add_fd_flags(fd, O_NONBLOCK).map_err(Error::SettingNonBlocking)?;
        Ok(EventFd {
            inner: eventfd,
            done: false,
        })
    }
}

impl Stream for EventFd {
    type Item = Result<u64>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        if self.done {
            return Poll::Ready(None);
        }

        let res = self
            .inner
            .read()
            .map(|v| Poll::Ready(Some(Ok(v))))
            .or_else(|e| {
                if e.errno() == EWOULDBLOCK {
                    add_read_waker(self.inner.as_raw_fd(), cx.waker().clone())
                        .map(|()| Poll::Pending)
                        .map_err(Error::AddingWaker)
                } else {
                    Err(Error::EventFdRead(e))
                }
            });

        match res {
            Ok(v) => v,
            Err(e) => {
                self.done = true;
                Poll::Ready(Some(Err(e)))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cros_async::{select2, SelectResult};
    use futures::future::pending;
    use futures::pin_mut;
    use futures::stream::StreamExt;

    #[test]
    fn eventfd_write_read() {
        let evt = EventFd::new().unwrap();
        async fn read_one(mut evt: EventFd) -> u64 {
            if let Some(Ok(e)) = evt.next().await {
                e
            } else {
                66
            }
        }
        async fn write_pend(evt: sys_util::EventFd) {
            evt.write(55).unwrap();
            let () = pending().await;
        }
        let write_evt = evt.inner.try_clone().unwrap();

        let r = read_one(evt);
        pin_mut!(r);
        let w = write_pend(write_evt);
        pin_mut!(w);

        if let Ok((SelectResult::Finished(read_res), SelectResult::Pending(_pend_fut))) =
            select2(r, w)
        {
            assert_eq!(read_res, 55);
        } else {
            panic!("wrong futures returned from select2");
        }
    }
}
<commit_msg>async_core: fix formatting of use statement<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use futures::Stream;
use std::convert::TryFrom;
use std::fmt::{self, Display};
use std::os::unix::io::AsRawFd;
use std::pin::Pin;
use std::task::{Context, Poll};

use libc::{EWOULDBLOCK, O_NONBLOCK};

use sys_util::{self, add_fd_flags};

use cros_async::fd_executor::{self, add_read_waker};

/// Errors generated while polling for events.
#[derive(Debug)]
pub enum Error {
    /// An error occurred attempting to register a waker with the executor.
    AddingWaker(fd_executor::Error),
    /// Failure creating the event FD.
    EventFdCreate(sys_util::Error),
    /// An error occurred when reading the event FD.
    EventFdRead(sys_util::Error),
    /// An error occurred when setting the event FD non-blocking.
    SettingNonBlocking(sys_util::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

impl std::error::Error for Error {}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;

        match self {
            AddingWaker(e) => write!(
                f,
                "An error occurred attempting to register a waker with the executor: {}.",
                e
            ),
            EventFdCreate(e) => write!(f, "An error occurred when creating the event FD: {}.", e),
            EventFdRead(e) => write!(f, "An error occurred when reading the event FD: {}.", e),
            SettingNonBlocking(e) => {
                write!(f, "An error occurred setting the FD non-blocking: {}.", e)
            }
        }
    }
}

/// Asynchronous version of `sys_util::EventFd`. Provides an implementation of `futures::Stream` so
/// that events can be consumed in an async context.
///
/// # Example
///
/// ```
/// use std::convert::TryInto;
///
/// use async_core::{EventFd };
/// use futures::StreamExt;
/// use sys_util::{self};
///
/// async fn process_events() -> std::result::Result<(), Box<dyn std::error::Error>> {
///     let mut async_events: EventFd = sys_util::EventFd::new()?.try_into()?;
///     while let Some(e) = async_events.next().await {
///         // Handle event here.
///     }
///     Ok(())
/// }
/// ```
pub struct EventFd {
    inner: sys_util::EventFd,
    done: bool,
}

impl EventFd {
    pub fn new() -> Result<EventFd> {
        Self::try_from(sys_util::EventFd::new().map_err(Error::EventFdCreate)?)
    }
}

impl TryFrom<sys_util::EventFd> for EventFd {
    type Error = crate::eventfd::Error;

    fn try_from(eventfd: sys_util::EventFd) -> Result<EventFd> {
        let fd = eventfd.as_raw_fd();
        add_fd_flags(fd, O_NONBLOCK).map_err(Error::SettingNonBlocking)?;
        Ok(EventFd {
            inner: eventfd,
            done: false,
        })
    }
}

impl Stream for EventFd {
    type Item = Result<u64>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
        if self.done {
            return Poll::Ready(None);
        }

        let res = self
            .inner
            .read()
            .map(|v| Poll::Ready(Some(Ok(v))))
            .or_else(|e| {
                if e.errno() == EWOULDBLOCK {
                    add_read_waker(self.inner.as_raw_fd(), cx.waker().clone())
                        .map(|()| Poll::Pending)
                        .map_err(Error::AddingWaker)
                } else {
                    Err(Error::EventFdRead(e))
                }
            });

        match res {
            Ok(v) => v,
            Err(e) => {
                self.done = true;
                Poll::Ready(Some(Err(e)))
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use cros_async::{select2, SelectResult};
    use futures::future::pending;
    use futures::pin_mut;
    use futures::stream::StreamExt;

    #[test]
    fn eventfd_write_read() {
        let evt = EventFd::new().unwrap();
        async fn read_one(mut evt: EventFd) -> u64 {
            if let Some(Ok(e)) = evt.next().await {
                e
            } else {
                66
            }
        }
        async fn write_pend(evt: sys_util::EventFd) {
            evt.write(55).unwrap();
            let () = pending().await;
        }
        let write_evt = evt.inner.try_clone().unwrap();

        let r = read_one(evt);
        pin_mut!(r);
        let w = write_pend(write_evt);
        pin_mut!(w);

        if let Ok((SelectResult::Finished(read_res), SelectResult::Pending(_pend_fut))) =
            select2(r, w)
        {
            assert_eq!(read_res, 55);
        } else {
            panic!("wrong futures returned from select2");
        }
    }
}
<|endoftext|>