<commit_before>use derive_builder::Builder;

#[derive(Debug, Builder)]
#[builder(build_fn(name = "final_build"))]
pub struct SkimOptions<'a> {
    pub bind: Vec<&'a str>,
    pub multi: bool,
    #[builder(default = "Some(\"> \")")]
    pub prompt: Option<&'a str>,
    #[builder(default = "Some(\"c> \")")]
    pub cmd_prompt: Option<&'a str>,
    pub expect: Option<String>,
    pub tac: bool,
    pub tiebreak: Option<String>,
    pub ansi: bool,
    pub exact: bool,
    pub cmd: Option<&'a str>,
    pub interactive: bool,
    pub query: Option<&'a str>,
    pub cmd_query: Option<&'a str>,
    pub regex: bool,
    pub delimiter: Option<&'a str>,
    pub nth: Option<&'a str>,
    pub with_nth: Option<&'a str>,
    #[builder(default = "Some(\"{}\")")]
    pub replstr: Option<&'a str>,
    pub color: Option<&'a str>,
    #[builder(default = "Some(\"0,0,0,0\")")]
    pub margin: Option<&'a str>,
    pub no_height: bool,
    #[builder(default = "Some(\"10\")")]
    pub min_height: Option<&'a str>,
    pub height: Option<&'a str>,
    pub preview: Option<&'a str>,
    #[builder(default = "Some(\"right:50%\")")]
    pub preview_window: Option<&'a str>,
    pub reverse: bool,
    pub read0: bool,
    pub print0: bool,
    pub tabstop: Option<&'a str>,
    pub print_query: bool,
    pub print_cmd: bool,
    pub no_hscroll: bool,
    pub inline_info: bool,
    pub header: Option<&'a str>,
    pub header_lines: usize,
    pub layout: &'a str,
}

impl<'a> SkimOptionsBuilder<'a> {
    pub fn build(&mut self) -> Result<SkimOptions<'a>, String> {
        if let Some(true) = self.no_height {
            self.height = Some(Some("100%"));
        }

        if let Some(true) = self.reverse {
            self.layout = Some("reverse");
        }

        self.final_build()
    }
}
<commit_msg>[option] add default options<commit_after>use derive_builder::Builder;

#[derive(Debug, Builder)]
#[builder(build_fn(name = "final_build"))]
#[builder(default)]
pub struct SkimOptions<'a> {
    pub bind: Vec<&'a str>,
    pub multi: bool,
    pub prompt: Option<&'a str>,
    pub cmd_prompt: Option<&'a str>,
    pub expect: Option<String>,
    pub tac: bool,
    pub tiebreak: Option<String>,
    pub ansi: bool,
    pub exact: bool,
    pub cmd: Option<&'a str>,
    pub interactive: bool,
    pub query: Option<&'a str>,
    pub cmd_query: Option<&'a str>,
    pub regex: bool,
    pub delimiter: Option<&'a str>,
    pub nth: Option<&'a str>,
    pub with_nth: Option<&'a str>,
    pub replstr: Option<&'a str>,
    pub color: Option<&'a str>,
    pub margin: Option<&'a str>,
    pub no_height: bool,
    pub min_height: Option<&'a str>,
    pub height: Option<&'a str>,
    pub preview: Option<&'a str>,
    pub preview_window: Option<&'a str>,
    pub reverse: bool,
    pub read0: bool,
    pub print0: bool,
    pub tabstop: Option<&'a str>,
    pub print_query: bool,
    pub print_cmd: bool,
    pub no_hscroll: bool,
    pub inline_info: bool,
    pub header: Option<&'a str>,
    pub header_lines: usize,
    pub layout: &'a str,
}

impl<'a> Default for SkimOptions<'a> {
    fn default() -> Self {
        Self {
            bind: vec![],
            multi: false,
            prompt: Some("> "),
            cmd_prompt: Some("c> "),
            expect: None,
            tac: false,
            tiebreak: None,
            ansi: false,
            exact: false,
            cmd: None,
            interactive: false,
            query: None,
            cmd_query: None,
            regex: false,
            delimiter: None,
            nth: None,
            with_nth: None,
            replstr: Some("{}"),
            color: None,
            margin: Some("0,0,0,0"),
            no_height: false,
            min_height: Some("10"),
            height: Some("100%"),
            preview: None,
            preview_window: Some("right:50%"),
            reverse: false,
            read0: false,
            print0: false,
            tabstop: None,
            print_query: false,
            print_cmd: false,
            no_hscroll: false,
            inline_info: false,
            header: None,
            header_lines: 0,
            layout: "",
        }
    }
}

impl<'a> SkimOptionsBuilder<'a> {
    pub fn build(&mut self) -> Result<SkimOptions<'a>, String> {
        if let Some(true) = self.no_height {
            self.height = Some(Some("100%"));
        }

        if let Some(true) = self.reverse {
            self.layout = Some("reverse");
        }

        self.final_build()
    }
}
<|endoftext|>


<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>options: Honor distrust-clang-mangling.<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>//! A set of exports which can be helpful to use.
//!
//! Note that the `SerenityError` re-export is equivalent to
//! [`serenity::Error`], although is re-exported as a separate name to remove
//! likely ambiguity with other crate error enums.
//!
//! # Examples
//!
//! Import all of the exports:
//!
//! ```rust
//! use serenity::prelude::*;
//! ```
//!
//! [`serenity::Error`]: ../enum.Error.html

pub use error::Error as SerenityError;
pub use model::Mentionable;

#[cfg(feature = "client")]
pub use client::{Client, ClientError as ClientError, Context, EventHandler};
#[cfg(feature = "gateway")]
pub use gateway::GatewayError;
#[cfg(feature = "http")]
pub use http::HttpError;
#[cfg(feature = "model")]
pub use model::ModelError;
#[cfg(feature = "voice")]
pub use voice::VoiceError;
<commit_msg>Re-export parking_lot::{Arc, Mutex} from prelude<commit_after>//! A set of exports which can be helpful to use.
//!
//! Note that the `SerenityError` re-export is equivalent to
//! [`serenity::Error`], although is re-exported as a separate name to remove
//! likely ambiguity with other crate error enums.
//!
//! # Examples
//!
//! Import all of the exports:
//!
//! ```rust
//! use serenity::prelude::*;
//! ```
//!
//! [`serenity::Error`]: ../enum.Error.html

pub use error::Error as SerenityError;
pub use model::Mentionable;
pub use parking_lot::{Mutex, RwLock};

#[cfg(feature = "client")]
pub use client::{Client, ClientError as ClientError, Context, EventHandler};
#[cfg(feature = "gateway")]
pub use gateway::GatewayError;
#[cfg(feature = "http")]
pub use http::HttpError;
#[cfg(feature = "model")]
pub use model::ModelError;
#[cfg(feature = "voice")]
pub use voice::VoiceError;
<|endoftext|>


<commit_before>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    pub is_seeking: bool,
    current_depth: u64,
    goal_depth: Option<u64>,
}

enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            is_seeking: false,
            current_depth: 0,
            goal_depth: None,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match self.instruction_pointer {
            None => {},
            Some(mut index) => {
                if self.is_seeking {
                    let (new_index, still_seeking) = self.seek_forward(index);
                    self.is_seeking = still_seeking;
                    index = new_index;
                }
                while index < self.instructions.len() {
                    let command = self.instructions[index];
                    if command == Command::JumpForward {
                        index = self.start_jump_forward(vm, index);
                    } else if command == Command::JumpBackward {
                        index = self.jump_backward(&vm, index);
                    } else {
                        vm.apply(command);
                        index = index + 1;
                    }
                }
                self.instruction_pointer = Some(index);
            }
        }
    }

    fn jump_backward (&mut self, vm: &VM, starting_index: usize) -> usize {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth = self.current_depth - 1;
                starting_index + 1
            },
            _ => {
                let goal_depth = self.current_depth;
                for index in (0..starting_index).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => {
                            self.current_depth = self.current_depth + 1;
                        },
                        Command::JumpForward => {
                            if self.current_depth == goal_depth { return index + 1 }
                            self.current_depth = self.current_depth - 1;
                        },
                        _ => {},
                    }
                }
                panic!("No starting brace found!");
            },
        }
    }

    fn seek_forward(&mut self, starting_index: usize) -> (usize, bool) {
        let goal_depth = self.goal_depth.unwrap();
        for index in starting_index..self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth = self.current_depth + 1,
                Command::JumpBackward => self.current_depth = self.current_depth - 1,
                _ => {},
            }
            if self.current_depth == goal_depth { return (index + 1, false) }
        }
        (self.instructions.len(), true)
    }

    fn start_jump_forward(&mut self, vm: &VM, index: usize) -> usize {
        if vm.cells[vm.data_pointer] == 0 {
            self.goal_depth = Some(self.current_depth);
            let (index, still_seeking) = self.seek_forward(index);
            self.is_seeking = still_seeking;
            return index;
        } else {
            self.current_depth = self.current_depth + 1;
            return index + 1;
        }
    }
}
<commit_msg>Replace primitive program instance variables with ProgramStatus<commit_after>use command::Command;
use vm::VM;

pub struct Program {
    instructions : Vec<Command>,
    instruction_pointer: Option<usize>,
    current_depth: u64,
    pub status: ProgramStatus,
}

enum ProgramStatus {
    Normal,
    Seeking(u64),
}

impl Program {
    pub fn new () -> Program {
        Program {
            instructions: Vec::new(),
            instruction_pointer: None,
            current_depth: 0,
            status: ProgramStatus::Normal,
        }
    }

    pub fn append(&mut self, instructions: &[Command]) {
        self.instructions.extend(instructions.iter().cloned());
        if self.instruction_pointer.is_none() { self.instruction_pointer = Some(0); }
    }

    pub fn execute(&mut self, vm: &mut VM) {
        match self.instruction_pointer {
            None => {},
            Some(mut index) => {
                if self.is_seeking {
                    let (new_index, still_seeking) = self.seek_forward(index);
                    self.is_seeking = still_seeking;
                    index = new_index;
                }
                while index < self.instructions.len() {
                    let command = self.instructions[index];
                    if command == Command::JumpForward {
                        index = self.start_jump_forward(vm, index);
                    } else if command == Command::JumpBackward {
                        index = self.jump_backward(&vm, index);
                    } else {
                        vm.apply(command);
                        index = index + 1;
                    }
                }
                self.instruction_pointer = Some(index);
            }
        }
    }

    fn jump_backward (&mut self, vm: &VM, starting_index: usize) -> usize {
        match vm.cells[vm.data_pointer] {
            0 => {
                self.current_depth = self.current_depth - 1;
                starting_index + 1
            },
            _ => {
                let goal_depth = self.current_depth;
                for index in (0..starting_index).rev() {
                    match self.instructions[index] {
                        Command::JumpBackward => {
                            self.current_depth = self.current_depth + 1;
                        },
                        Command::JumpForward => {
                            if self.current_depth == goal_depth { return index + 1 }
                            self.current_depth = self.current_depth - 1;
                        },
                        _ => {},
                    }
                }
                panic!("No starting brace found!");
            },
        }
    }

    fn seek_forward(&mut self, starting_index: usize) -> (usize, bool) {
        let goal_depth = self.goal_depth.unwrap();
        for index in starting_index..self.instructions.len() {
            match self.instructions[index] {
                Command::JumpForward => self.current_depth = self.current_depth + 1,
                Command::JumpBackward => self.current_depth = self.current_depth - 1,
                _ => {},
            }
            if self.current_depth == goal_depth { return (index + 1, false) }
        }
        (self.instructions.len(), true)
    }

    fn start_jump_forward(&mut self, vm: &VM, index: usize) -> usize {
        if vm.cells[vm.data_pointer] == 0 {
            self.goal_depth = Some(self.current_depth);
            let (index, still_seeking) = self.seek_forward(index);
            self.is_seeking = still_seeking;
            return index;
        } else {
            self.current_depth = self.current_depth + 1;
            return index + 1;
        }
    }
}
<|endoftext|>


<commit_before>//! Checks for usage of &Vec[_] and &String
//!
//! This lint is **warn** by default

use rustc::lint::*;
use rustc_front::hir::*;
use rustc::middle::ty;

use utils::{span_lint, match_type};
use utils::{STRING_PATH, VEC_PATH};

declare_lint! {
    pub PTR_ARG,
    Allow,
    "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \
     instead, respectively"
}

#[derive(Copy,Clone)]
pub struct PtrArg;

impl LintPass for PtrArg {
    fn get_lints(&self) -> LintArray {
        lint_array!(PTR_ARG)
    }
}

impl LateLintPass for PtrArg {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if let &ItemFn(ref decl, _, _, _, _, _) = &item.node {
            check_fn(cx, decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
        if let &MethodImplItem(ref sig, _) = &item.node {
            check_fn(cx, &sig.decl);
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        if let &MethodTraitItem(ref sig, _) = &item.node {
            check_fn(cx, &sig.decl);
        }
    }
}

fn check_fn(cx: &LateContext, decl: &FnDecl) {
    for arg in &decl.inputs {
        if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) {
            if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty {
                if match_type(cx, ty, &VEC_PATH) {
                    span_lint(cx, PTR_ARG, arg.ty.span,
                              "writing `&Vec<_>` instead of `&[_]` involves one more reference \
                               and cannot be used with non-Vec-based slices. Consider changing \
                               the type to `&[...]`");
                } else if match_type(cx, ty, &STRING_PATH) {
                    span_lint(cx, PTR_ARG, arg.ty.span,
                              "writing `&String` instead of `&str` involves a new object \
                               where a slice will do. Consider changing the type to `&str`");
                }
            }
        }
    }
}
<commit_msg>Fix documentation that disagrees with code<commit_after>//! Checks for usage of &Vec[_] and &String
//!
//! This lint is **allow** by default

use rustc::lint::*;
use rustc_front::hir::*;
use rustc::middle::ty;

use utils::{span_lint, match_type};
use utils::{STRING_PATH, VEC_PATH};

declare_lint! {
    pub PTR_ARG,
    Allow,
    "fn arguments of the type `&Vec<...>` or `&String`, suggesting to use `&[...]` or `&str` \
     instead, respectively"
}

#[derive(Copy,Clone)]
pub struct PtrArg;

impl LintPass for PtrArg {
    fn get_lints(&self) -> LintArray {
        lint_array!(PTR_ARG)
    }
}

impl LateLintPass for PtrArg {
    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if let &ItemFn(ref decl, _, _, _, _, _) = &item.node {
            check_fn(cx, decl);
        }
    }

    fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
        if let &MethodImplItem(ref sig, _) = &item.node {
            check_fn(cx, &sig.decl);
        }
    }

    fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
        if let &MethodTraitItem(ref sig, _) = &item.node {
            check_fn(cx, &sig.decl);
        }
    }
}

fn check_fn(cx: &LateContext, decl: &FnDecl) {
    for arg in &decl.inputs {
        if let Some(pat_ty) = cx.tcx.pat_ty_opt(&arg.pat) {
            if let ty::TyRef(_, ty::TypeAndMut { ty, mutbl: MutImmutable }) = pat_ty.sty {
                if match_type(cx, ty, &VEC_PATH) {
                    span_lint(cx, PTR_ARG, arg.ty.span,
                              "writing `&Vec<_>` instead of `&[_]` involves one more reference \
                               and cannot be used with non-Vec-based slices. Consider changing \
                               the type to `&[...]`");
                } else if match_type(cx, ty, &STRING_PATH) {
                    span_lint(cx, PTR_ARG, arg.ty.span,
                              "writing `&String` instead of `&str` involves a new object \
                               where a slice will do. Consider changing the type to `&str`");
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::error::Result;
use proc_macro2::TokenStream;
use std::fs::File;
use std::io::Write;
use std::path::Path;

pub fn write<P: AsRef<Path>>(path: P, content: TokenStream) -> Result<()> {
    let mut file = File::create(path)?;
    write!(
        file,
        "// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT\n\n"
    )?;
    let mut config = rustfmt::Config::default();
    config.set().emit_mode(rustfmt::EmitMode::Stdout);
    config.set().verbose(rustfmt::Verbosity::Quiet);
    config.set().format_macro_matchers(true);
    config.set().normalize_doc_attributes(true);
    let mut session = rustfmt::Session::new(config, Some(&mut file));
    session.format(rustfmt::Input::Text(content.to_string()))?;
    Ok(())
}
<commit_msg>Buffer output when codegening files<commit_after>use crate::error::Result;
use proc_macro2::TokenStream;
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::Path;

pub fn write<P: AsRef<Path>>(path: P, content: TokenStream) -> Result<()> {
    let mut file = File::create(path).map(BufWriter::new)?;
    write!(
        file,
        "// THIS FILE IS AUTOMATICALLY GENERATED; DO NOT EDIT\n\n"
    )?;
    let mut config = rustfmt::Config::default();
    config.set().emit_mode(rustfmt::EmitMode::Stdout);
    config.set().verbose(rustfmt::Verbosity::Quiet);
    config.set().format_macro_matchers(true);
    config.set().normalize_doc_attributes(true);
    let mut session = rustfmt::Session::new(config, Some(&mut file));
    session.format(rustfmt::Input::Text(content.to_string()))?;
    Ok(())
}
<|endoftext|>


<commit_before>#![unstable(feature = "thread_local_internals", issue = "none")]
#![cfg(target_thread_local)]

pub use crate::sys_common::thread_local_dtor::register_dtor_fallback as register_dtor;
<commit_msg>Windows thread-local keyless drop<commit_after>//! Implements thread-local destructors that are not associated with any
//! particular data.

#![unstable(feature = "thread_local_internals", issue = "none")]
#![cfg(target_thread_local)]
use super::c;

// Using a per-thread list avoids the problems in synchronizing global state.
#[thread_local]
static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();

pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
    DESTRUCTORS.push((t, dtor));
}

// See windows/thread_local_keys.rs for an explanation of this callback function.
// The short version is that all the function pointers in the `.CRT$XL*` array
// will be called whenever a thread or process starts or ends.

#[link_section = ".CRT$XLD"]
#[doc(hidden)]
#[used]
pub static TLS_CALLBACK: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::LPVOID) = tls_callback;

unsafe extern "system" fn tls_callback(_: c::LPVOID, reason: c::DWORD, _: c::LPVOID) {
    if reason == c::DLL_THREAD_DETACH || reason == c::DLL_PROCESS_DETACH {
        // Drop all the destructors.
        //
        // Note: While this is potentially an infinite loop, it *should* be
        // the case that this loop always terminates because we provide the
        // guarantee that a TLS key cannot be set after it is flagged for
        // destruction.
        while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
            (dtor)(ptr);
        }
        // We're done so free the memory.
        DESTRUCTORS.shrink_to_fit();
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use io;
use message::*;
use serialize::*;

#[inline]
unsafe fn ptr_inc(p : &mut *mut u8, count : int) {
    *p = std::ptr::mut_offset(*p, count);
}

#[inline]
unsafe fn ptr_sub<T>(p1 : * T, p2 : * T) -> uint {
    let p1Addr : uint = std::cast::transmute(p1);
    let p2Addr : uint = std::cast::transmute(p2);
    return (p1Addr - p2Addr) / std::mem::size_of::<T>();
}

#[inline]
unsafe fn mut_ptr_sub <T>(p1 : *mut T, p2 : *mut T) -> uint {
    let p1Addr : uint = std::cast::transmute(p1);
    let p2Addr : uint = std::cast::transmute(p2);
    return (p1Addr - p2Addr) / std::mem::size_of::<T>();
}

pub struct PackedInputStream<'a, 'b,  R> {
    inner : &'a mut io::BufferedInputStream<'b, R>
}

macro_rules! refresh_buffer(
    ($inner:expr, $size:ident, $inPtr:ident, $inEnd:ident, $out:ident,
     $outBuf:ident, $bufferBegin:ident) => (
        {
            $inner.skip($size);
            let (b, e) = $inner.getReadBuffer();
            $inPtr = b;
            $inEnd = e;
            $size = ptr_sub($inEnd, $inPtr);
            $bufferBegin = b;
            assert!($size > 0);
        }
        );
    )

impl <'a, 'b, R : std::io::Reader> std::io::Reader for PackedInputStream<'a, 'b, R> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        unsafe {
            let mut out = outBuf.unsafe_mut_ref(0);
            let outEnd = outBuf.unsafe_mut_ref(len);

            let (mut inPtr, mut inEnd) = self.inner.getReadBuffer();
            let mut bufferBegin = inPtr;
            let mut size = ptr_sub(inEnd, inPtr);
            if size == 0 {
                return Some(0);
            }

            loop {

                let mut tag : u8;

                assert!(mut_ptr_sub(out, outBuf.unsafe_mut_ref(0)) % 8 == 0,
                        "Output pointer should always be aligned here.");

                if ptr_sub(inEnd, inPtr) < 10 {
                    if out >= outEnd {
                        self.inner.skip(ptr_sub(inPtr, bufferBegin));
                        return Some(mut_ptr_sub(out, outBuf.unsafe_mut_ref(0)));
                    }

                    if ptr_sub(inEnd, inPtr) == 0 {
                        refresh_buffer!(self.inner, size, inPtr, inEnd, out, outBuf, bufferBegin);
                        continue;
                    }

                    //# We have at least 1, but not 10, bytes availabe. We need to read
                    //# slowly, doing a bounds check on each byte.

                    tag = *inPtr;
                    inPtr = std::ptr::offset(inPtr, 1);

                    for i in range(0, 8) {
                        if (tag & (1u8 << i)) != 0 {
                            if ptr_sub(inEnd, inPtr) == 0 {
                                refresh_buffer!(self.inner, size, inPtr, inEnd,
                                                out, outBuf, bufferBegin);
                            }
                            *out = *inPtr;
                            out = std::ptr::mut_offset(out, 1);
                            inPtr = std::ptr::offset(inPtr, 1);
                        } else {
                            *out = 0;
                            out = std::ptr::mut_offset(out, 1);
                        }
                    }

                    if ptr_sub(inEnd, inPtr) == 0 && (tag == 0 || tag == 0xff) {
                        refresh_buffer!(self.inner, size, inPtr, inEnd,
                                        out, outBuf, bufferBegin);
                    }
                } else {
                    tag = *inPtr;
                    inPtr = std::ptr::offset(inPtr, 1);

                    for n in range(0, 8) {
                        let isNonzero = (tag & (1 as u8 << n)) != 0;
                        *out = (*inPtr) & ((-(isNonzero as i8)) as u8);
                        out = std::ptr::mut_offset(out, 1);
                        inPtr = std::ptr::offset(inPtr, isNonzero as int);
                    }
                }
                if (tag == 0) {
                    assert!(ptr_sub(inEnd, inPtr) > 0,
                            "Should always have non-empty buffer here");

                    let runLength : uint = (*inPtr) as uint * 8;
                    inPtr = std::ptr::offset(inPtr, 1);

                    assert!(runLength <= mut_ptr_sub(outEnd, out),
                            "Packed input did not end cleanly on a segment boundary");

                    std::ptr::set_memory(out, 0, runLength);
                    out = std::ptr::mut_offset(out, runLength as int);

                } else if (tag == 0xff) {
                    assert!(ptr_sub(inEnd, inPtr) > 0,
                            "Should always have non-empty buffer here");

                    let mut runLength : uint = (*inPtr) as uint * 8;
                    inPtr = std::ptr::offset(inPtr, 1);

                    assert!(runLength <= mut_ptr_sub(outEnd, out),
                            "Packed input did not end cleanly on a segment boundary");

                    let inRemaining = ptr_sub(inEnd, inPtr);
                    if (inRemaining >= runLength) {
                        //# Fast path.
                        std::ptr::copy_nonoverlapping_memory(out, inPtr, runLength);
                        out = std::ptr::mut_offset(out, runLength as int);
                        inPtr = std::ptr::offset(inPtr, runLength as int);
                    } else {
                        //# Copy over the first buffer, then do one big read for the rest.
                        std::ptr::copy_nonoverlapping_memory(out, inPtr, inRemaining);
                        out = std::ptr::mut_offset(out, inRemaining as int);
                        runLength -= inRemaining;

                        self.inner.skip(size);
                        do std::vec::raw::mut_buf_as_slice::<u8,()>(out, runLength) |buf| {
                            self.inner.read(buf);
                        }
                        out = std::ptr::mut_offset(out, runLength as int);

                        if (out == outEnd) {
                            return Some(len);
                        } else {
                            let (b, e) = self.inner.getReadBuffer();
                            inPtr = b;
                            inEnd = e;
                            size = ptr_sub(e, b);
                            bufferBegin = inPtr;
                            continue;
                        }
                    }
                }

                if (out == outEnd) {
                    self.inner.skip(ptr_sub(inPtr, bufferBegin));
                    return Some(len);
                }
            }
        }
    }
}

pub struct PackedOutputStream<'a, 'b, W> {
    inner : &'a mut io::BufferedOutputStream<'b, W>
}

impl <'a, 'b, W : std::io::Writer> std::io::Writer for PackedOutputStream<'a, 'b, W> {
    fn write(&mut self, inBuf : &[u8]) {
        unsafe {
            let (mut out, mut bufferEnd) = self.inner.getWriteBuffer();
            let mut bufferBegin = out;
            let mut slowBuffer : [u8,..20] = [0, ..20];

            let mut inPtr : *u8 = inBuf.unsafe_ref(0);
            let inEnd : *u8 = inBuf.unsafe_ref(inBuf.len());

            while (inPtr < inEnd) {

                if (mut_ptr_sub(bufferEnd, out) < 10) {
                    //# Oops, we're out of space. We need at least 10
                    //# bytes for the fast path, since we don't
                    //# bounds-check on every byte.
                    self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));

                    out = slowBuffer.unsafe_mut_ref(0);
                    bufferEnd = slowBuffer.unsafe_mut_ref(20);
                    bufferBegin = out;
                }

                let tagPos : *mut u8 = out;
                ptr_inc(&mut out, 1);

                let bit0 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit0 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit1 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit1 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit2 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit2 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit3 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit3 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit4 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit4 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit5 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit5 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit6 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit6 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let bit7 = (*inPtr != 0) as u8;
                *out = *inPtr;
                ptr_inc(&mut out, bit7 as int);
                inPtr = std::ptr::offset(inPtr, 1);

                let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                    | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

                *tagPos = tag;

                if (tag == 0) {
                    //# An all-zero word is followed by a count of
                    //# consecutive zero words (not including the first
                    //# one).

                    let mut inWord : *u64 = std::cast::transmute(inPtr);
                    let mut limit : *u64 = std::cast::transmute(inEnd);
                    if (ptr_sub(limit, inWord) > 255) {
                        limit = std::ptr::offset(inWord, 255);
                    }
                    while (inWord < limit && *inWord == 0) {
                        inWord = std::ptr::offset(inWord, 1)
                    }
                    *out = ptr_sub(inWord, std::cast::transmute::<*u8, *u64>(inPtr)) as u8;

                    ptr_inc(&mut out, 1);
                    inPtr = std::cast::transmute::<*u64, *u8>(inWord);

                } else if (tag == 0xff) {
                    //# An all-nonzero word is followed by a count of
                    //# consecutive uncompressed words, followed by the
                    //# uncompressed words themselves.

                    //# Count the number of consecutive words in the input
                    //# which have no more than a single zero-byte. We look
                    //# for at least two zeros because that's the point
                    //# where our compression scheme becomes a net win.
                    let runStart = inPtr;
                    let mut limit = inEnd;
                    if (ptr_sub(limit, inPtr) > 255 * 8) {
                        limit = std::ptr::offset(inPtr, 255 * 8);
                    }

                    while (inPtr < limit) {
                        let mut c = 0;

                        for _ in range(0,8) {
                            c += (*inPtr == 0) as u8;
                            inPtr = std::ptr::offset(inPtr, 1);
                        }

                        if (c >= 2) {
                            //# Un-read the word with multiple zeros, since
                            //# we'll want to compress that one.
                            inPtr = std::ptr::offset(inPtr, -8);
                            break;
                        }
                    }
                    let count : uint = ptr_sub(inPtr, runStart);
                    *out = (count / 8) as u8;
                    ptr_inc(&mut out, 1);

                    if (count <= mut_ptr_sub(bufferEnd, out)) {
                        //# There's enough space to memcpy.

                        let src : *u8 = runStart;
                        std::ptr::copy_nonoverlapping_memory(out, src, count);

                        ptr_inc(&mut out, count as int);
                    } else {
                        //# Input overruns the output buffer. We'll give it
                        //# to the output stream in one chunk and let it
                        //# decide what to do.
                        self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));

                        do std::vec::raw::buf_as_slice::<u8,()>(runStart, count) |buf| {
                            self.inner.write(buf);
                        }

                        let (out1, bufferEnd1) = self.inner.getWriteBuffer();
                        out = out1; bufferEnd = bufferEnd1;
                        bufferBegin = out;
                    }
                }
            }

            self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));
            self.inner.flush();
        }
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub trait WritePacked {
    fn writePackedMessage(&mut self, message : &MessageBuilder);
}

