<commit_before>use bindgen::{Builder, CodegenConfig, builder};
use clap::{App, Arg};
use std::fs::File;
use std::io::{self, Error, ErrorKind};

/// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
pub fn builder_from_flags<I>
    (args: I)
     -> Result<(Builder, Box<io::Write>, bool), io::Error>
    where I: Iterator<Item = String>,
{
    let matches = App::new("bindgen")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Generates Rust bindings from C/C++ headers.")
        .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
        .args(&[
            Arg::with_name("header")
                .help("C or C++ header file")
                .required(true),
            Arg::with_name("bitfield-enum")
                .long("bitfield-enum")
                .help("Mark any enum whose name matches <regex> as a set of \
                       bitfield flags instead of an enumeration.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("constified-enum")
                .long("constified-enum")
                .help("Mark any enum whose name matches <regex> as a set of \
                       constants instead of an enumeration.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("blacklist-type")
                .long("blacklist-type")
                .help("Mark a type as hidden.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("no-derive-debug")
                .long("no-derive-debug")
                .help("Avoid deriving Debug on any type."),
            Arg::with_name("no-derive-default")
                .long("no-derive-default")
                .hidden(true)
                .help("Avoid deriving Default on any type."),
            Arg::with_name("with-derive-default")
                .long("with-derive-default")
                .help("Deriving Default on any type."),
            Arg::with_name("no-doc-comments")
                .long("no-doc-comments")
                .help("Avoid including doc comments in the output, see: \
                      https://github.com/servo/rust-bindgen/issues/426"),
            Arg::with_name("no-recursive-whitelist")
                .long("no-recursive-whitelist")
                .help("Avoid whitelisting types recursively"),
            Arg::with_name("objc-extern-crate")
                .long("objc-extern-crate")
                .help("Use extern crate instead of use for objc"),
            Arg::with_name("distrust-clang-mangling")
                .long("distrust-clang-mangling")
                .help("Do not trust the libclang-provided mangling"),
            Arg::with_name("builtins")
                .long("builtins")
                .help("Output bindings for builtin definitions, e.g. \
                       __builtin_va_list."),
            Arg::with_name("ctypes-prefix")
                .long("ctypes-prefix")
                .help("Use the given prefix before raw types instead of \
                      ::std::os::raw.")
                .value_name("prefix")
                .takes_value(true),
            // All positional arguments after the end of options marker, `--`
            Arg::with_name("clang-args")
                .multiple(true),
            Arg::with_name("dummy-uses")
                .long("dummy-uses")
                .help("For testing purposes, generate a C/C++ file containing \
                       dummy uses of all types defined in the input header.")
                .takes_value(true),
            Arg::with_name("emit-clang-ast")
                .long("emit-clang-ast")
                .help("Output the Clang AST for debugging purposes."),
            Arg::with_name("emit-ir")
                .long("emit-ir")
                .help("Output our internal IR for debugging purposes."),
            Arg::with_name("emit-ir-graphviz")
                .long("emit-ir-graphviz")
                .help("Dump graphviz dot file.")
                .value_name("path")
                .takes_value(true),
            Arg::with_name("enable-cxx-namespaces")
                .long("enable-cxx-namespaces")
                .help("Enable support for C++ namespaces."),
            Arg::with_name("disable-name-namespacing")
                .long("disable-name-namespacing")
                .help("Disable name namespacing if namespaces are disabled."),
            Arg::with_name("framework")
                .long("framework-link")
                .help("Link to framework.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("ignore-functions")
                .long("ignore-functions")
                .help("Do not generate bindings for functions or methods. This \
                       is useful when you only care about struct layouts."),
            Arg::with_name("generate")
                .long("generate")
                .help("Generate a given kind of items, split by commas. \
                       Valid values are \"functions\",\"types\", \"vars\" and \
                       \"methods\".")
                .takes_value(true),
            Arg::with_name("ignore-methods")
                .long("ignore-methods")
                .help("Do not generate bindings for methods."),
            Arg::with_name("dynamic")
                .short("l")
                .long("link")
                .help("Link to dynamic library.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("no-convert-floats")
                .long("no-convert-floats")
                .help("Don't automatically convert floats to f32/f64."),
            Arg::with_name("no-prepend-enum-name")
                .long("no-prepend-enum-name")
                .help("Do not prepend the enum name to bitfield or constant variants"),
            Arg::with_name("no-unstable-rust")
                .long("no-unstable-rust")
                .help("Do not generate unstable Rust code.")
                .multiple(true), // FIXME: Pass legacy test suite
            Arg::with_name("opaque-type")
                .long("opaque-type")
                .help("Mark a type as opaque.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("output")
                .short("o")
                .long("output")
                .help("Write Rust bindings to <output>.")
                .takes_value(true),
            Arg::with_name("raw-line")
                .long("raw-line")
                .help("Add a raw line of Rust code at the beginning of output.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("static")
                .long("static-link")
                .help("Link to static library.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("use-core")
                .long("use-core")
                .help("Use types from Rust core instead of std."),
            Arg::with_name("conservative-inline-namespaces")
                .long("conservative-inline-namespaces")
                .help("Conservatively generate inline namespaces to avoid name \
                       conflicts."),
            Arg::with_name("use-msvc-mangling")
                .long("use-msvc-mangling")
                .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
            Arg::with_name("whitelist-function")
                .long("whitelist-function")
                .help("Whitelist all the free-standing functions matching \
                       <regex>. Other non-whitelisted functions will not be \
                       generated.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("whitelist-type")
                .long("whitelist-type")
                .help("Whitelist the type. Other non-whitelisted types will \
                       not be generated.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("whitelist-var")
                .long("whitelist-var")
                .help("Whitelist all the free-standing variables matching \
                       <regex>. Other non-whitelisted variables will not be \
                       generated.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("verbose")
                .long("verbose")
                .help("Print verbose error messages"),
        ]) // .args()
        .get_matches_from(args);

    let mut builder = builder();

    if let Some(header) = matches.value_of("header") {
        builder = builder.header(header);
    } else {
        return Err(Error::new(ErrorKind::Other, "Header not found"));
    }

    if let Some(bitfields) = matches.values_of("bitfield-enum") {
        for regex in bitfields {
            builder = builder.bitfield_enum(regex);
        }
    }

    if let Some(bitfields) = matches.values_of("constified-enum") {
        for regex in bitfields {
            builder = builder.constified_enum(regex);
        }
    }

    if let Some(hidden_types) = matches.values_of("blacklist-type") {
        for ty in hidden_types {
            builder = builder.hide_type(ty);
        }
    }

    if matches.is_present("builtins") {
        builder = builder.emit_builtins();
    }

    if matches.is_present("no-derive-debug") {
        builder = builder.derive_debug(false);
    }

    if matches.is_present("with-derive-default") {
        builder = builder.derive_default(true);
    }

    if matches.is_present("no-derive-default") {
        builder = builder.derive_default(false);
    }

    if matches.is_present("no-prepend-enum-name") {
        builder = builder.prepend_enum_name(false);
    }

    if let Some(prefix) = matches.value_of("ctypes-prefix") {
        builder = builder.ctypes_prefix(prefix);
    }

    if let Some(dummy) = matches.value_of("dummy-uses") {
        builder = builder.dummy_uses(dummy);
    }

    if let Some(links) = matches.values_of("dynamic") {
        for library in links {
            builder = builder.link(library);
        }
    }

    if let Some(what_to_generate) = matches.value_of("generate") {
        let mut config = CodegenConfig::nothing();
        for what in what_to_generate.split(",") {
            match what {
                "functions" => config.functions = true,
                "types" => config.types = true,
                "vars" => config.vars = true,
                "methods" => config.methods = true,
                _ => {
                    return Err(Error::new(ErrorKind::Other,
                                          "Unknown generate item"));
                }
            }
        }
        builder = builder.with_codegen_config(config);
    }

    if matches.is_present("emit-clang-ast") {
        builder = builder.emit_clang_ast();
    }

    if matches.is_present("emit-ir") {
        builder = builder.emit_ir();
    }

    if let Some(path) = matches.value_of("emit-ir-graphviz") {
        builder = builder.emit_ir_graphviz(path);
    }

    if matches.is_present("enable-cxx-namespaces") {
        builder = builder.enable_cxx_namespaces();
    }

    if matches.is_present("disable-name-namespacing") {
        builder = builder.disable_name_namespacing();
    }

    if let Some(links) = matches.values_of("framework") {
        for framework in links {
            builder = builder.link_framework(framework);
        }
    }

    if matches.is_present("ignore-functions") {
        builder = builder.ignore_functions();
    }

    if matches.is_present("ignore-methods") {
        builder = builder.ignore_methods();
    }

    if matches.is_present("no-unstable-rust") {
        builder = builder.no_unstable_rust();
    }

    if matches.is_present("no-convert-floats") {
        builder = builder.no_convert_floats();
    }

    if matches.is_present("no-doc-comments") {
        builder = builder.generate_comments(false);
    }

    if matches.is_present("no-recursive-whitelist") {
        builder = builder.whitelist_recursively(false);
    }

    if let Some(opaque_types) = matches.values_of("opaque-type") {
        for ty in opaque_types {
            builder = builder.opaque_type(ty);
        }
    }

    if let Some(lines) = matches.values_of("raw-line") {
        for line in lines {
            builder = builder.raw_line(line);
        }
    }

    if let Some(links) = matches.values_of("static") {
        for library in links {
            builder = builder.link_static(library);
        }
    }

    if matches.is_present("use-core") {
        builder = builder.use_core();
    }

    if matches.is_present("conservative-inline-namespaces") {
        builder = builder.conservative_inline_namespaces();
    }

    if let Some(whitelist) = matches.values_of("whitelist-function") {
        for regex in whitelist {
            builder = builder.whitelisted_function(regex);
        }
    }

    if let Some(whitelist) = matches.values_of("whitelist-type") {
        for regex in whitelist {
            builder = builder.whitelisted_type(regex);
        }
    }

    if let Some(whitelist) = matches.values_of("whitelist-var") {
        for regex in whitelist {
            builder = builder.whitelisted_var(regex);
        }
    }

    if let Some(args) = matches.values_of("clang-args") {
        for arg in args {
            builder = builder.clang_arg(arg);
        }
    }

    let output = if let Some(path) = matches.value_of("output") {
        let file = try!(File::create(path));
        Box::new(io::BufWriter::new(file)) as Box<io::Write>
    } else {
        Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
    };

    let verbose = matches.is_present("verbose");

    Ok((builder, output, verbose))
}
<commit_msg>Auto merge of #579 - emilio:mangling, r=fitzgen<commit_after>use bindgen::{Builder, CodegenConfig, builder};
use clap::{App, Arg};
use std::fs::File;
use std::io::{self, Error, ErrorKind};

/// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
pub fn builder_from_flags<I>
    (args: I)
     -> Result<(Builder, Box<io::Write>, bool), io::Error>
    where I: Iterator<Item = String>,
{
    let matches = App::new("bindgen")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Generates Rust bindings from C/C++ headers.")
        .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
        .args(&[
            Arg::with_name("header")
                .help("C or C++ header file")
                .required(true),
            Arg::with_name("bitfield-enum")
                .long("bitfield-enum")
                .help("Mark any enum whose name matches <regex> as a set of \
                       bitfield flags instead of an enumeration.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("constified-enum")
                .long("constified-enum")
                .help("Mark any enum whose name matches <regex> as a set of \
                       constants instead of an enumeration.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("blacklist-type")
                .long("blacklist-type")
                .help("Mark a type as hidden.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("no-derive-debug")
                .long("no-derive-debug")
                .help("Avoid deriving Debug on any type."),
            Arg::with_name("no-derive-default")
                .long("no-derive-default")
                .hidden(true)
                .help("Avoid deriving Default on any type."),
            Arg::with_name("with-derive-default")
                .long("with-derive-default")
                .help("Deriving Default on any type."),
            Arg::with_name("no-doc-comments")
                .long("no-doc-comments")
                .help("Avoid including doc comments in the output, see: \
                      https://github.com/servo/rust-bindgen/issues/426"),
            Arg::with_name("no-recursive-whitelist")
                .long("no-recursive-whitelist")
                .help("Avoid whitelisting types recursively"),
            Arg::with_name("objc-extern-crate")
                .long("objc-extern-crate")
                .help("Use extern crate instead of use for objc"),
            Arg::with_name("distrust-clang-mangling")
                .long("distrust-clang-mangling")
                .help("Do not trust the libclang-provided mangling"),
            Arg::with_name("builtins")
                .long("builtins")
                .help("Output bindings for builtin definitions, e.g. \
                       __builtin_va_list."),
            Arg::with_name("ctypes-prefix")
                .long("ctypes-prefix")
                .help("Use the given prefix before raw types instead of \
                      ::std::os::raw.")
                .value_name("prefix")
                .takes_value(true),
            // All positional arguments after the end of options marker, `--`
            Arg::with_name("clang-args")
                .multiple(true),
            Arg::with_name("dummy-uses")
                .long("dummy-uses")
                .help("For testing purposes, generate a C/C++ file containing \
                       dummy uses of all types defined in the input header.")
                .takes_value(true),
            Arg::with_name("emit-clang-ast")
                .long("emit-clang-ast")
                .help("Output the Clang AST for debugging purposes."),
            Arg::with_name("emit-ir")
                .long("emit-ir")
                .help("Output our internal IR for debugging purposes."),
            Arg::with_name("emit-ir-graphviz")
                .long("emit-ir-graphviz")
                .help("Dump graphviz dot file.")
                .value_name("path")
                .takes_value(true),
            Arg::with_name("enable-cxx-namespaces")
                .long("enable-cxx-namespaces")
                .help("Enable support for C++ namespaces."),
            Arg::with_name("disable-name-namespacing")
                .long("disable-name-namespacing")
                .help("Disable name namespacing if namespaces are disabled."),
            Arg::with_name("framework")
                .long("framework-link")
                .help("Link to framework.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("ignore-functions")
                .long("ignore-functions")
                .help("Do not generate bindings for functions or methods. This \
                       is useful when you only care about struct layouts."),
            Arg::with_name("generate")
                .long("generate")
                .help("Generate a given kind of items, split by commas. \
                       Valid values are \"functions\",\"types\", \"vars\" and \
                       \"methods\".")
                .takes_value(true),
            Arg::with_name("ignore-methods")
                .long("ignore-methods")
                .help("Do not generate bindings for methods."),
            Arg::with_name("dynamic")
                .short("l")
                .long("link")
                .help("Link to dynamic library.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("no-convert-floats")
                .long("no-convert-floats")
                .help("Don't automatically convert floats to f32/f64."),
            Arg::with_name("no-prepend-enum-name")
                .long("no-prepend-enum-name")
                .help("Do not prepend the enum name to bitfield or constant variants"),
            Arg::with_name("no-unstable-rust")
                .long("no-unstable-rust")
                .help("Do not generate unstable Rust code.")
                .multiple(true), // FIXME: Pass legacy test suite
            Arg::with_name("opaque-type")
                .long("opaque-type")
                .help("Mark a type as opaque.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("output")
                .short("o")
                .long("output")
                .help("Write Rust bindings to <output>.")
                .takes_value(true),
            Arg::with_name("raw-line")
                .long("raw-line")
                .help("Add a raw line of Rust code at the beginning of output.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("static")
                .long("static-link")
                .help("Link to static library.")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("use-core")
                .long("use-core")
                .help("Use types from Rust core instead of std."),
            Arg::with_name("conservative-inline-namespaces")
                .long("conservative-inline-namespaces")
                .help("Conservatively generate inline namespaces to avoid name \
                       conflicts."),
            Arg::with_name("use-msvc-mangling")
                .long("use-msvc-mangling")
                .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
            Arg::with_name("whitelist-function")
                .long("whitelist-function")
                .help("Whitelist all the free-standing functions matching \
                       <regex>. Other non-whitelisted functions will not be \
                       generated.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("whitelist-type")
                .long("whitelist-type")
                .help("Whitelist the type. Other non-whitelisted types will \
                       not be generated.")
                .value_name("type")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("whitelist-var")
                .long("whitelist-var")
                .help("Whitelist all the free-standing variables matching \
                       <regex>. Other non-whitelisted variables will not be \
                       generated.")
                .value_name("regex")
                .takes_value(true)
                .multiple(true)
                .number_of_values(1),
            Arg::with_name("verbose")
                .long("verbose")
                .help("Print verbose error messages"),
        ]) // .args()
        .get_matches_from(args);

    let mut builder = builder();

    if let Some(header) = matches.value_of("header") {
        builder = builder.header(header);
    } else {
        return Err(Error::new(ErrorKind::Other, "Header not found"));
    }

    if let Some(bitfields) = matches.values_of("bitfield-enum") {
        for regex in bitfields {
            builder = builder.bitfield_enum(regex);
        }
    }

    if let Some(bitfields) = matches.values_of("constified-enum") {
        for regex in bitfields {
            builder = builder.constified_enum(regex);
        }
    }

    if let Some(hidden_types) = matches.values_of("blacklist-type") {
        for ty in hidden_types {
            builder = builder.hide_type(ty);
        }
    }

    if matches.is_present("builtins") {
        builder = builder.emit_builtins();
    }

    if matches.is_present("no-derive-debug") {
        builder = builder.derive_debug(false);
    }

    if matches.is_present("with-derive-default") {
        builder = builder.derive_default(true);
    }

    if matches.is_present("no-derive-default") {
        builder = builder.derive_default(false);
    }

    if matches.is_present("no-prepend-enum-name") {
        builder = builder.prepend_enum_name(false);
    }

    if let Some(prefix) = matches.value_of("ctypes-prefix") {
        builder = builder.ctypes_prefix(prefix);
    }

    if let Some(dummy) = matches.value_of("dummy-uses") {
        builder = builder.dummy_uses(dummy);
    }

    if let Some(links) = matches.values_of("dynamic") {
        for library in links {
            builder = builder.link(library);
        }
    }

    if let Some(what_to_generate) = matches.value_of("generate") {
        let mut config = CodegenConfig::nothing();
        for what in what_to_generate.split(",") {
            match what {
                "functions" => config.functions = true,
                "types" => config.types = true,
                "vars" => config.vars = true,
                "methods" => config.methods = true,
                _ => {
                    return Err(Error::new(ErrorKind::Other,
                                          "Unknown generate item"));
                }
            }
        }
        builder = builder.with_codegen_config(config);
    }

    if matches.is_present("emit-clang-ast") {
        builder = builder.emit_clang_ast();
    }

    if matches.is_present("emit-ir") {
        builder = builder.emit_ir();
    }

    if let Some(path) = matches.value_of("emit-ir-graphviz") {
        builder = builder.emit_ir_graphviz(path);
    }

    if matches.is_present("enable-cxx-namespaces") {
        builder = builder.enable_cxx_namespaces();
    }

    if matches.is_present("disable-name-namespacing") {
        builder = builder.disable_name_namespacing();
    }

    if let Some(links) = matches.values_of("framework") {
        for framework in links {
            builder = builder.link_framework(framework);
        }
    }

    if matches.is_present("ignore-functions") {
        builder = builder.ignore_functions();
    }

    if matches.is_present("ignore-methods") {
        builder = builder.ignore_methods();
    }

    if matches.is_present("no-unstable-rust") {
        builder = builder.no_unstable_rust();
    }

    if matches.is_present("no-convert-floats") {
        builder = builder.no_convert_floats();
    }

    if matches.is_present("no-doc-comments") {
        builder = builder.generate_comments(false);
    }

    if matches.is_present("no-recursive-whitelist") {
        builder = builder.whitelist_recursively(false);
    }

    if let Some(opaque_types) = matches.values_of("opaque-type") {
        for ty in opaque_types {
            builder = builder.opaque_type(ty);
        }
    }

    if let Some(lines) = matches.values_of("raw-line") {
        for line in lines {
            builder = builder.raw_line(line);
        }
    }

    if let Some(links) = matches.values_of("static") {
        for library in links {
            builder = builder.link_static(library);
        }
    }

    if matches.is_present("use-core") {
        builder = builder.use_core();
    }

    if matches.is_present("distrust-clang-mangling") {
        builder = builder.trust_clang_mangling(false);
    }

    if matches.is_present("conservative-inline-namespaces") {
        builder = builder.conservative_inline_namespaces();
    }

    if let Some(whitelist) = matches.values_of("whitelist-function") {
        for regex in whitelist {
            builder = builder.whitelisted_function(regex);
        }
    }

    if let Some(whitelist) = matches.values_of("whitelist-type") {
        for regex in whitelist {
            builder = builder.whitelisted_type(regex);
        }
    }

    if let Some(whitelist) = matches.values_of("whitelist-var") {
        for regex in whitelist {
            builder = builder.whitelisted_var(regex);
        }
    }

    if let Some(args) = matches.values_of("clang-args") {
        for arg in args {
            builder = builder.clang_arg(arg);
        }
    }

    let output = if let Some(path) = matches.value_of("output") {
        let file = try!(File::create(path));
        Box::new(io::BufWriter::new(file)) as Box<io::Write>
    } else {
        Box::new(io::BufWriter::new(io::stdout())) as Box<io::Write>
    };

    let verbose = matches.is_present("verbose");

    Ok((builder, output, verbose))
}
<|endoftext|>


<commit_before>extern crate libc;
use core::prelude::*;
pub use self::libc::{c_void, c_int, size_t};
pub use self::libc::{mmap, mprotect, munmap};
pub use self::libc::MAP_FAILED;

use core::ptr;

pub fn page_size() -> usize {
  unsafe {
    libc::sysconf(libc::_SC_PAGESIZE) as usize
  }
}

pub const GUARD_PROT:  c_int = libc::PROT_NONE;
pub const STACK_PROT:  c_int = libc::PROT_READ
                             | libc::PROT_WRITE;
pub const STACK_FLAGS: c_int = libc::MAP_STACK
                             | libc::MAP_PRIVATE
                             | libc::MAP_ANON;

pub unsafe fn map_stack(len: usize) -> Option<*mut u8> {
  let ptr = mmap(ptr::null_mut(), len as size_t,
                 STACK_PROT, STACK_FLAGS, -1, 0);
  if ptr != MAP_FAILED {
    Some(ptr as *mut u8)
  }
  else {
    None
  }
}

pub unsafe fn protect_stack(ptr: *mut u8) -> bool {
  mprotect(ptr as *mut c_void, page_size() as size_t, GUARD_PROT) == 0
}

pub unsafe fn unmap_stack(ptr: *mut u8, len: usize) -> bool {
  munmap(ptr as *mut c_void, len as size_t) == 0
}
<commit_msg>don't re-export os::unix internals<commit_after>extern crate libc;
use core::prelude::*;
use self::libc::{c_void, c_int, size_t};
use self::libc::{mmap, mprotect, munmap};
use self::libc::MAP_FAILED;

use core::ptr;

pub fn page_size() -> usize {
  unsafe {
    libc::sysconf(libc::_SC_PAGESIZE) as usize
  }
}

const GUARD_PROT:  c_int = libc::PROT_NONE;
const STACK_PROT:  c_int = libc::PROT_READ
                         | libc::PROT_WRITE;
const STACK_FLAGS: c_int = libc::MAP_STACK
                         | libc::MAP_PRIVATE
                         | libc::MAP_ANON;

pub unsafe fn map_stack(len: usize) -> Option<*mut u8> {
  let ptr = mmap(ptr::null_mut(), len as size_t,
                 STACK_PROT, STACK_FLAGS, -1, 0);
  if ptr != MAP_FAILED {
    Some(ptr as *mut u8)
  }
  else {
    None
  }
}

pub unsafe fn protect_stack(ptr: *mut u8) -> bool {
  mprotect(ptr as *mut c_void, page_size() as size_t, GUARD_PROT) == 0
}

pub unsafe fn unmap_stack(ptr: *mut u8, len: usize) -> bool {
  munmap(ptr as *mut c_void, len as size_t) == 0
}
<|endoftext|>


<commit_before>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};

use id::Id;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer<'a> {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Id<'a, Program>,
  tris: Tess,
  tri_vert_nb: usize,
  disc_program: Id<'a, Program>,
  discs: Tess,
  disc_vert_nb: usize,
  text_program: Id<'a, Program>,
  text_quad: Tess,
  overlay_unit: OverlayUnit,
}

impl<'a> Renderer<'a> {
  pub fn new(w: u32, h: u32, max_tris: usize, max_discs: usize, scene: &mut Scene<'a>) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get_id("overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let disc_program = scene.get_id("overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get_id("overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: tris,
      tri_vert_nb: 0,
      disc_program: disc_program,
      discs: discs,
      disc_vert_nb: 0,
      text_program: text_program,
      text_quad: text_quad,
      overlay_unit: OverlayUnit::new(w, h)
    }
  }

  fn dispatch(&mut self, input: &RenderInput) {
    let mut tris = self.tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut discs = self.discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      tris[tri_i] = a;
      tri_i += 1;

      tris[tri_i] = b;
      tri_i += 1;

      tris[tri_i] = c;
      tri_i += 1;
    }

    for disc in input.discs {
      discs[disc_i] = *disc;
      disc_i += 1;
    }

    self.tri_vert_nb = tri_i;
    self.disc_vert_nb = disc_i;
  }

  pub fn render(&mut self, scene: &mut Scene<'a>, input: RenderInput) -> &Texture2D {
    self.dispatch(&input);

    let tri_program = scene.get_by_id(&self.tri_program).unwrap();
    let disc_program = scene.get_by_id(&self.disc_program).unwrap();
    let text_program = scene.get_by_id(&self.text_program).unwrap();

    let tris = TessRender::one_sub(&self.tris, self.tri_vert_nb);
    let discs = TessRender::one_sub(&self.discs, self.disc_vert_nb);
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.overlay_unit.from_window(tex_w, tex_h)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&tri_program, vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&disc_program, vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&text_program, text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles, ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// Overlay units are used to position stuff in overlay in a universal way and screen independent
/// way. The screen uses normalized coordinates with the origin at lower left as the following
/// diagram:
///
/// ^ y (1)
/// |
/// |
/// |
/// O------> x (1)
#[derive(Copy, Clone, Debug, PartialEq)]
struct OverlayUnit {
  rw: f32,
  rh: f32
}

impl OverlayUnit {
  pub fn new(w: u32, h: u32) -> Self {
    OverlayUnit {
      rw: 1. / (w as f32),
      rh: 1. / (h as f32)
    }
  }

  pub fn from_window(&self, x: u32, y: u32) -> [f32; 2] {
    let x_ = x as f32 * self.rw;
    assert!(x_ >= 0. && x_ <= 1., "x={}", x_);

    let y_ = y as f32 * self.rh;
    assert!(y_ >= 0. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<commit_msg>Fixed overaly shaders’ paths.<commit_after>use luminance::{Dim2, Equation, Factor, Flat, Framebuffer, Mode, Pipe, Pipeline, RenderCommand, ShadingCommand, Tess, TessRender, TessVertices, Uniform, Unit, Vertex, VertexFormat};

use id::Id;
use scene::Scene;
use shader::Program;
use text::TextTexture;
use texture::{RGBA32F, Texture};

/// Vertex used in overlay’s objects.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vert {
  /// Position.
  pub pos: [f32; 3],
  /// Color.
  pub color: [f32; 4]
}

impl Vert {
  pub fn new(pos: [f32; 3], color: [f32; 4]) -> Self {
    Vert {
      pos: pos,
      color: color
    }
  }
}

impl Vertex for Vert {
  fn vertex_format() -> VertexFormat {
    <([f32; 3], [f32; 4]) as Vertex>::vertex_format()
  }
}

pub struct Triangle(pub Vert, pub Vert, pub Vert);

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Disc {
  center: Vert,
  radius: f32
}

impl Disc {
  pub fn new(center: Vert, radius: f32) -> Self {
    Disc {
      center: center,
      radius: radius
    }
  }
}

impl Vertex for Disc {
  fn vertex_format() -> VertexFormat {
    <(Vert, f32) as Vertex>::vertex_format()
  }
}

pub type Texture2D = Texture<Flat, Dim2, RGBA32F>;

pub struct Text<'a> {
  text_texture: &'a TextTexture,
  left_upper: Vert
}

impl<'a> Text<'a> {
  pub fn new(text_texture: &'a TextTexture, left_upper: Vert) -> Self {
    Text {
      text_texture: text_texture,
      left_upper: left_upper
    }
  }
}

const DISC_SCREEN_RATIO: &'static Uniform<f32> = &Uniform::new(0);

const TEXT_SAMPLER: &'static Uniform<Unit> = &Uniform::new(0);
const TEXT_POS: &'static Uniform<[f32; 3]> = &Uniform::new(1);
const TEXT_SIZE: &'static Uniform<[f32; 2]> = &Uniform::new(2);
const TEXT_SCALE: &'static Uniform<f32> = &Uniform::new(3);
const TEXT_COLOR: &'static Uniform<[f32; 4]> = &Uniform::new(4);

/// A renderer responsible of rendering shapes.
pub struct Renderer<'a> {
  framebuffer: Framebuffer<Flat, Dim2, Texture2D, ()>,
  ratio: f32,
  tri_program: Id<'a, Program>,
  tris: Tess,
  tri_vert_nb: usize,
  disc_program: Id<'a, Program>,
  discs: Tess,
  disc_vert_nb: usize,
  text_program: Id<'a, Program>,
  text_quad: Tess,
  overlay_unit: OverlayUnit,
}

impl<'a> Renderer<'a> {
  pub fn new(w: u32, h: u32, max_tris: usize, max_discs: usize, scene: &mut Scene<'a>) -> Self {
    let fb = Framebuffer::new((w, h), 0).unwrap();

    let tri_program = scene.get_id("spectra/overlay/triangle.glsl", vec![]).unwrap();
    let tris = Tess::new(Mode::Triangle, TessVertices::Reserve::<Vert>(max_tris * 3), None);

    let disc_program = scene.get_id("spectra/overlay/disc.glsl", vec![DISC_SCREEN_RATIO.sem("ratio")]).unwrap();
    let discs = Tess::new(Mode::Point, TessVertices::Reserve::<Disc>(max_discs), None);

    let text_program = scene.get_id("spectra/overlay/text.glsl", vec![
      TEXT_SAMPLER.sem("text_texture"),
      TEXT_POS.sem("pos"),
      TEXT_SIZE.sem("size"),
      TEXT_SCALE.sem("scale"),
      TEXT_COLOR.sem("color")
    ]).unwrap();

    let text_quad = Tess::attributeless(Mode::TriangleStrip, 4);

    Renderer {
      framebuffer: fb,
      ratio: w as f32 / h as f32,
      tri_program: tri_program,
      tris: tris,
      tri_vert_nb: 0,
      disc_program: disc_program,
      discs: discs,
      disc_vert_nb: 0,
      text_program: text_program,
      text_quad: text_quad,
      overlay_unit: OverlayUnit::new(w, h)
    }
  }

  fn dispatch(&mut self, input: &RenderInput) {
    let mut tris = self.tris.as_slice_mut().unwrap();
    let mut tri_i = 0;
    let mut discs = self.discs.as_slice_mut().unwrap();
    let mut disc_i = 0;

    for &Triangle(a, b, c) in input.triangles {
      tris[tri_i] = a;
      tri_i += 1;

      tris[tri_i] = b;
      tri_i += 1;

      tris[tri_i] = c;
      tri_i += 1;
    }

    for disc in input.discs {
      discs[disc_i] = *disc;
      disc_i += 1;
    }

    self.tri_vert_nb = tri_i;
    self.disc_vert_nb = disc_i;
  }

  pub fn render(&mut self, scene: &mut Scene<'a>, input: RenderInput) -> &Texture2D {
    self.dispatch(&input);

    let tri_program = scene.get_by_id(&self.tri_program).unwrap();
    let disc_program = scene.get_by_id(&self.disc_program).unwrap();
    let text_program = scene.get_by_id(&self.text_program).unwrap();

    let tris = TessRender::one_sub(&self.tris, self.tri_vert_nb);
    let discs = TessRender::one_sub(&self.discs, self.disc_vert_nb);
    let text_quad = TessRender::one_whole(&self.text_quad);

    // FIXME: no alloc?
    let text_uniforms: Vec<_> = input.texts.map(|(texts, text_scale)| texts.iter().map(|text| {
      let (tex_w, tex_h) = text.text_texture.size();

      [
        TEXT_SAMPLER.alter(Unit::new(0)),
        TEXT_POS.alter(text.left_upper.pos),
        TEXT_SIZE.alter(self.overlay_unit.from_window(tex_w, tex_h)),
        TEXT_SCALE.alter(text_scale),
        TEXT_COLOR.alter(text.left_upper.color),
      ]
    }).collect()).unwrap_or(Vec::new());

    let text_textures: Vec<_> = input.texts.map(|(texts, _)| texts.iter().map(|text| [&***text.text_texture]).collect()).unwrap_or(Vec::new());

    let text_render_cmds: Vec<_> = input.texts.iter().enumerate().map(|(i, _)| {
        let blending = (Equation::Additive, Factor::One, Factor::SrcAlphaComplement);
        Pipe::empty()
          .uniforms(&text_uniforms[i])
          .textures(&text_textures[i])
          .unwrap(RenderCommand::new(Some(blending), true, vec![
            Pipe::new(text_quad.clone())
          ]))
      }).collect();

    let disc_uniforms = [
      DISC_SCREEN_RATIO.alter(self.ratio)
    ];

    Pipeline::new(&self.framebuffer, [0., 0., 0., 0.], &[], &[], vec![
      // render triangles
      Pipe::new(ShadingCommand::new(&tri_program, vec![
        Pipe::new(RenderCommand::new(None, true, vec![
          Pipe::new(tris)
        ]))
      ])),
      // render discs
      Pipe::empty()
        .uniforms(&disc_uniforms)
        .unwrap(ShadingCommand::new(&disc_program, vec![
          Pipe::new(RenderCommand::new(None, true, vec![
            Pipe::new(discs)
          ]))
        ])),
      // render texts
      Pipe::new(ShadingCommand::new(&text_program, text_render_cmds))
    ]).run();

    &self.framebuffer.color_slot
  }
}

pub struct RenderInput<'a, 'b> where 'b: 'a {
  triangles: &'a [Triangle],
  discs: &'a [Disc],
  texts: Option<(&'a [Text<'b>], f32)>
}

impl<'a, 'b> RenderInput<'a, 'b> {
  pub fn new() -> Self {
    RenderInput {
      triangles: &[],
      discs: &[],
      texts: None,
    }
  }

  pub fn triangles(self, triangles: &'a [Triangle]) -> Self {
    RenderInput {
      triangles: triangles, ..self
    }
  }

  pub fn discs(self, discs: &'a [Disc]) -> Self {
    RenderInput {
      discs: discs,
      ..self
    }
  }

  pub fn texts(self, texts: &'a [Text<'b>], scale: f32) -> Self {
    RenderInput {
      texts: Some((texts, scale.max(0.))),
      ..self
    }
  }
}

/// Overlay units are used to position stuff in overlay in a universal way and screen independent
/// way. The screen uses normalized coordinates with the origin at lower left as the following
/// diagram:
///
/// ^ y (1)
/// |
/// |
/// |
/// O------> x (1)
#[derive(Copy, Clone, Debug, PartialEq)]
struct OverlayUnit {
  rw: f32,
  rh: f32
}

impl OverlayUnit {
  pub fn new(w: u32, h: u32) -> Self {
    OverlayUnit {
      rw: 1. / (w as f32),
      rh: 1. / (h as f32)
    }
  }

  pub fn from_window(&self, x: u32, y: u32) -> [f32; 2] {
    let x_ = x as f32 * self.rw;
    assert!(x_ >= 0. && x_ <= 1., "x={}", x_);

    let y_ = y as f32 * self.rh;
    assert!(y_ >= 0. && y_ <= 1., "y={}", y_);

    [x_, y_]
  }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::f32::consts;
use std::u16;
use num;
use rand;
use rand::Rng;
use backend::obj::*;
use serialize::base64::{self, ToBase64};

pub type Dna = Box<[u8]>;

#[allow(dead_code)]
pub trait Generator {
	fn next_float<T>(&mut self, min: T, max: T) -> T where T: rand::Rand + num::Float;

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + num::ToPrimitive + num::FromPrimitive + Copy;

	fn ball(&mut self) -> Shape {
		let radius: f32 = self.next_float(0.5, 0.75);
		Shape::new_ball(radius)
	}

	fn quad(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio: f32 = self.next_float(1.0, 2.0);
		Shape::new_box(radius, ratio)
	}

	fn vbar(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio: f32 = self.next_float(0.1, 0.2);
		Shape::new_box(radius, ratio)
	}

	fn triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = self.next_float(consts::PI * 0.5, consts::PI * 0.8);
		let alpha2 = self.next_float(consts::PI * 1.2, consts::PI * 1.5);
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn iso_triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = self.next_float(consts::PI * 0.5, consts::PI * 0.8);
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn eq_triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = consts::PI * 2. / 3.;
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn star(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let n = self.next_integer(3, 8);
		let ratio1 = self.next_float(0.5, 1.0);
		let ratio2 = self.next_float(0.7, 0.9) * (1. / ratio1);
		Shape::new_star(n, radius, ratio1, ratio2)
	}

	fn poly(&mut self, upside_down: bool) -> Shape {
		let n = self.next_integer(3, 8);
		self.npoly(n, upside_down)
	}

	fn npoly(&mut self, n: AttachmentIndex, upside_down: bool) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio1 = f32::cos(consts::PI / n as f32);
		let corrected_radius = if upside_down { radius * ratio1 } else { radius };

		if n <= 8 {
			Shape::new_poly(if upside_down { -1 } else { 1 } * n as i8, corrected_radius)
		} else {
			let ratio2 = 1. / ratio1;
			if upside_down {
				Shape::new_star(n, corrected_radius, ratio2, ratio1)
			} else {
				Shape::new_star(n, corrected_radius, ratio1, ratio2)
			}
		}
	}
}

#[allow(dead_code)]
pub struct Randomizer {
	rng: rand::ThreadRng,
}

#[allow(dead_code)]
impl Randomizer {
	pub fn new() -> Self {
		Randomizer { rng: rand::thread_rng() }
	}
}

impl Generator for Randomizer {
	fn next_float<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		self.rng.gen::<T>() * (max - min) + min
	}

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + Copy {
		self.rng.gen::<T>() % (max - min + T::one()) + min
	}
}

pub struct Genome {
	dna: Box<[u8]>,
	ptr: usize,
}

impl Genome {
	pub fn new(dna: &[u8]) -> Self {
		Genome {
			ptr: 0,
			dna: dna.to_owned().into_boxed_slice(),
		}
	}

	fn next_byte(&mut self) -> u8 {
		let next = self.dna[self.ptr];
		self.ptr = (self.ptr + 1) % self.dna.len();
		next
	}

	fn next_bytes(&mut self, n: u8) -> i64 {
		let bytes = (0..n).fold(0, |a, _| a << 8 | self.next_byte() as i64);
		bytes
	}

	fn next_i32(&mut self, min: i32, max: i32) -> i32 {
		let diff = max as i64 - min as i64 + 1i64;
		if diff <= 0 {
			min
		} else {
			for i in 1..4 {
				if diff < (1 << (i * 8)) {
					return (self.next_bytes(i) % diff + min as i64) as i32;
				}
			}
			min
		}
	}

	pub fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Self {
		let p: usize = rng.gen::<usize>() % (self.dna.len() * 8);
		let mut new_genes = self.dna.to_vec();
		let byte = p / 8;
		let bit = p % 8;
		new_genes[byte] ^= 1 << bit;
		Genome {
			ptr: 0,
			dna: new_genes.into_boxed_slice(),
		}
	}

	pub fn dna(&self) -> &Box<[u8]> {
		&self.dna
	}
}

impl fmt::Display for Genome {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.dna.to_base64(base64::STANDARD))
	}
}

impl Generator for Genome {
	fn next_float<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		let u0 = self.next_bytes(2) as u16;
		let n: T = T::from(u0).unwrap() / T::from(u16::MAX).unwrap();
		n * (max - min) + min
	}

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + num::ToPrimitive + num::FromPrimitive + Copy {
		num::NumCast::from(min)
			.and_then(|a| num::NumCast::from(max).map(|b| self.next_i32(a, b)))
			.and_then(|value| num::FromPrimitive::from_i32(value))
			.unwrap_or(min)
	}
}
<commit_msg>Limits to number of sides in stars, attempting to prevent physics issues<commit_after>use std::fmt;
use std::f32::consts;
use std::u16;
use num;
use rand;
use rand::Rng;
use backend::obj::*;
use serialize::base64::{self, ToBase64};

pub type Dna = Box<[u8]>;

const MAX_POLY_SIDES: u8 = 8; // in conformity with box2d?

#[allow(dead_code)]
pub trait Generator {
	fn next_float<T>(&mut self, min: T, max: T) -> T where T: rand::Rand + num::Float;

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + num::ToPrimitive + num::FromPrimitive + Copy;

	fn ball(&mut self) -> Shape {
		let radius: f32 = self.next_float(0.5, 0.75);
		Shape::new_ball(radius)
	}

	fn quad(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio: f32 = self.next_float(1.0, 2.0);
		Shape::new_box(radius, ratio)
	}

	fn vbar(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio: f32 = self.next_float(0.1, 0.2);
		Shape::new_box(radius, ratio)
	}

	fn triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = self.next_float(consts::PI * 0.5, consts::PI * 0.8);
		let alpha2 = self.next_float(consts::PI * 1.2, consts::PI * 1.5);
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn iso_triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = self.next_float(consts::PI * 0.5, consts::PI * 0.8);
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn eq_triangle(&mut self) -> Shape {
		let radius = self.next_float(0.5, 1.0);
		let alpha1 = consts::PI * 2. / 3.;
		let alpha2 = consts::PI * 2. - alpha1;
		Shape::new_triangle(radius, alpha1, alpha2)
	}

	fn star(&mut self) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		// if pie slices are too small physics freaks out
		let n = self.next_integer(3,
		                          if radius > 1.5 { MAX_POLY_SIDES } else { MAX_POLY_SIDES - 2 });
		let ratio1 = self.next_float(0.5, 1.0);
		let ratio2 = self.next_float(0.7, 0.9) * (1. / ratio1);
		Shape::new_star(n, radius, ratio1, ratio2)
	}

	fn poly(&mut self, upside_down: bool) -> Shape {
		let n = self.next_integer(3, MAX_POLY_SIDES);
		self.npoly(n, upside_down)
	}

	fn npoly(&mut self, n: AttachmentIndex, upside_down: bool) -> Shape {
		let radius: f32 = self.next_float(1.0, 2.0);
		let ratio1 = f32::cos(consts::PI / n as f32);
		let corrected_radius = if upside_down { radius * ratio1 } else { radius };

		if n <= MAX_POLY_SIDES {
			Shape::new_poly(if upside_down { -1 } else { 1 } * n as i8, corrected_radius)
		} else {
			let ratio2 = 1. / ratio1;
			if upside_down {
				Shape::new_star(n, corrected_radius, ratio2, ratio1)
			} else {
				Shape::new_star(n, corrected_radius, ratio1, ratio2)
			}
		}
	}
}

#[allow(dead_code)]
pub struct Randomizer {
	rng: rand::ThreadRng,
}

#[allow(dead_code)]
impl Randomizer {
	pub fn new() -> Self {
		Randomizer { rng: rand::thread_rng() }
	}
}

impl Generator for Randomizer {
	fn next_float<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		self.rng.gen::<T>() * (max - min) + min
	}

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + Copy {
		self.rng.gen::<T>() % (max - min + T::one()) + min
	}
}

pub struct Genome {
	dna: Box<[u8]>,
	ptr: usize,
}

impl Genome {
	pub fn new(dna: &[u8]) -> Self {
		Genome {
			ptr: 0,
			dna: dna.to_owned().into_boxed_slice(),
		}
	}

	fn next_byte(&mut self) -> u8 {
		let next = self.dna[self.ptr];
		self.ptr = (self.ptr + 1) % self.dna.len();
		next
	}

	fn next_bytes(&mut self, n: u8) -> i64 {
		let bytes = (0..n).fold(0, |a, _| a << 8 | self.next_byte() as i64);
		bytes
	}

	fn next_i32(&mut self, min: i32, max: i32) -> i32 {
		let diff = max as i64 - min as i64 + 1i64;
		if diff <= 0 {
			min
		} else {
			for i in 1..4 {
				if diff < (1 << (i * 8)) {
					return (self.next_bytes(i) % diff + min as i64) as i32;
				}
			}
			min
		}
	}

	pub fn mutate<R: rand::Rng>(&self, rng: &mut R) -> Self {
		let p: usize = rng.gen::<usize>() % (self.dna.len() * 8);
		let mut new_genes = self.dna.to_vec();
		let byte = p / 8;
		let bit = p % 8;
		new_genes[byte] ^= 1 << bit;
		Genome {
			ptr: 0,
			dna: new_genes.into_boxed_slice(),
		}
	}

	pub fn dna(&self) -> &Box<[u8]> {
		&self.dna
	}
}

impl fmt::Display for Genome {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "{}", self.dna.to_base64(base64::STANDARD))
	}
}

impl Generator for Genome {
	fn next_float<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Float {
		let u0 = self.next_bytes(2) as u16;
		let n: T = T::from(u0).unwrap() / T::from(u16::MAX).unwrap();
		n * (max - min) + min
	}

	fn next_integer<T>(&mut self, min: T, max: T) -> T
		where T: rand::Rand + num::Integer + num::ToPrimitive + num::FromPrimitive + Copy {
		num::NumCast::from(min)
			.and_then(|a| num::NumCast::from(max).map(|b| self.next_i32(a, b)))
			.and_then(|value| num::FromPrimitive::from_i32(value))
			.unwrap_or(min)
	}
}
<|endoftext|>


<commit_before>use codegen::RustWriter;
use std::str;

pub struct Grammar {
	initializer: Option<~str>,
	rules: ~[~Rule]
}

pub struct Rule {
	name: ~str,
	expr: ~Expr,
	ret_type: ~str,
	exported: bool,
}

pub struct CharSetCase {
	start: char,
	end: char
}

pub struct TaggedExpr {
	name: Option<~str>,
	expr: ~Expr
}

pub enum Expr {
	AnyCharExpr,
	LiteralExpr(~str),
	CharSetExpr(bool, ~[CharSetCase]),
	RuleExpr(~str),
	SequenceExpr(~[~Expr]),
	ChoiceExpr(~[~Expr]),
	OptionalExpr(~Expr),
	ZeroOrMore(~Expr),
	OneOrMore(~Expr),
	DelimitedExpr(~Expr, ~Expr),
	PosAssertExpr(~Expr),
	NegAssertExpr(~Expr),
	StringifyExpr(~Expr),
	ActionExpr(~[TaggedExpr], ~str),
}

pub fn compile_grammar(w: &RustWriter, grammar: &Grammar) {
	compile_header(w, grammar.initializer.as_ref().map_default("", |s| s.as_slice()));

	for rule in grammar.rules.iter() {
		compile_rule(w, *rule);
	}
}

fn compile_header(w: &RustWriter, header: &str) {
	w.write("// Generated by rust-peg. Do not edit.
extern mod std;
use std::str::{CharRange};
    ");

 	w.write(header);

 	w.write("
#[inline]
fn slice_eq(input: &str, pos: uint, m: &str) -> Result<(uint, ()), uint> {
    let l = m.len();
    if (input.len() >= pos + l && input.slice(pos, pos+l) == m) {
        Ok((pos+l, ()))
    } else {
        Err(pos)
    }
}

#[inline]
fn any_char(input: &str, pos: uint) -> Result<(uint, ()), uint> {
    if input.len() > pos {
        Ok((input.char_range_at(pos).next, ()))
    } else {
        Err(pos)
    }
}

fn pos_to_line(input: &str, pos: uint) -> uint {
	let mut remaining = pos as int;
	let mut lineno: uint = 1;
	for line in input.lines() {
		remaining -= (line.len() as int) + 1;
		if (remaining <= 0) {
			return lineno;
		}
		lineno+=1;
	}
	return lineno;
}
");
}

fn compile_rule(w: &RustWriter, rule: &Rule) {
	w.line("#[allow(unused_variable)]");
	w.def_fn(false, "parse_"+rule.name, "input: &str, pos: uint", "Result<(uint, " + rule.ret_type + ") , uint>", || {
		compile_expr(w, rule.expr, rule.ret_type != ~"()");
	});

	if rule.exported {
		compile_rule_export(w, rule);
	}
}

fn compile_rule_export(w: &RustWriter, rule: &Rule) {
	w.def_fn(true, rule.name, "input: &str", "Result<"+rule.ret_type+", ~str>", || {
		w.match_block("parse_"+rule.name+"(input, 0)", || {
			w.match_case("Ok((pos, value))", || {
				w.if_else("pos == input.len()",
					|| { w.line("Ok(value)"); },
					|| { w.line("Err(~\"Expected end of input at \" + pos_to_line(input, pos).to_str())"); }
				)
			});
			w.match_inline_case("Err(pos)", "Err(\"Error at \"+ pos_to_line(input, pos).to_str())");
		});
	});
}

fn compile_match_and_then(w: &RustWriter, e: &Expr, value_name: Option<&str>, then: ||) {
	w.let_block("seq_res", || {
		compile_expr(w, e, value_name.is_some());
	});
	w.match_block("seq_res", || {
		w.match_inline_case("Err(pos)", "Err(pos)");
		w.match_case("Ok((pos, "+value_name.unwrap_or("_")+"))", || {
			then();
		});
	});
}

fn compile_zero_or_more(w: &RustWriter, e: &Expr, list_initial: Option<&str>) {
	w.let_mut_stmt("repeat_pos", "pos");
	let result_used = list_initial.is_some();
	if (result_used) {
		w.let_mut_stmt("repeat_value", list_initial.unwrap());
	}
	w.loop_block(|| {
		w.let_block("step_res", || {
			w.let_stmt("pos", "repeat_pos");
			compile_expr(w, e, result_used);
		});
		w.match_block("step_res", || {
			let match_arm = if result_used {
				"Ok((newpos, value))"
			} else {
				"Ok((newpos, _))"
			};
			w.match_case(match_arm, || {
				w.line("repeat_pos = newpos;");
				if result_used {
					w.line("repeat_value.push(value);");
				}
			});
			w.match_case("Err(..)", || {
				w.line("break;");
			});
		});
	});
	if result_used {
		w.line("Ok((repeat_pos, repeat_value))");
	} else {
		w.line("Ok((repeat_pos, ()))");
	}
}

fn compile_expr(w: &RustWriter, e: &Expr, result_used: bool) {
	match *e {
		AnyCharExpr => {
			w.line("any_char(input, pos)");
			/*w.if_else("input.len() > pos",
				||{ w.line("Ok(pos+1)"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		LiteralExpr(ref s) => {
			w.line("slice_eq(input, pos, \""+s.escape_default()+"\")");
			/*w.if_else("slice_eq(input, pos, \""+*s+"\")",
				||{ w.line("Ok(pos+" + s.len().to_str() + ")"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		CharSetExpr(invert, ref cases) => {
			let result_strs = ("Ok((next, ()))", "Err(pos)");
			let (y_str, n_str) = if !invert { result_strs } else { result_strs.swap() };

			w.if_else("input.len() > pos",
				|| {
					w.line("let CharRange {ch, next} = input.char_range_at(pos);");
					w.match_block("ch", || {
						w.write_indent();
						for (i, case) in cases.iter().enumerate() {
							if i != 0 { w.write(" | "); }
							if case.start == case.end {
								w.write("'"+str::from_char(case.start).escape_default()+"'");
							} else {
								let start = str::from_char(case.start).escape_default();
								let end = str::from_char(case.end).escape_default();
								w.write("'"+start+"'..'"+end+"'");
							}
						}
						w.write(" => { "+y_str+" }\n");
						w.match_inline_case("_", n_str);
					});
				},
				|| { w.line("Err(pos)"); }
			)
		}

		RuleExpr(ref ruleName) => {
			w.line("parse_"+*ruleName+"(input, pos)");
		}

		SequenceExpr(ref exprs) => {
			fn write_seq(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0], false);
				} else {
					compile_match_and_then(w, exprs[0], None, || {
						write_seq(w, exprs.tail());
					});
				}
			}

			if (exprs.len() > 0 ) {
				write_seq(w, *exprs);
			}
		}

		ChoiceExpr(ref exprs) => {
			fn write_choice(w: &RustWriter, exprs: &[~Expr], result_used: bool) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0], result_used);
				} else {
					w.let_block("choice_res", || {
						compile_expr(w, exprs[0], result_used);
					});
					w.match_block("choice_res", || {
						w.match_inline_case("Ok((pos, value))", "Ok((pos, value))");
						w.match_case("Err(..)", || {
							write_choice(w, exprs.tail(), result_used);
						});
					});
				}
			}

			if (exprs.len() > 0 ) {
				write_choice(w, *exprs, result_used);
			}
		}

		OptionalExpr(ref e) => {
			w.let_block("optional_res", || {
				compile_expr(w, *e, result_used);
			});
			w.match_block("optional_res", || {
				w.match_inline_case("Ok((newpos, value))", "Ok((newpos, Some(value)))");
				w.match_inline_case("Err(..)", "Ok((pos, None))");
			});
		}

		ZeroOrMore(ref e) => {
			compile_zero_or_more(w, *e, if result_used { Some("~[]") } else { None });
		}

		OneOrMore(ref e) => {
			compile_match_and_then(w, *e, if result_used { Some("first_value") } else { None }, || {
				compile_zero_or_more(w, *e, if result_used { Some("~[first_value]") } else { None });
			});
		}

		DelimitedExpr(_, _) => fail!("not implemented"),
		StringifyExpr(..) => fail!("not implemented"),

		PosAssertExpr(ref e) => {
			w.let_block("assert_res", || {
				compile_expr(w, *e, false);
			});
			w.match_block("assert_res", || {
				w.match_inline_case("Ok(..)", "Ok((pos, ()))");
				w.match_inline_case("Err(..)", "Err(pos)");
			});
		}

		NegAssertExpr(ref e) => {
			w.let_block("neg_assert_res", || {
				compile_expr(w, *e, false);
			});
			w.match_block("neg_assert_res", || {
				w.match_inline_case("Err(..)", "Ok((pos, ()))");
				w.match_inline_case("Ok(..)", "Err(pos)");
			});
		}

		ActionExpr(ref exprs, ref code) => {
			w.let_stmt("start_pos", "pos");
			fn write_seq(w: &RustWriter, exprs: &[TaggedExpr], code: &str) {
				if (exprs.len() > 0) {
					let name = exprs.head().name.as_ref().map(|s| s.as_slice());
					compile_match_and_then(w, exprs.head().expr, name, || {
						write_seq(w, exprs.tail(), code);
					});
				} else {
					w.let_stmt("match_str",  "input.slice(start_pos, pos);");
					w.write_indent();
					w.write("Ok((pos, {");
					w.write(code);
					w.write("}))\n");
				}
			}

			write_seq(w, *exprs, *code);
		}
	}
}

<commit_msg>Update map_default -> map_or<commit_after>use codegen::RustWriter;
use std::str;

pub struct Grammar {
	initializer: Option<~str>,
	rules: ~[~Rule]
}

pub struct Rule {
	name: ~str,
	expr: ~Expr,
	ret_type: ~str,
	exported: bool,
}

pub struct CharSetCase {
	start: char,
	end: char
}

pub struct TaggedExpr {
	name: Option<~str>,
	expr: ~Expr
}

pub enum Expr {
	AnyCharExpr,
	LiteralExpr(~str),
	CharSetExpr(bool, ~[CharSetCase]),
	RuleExpr(~str),
	SequenceExpr(~[~Expr]),
	ChoiceExpr(~[~Expr]),
	OptionalExpr(~Expr),
	ZeroOrMore(~Expr),
	OneOrMore(~Expr),
	DelimitedExpr(~Expr, ~Expr),
	PosAssertExpr(~Expr),
	NegAssertExpr(~Expr),
	StringifyExpr(~Expr),
	ActionExpr(~[TaggedExpr], ~str),
}

pub fn compile_grammar(w: &RustWriter, grammar: &Grammar) {
	compile_header(w, grammar.initializer.as_ref().map_or("", |s| s.as_slice()));

	for rule in grammar.rules.iter() {
		compile_rule(w, *rule);
	}
}

fn compile_header(w: &RustWriter, header: &str) {
	w.write("// Generated by rust-peg. Do not edit.
extern mod std;
use std::str::{CharRange};
    ");

 	w.write(header);

 	w.write("
#[inline]
fn slice_eq(input: &str, pos: uint, m: &str) -> Result<(uint, ()), uint> {
    let l = m.len();
    if (input.len() >= pos + l && input.slice(pos, pos+l) == m) {
        Ok((pos+l, ()))
    } else {
        Err(pos)
    }
}

#[inline]
fn any_char(input: &str, pos: uint) -> Result<(uint, ()), uint> {
    if input.len() > pos {
        Ok((input.char_range_at(pos).next, ()))
    } else {
        Err(pos)
    }
}

fn pos_to_line(input: &str, pos: uint) -> uint {
	let mut remaining = pos as int;
	let mut lineno: uint = 1;
	for line in input.lines() {
		remaining -= (line.len() as int) + 1;
		if (remaining <= 0) {
			return lineno;
		}
		lineno+=1;
	}
	return lineno;
}
");
}

fn compile_rule(w: &RustWriter, rule: &Rule) {
	w.line("#[allow(unused_variable)]");
	w.def_fn(false, "parse_"+rule.name, "input: &str, pos: uint", "Result<(uint, " + rule.ret_type + ") , uint>", || {
		compile_expr(w, rule.expr, rule.ret_type != ~"()");
	});

	if rule.exported {
		compile_rule_export(w, rule);
	}
}

fn compile_rule_export(w: &RustWriter, rule: &Rule) {
	w.def_fn(true, rule.name, "input: &str", "Result<"+rule.ret_type+", ~str>", || {
		w.match_block("parse_"+rule.name+"(input, 0)", || {
			w.match_case("Ok((pos, value))", || {
				w.if_else("pos == input.len()",
					|| { w.line("Ok(value)"); },
					|| { w.line("Err(~\"Expected end of input at \" + pos_to_line(input, pos).to_str())"); }
				)
			});
			w.match_inline_case("Err(pos)", "Err(\"Error at \"+ pos_to_line(input, pos).to_str())");
		});
	});
}

fn compile_match_and_then(w: &RustWriter, e: &Expr, value_name: Option<&str>, then: ||) {
	w.let_block("seq_res", || {
		compile_expr(w, e, value_name.is_some());
	});
	w.match_block("seq_res", || {
		w.match_inline_case("Err(pos)", "Err(pos)");
		w.match_case("Ok((pos, "+value_name.unwrap_or("_")+"))", || {
			then();
		});
	});
}

fn compile_zero_or_more(w: &RustWriter, e: &Expr, list_initial: Option<&str>) {
	w.let_mut_stmt("repeat_pos", "pos");
	let result_used = list_initial.is_some();
	if (result_used) {
		w.let_mut_stmt("repeat_value", list_initial.unwrap());
	}
	w.loop_block(|| {
		w.let_block("step_res", || {
			w.let_stmt("pos", "repeat_pos");
			compile_expr(w, e, result_used);
		});
		w.match_block("step_res", || {
			let match_arm = if result_used {
				"Ok((newpos, value))"
			} else {
				"Ok((newpos, _))"
			};
			w.match_case(match_arm, || {
				w.line("repeat_pos = newpos;");
				if result_used {
					w.line("repeat_value.push(value);");
				}
			});
			w.match_case("Err(..)", || {
				w.line("break;");
			});
		});
	});
	if result_used {
		w.line("Ok((repeat_pos, repeat_value))");
	} else {
		w.line("Ok((repeat_pos, ()))");
	}
}

fn compile_expr(w: &RustWriter, e: &Expr, result_used: bool) {
	match *e {
		AnyCharExpr => {
			w.line("any_char(input, pos)");
			/*w.if_else("input.len() > pos",
				||{ w.line("Ok(pos+1)"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		LiteralExpr(ref s) => {
			w.line("slice_eq(input, pos, \""+s.escape_default()+"\")");
			/*w.if_else("slice_eq(input, pos, \""+*s+"\")",
				||{ w.line("Ok(pos+" + s.len().to_str() + ")"); },
				||{ w.line("Err(pos)"); }
			);*/
		}

		CharSetExpr(invert, ref cases) => {
			let result_strs = ("Ok((next, ()))", "Err(pos)");
			let (y_str, n_str) = if !invert { result_strs } else { result_strs.swap() };

			w.if_else("input.len() > pos",
				|| {
					w.line("let CharRange {ch, next} = input.char_range_at(pos);");
					w.match_block("ch", || {
						w.write_indent();
						for (i, case) in cases.iter().enumerate() {
							if i != 0 { w.write(" | "); }
							if case.start == case.end {
								w.write("'"+str::from_char(case.start).escape_default()+"'");
							} else {
								let start = str::from_char(case.start).escape_default();
								let end = str::from_char(case.end).escape_default();
								w.write("'"+start+"'..'"+end+"'");
							}
						}
						w.write(" => { "+y_str+" }\n");
						w.match_inline_case("_", n_str);
					});
				},
				|| { w.line("Err(pos)"); }
			)
		}

		RuleExpr(ref ruleName) => {
			w.line("parse_"+*ruleName+"(input, pos)");
		}

		SequenceExpr(ref exprs) => {
			fn write_seq(w: &RustWriter, exprs: &[~Expr]) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0], false);
				} else {
					compile_match_and_then(w, exprs[0], None, || {
						write_seq(w, exprs.tail());
					});
				}
			}

			if (exprs.len() > 0 ) {
				write_seq(w, *exprs);
			}
		}

		ChoiceExpr(ref exprs) => {
			fn write_choice(w: &RustWriter, exprs: &[~Expr], result_used: bool) {
				if (exprs.len() == 1) {
					compile_expr(w, exprs[0], result_used);
				} else {
					w.let_block("choice_res", || {
						compile_expr(w, exprs[0], result_used);
					});
					w.match_block("choice_res", || {
						w.match_inline_case("Ok((pos, value))", "Ok((pos, value))");
						w.match_case("Err(..)", || {
							write_choice(w, exprs.tail(), result_used);
						});
					});
				}
			}

			if (exprs.len() > 0 ) {
				write_choice(w, *exprs, result_used);
			}
		}

		OptionalExpr(ref e) => {
			w.let_block("optional_res", || {
				compile_expr(w, *e, result_used);
			});
			w.match_block("optional_res", || {
				w.match_inline_case("Ok((newpos, value))", "Ok((newpos, Some(value)))");
				w.match_inline_case("Err(..)", "Ok((pos, None))");
			});
		}

		ZeroOrMore(ref e) => {
			compile_zero_or_more(w, *e, if result_used { Some("~[]") } else { None });
		}

		OneOrMore(ref e) => {
			compile_match_and_then(w, *e, if result_used { Some("first_value") } else { None }, || {
				compile_zero_or_more(w, *e, if result_used { Some("~[first_value]") } else { None });
			});
		}

		DelimitedExpr(_, _) => fail!("not implemented"),
		StringifyExpr(..) => fail!("not implemented"),

		PosAssertExpr(ref e) => {
			w.let_block("assert_res", || {
				compile_expr(w, *e, false);
			});
			w.match_block("assert_res", || {
				w.match_inline_case("Ok(..)", "Ok((pos, ()))");
				w.match_inline_case("Err(..)", "Err(pos)");
			});
		}

		NegAssertExpr(ref e) => {
			w.let_block("neg_assert_res", || {
				compile_expr(w, *e, false);
			});
			w.match_block("neg_assert_res", || {
				w.match_inline_case("Err(..)", "Ok((pos, ()))");
				w.match_inline_case("Ok(..)", "Err(pos)");
			});
		}

		ActionExpr(ref exprs, ref code) => {
			w.let_stmt("start_pos", "pos");
			fn write_seq(w: &RustWriter, exprs: &[TaggedExpr], code: &str) {
				if (exprs.len() > 0) {
					let name = exprs.head().name.as_ref().map(|s| s.as_slice());
					compile_match_and_then(w, exprs.head().expr, name, || {
						write_seq(w, exprs.tail(), code);
					});
				} else {
					w.let_stmt("match_str",  "input.slice(start_pos, pos);");
					w.write_indent();
					w.write("Ok((pos, {");
					w.write(code);
					w.write("}))\n");
				}
			}

			write_seq(w, *exprs, *code);
		}
	}
}

<|endoftext|>


<commit_before>// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Evil private APIs.
//!
//! These are liable to change at any time. Use with caution!

use geometry::CGRect;
use std::ptr;

pub struct CGSRegion {
    region: ffi::CGSRegionRef,
}

impl Drop for CGSRegion {
    fn drop(&mut self) {
        unsafe {
            ffi::CGSRegionRelease(self.region)
        }
    }
}

impl CGSRegion {
    #[inline]
    pub fn from_rect(rect: &CGRect) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }
}

mod ffi {
    use geometry::CGRect;

    // This is an enum so that we can't easily make instances of this opaque type.
    enum CGSRegionObject {}

    pub type CGError = OSStatus;
    pub type CGSRegionRef = *mut CGSRegionObject;
    pub type OSStatus = i32;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGSRegionRelease(region: CGSRegionRef);
        pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError;
    }
}

<commit_msg>private: Add a binding to `CGSNewRegionWithRectList`.<commit_after>// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Evil private APIs.
//!
//! These are liable to change at any time. Use with caution!

use geometry::CGRect;
use std::ptr;

pub struct CGSRegion {
    region: ffi::CGSRegionRef,
}

impl Drop for CGSRegion {
    fn drop(&mut self) {
        unsafe {
            ffi::CGSRegionRelease(self.region)
        }
    }
}

impl CGSRegion {
    #[inline]
    pub fn from_rect(rect: &CGRect) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }

    #[inline]
    pub fn from_rects(rects: &[CGRect]) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(),
                                                  rects.len() as c_uint,
                                                  &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }
}

mod ffi {
    use geometry::CGRect;
    use libc::c_uint;

    // This is an enum so that we can't easily make instances of this opaque type.
    enum CGSRegionObject {}

    pub type CGError = OSStatus;
    pub type CGSRegionRef = *mut CGSRegionObject;
    pub type OSStatus = i32;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGSRegionRelease(region: CGSRegionRef);
        pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError;
        pub fn CGSNewRegionWithRectList(rects: *const CGRect,
                                        rectCount: c_uint,
                                        outRegion: *mut CGSRegionRef)
                                        -> CGError;
    }
}

<|endoftext|>