impl <'self, T : std::io::Writer> WritePacked for io::BufferedOutputStream<'self, T> {
    fn writePackedMessage(&mut self, message : &MessageBuilder) {
        let mut packedOutputStream = PackedOutputStream {inner : self};
        writeMessage(&mut packedOutputStream, message);
    }
}

pub struct WritePackedWrapper<'a, T> {writer : &'a mut T }

impl <'a, T: std::io::Writer> WritePacked for WritePackedWrapper<'a, T> {
    fn writePackedMessage(&mut self, message : &MessageBuilder) {
        let mut buffered = io::BufferedOutputStream::new(self.writer);
        buffered.writePackedMessage(message);
    }
}
<commit_msg>use RawPtr::offset()<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use io;
use message::*;
use serialize::*;

#[inline]
unsafe fn ptr_sub<T>(p1 : * T, p2 : * T) -> uint {
    let p1Addr : uint = std::cast::transmute(p1);
    let p2Addr : uint = std::cast::transmute(p2);
    return (p1Addr - p2Addr) / std::mem::size_of::<T>();
}

#[inline]
unsafe fn mut_ptr_sub <T>(p1 : *mut T, p2 : *mut T) -> uint {
    let p1Addr : uint = std::cast::transmute(p1);
    let p2Addr : uint = std::cast::transmute(p2);
    return (p1Addr - p2Addr) / std::mem::size_of::<T>();
}

pub struct PackedInputStream<'a, 'b,  R> {
    inner : &'a mut io::BufferedInputStream<'b, R>
}

macro_rules! refresh_buffer(
    ($inner:expr, $size:ident, $inPtr:ident, $inEnd:ident, $out:ident,
     $outBuf:ident, $bufferBegin:ident) => (
        {
            $inner.skip($size);
            let (b, e) = $inner.getReadBuffer();
            $inPtr = b;
            $inEnd = e;
            $size = ptr_sub($inEnd, $inPtr);
            $bufferBegin = b;
            assert!($size > 0);
        }
        );
    )

impl <'a, 'b, R : std::io::Reader> std::io::Reader for PackedInputStream<'a, 'b, R> {
    fn eof(&mut self) -> bool {
        self.inner.eof()
    }

    fn read(&mut self, outBuf: &mut [u8]) -> Option<uint> {
        let len = outBuf.len();

        if (len == 0) { return Some(0); }

        assert!(len % 8 == 0, "PackInputStream reads must be word-aligned");

        unsafe {
            let mut out = outBuf.unsafe_mut_ref(0);
            let outEnd = outBuf.unsafe_mut_ref(len);

            let (mut inPtr, mut inEnd) = self.inner.getReadBuffer();
            let mut bufferBegin = inPtr;
            let mut size = ptr_sub(inEnd, inPtr);
            if size == 0 {
                return Some(0);
            }

            loop {

                let mut tag : u8;

                assert!(mut_ptr_sub(out, outBuf.unsafe_mut_ref(0)) % 8 == 0,
                        "Output pointer should always be aligned here.");

                if ptr_sub(inEnd, inPtr) < 10 {
                    if out >= outEnd {
                        self.inner.skip(ptr_sub(inPtr, bufferBegin));
                        return Some(mut_ptr_sub(out, outBuf.unsafe_mut_ref(0)));
                    }

                    if ptr_sub(inEnd, inPtr) == 0 {
                        refresh_buffer!(self.inner, size, inPtr, inEnd, out, outBuf, bufferBegin);
                        continue;
                    }

                    //# We have at least 1, but not 10, bytes availabe. We need to read
                    //# slowly, doing a bounds check on each byte.

                    tag = *inPtr;
                    inPtr = inPtr.offset(1);

                    for i in range(0, 8) {
                        if (tag & (1u8 << i)) != 0 {
                            if ptr_sub(inEnd, inPtr) == 0 {
                                refresh_buffer!(self.inner, size, inPtr, inEnd,
                                                out, outBuf, bufferBegin);
                            }
                            *out = *inPtr;
                            out = out.offset(1);
                            inPtr = inPtr.offset(1);
                        } else {
                            *out = 0;
                            out = out.offset(1);
                        }
                    }

                    if ptr_sub(inEnd, inPtr) == 0 && (tag == 0 || tag == 0xff) {
                        refresh_buffer!(self.inner, size, inPtr, inEnd,
                                        out, outBuf, bufferBegin);
                    }
                } else {
                    tag = *inPtr;
                    inPtr = inPtr.offset(1);

                    for n in range(0, 8) {
                        let isNonzero = (tag & (1 as u8 << n)) != 0;
                        *out = (*inPtr) & ((-(isNonzero as i8)) as u8);
                        out = out.offset(1);
                        inPtr = inPtr.offset(isNonzero as int);
                    }
                }
                if (tag == 0) {
                    assert!(ptr_sub(inEnd, inPtr) > 0,
                            "Should always have non-empty buffer here");

                    let runLength : uint = (*inPtr) as uint * 8;
                    inPtr = inPtr.offset(1);

                    assert!(runLength <= mut_ptr_sub(outEnd, out),
                            "Packed input did not end cleanly on a segment boundary");

                    std::ptr::set_memory(out, 0, runLength);
                    out = out.offset(runLength as int);

                } else if (tag == 0xff) {
                    assert!(ptr_sub(inEnd, inPtr) > 0,
                            "Should always have non-empty buffer here");

                    let mut runLength : uint = (*inPtr) as uint * 8;
                    inPtr = inPtr.offset(1);

                    assert!(runLength <= mut_ptr_sub(outEnd, out),
                            "Packed input did not end cleanly on a segment boundary");

                    let inRemaining = ptr_sub(inEnd, inPtr);
                    if (inRemaining >= runLength) {
                        //# Fast path.
                        std::ptr::copy_nonoverlapping_memory(out, inPtr, runLength);
                        out = out.offset(runLength as int);
                        inPtr = inPtr.offset(runLength as int);
                    } else {
                        //# Copy over the first buffer, then do one big read for the rest.
                        std::ptr::copy_nonoverlapping_memory(out, inPtr, inRemaining);
                        out = out.offset(inRemaining as int);
                        runLength -= inRemaining;

                        self.inner.skip(size);
                        do std::vec::raw::mut_buf_as_slice::<u8,()>(out, runLength) |buf| {
                            self.inner.read(buf);
                        }
                        out = out.offset(runLength as int);

                        if (out == outEnd) {
                            return Some(len);
                        } else {
                            let (b, e) = self.inner.getReadBuffer();
                            inPtr = b;
                            inEnd = e;
                            size = ptr_sub(e, b);
                            bufferBegin = inPtr;
                            continue;
                        }
                    }
                }

                if (out == outEnd) {
                    self.inner.skip(ptr_sub(inPtr, bufferBegin));
                    return Some(len);
                }
            }
        }
    }
}

pub struct PackedOutputStream<'a, 'b, W> {
    inner : &'a mut io::BufferedOutputStream<'b, W>
}

impl <'a, 'b, W : std::io::Writer> std::io::Writer for PackedOutputStream<'a, 'b, W> {
    fn write(&mut self, inBuf : &[u8]) {
        unsafe {
            let (mut out, mut bufferEnd) = self.inner.getWriteBuffer();
            let mut bufferBegin = out;
            let mut slowBuffer : [u8,..20] = [0, ..20];

            let mut inPtr : *u8 = inBuf.unsafe_ref(0);
            let inEnd : *u8 = inBuf.unsafe_ref(inBuf.len());

            while (inPtr < inEnd) {

                if (mut_ptr_sub(bufferEnd, out) < 10) {
                    //# Oops, we're out of space. We need at least 10
                    //# bytes for the fast path, since we don't
                    //# bounds-check on every byte.
                    self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));

                    out = slowBuffer.unsafe_mut_ref(0);
                    bufferEnd = slowBuffer.unsafe_mut_ref(20);
                    bufferBegin = out;
                }

                let tagPos : *mut u8 = out;
                out = out.offset(1);

                let bit0 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit0 as int);
                inPtr = inPtr.offset(1);

                let bit1 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit1 as int);
                inPtr = inPtr.offset(1);

                let bit2 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit2 as int);
                inPtr = inPtr.offset(1);

                let bit3 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit3 as int);
                inPtr = inPtr.offset(1);

                let bit4 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit4 as int);
                inPtr = inPtr.offset(1);

                let bit5 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit5 as int);
                inPtr = inPtr.offset(1);

                let bit6 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit6 as int);
                inPtr = inPtr.offset(1);

                let bit7 = (*inPtr != 0) as u8;
                *out = *inPtr;
                out = out.offset(bit7 as int);
                inPtr = inPtr.offset(1);

                let tag : u8 = (bit0 << 0) | (bit1 << 1) | (bit2 << 2) | (bit3 << 3)
                    | (bit4 << 4) | (bit5 << 5) | (bit6 << 6) | (bit7 << 7);

                *tagPos = tag;

                if (tag == 0) {
                    //# An all-zero word is followed by a count of
                    //# consecutive zero words (not including the first
                    //# one).

                    let mut inWord : *u64 = std::cast::transmute(inPtr);
                    let mut limit : *u64 = std::cast::transmute(inEnd);
                    if (ptr_sub(limit, inWord) > 255) {
                        limit = inWord.offset(255);
                    }
                    while (inWord < limit && *inWord == 0) {
                        inWord = inWord.offset(1);
                    }
                    *out = ptr_sub(inWord, std::cast::transmute::<*u8, *u64>(inPtr)) as u8;

                    out = out.offset(1);
                    inPtr = std::cast::transmute::<*u64, *u8>(inWord);

                } else if (tag == 0xff) {
                    //# An all-nonzero word is followed by a count of
                    //# consecutive uncompressed words, followed by the
                    //# uncompressed words themselves.

                    //# Count the number of consecutive words in the input
                    //# which have no more than a single zero-byte. We look
                    //# for at least two zeros because that's the point
                    //# where our compression scheme becomes a net win.
                    let runStart = inPtr;
                    let mut limit = inEnd;
                    if (ptr_sub(limit, inPtr) > 255 * 8) {
                        limit = inPtr.offset(255 * 8);
                    }

                    while (inPtr < limit) {
                        let mut c = 0;

                        for _ in range(0,8) {
                            c += (*inPtr == 0) as u8;
                            inPtr = inPtr.offset(1);
                        }

                        if (c >= 2) {
                            //# Un-read the word with multiple zeros, since
                            //# we'll want to compress that one.
                            inPtr = inPtr.offset(-8);
                            break;
                        }
                    }
                    let count : uint = ptr_sub(inPtr, runStart);
                    *out = (count / 8) as u8;
                    out = out.offset(1);

                    if (count <= mut_ptr_sub(bufferEnd, out)) {
                        //# There's enough space to memcpy.

                        let src : *u8 = runStart;
                        std::ptr::copy_nonoverlapping_memory(out, src, count);

                        out = out.offset(count as int);
                    } else {
                        //# Input overruns the output buffer. We'll give it
                        //# to the output stream in one chunk and let it
                        //# decide what to do.
                        self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));

                        do std::vec::raw::buf_as_slice::<u8,()>(runStart, count) |buf| {
                            self.inner.write(buf);
                        }

                        let (out1, bufferEnd1) = self.inner.getWriteBuffer();
                        out = out1; bufferEnd = bufferEnd1;
                        bufferBegin = out;
                    }
                }
            }

            self.inner.write_ptr(bufferBegin, mut_ptr_sub(out, bufferBegin));
            self.inner.flush();
        }
    }

   fn flush(&mut self) { self.inner.flush(); }
}

pub trait WritePacked {
    fn writePackedMessage(&mut self, message : &MessageBuilder);
}

impl <'self, T : std::io::Writer> WritePacked for io::BufferedOutputStream<'self, T> {
    fn writePackedMessage(&mut self, message : &MessageBuilder) {
        let mut packedOutputStream = PackedOutputStream {inner : self};
        writeMessage(&mut packedOutputStream, message);
    }
}

pub struct WritePackedWrapper<'a, T> {writer : &'a mut T }

impl <'a, T: std::io::Writer> WritePacked for WritePackedWrapper<'a, T> {
    fn writePackedMessage(&mut self, message : &MessageBuilder) {
        let mut buffered = io::BufferedOutputStream::new(self.writer);
        buffered.writePackedMessage(message);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::{Show, Formatter};
use serialize::{Decodable, Decoder, Encodable, Encoder};

use url::Url;

use core::{Summary, Package, PackageId};
use sources::{PathSource, GitSource};
use sources::git;
use util::{Config, CargoResult, CargoError};
use util::errors::human;

/// A Source finds and downloads remote packages based on names and
/// versions.
pub trait Source {
    /// The update method performs any network operations required to
    /// get the entire list of all names, versions and dependencies of
    /// packages managed by the Source.
    fn update(&mut self) -> CargoResult<()>;

    /// The list method lists all names, versions and dependencies of
    /// packages managed by the source. It assumes that `update` has
    /// already been called and no additional network operations are
    /// required.
    fn list(&self) -> CargoResult<Vec<Summary>>;

    /// The download method fetches the full package for each name and
    /// version specified.
    fn download(&self, packages: &[PackageId]) -> CargoResult<()>;

    /// The get method returns the Path of each specified package on the
    /// local file system. It assumes that `download` was already called,
    /// and that the packages are already locally available on the file
    /// system.
    fn get(&self, packages: &[PackageId]) -> CargoResult<Vec<Package>>;

    /// Generates a unique string which represents the fingerprint of the
    /// current state of the source.
    ///
    /// This fingerprint is used to determine the "fresheness" of the source
    /// later on. It must be guaranteed that the fingerprint of a source is
    /// constant if and only if the output product will remain constant.
    ///
    /// The `pkg` argument is the package which this fingerprint should only be
    /// interested in for when this source may contain multiple packages.
    fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
}

#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SourceKind {
    /// GitKind(<git reference>) represents a git repository
    GitKind(String),
    /// represents a local path
    PathKind,
    /// represents the central registry
    RegistryKind
}

#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum Location {
    Local(Path),
    Remote(Url),
}

type Error = Box<CargoError + Send>;

impl<E, D: Decoder<E>> Decodable<D, E> for Location {
    fn decode(d: &mut D) -> Result<Location, E> {
        let url: String  = raw_try!(Decodable::decode(d));
        Ok(Location::parse(url.as_slice()).unwrap())
    }
}

impl<E, S: Encoder<E>> Encodable<S, E> for Location {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        self.to_string().encode(e)
    }
}

#[deriving(Encodable, Decodable, Clone, Eq, Hash)]
pub struct SourceId {
    pub kind: SourceKind,
    pub location: Location,
}

impl Show for Location {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Local(ref p) => write!(f, "file:{}", p.display()),
            Remote(ref u) => write!(f, "{}", u),
        }
    }
}

impl Location {
    pub fn parse(s: &str) -> CargoResult<Location> {
        if s.starts_with("file:") {
            Ok(Local(Path::new(s.slice_from(5))))
        } else {
            Url::parse(s).map(Remote).map_err(|e| {
                human(format!("invalid url `{}`: `{}", s, e))
            })
        }
    }
}

impl Show for SourceId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            SourceId { kind: PathKind, ref location } => {
                try!(write!(f, "{}", location))
            },
            SourceId { kind: GitKind(ref reference), ref location } => {
                try!(write!(f, "{}", location));
                if reference.as_slice() != "master" {
                    try!(write!(f, "#ref={}", reference));
                }
            },
            SourceId { kind: RegistryKind, .. } => {
                // TODO: Central registry vs. alternates
                try!(write!(f, "the package registry"));
            }
        }

        Ok(())
    }
}

// This custom implementation handles situations such as when two git sources
// point at *almost* the same URL, but not quite, even when they actually point
// to the same repository.
impl PartialEq for SourceId {
    fn eq(&self, other: &SourceId) -> bool {
        if self.kind != other.kind { return false }
        if self.location == other.location { return true }

        match (&self.kind, &other.kind, &self.location, &other.location) {
            (&GitKind(..), &GitKind(..),
             &Remote(ref u1), &Remote(ref u2)) => {
                git::canonicalize_url(u1.to_string().as_slice()) ==
                    git::canonicalize_url(u2.to_string().as_slice())
            }
            _ => false,
        }
    }
}

impl SourceId {
    pub fn new(kind: SourceKind, location: Location) -> SourceId {
        SourceId { kind: kind, location: location }
    }

    // Pass absolute path
    pub fn for_path(path: &Path) -> SourceId {
        SourceId::new(PathKind, Local(path.clone()))
    }

    pub fn for_git(url: &Url, reference: &str) -> SourceId {
        SourceId::new(GitKind(reference.to_string()), Remote(url.clone()))
    }

    pub fn for_central() -> SourceId {
        SourceId::new(RegistryKind,
                      Remote(Url::parse("https://example.com").unwrap()))
    }

    pub fn get_location<'a>(&'a self) -> &'a Location {
        &self.location
    }

    pub fn is_path(&self) -> bool {
        self.kind == PathKind
    }

    pub fn is_git(&self) -> bool {
        match self.kind {
            GitKind(_) => true,
            _ => false
        }
    }

    pub fn load(&self, config: &mut Config) -> Box<Source> {
        match self.kind {
            GitKind(..) => box GitSource::new(self, config) as Box<Source>,
            PathKind => {
                let path = match self.location {
                    Local(ref p) => p,
                    Remote(..) => fail!("path sources cannot be remote"),
                };
                box PathSource::new(path, self) as Box<Source>
            },
            RegistryKind => unimplemented!()
        }
    }
}

pub struct SourceSet {
    sources: Vec<Box<Source>>
}

impl SourceSet {
    pub fn new(sources: Vec<Box<Source>>) -> SourceSet {
        SourceSet { sources: sources }
    }
}

impl Source for SourceSet {
    fn update(&mut self) -> CargoResult<()> {
        for source in self.sources.mut_iter() {
            try!(source.update());
        }

        Ok(())
    }

    fn list(&self) -> CargoResult<Vec<Summary>> {
        let mut ret = Vec::new();

        for source in self.sources.iter() {
            ret.push_all(try!(source.list()).as_slice());
        }

        Ok(ret)
    }

    fn download(&self, packages: &[PackageId]) -> CargoResult<()> {
        for source in self.sources.iter() {
            try!(source.download(packages));
        }

        Ok(())
    }

    fn get(&self, packages: &[PackageId]) -> CargoResult<Vec<Package>> {
        let mut ret = Vec::new();

        for source in self.sources.iter() {
            ret.push_all(try!(source.get(packages)).as_slice());
        }

        Ok(ret)
    }

    fn fingerprint(&self, id: &Package) -> CargoResult<String> {
        let mut ret = String::new();
        for source in self.sources.iter() {
            ret.push_str(try!(source.fingerprint(id)).as_slice());
        }
        return Ok(ret);
    }
}

#[cfg(test)]
mod tests {
    use super::{SourceId, Remote, GitKind};

    #[test]
    fn github_sources_equal() {
        let loc = Remote(from_str("https://github.com/foo/bar").unwrap());
        let s1 = SourceId::new(GitKind("master".to_string()), loc);

        let loc = Remote(from_str("git://github.com/foo/bar").unwrap());
        let mut s2 = SourceId::new(GitKind("master".to_string()), loc);

        assert_eq!(s1, s2);

        s2.kind = GitKind("foo".to_string());
        assert!(s1 != s2);
    }
}
<commit_msg>auto merge of #224 : alexcrichton/cargo/canonical-hash, r=wycats<commit_after>use std::fmt;
use std::fmt::{Show, Formatter};
use std::hash;
use serialize::{Decodable, Decoder, Encodable, Encoder};

use url::Url;

use core::{Summary, Package, PackageId};
use sources::{PathSource, GitSource};
use sources::git;
use util::{Config, CargoResult, CargoError};
use util::errors::human;

/// A Source finds and downloads remote packages based on names and
/// versions.
pub trait Source {
    /// The update method performs any network operations required to
    /// get the entire list of all names, versions and dependencies of
    /// packages managed by the Source.
    fn update(&mut self) -> CargoResult<()>;

    /// The list method lists all names, versions and dependencies of
    /// packages managed by the source. It assumes that `update` has
    /// already been called and no additional network operations are
    /// required.
    fn list(&self) -> CargoResult<Vec<Summary>>;

    /// The download method fetches the full package for each name and
    /// version specified.
    fn download(&self, packages: &[PackageId]) -> CargoResult<()>;

    /// The get method returns the Path of each specified package on the
    /// local file system. It assumes that `download` was already called,
    /// and that the packages are already locally available on the file
    /// system.
    fn get(&self, packages: &[PackageId]) -> CargoResult<Vec<Package>>;

    /// Generates a unique string which represents the fingerprint of the
    /// current state of the source.
    ///
    /// This fingerprint is used to determine the "fresheness" of the source
    /// later on. It must be guaranteed that the fingerprint of a source is
    /// constant if and only if the output product will remain constant.
    ///
    /// The `pkg` argument is the package which this fingerprint should only be
    /// interested in for when this source may contain multiple packages.
    fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
}

#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SourceKind {
    /// GitKind(<git reference>) represents a git repository
    GitKind(String),
    /// represents a local path
    PathKind,
    /// represents the central registry
    RegistryKind
}

#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum Location {
    Local(Path),
    Remote(Url),
}

type Error = Box<CargoError + Send>;

impl<E, D: Decoder<E>> Decodable<D, E> for Location {
    fn decode(d: &mut D) -> Result<Location, E> {
        let url: String  = raw_try!(Decodable::decode(d));
        Ok(Location::parse(url.as_slice()).unwrap())
    }
}

impl<E, S: Encoder<E>> Encodable<S, E> for Location {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        self.to_string().encode(e)
    }
}

#[deriving(Encodable, Decodable, Clone, Eq)]
pub struct SourceId {
    pub kind: SourceKind,
    pub location: Location,
}

impl Show for Location {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Local(ref p) => write!(f, "file:{}", p.display()),
            Remote(ref u) => write!(f, "{}", u),
        }
    }
}

impl Location {
    pub fn parse(s: &str) -> CargoResult<Location> {
        if s.starts_with("file:") {
            Ok(Local(Path::new(s.slice_from(5))))
        } else {
            Url::parse(s).map(Remote).map_err(|e| {
                human(format!("invalid url `{}`: `{}", s, e))
            })
        }
    }
}

impl Show for SourceId {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            SourceId { kind: PathKind, ref location } => {
                try!(write!(f, "{}", location))
            },
            SourceId { kind: GitKind(ref reference), ref location } => {
                try!(write!(f, "{}", location));
                if reference.as_slice() != "master" {
                    try!(write!(f, "#ref={}", reference));
                }
            },
            SourceId { kind: RegistryKind, .. } => {
                // TODO: Central registry vs. alternates
                try!(write!(f, "the package registry"));
            }
        }

        Ok(())
    }
}

// This custom implementation handles situations such as when two git sources
// point at *almost* the same URL, but not quite, even when they actually point
// to the same repository.
impl PartialEq for SourceId {
    fn eq(&self, other: &SourceId) -> bool {
        if self.kind != other.kind { return false }
        if self.location == other.location { return true }

        match (&self.kind, &other.kind, &self.location, &other.location) {
            (&GitKind(..), &GitKind(..),
             &Remote(ref u1), &Remote(ref u2)) => {
                git::canonicalize_url(u1.to_string().as_slice()) ==
                    git::canonicalize_url(u2.to_string().as_slice())
            }
            _ => false,
        }
    }
}

impl<S: hash::Writer> hash::Hash<S> for SourceId {
    fn hash(&self, into: &mut S) {
        match *self {
            SourceId {
                kind: ref kind @ GitKind(..),
                location: Remote(ref url)
            } => {
                kind.hash(into);
                git::canonicalize_url(url.to_string().as_slice()).hash(into);
            }
            _ => {
                self.kind.hash(into);
                self.location.hash(into);
            }
        }
    }
}

impl SourceId {
    pub fn new(kind: SourceKind, location: Location) -> SourceId {
        SourceId { kind: kind, location: location }
    }

    // Pass absolute path
    pub fn for_path(path: &Path) -> SourceId {
        SourceId::new(PathKind, Local(path.clone()))
    }

    pub fn for_git(url: &Url, reference: &str) -> SourceId {
        SourceId::new(GitKind(reference.to_string()), Remote(url.clone()))
    }

    pub fn for_central() -> SourceId {
        SourceId::new(RegistryKind,
                      Remote(Url::parse("https://example.com").unwrap()))
    }

    pub fn get_location<'a>(&'a self) -> &'a Location {
        &self.location
    }

    pub fn is_path(&self) -> bool {
        self.kind == PathKind
    }

    pub fn is_git(&self) -> bool {
        match self.kind {
            GitKind(_) => true,
            _ => false
        }
    }

    pub fn load(&self, config: &mut Config) -> Box<Source> {
        match self.kind {
            GitKind(..) => box GitSource::new(self, config) as Box<Source>,
            PathKind => {
                let path = match self.location {
                    Local(ref p) => p,
                    Remote(..) => fail!("path sources cannot be remote"),
                };
                box PathSource::new(path, self) as Box<Source>
            },
            RegistryKind => unimplemented!()
        }
    }
}

pub struct SourceSet {
    sources: Vec<Box<Source>>
}

impl SourceSet {
    pub fn new(sources: Vec<Box<Source>>) -> SourceSet {
        SourceSet { sources: sources }
    }
}

impl Source for SourceSet {
    fn update(&mut self) -> CargoResult<()> {
        for source in self.sources.mut_iter() {
            try!(source.update());
        }

        Ok(())
    }

    fn list(&self) -> CargoResult<Vec<Summary>> {
        let mut ret = Vec::new();

        for source in self.sources.iter() {
            ret.push_all(try!(source.list()).as_slice());
        }

        Ok(ret)
    }

    fn download(&self, packages: &[PackageId]) -> CargoResult<()> {
        for source in self.sources.iter() {
            try!(source.download(packages));
        }

        Ok(())
    }

    fn get(&self, packages: &[PackageId]) -> CargoResult<Vec<Package>> {
        let mut ret = Vec::new();

        for source in self.sources.iter() {
            ret.push_all(try!(source.get(packages)).as_slice());
        }

        Ok(ret)
    }

    fn fingerprint(&self, id: &Package) -> CargoResult<String> {
        let mut ret = String::new();
        for source in self.sources.iter() {
            ret.push_str(try!(source.fingerprint(id)).as_slice());
        }
        return Ok(ret);
    }
}

#[cfg(test)]
mod tests {
    use super::{SourceId, Remote, GitKind};

    #[test]
    fn github_sources_equal() {
        let loc = Remote(from_str("https://github.com/foo/bar").unwrap());
        let s1 = SourceId::new(GitKind("master".to_string()), loc);

        let loc = Remote(from_str("git://github.com/foo/bar").unwrap());
        let mut s2 = SourceId::new(GitKind("master".to_string()), loc);

        assert_eq!(s1, s2);

        s2.kind = GitKind("foo".to_string());
        assert!(s1 != s2);
    }
}
<|endoftext|>