<commit_before>#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![feature(rustc_private)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_interface;

use rustc_interface::interface;
use rustc_tools_util::*;

use std::path::{Path, PathBuf};
use std::process::{exit, Command};

mod lintlist;

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        let previous = config.register_lints.take();
        config.register_lints = Some(Box::new(move |sess, mut lint_store| {
            // technically we're ~guaranteed that this is none but might as well call anything that
            // is there already. Certainly it can't hurt.
            if let Some(previous) = &previous {
                (previous)(sess, lint_store);
            }

            let conf = clippy_lints::read_conf(&[], &sess);
            clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
            clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf);
            clippy_lints::register_renamed(&mut lint_store);
        }));
    }
}

#[allow(clippy::find_map, clippy::filter_map)]
fn describe_lints() {
    use lintlist::*;
    use std::collections::HashSet;

    println!(
        "
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)

"
    );

    let lint_level = |lint: &Lint| {
        LINT_LEVELS
            .iter()
            .find(|level_mapping| level_mapping.0 == lint.group)
            .map(|(_, level)| match level {
                Level::Allow => "allow",
                Level::Warn => "warn",
                Level::Deny => "deny",
            })
            .unwrap()
    };

    let mut lints: Vec<_> = ALL_LINTS.iter().collect();
    // The sort doesn't case-fold but it's doubtful we care.
    lints.sort_by_cached_key(|x: &&Lint| (lint_level(x), x.name));

    let max_lint_name_len = lints
        .iter()
        .map(|lint| lint.name.len())
        .map(|len| len + "clippy::".len())
        .max()
        .unwrap_or(0);

    let padded = |x: &str| {
        let mut s = " ".repeat(max_lint_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    let scoped = |x: &str| format!("clippy::{}", x);

    let lint_groups: HashSet<_> = lints.iter().map(|lint| lint.group).collect();

    println!("Lint checks provided by clippy:\n");
    println!("    {}  {:7.7}  meaning", padded("name"), "default");
    println!("    {}  {:7.7}  -------", padded("----"), "-------");

    let print_lints = |lints: &[&Lint]| {
        for lint in lints {
            let name = lint.name.replace("_", "-");
            println!(
                "    {}  {:7.7}  {}",
                padded(&scoped(&name)),
                lint_level(lint),
                lint.desc
            );
        }
        println!("\n");
    };

    print_lints(&lints);

    let max_group_name_len = std::cmp::max(
        "clippy::all".len(),
        lint_groups
            .iter()
            .map(|group| group.len())
            .map(|len| len + "clippy::".len())
            .max()
            .unwrap_or(0),
    );

    let padded_group = |x: &str| {
        let mut s = " ".repeat(max_group_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint groups provided by clippy:\n");
    println!("    {}  sub-lints", padded_group("name"));
    println!("    {}  ---------", padded_group("----"));
    println!("    {}  the set of all clippy lints", padded_group("clippy::all"));

    let print_lint_groups = || {
        for group in lint_groups {
            let name = group.to_lowercase().replace("_", "-");
            let desc = lints
                .iter()
                .filter(|&lint| lint.group == group)
                .map(|lint| lint.name)
                .map(|name| name.replace("_", "-"))
                .collect::<Vec<String>>()
                .join(", ");
            println!("    {}  {}", padded_group(&scoped(&name)), desc);
        }
        println!("\n");
    };

    print_lint_groups();
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

pub fn main() {
    rustc_driver::init_rustc_env_logger();
    rustc_driver::install_ice_hook();
    exit(
        rustc_driver::catch_fatal_errors(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                let version_info = rustc_tools_util::get_version_info!();
                println!("{}", version_info);
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(PathBuf::from)
                .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| {
                        toolchain.map(|toolchain| {
                            let mut path = PathBuf::from(home);
                            path.push("toolchains");
                            path.push(toolchain);
                            path
                        })
                    })
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| PathBuf::from(s.trim()))
                })
                .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
                .map(|pb| pb.to_string_lossy().to_string())
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            let wrapper_mode = Path::new(&orig_args[1]).file_stem() == Some("rustc".as_ref());

            if wrapper_mode {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }

            if !wrapper_mode && std::env::args().any(|a| a == "--help" || a == "-h") {
                display_help();
                exit(0);
            }

            let should_describe_lints = || {
                let args: Vec<_> = std::env::args().collect();
                args.windows(2).any(|args| {
                    args[1] == "help"
                        && match args[0].as_str() {
                            "-W" | "-A" | "-D" | "-F" => true,
                            _ => false,
                        }
                })
            };

            if !wrapper_mode && should_describe_lints() {
                describe_lints();
                exit(0);
            }

            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
                if clippy_enabled { &mut clippy } else { &mut default };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        })
        .and_then(|result| result)
        .is_err() as i32,
    )
}
<commit_msg>display help on empty command line arguments<commit_after>#![cfg_attr(feature = "deny-warnings", deny(warnings))]
#![feature(rustc_private)]

// FIXME: switch to something more ergonomic here, once available.
// (Currently there is no way to opt into sysroot crates without `extern crate`.)
#[allow(unused_extern_crates)]
extern crate rustc_driver;
#[allow(unused_extern_crates)]
extern crate rustc_interface;

use rustc_interface::interface;
use rustc_tools_util::*;

use std::path::{Path, PathBuf};
use std::process::{exit, Command};

mod lintlist;

/// If a command-line option matches `find_arg`, then apply the predicate `pred` on its value. If
/// true, then return it. The parameter is assumed to be either `--arg=value` or `--arg value`.
fn arg_value<'a>(
    args: impl IntoIterator<Item = &'a String>,
    find_arg: &str,
    pred: impl Fn(&str) -> bool,
) -> Option<&'a str> {
    let mut args = args.into_iter().map(String::as_str);

    while let Some(arg) = args.next() {
        let arg: Vec<_> = arg.splitn(2, '=').collect();
        if arg.get(0) != Some(&find_arg) {
            continue;
        }

        let value = arg.get(1).cloned().or_else(|| args.next());
        if value.as_ref().map_or(false, |p| pred(p)) {
            return value;
        }
    }
    None
}

#[test]
fn test_arg_value() {
    let args: Vec<_> = ["--bar=bar", "--foobar", "123", "--foo"]
        .iter()
        .map(std::string::ToString::to_string)
        .collect();

    assert_eq!(arg_value(None, "--foobar", |_| true), None);
    assert_eq!(arg_value(&args, "--bar", |_| false), None);
    assert_eq!(arg_value(&args, "--bar", |_| true), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "bar"), Some("bar"));
    assert_eq!(arg_value(&args, "--bar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "foo"), None);
    assert_eq!(arg_value(&args, "--foobar", |p| p == "123"), Some("123"));
    assert_eq!(arg_value(&args, "--foo", |_| true), None);
}

#[allow(clippy::too_many_lines)]

struct ClippyCallbacks;

impl rustc_driver::Callbacks for ClippyCallbacks {
    fn config(&mut self, config: &mut interface::Config) {
        let previous = config.register_lints.take();
        config.register_lints = Some(Box::new(move |sess, mut lint_store| {
            // technically we're ~guaranteed that this is none but might as well call anything that
            // is there already. Certainly it can't hurt.
            if let Some(previous) = &previous {
                (previous)(sess, lint_store);
            }

            let conf = clippy_lints::read_conf(&[], &sess);
            clippy_lints::register_plugins(&mut lint_store, &sess, &conf);
            clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf);
            clippy_lints::register_renamed(&mut lint_store);
        }));
    }
}

#[allow(clippy::find_map, clippy::filter_map)]
fn describe_lints() {
    use lintlist::*;
    use std::collections::HashSet;

    println!(
        "
Available lint options:
    -W <foo>           Warn about <foo>
    -A <foo>           Allow <foo>
    -D <foo>           Deny <foo>
    -F <foo>           Forbid <foo> (deny <foo> and all attempts to override)

"
    );

    let lint_level = |lint: &Lint| {
        LINT_LEVELS
            .iter()
            .find(|level_mapping| level_mapping.0 == lint.group)
            .map(|(_, level)| match level {
                Level::Allow => "allow",
                Level::Warn => "warn",
                Level::Deny => "deny",
            })
            .unwrap()
    };

    let mut lints: Vec<_> = ALL_LINTS.iter().collect();
    // The sort doesn't case-fold but it's doubtful we care.
    lints.sort_by_cached_key(|x: &&Lint| (lint_level(x), x.name));

    let max_lint_name_len = lints
        .iter()
        .map(|lint| lint.name.len())
        .map(|len| len + "clippy::".len())
        .max()
        .unwrap_or(0);

    let padded = |x: &str| {
        let mut s = " ".repeat(max_lint_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    let scoped = |x: &str| format!("clippy::{}", x);

    let lint_groups: HashSet<_> = lints.iter().map(|lint| lint.group).collect();

    println!("Lint checks provided by clippy:\n");
    println!("    {}  {:7.7}  meaning", padded("name"), "default");
    println!("    {}  {:7.7}  -------", padded("----"), "-------");

    let print_lints = |lints: &[&Lint]| {
        for lint in lints {
            let name = lint.name.replace("_", "-");
            println!(
                "    {}  {:7.7}  {}",
                padded(&scoped(&name)),
                lint_level(lint),
                lint.desc
            );
        }
        println!("\n");
    };

    print_lints(&lints);

    let max_group_name_len = std::cmp::max(
        "clippy::all".len(),
        lint_groups
            .iter()
            .map(|group| group.len())
            .map(|len| len + "clippy::".len())
            .max()
            .unwrap_or(0),
    );

    let padded_group = |x: &str| {
        let mut s = " ".repeat(max_group_name_len - x.chars().count());
        s.push_str(x);
        s
    };

    println!("Lint groups provided by clippy:\n");
    println!("    {}  sub-lints", padded_group("name"));
    println!("    {}  ---------", padded_group("----"));
    println!("    {}  the set of all clippy lints", padded_group("clippy::all"));

    let print_lint_groups = || {
        for group in lint_groups {
            let name = group.to_lowercase().replace("_", "-");
            let desc = lints
                .iter()
                .filter(|&lint| lint.group == group)
                .map(|lint| lint.name)
                .map(|name| name.replace("_", "-"))
                .collect::<Vec<String>>()
                .join(", ");
            println!("    {}  {}", padded_group(&scoped(&name)), desc);
        }
        println!("\n");
    };

    print_lint_groups();
}

fn display_help() {
    println!(
        "\
Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"
    );
}

pub fn main() {
    rustc_driver::init_rustc_env_logger();
    rustc_driver::install_ice_hook();
    exit(
        rustc_driver::catch_fatal_errors(move || {
            use std::env;

            if std::env::args().any(|a| a == "--version" || a == "-V") {
                let version_info = rustc_tools_util::get_version_info!();
                println!("{}", version_info);
                exit(0);
            }

            let mut orig_args: Vec<String> = env::args().collect();

            // Get the sysroot, looking from most specific to this invocation to the least:
            // - command line
            // - runtime environment
            //    - SYSROOT
            //    - RUSTUP_HOME, MULTIRUST_HOME, RUSTUP_TOOLCHAIN, MULTIRUST_TOOLCHAIN
            // - sysroot from rustc in the path
            // - compile-time environment
            let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
            let have_sys_root_arg = sys_root_arg.is_some();
            let sys_root = sys_root_arg
                .map(PathBuf::from)
                .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from))
                .or_else(|| {
                    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
                    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
                    home.and_then(|home| {
                        toolchain.map(|toolchain| {
                            let mut path = PathBuf::from(home);
                            path.push("toolchains");
                            path.push(toolchain);
                            path
                        })
                    })
                })
                .or_else(|| {
                    Command::new("rustc")
                        .arg("--print")
                        .arg("sysroot")
                        .output()
                        .ok()
                        .and_then(|out| String::from_utf8(out.stdout).ok())
                        .map(|s| PathBuf::from(s.trim()))
                })
                .or_else(|| option_env!("SYSROOT").map(PathBuf::from))
                .map(|pb| pb.to_string_lossy().to_string())
                .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust");

            // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
            // We're invoking the compiler programmatically, so we ignore this/
            let wrapper_mode = orig_args.get(1).map(Path::new).and_then(Path::file_stem) == Some("rustc".as_ref());

            if wrapper_mode {
                // we still want to be able to invoke it normally though
                orig_args.remove(1);
            }

            if !wrapper_mode && (orig_args.iter().any(|a| a == "--help" || a == "-h") || orig_args.len() == 1) {
                display_help();
                exit(0);
            }

            let should_describe_lints = || {
                let args: Vec<_> = std::env::args().collect();
                args.windows(2).any(|args| {
                    args[1] == "help"
                        && match args[0].as_str() {
                            "-W" | "-A" | "-D" | "-F" => true,
                            _ => false,
                        }
                })
            };

            if !wrapper_mode && should_describe_lints() {
                describe_lints();
                exit(0);
            }

            // this conditional check for the --sysroot flag is there so users can call
            // `clippy_driver` directly
            // without having to pass --sysroot or anything
            let mut args: Vec<String> = if have_sys_root_arg {
                orig_args.clone()
            } else {
                orig_args
                    .clone()
                    .into_iter()
                    .chain(Some("--sysroot".to_owned()))
                    .chain(Some(sys_root))
                    .collect()
            };

            // this check ensures that dependencies are built but not linted and the final
            // crate is
            // linted but not built
            let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true")
                || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some();

            if clippy_enabled {
                args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]);
                if let Ok(extra_args) = env::var("CLIPPY_ARGS") {
                    args.extend(extra_args.split("__CLIPPY_HACKERY__").filter_map(|s| {
                        if s.is_empty() {
                            None
                        } else {
                            Some(s.to_string())
                        }
                    }));
                }
            }

            let mut clippy = ClippyCallbacks;
            let mut default = rustc_driver::DefaultCallbacks;
            let callbacks: &mut (dyn rustc_driver::Callbacks + Send) =
                if clippy_enabled { &mut clippy } else { &mut default };
            let args = args;
            rustc_driver::run_compiler(&args, callbacks, None, None)
        })
        .and_then(|result| result)
        .is_err() as i32,
    )
}
<|endoftext|>


<commit_before>use std::fmt;
use std::borrow::Borrow;
use std::sync::{Arc, RwLock};
use std::collections::HashSet;

use rustc_serialize::{Decoder, Decodable};

lazy_static! {
    static ref ATOMS: RwLock<HashSet<Atom>> = RwLock::new(HashSet::new());
}

// TODO(tailhook) optimize Eq to compare pointers
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Atom(Arc<String>);

impl<'a> From<&'a str> for Atom {
    fn from(s: &'a str) -> Atom {
        if let Some(a) = ATOMS.read().expect("atoms locked").get(s) {
            return a.clone();
        }
        let newatom = Atom(Arc::new(String::from(s)));
        let mut atoms = ATOMS.write().expect("atoms locked");
        if !atoms.insert(newatom.clone()) {
            // Race condition happened, but now we are still holding lock
            // so it's safe to unwrap
            return atoms.get(s).unwrap().clone();
        } else {
            return newatom;
        }
    }
}
impl From<String> for Atom {
    fn from(s: String) -> Atom {
        if let Some(a) = ATOMS.read().expect("atoms locked").get(&s) {
            return a.clone();
        }
        let newatom = Atom(Arc::new(s));
        let mut atoms = ATOMS.write().expect("atoms locked");
        if !atoms.insert(newatom.clone()) {
            // Race condition happened, but now we are still holding lock
            // so it's safe to unwrap
            return atoms.get(&newatom).unwrap().clone();
        } else {
            return newatom;
        }
    }
}

impl Borrow<str> for Atom {
    fn borrow(&self) -> &str {
        &self.0[..]
    }
}

impl Borrow<String> for Atom {
    fn borrow(&self) -> &String {
        &self.0
    }
}

impl fmt::Debug for Atom {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "a{:?}", self.0)
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

impl Decodable for Atom {
    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
        d.read_str().map(Atom::from)
    }
}
<commit_msg>Implement `Deref<Target=str>` for Atom<commit_after>use std::fmt;
use std::ops::Deref;
use std::borrow::Borrow;
use std::sync::{Arc, RwLock};
use std::collections::HashSet;

use rustc_serialize::{Decoder, Decodable};

lazy_static! {
    static ref ATOMS: RwLock<HashSet<Atom>> = RwLock::new(HashSet::new());
}

// TODO(tailhook) optimize Eq to compare pointers
#[derive(Clone, PartialEq, Eq, Hash)]
pub struct Atom(Arc<String>);

impl<'a> From<&'a str> for Atom {
    fn from(s: &'a str) -> Atom {
        if let Some(a) = ATOMS.read().expect("atoms locked").get(s) {
            return a.clone();
        }
        let newatom = Atom(Arc::new(String::from(s)));
        let mut atoms = ATOMS.write().expect("atoms locked");
        if !atoms.insert(newatom.clone()) {
            // Race condition happened, but now we are still holding lock
            // so it's safe to unwrap
            return atoms.get(s).unwrap().clone();
        } else {
            return newatom;
        }
    }
}
impl From<String> for Atom {
    fn from(s: String) -> Atom {
        if let Some(a) = ATOMS.read().expect("atoms locked").get(&s) {
            return a.clone();
        }
        let newatom = Atom(Arc::new(s));
        let mut atoms = ATOMS.write().expect("atoms locked");
        if !atoms.insert(newatom.clone()) {
            // Race condition happened, but now we are still holding lock
            // so it's safe to unwrap
            return atoms.get(&newatom).unwrap().clone();
        } else {
            return newatom;
        }
    }
}

impl Borrow<str> for Atom {
    fn borrow(&self) -> &str {
        &self.0[..]
    }
}

impl Borrow<String> for Atom {
    fn borrow(&self) -> &String {
        &self.0
    }
}

impl fmt::Debug for Atom {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "a{:?}", self.0)
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(fmt)
    }
}

impl Decodable for Atom {
    fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
        d.read_str().map(Atom::from)
    }
}

impl Deref for Atom {
    type Target = str;
    fn deref(&self) -> &str {
        &self.0
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
    Setup(Setup),
}

#[derive(Clone)]
pub struct Setup {
    pub elements:Vec<Sexp>,
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn insert_dummy_setup(&mut self) {
        self.elements.push(Element::Setup(Setup { elements:vec![] }))
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
                Element::Setup(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
    pub fn has_net(&self, name:&'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true
            }
        }
        return false
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
            Element::Setup(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

impl fmt::Display for Setup {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(setup "));
        for e in &self.elements {
            try!(write!(f, "{}", e));
        }
        write!(f, ")")
    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse_setup(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("setup"));
    let mut v = vec![];
    v.extend_from_slice(l);
    let s = Setup { elements:v };
    Ok(Element::Setup(s))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            "setup" => layout.elements.push(try!(parse_setup(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>simplify Setup<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub setup:Setup,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Setup {
    pub elements:Vec<Sexp>,
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
            setup:Setup{elements:vec![]},
        }
    }

    pub fn nets(&self) -> Vec<&Net> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::Net(ref net) => v.push(net),
                _ => (),
            }
        }
        v
    }

    pub fn netclasses(&self) -> Vec<&NetClass> {
        let mut v = vec![];
        for element in &self.elements {
            match *element {
                Element::NetClass(ref net_class) => v.push(net_class),
                _ => (),
            }
        }
        v
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }

    pub fn add_net(&mut self, num:i64, name:&'static str) {
        self.elements.push(Element::Net(Net { num:num, name:String::from(name) }));
    }
    pub fn add_netclass(&mut self, name:&'static str, desc:&'static str, clearance:f64, trace_width:f64, via_dia:f64, via_drill:f64, uvia_dia:f64, uvia_drill:f64, nets:Vec<String>) {
        self.elements.push(Element::NetClass(NetClass {
            name:String::from(name),
            desc:String::from(desc),
            clearance:clearance,
            trace_width:trace_width,
            via_dia:via_dia,
            via_drill:via_drill,
            uvia_dia:uvia_dia,
            uvia_drill:uvia_drill,
            nets:nets
            }));
    }
}

impl NetClass {
    pub fn equal_no_net(&self, other:&NetClass) -> bool {
        let mut s1 = self.clone();
        s1.nets = vec![];
        let mut s2 = other.clone();
        s2.nets = vec![];
        return s1 == s2;
    }
    pub fn has_net(&self, name:&'static str) -> bool {
        for net in &self.nets {
            if &net[..] == name {
                return true
            }
        }
        return false
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        try!(writeln!(f, "  {}", self.setup));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

impl fmt::Display for Setup {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(setup"));
        for e in &self.elements {
            try!(write!(f, " {}", e));
        }
        write!(f, ")")
    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse_setup(e:&Sexp) -> ERes<Setup> {
    let l = try!(e.slice_atom("setup"));
    let mut v = vec![];
    v.extend_from_slice(l);
    let s = Setup { elements:v };
    Ok(s)
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            "setup" => layout.setup = try!(parse_setup(e)),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>//! Public/Private keys

use std::fmt;
use std::rand::Rng;
use constants;
use ffi;

use super::Result;

/// Secret 256-bit nonce used as `k` in an ECDSA signature
pub struct Nonce([u8, ..constants::NONCE_SIZE]);

/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);

/// Public key
#[deriving(PartialEq, Eq, Show)]
pub struct PublicKey(PublicKeyData);

enum PublicKeyData {
    Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
    Uncompressed([u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
}

fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8, ..32] {
    [rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen()]
}

impl Nonce {
    /// Creates a new random nonce
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> Nonce {
        Nonce(random_32_bytes(rng))
    }

    /// Converts the nonce to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &Nonce(ref data) = self;
        data.as_ptr()
    }
}

impl SecretKey {
    /// Creates a new random secret key
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> SecretKey {
        SecretKey(random_32_bytes(rng))
    }

    /// Converts the secret key to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &SecretKey(ref data) = self;
        data.as_ptr()
    }
}

impl PublicKey {
    /// Creates a new zeroed out public key
    #[inline]
    pub fn new(compressed: bool) -> PublicKey {
        PublicKey(
            if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
            else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
        )
    }

    /// Creates a new public key from a secret key
    #[inline]
    pub fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey {
        let mut pk = PublicKey::new(compressed);
        let compressed = if compressed {1} else {0};
        unsafe {
            let mut len = 0;
            while ffi::secp256k1_ecdsa_pubkey_create(
                pk.as_mut_ptr(), &mut len,
                sk.as_ptr(), compressed) != 1 {
                // loop
            }
            assert_eq!(len as uint, pk.len());
        };
        pk
    }

    /// Returns whether the public key is compressed or uncompressed
    #[inline]
    pub fn is_compressed(&self) -> bool {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(_) => true,
            Uncompressed(_) => false
        }
    }

    /// Returns the length of the public key
    #[inline]
    pub fn len(&self) -> uint {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.len(),
            Uncompressed(ref x) => x.len()
        }
    }

    /// Converts the public key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &PublicKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the public key to a raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.as_ptr(),
            Uncompressed(ref x) => x.as_ptr()
        }
    }

    /// Converts the public key to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &PublicKey(ref mut data) = self;
        match *data {
            Compressed(ref mut x) => x.as_mut_ptr(),
            Uncompressed(ref mut x) => x.as_mut_ptr()
        }
    }
}

impl PublicKeyData {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            Compressed(ref x) => x.as_slice(),
            Uncompressed(ref x) => x.as_slice()
        }
    }
}

// We have to do all these impls ourselves as Rust can't derive
// them for arrays
impl PartialEq for PublicKeyData {
    fn eq(&self, other: &PublicKeyData) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for PublicKeyData {}

impl fmt::Show for PublicKeyData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

<commit_msg>Add keypair slice methods and unit tests<commit_after>//! Public/Private keys

use std::intrinsics::copy_nonoverlapping_memory;
use std::fmt;
use std::rand::Rng;
use constants;
use ffi;

use super::{Result, InvalidPublicKey, InvalidSecretKey};

/// Secret 256-bit nonce used as `k` in an ECDSA signature
pub struct Nonce([u8, ..constants::NONCE_SIZE]);

/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);

/// Public key
#[deriving(PartialEq, Eq, Show)]
pub struct PublicKey(PublicKeyData);

enum PublicKeyData {
    Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
    Uncompressed([u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
}

fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8, ..32] {
    [rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen()]
}

impl Nonce {
    /// Creates a new random nonce
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> Nonce {
        Nonce(random_32_bytes(rng))
    }

    /// Converts the nonce to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &Nonce(ref data) = self;
        data.as_ptr()
    }
}

impl SecretKey {
    /// Creates a new random secret key
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> SecretKey {
        SecretKey(random_32_bytes(rng))
    }

    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<SecretKey> {
        match data.len() {
            constants::SECRET_KEY_SIZE => {
                let mut ret = [0, ..constants::SECRET_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(SecretKey(ret))
            }
            _ => Err(InvalidSecretKey)
        }
    }

    /// Converts the secret key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &SecretKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the secret key to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &SecretKey(ref data) = self;
        data.as_ptr()
    }
}

impl PublicKey {
    /// Creates a new zeroed out public key
    #[inline]
    pub fn new(compressed: bool) -> PublicKey {
        PublicKey(
            if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
            else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
        )
    }

    /// Creates a new public key from a secret key
    #[inline]
    pub fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey {
        let mut pk = PublicKey::new(compressed);
        let compressed = if compressed {1} else {0};
        unsafe {
            let mut len = 0;
            while ffi::secp256k1_ecdsa_pubkey_create(
                pk.as_mut_ptr(), &mut len,
                sk.as_ptr(), compressed) != 1 {
                // loop
            }
            assert_eq!(len as uint, pk.len());
        };
        pk
    }

    /// Creates a public key directly from a slice
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
        match data.len() {
            constants::COMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Compressed(ret)))
            }
            constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Uncompressed(ret)))
            }
            _ => Err(InvalidPublicKey)
        }
    }

    /// Returns whether the public key is compressed or uncompressed
    #[inline]
    pub fn is_compressed(&self) -> bool {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(_) => true,
            Uncompressed(_) => false
        }
    }

    /// Returns the length of the public key
    #[inline]
    pub fn len(&self) -> uint {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.len(),
            Uncompressed(ref x) => x.len()
        }
    }

    /// Converts the public key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &PublicKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the public key to a raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.as_ptr(),
            Uncompressed(ref x) => x.as_ptr()
        }
    }

    /// Converts the public key to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &PublicKey(ref mut data) = self;
        match *data {
            Compressed(ref mut x) => x.as_mut_ptr(),
            Uncompressed(ref mut x) => x.as_mut_ptr()
        }
    }
}

impl PublicKeyData {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            Compressed(ref x) => x.as_slice(),
            Uncompressed(ref x) => x.as_slice()
        }
    }
}

// We have to do all these impls ourselves as Rust can't derive
// them for arrays
impl PartialEq for PublicKeyData {
    fn eq(&self, other: &PublicKeyData) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for PublicKeyData {}

impl fmt::Show for PublicKeyData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl PartialEq for SecretKey {
    fn eq(&self, other: &SecretKey) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for SecretKey {}

impl fmt::Show for SecretKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

#[cfg(test)]
mod test {
    use super::super::{Secp256k1, InvalidPublicKey};
    use super::*;

    #[test]
    fn from_slice() {
        assert_eq!(PublicKey::from_slice([]), Err(InvalidPublicKey));
        assert_eq!(PublicKey::from_slice([1, 2, 3]), Err(InvalidPublicKey));

        let uncompressed = PublicKey::from_slice([1, ..65]);
        assert!(uncompressed.is_ok());
        assert!(!uncompressed.unwrap().is_compressed());

        let compressed = PublicKey::from_slice([1, ..33]);
        assert!(compressed.is_ok());
        assert!(compressed.unwrap().is_compressed());
    }

    #[test]
    fn keypair_slice_round_trip() {
        let mut s = Secp256k1::new().unwrap();

        let (sk1, pk1) = s.generate_keypair(true);
        assert_eq!(SecretKey::from_slice(sk1.as_slice()), Ok(sk1));
        assert_eq!(PublicKey::from_slice(pk1.as_slice()), Ok(pk1));

        let (sk2, pk2) = s.generate_keypair(false);
        assert_eq!(SecretKey::from_slice(sk2.as_slice()), Ok(sk2));
        assert_eq!(PublicKey::from_slice(pk2.as_slice()), Ok(pk2));
    }
}

<|endoftext|>


<commit_before>use std::error::Error;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

struct Vertex {
	x: f32,
	y: f32,
	z: f32
}

pub struct WavefrontModel {
	vertices: Vec<Vertex>
}

impl WavefrontModel {
	pub fn new(path: &'static str) {
		let mut file = match File::open(&path) {
			// The `description` method of `io::Error` returns a string that describes the error
			Err(why) => panic!("couldn't open {}", Error::description(&why)),
			Ok(file) => file,
		};

		// Read the file contents into a string, returns `io::Result<usize>`
		let mut s = String::new();

		match file.read_to_string(&mut s) {
			Err(why) => panic!("couldn't read {}", Error::description(&why)),
			Ok(_) => print!("{}", s),
		}
	}

	// fn parseLine(line)
}<commit_msg>Print file line by line<commit_after>use std::fs::File;
use std::io::{ BufReader, BufRead };

struct Vertex {
	x: f32,
	y: f32,
	z: f32
}

pub struct WavefrontModel {
	vertices: Vec<Vertex>
}

impl WavefrontModel {
	pub fn new(path: &'static str) {
		let file = BufReader::new(File::open(&path).unwrap());

		for line in file.lines()  {
			println!("{}", line.unwrap())
		}
	}
}<|endoftext|>


<commit_before>use std::str::Chars;
use std::str::from_char;
use std::iter::Iterator;
use std::iter::Enumerate;

static LITERAL_EXPRESSION : &'static str = "LiteralExpression";
static DOT_EXPRESSION : &'static str = "DotExpression";
static CHAR_CLASS_EXPRESSION : &'static str = "CharClassExpression";

#[deriving(Eq)]
enum NodeContents {
  Text( ~str ),
  Children( ~[ ~Node ] )
}

#[deriving(Eq)]
struct Node {
  name: &'static str,
  start: uint,
  end: uint,
  contents: NodeContents
}

impl Node {
  fn matchedText( &self ) -> ~str {
    match self.contents {
      Text( ref x ) => x.to_owned(),

      // TODO: recurse through children and collect all text
      Children( _ ) => ~"foo"
    }
  }
}

type ParseState<'a> = Enumerate< Chars<'a> >;

struct ParseResult<'a> {
  node: Option< Node >,
  parse_state: ParseState<'a>
}

trait Expression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> >;
}

struct LiteralExpression {
  text: &'static str
}

impl Expression for LiteralExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
      Option< ParseResult<'a> > {
    let indices_and_chars =
      parse_state.take( self.text.len() ).collect::< ~[ ( uint, char ) ] >();
    let chars : ~str =
      indices_and_chars.iter().map( | &( _, ch ) | ch ).collect();

    if self.text == chars {
      Some( ParseResult { parse_state: Increment( parse_state.clone(),
                                                  self.text.len() ),
                          node: Some( Node {
                            name: LITERAL_EXPRESSION,
                            start: indices_and_chars.head().unwrap().val0(),
                            end: indices_and_chars.last().unwrap().val0() + 1,
                            contents: Text( self.text.to_owned() ) } ) } )
    } else {
      None
    }
  }
}

struct DotExpression;
impl Expression for DotExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> > {
    let mut new_parse_state = parse_state.clone();
    match new_parse_state.next() {
      Some( ( index, character ) ) => Some(
        ParseResult { parse_state: new_parse_state,
                      node: Some( Node {
                        name: DOT_EXPRESSION,
                        start: index,
                        end: index + 1,
                        contents: Text( from_char( character ) ) } ) } ),
      _ => None
    }
  }
}

struct NotExpression;
impl Expression for NotExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> > {
    None
  }
}

struct CharClassExpression {
  // All the single chars in the char class
  single_chars: ~[char],

  // Sequence of [from, to] (inclusive bounds) char ranges
  ranges: ~[(char, char)]
}

impl CharClassExpression {
  // Takes the inner content of square brackets, so for [a-z], send "a-z".
  fn new( contents: &str ) -> CharClassExpression {
    let mut char_class = CharClassExpression { single_chars: ~[],
                                               ranges: ~[] };
    let mut in_range = false;
    let mut prev_char : Option< char > = None;
    for character in contents.chars() {
      if in_range {
        char_class.ranges.push( ( prev_char.unwrap(), character ) );
        in_range = false;
        prev_char = None;
      } else {
        if character == '-' {
          if prev_char.is_some() {
            in_range = true;
          } else {
            char_class.single_chars.push( '-' );
          }
        } else {
          if prev_char.is_some() {
            char_class.single_chars.push( prev_char.unwrap() );
          }
          prev_char = Some( character );
        }
      }
    }

    if prev_char.is_some() {
      char_class.single_chars.push( prev_char.unwrap() )
    }

    // Handles char classes like [a-]
    if in_range {
      char_class.single_chars.push( '-' );
    }
    char_class
  }

  fn matches( &self, character: char ) -> bool {
    return self.single_chars.contains( &character ) ||
      self.ranges.iter().any(
        | &( from, to ) | character >= from && character <= to );
  }
}

impl Expression for CharClassExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
      Option< ParseResult<'a> > {
    let mut new_parse_state = parse_state.clone();
    match new_parse_state.next() {
      Some( ( index, ch ) ) if self.matches( ch ) => {
        Some( ParseResult { parse_state: new_parse_state,
                      node: Some( Node {
                        name: CHAR_CLASS_EXPRESSION,
                        start: index,
                        end: index + 1,
                        contents: Text( from_char( ch ) ) } ) } )
      }
      _ => None
    }
  }
}

fn Increment<B, T: Iterator<B> >( mut iter: T, steps: uint ) -> T {
  for i in range( 0, steps ) {
    iter.next();
  }
  iter
}

pub fn parseString( input: &str ) -> Node {
  Node { name: LITERAL_EXPRESSION,
         start: 0,
         end: 3,
         contents: Text( input.to_owned() ) }
}

#[cfg(test)]
mod parser_tests;
<commit_msg>New implementation of CharClassExpression::new()<commit_after>use std::str::Chars;
use std::str::from_char;
use std::iter::Iterator;
use std::iter::Enumerate;

static LITERAL_EXPRESSION : &'static str = "LiteralExpression";
static DOT_EXPRESSION : &'static str = "DotExpression";
static CHAR_CLASS_EXPRESSION : &'static str = "CharClassExpression";

#[deriving(Eq)]
enum NodeContents {
  Text( ~str ),
  Children( ~[ ~Node ] )
}

#[deriving(Eq)]
struct Node {
  name: &'static str,
  start: uint,
  end: uint,
  contents: NodeContents
}

impl Node {
  fn matchedText( &self ) -> ~str {
    match self.contents {
      Text( ref x ) => x.to_owned(),

      // TODO: recurse through children and collect all text
      Children( _ ) => ~"foo"
    }
  }
}

type ParseState<'a> = Enumerate< Chars<'a> >;

struct ParseResult<'a> {
  node: Option< Node >,
  parse_state: ParseState<'a>
}

trait Expression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> >;
}

struct LiteralExpression {
  text: &'static str
}

impl Expression for LiteralExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
      Option< ParseResult<'a> > {
    let indices_and_chars =
      parse_state.take( self.text.len() ).collect::< ~[ ( uint, char ) ] >();
    let chars : ~str =
      indices_and_chars.iter().map( | &( _, ch ) | ch ).collect();

    if self.text == chars {
      Some( ParseResult { parse_state: Increment( parse_state.clone(),
                                                  self.text.len() ),
                          node: Some( Node {
                            name: LITERAL_EXPRESSION,
                            start: indices_and_chars.head().unwrap().val0(),
                            end: indices_and_chars.last().unwrap().val0() + 1,
                            contents: Text( self.text.to_owned() ) } ) } )
    } else {
      None
    }
  }
}

struct DotExpression;
impl Expression for DotExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> > {
    let mut new_parse_state = parse_state.clone();
    match new_parse_state.next() {
      Some( ( index, character ) ) => Some(
        ParseResult { parse_state: new_parse_state,
                      node: Some( Node {
                        name: DOT_EXPRESSION,
                        start: index,
                        end: index + 1,
                        contents: Text( from_char( character ) ) } ) } ),
      _ => None
    }
  }
}

struct NotExpression;
impl Expression for NotExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) -> Option< ParseResult<'a> > {
    None
  }
}

struct CharClassExpression {
  // All the single chars in the char class
  single_chars: ~[ char ],

  // Sequence of [from, to] (inclusive bounds) char ranges
  ranges: ~[ ( char, char ) ]
}

impl CharClassExpression {
  // Takes the inner content of square brackets, so for [a-z], send "a-z".
  fn new( contents: &str ) -> CharClassExpression {
    fn rangeAtIndex( index: uint, chars: &[char] ) -> Option<( char, char )> {
      match ( chars.get( index ),
              chars.get( index + 1 ),
              chars.get( index + 2 ) ) {
        ( Some( char1 ), Some( char2 ), Some( char3 ) ) if *char2 == '-' =>
            Some( ( *char1, *char3 ) ),
        _ => None
      }
    }

    let chars: ~[ char ] = contents.chars().collect();
    let mut char_class = CharClassExpression { single_chars: ~[],
                                               ranges: ~[] };
    let mut index = 0;
    loop {
      match rangeAtIndex( index, chars ) {
        Some( range ) => {
          char_class.ranges.push( range );
          index += 3;
        },
        _ => {
          match chars.get( index ) {
            Some( character ) => char_class.single_chars.push( *character ),
            _ => break
          }
          index += 1;
        }
      };
    }

    char_class
  }

  fn matches( &self, character: char ) -> bool {
    return self.single_chars.contains( &character ) ||
      self.ranges.iter().any(
        | &( from, to ) | character >= from && character <= to );
  }
}

impl Expression for CharClassExpression {
  fn apply<'a>( &self, parse_state: &ParseState<'a> ) ->
      Option< ParseResult<'a> > {
    let mut new_parse_state = parse_state.clone();
    match new_parse_state.next() {
      Some( ( index, ch ) ) if self.matches( ch ) => {
        Some( ParseResult { parse_state: new_parse_state,
                      node: Some( Node {
                        name: CHAR_CLASS_EXPRESSION,
                        start: index,
                        end: index + 1,
                        contents: Text( from_char( ch ) ) } ) } )
      }
      _ => None
    }
  }
}

fn Increment<B, T: Iterator<B> >( mut iter: T, steps: uint ) -> T {
  for i in range( 0, steps ) {
    iter.next();
  }
  iter
}

pub fn parseString( input: &str ) -> Node {
  Node { name: LITERAL_EXPRESSION,
         start: 0,
         end: 3,
         contents: Text( input.to_owned() ) }
}

#[cfg(test)]
mod parser_tests;
<|endoftext|>


<commit_before>extern crate time;

use std::fmt;
use time::precise_time_ns;
use std::io::fs::File;
use std::mem;
use std::rt;
use std::sync::Arc;
use std::sync::Mutex;
use std::collections::HashMap;

#[derive(Clone)]
struct TimeDB {
    times: Arc<Mutex<HashMap<&'static str, InvocationTracking>>>,
}

fn time_db() -> TimeDB {
    use std::sync::{Once, ONCE_INIT};
    static mut TIMEDB : *const TimeDB = 0 as *const TimeDB;
    static mut ONCE: Once = ONCE_INIT;
    unsafe {
        ONCE.call_once(|| {
            let timedb = TimeDB {
                times: Arc::new(Mutex::new(HashMap::new())),
            };
            TIMEDB = mem::transmute(box timedb);

            // Make sure to free it at exit
            rt::at_exit(|| {
                mem::transmute::<_, Box<TimeDB>>(TIMEDB);
                TIMEDB = 0 as *const _;
            });
        });
        (*TIMEDB).clone()
    }
}

#[derive(Copy)]
struct InvocationTracking {
    count: u64,
    total_time: u64,
}

impl fmt::Show for InvocationTracking {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let avg_time = match self.count == 0 {
            true => 0.0f64,
            false => self.total_time as f64 / self.count as f64,
        };
        write!(f, "{} | {} ns/call", self.count, avg_time)
    }
}

impl InvocationTracking {
    fn new(t: &TimeIt) -> InvocationTracking {
        let mut i = InvocationTracking {
            count: 0,
            total_time: 0,
        };
        i.add_time(t);
        return i;
    }
    fn add_time(&mut self, t: &TimeIt) {
        let dur = precise_time_ns() - t.start_time;
        self.count += 1;
        self.total_time += dur;
    }
}

impl TimeDB {
    fn add_time(&mut self, time: &TimeIt) {
        let ref mut m = self.times.lock().unwrap();
        if !m.contains_key(time.name) {
            m.insert(time.name, InvocationTracking::new(time));
        } else {
            m.get_mut(time.name).unwrap().add_time(time);
        }
    }
}

impl fmt::Show for TimeDB {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ref m = self.times.lock().unwrap();
        for (name, res) in m.iter() {
            try!(writeln!(f, "{} => {}", name, res));
        }
        write!(f, "")
    }
}

pub struct TimeIt {
    start_time: u64,
    name: &'static str,
}

impl TimeIt {
    pub fn new(name: &'static str) -> TimeIt {
        TimeIt {
            start_time: precise_time_ns(),
            name: name,
        }
    }
}

impl Drop for TimeIt {
    fn drop(&mut self) {
        time_db().add_time(self);
    }
}

pub struct TimeFileSave {
    file_name: &'static str,
}

impl Drop for TimeFileSave {
    fn drop(&mut self) {
        match File::create(&Path::new(self.file_name)) {
            Err(_) => {}
            Ok(mut f) => {
                let m1 : TimeDB = time_db();
                let _ = write!(&mut f, "{}", m1);
            }
        };
    }
}

impl TimeFileSave {
    pub fn new(file_name: &'static str) -> TimeFileSave {
        TimeFileSave {
            file_name: file_name,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use TimeIt;
    use time_db;
    use TimeFileSave;

    #[test]
    fn test_times() {
        {
            time_3();
        }
        {
            TimeFileSave::new("test_result.txt");
        }
        let td = time_db();
        let m = td.times.lock().unwrap();
        assert_eq!(m.get("time_1").unwrap().count, 2);
        assert_eq!(m.get("time_3").unwrap().count, 1);
    }

    fn time_1() -> u64{
        let _ = TimeIt::new("time_1");
        let a = 3u64;
        return a * 3;
    }

    fn time_3() {
        TimeIt::new("time_3");
        time_1();
        time_1();
    }
}
<commit_msg>change usage<commit_after>extern crate time;

use std::fmt;
use time::precise_time_ns;
use std::io::fs::File;
use std::mem;
use std::rt;
use std::sync::Arc;
use std::sync::Mutex;
use std::collections::HashMap;

#[derive(Clone)]
struct TimeDB {
    times: Arc<Mutex<HashMap<&'static str, InvocationTracking>>>,
}

fn time_db() -> TimeDB {
    use std::sync::{Once, ONCE_INIT};
    static mut TIMEDB : *const TimeDB = 0 as *const TimeDB;
    static mut ONCE: Once = ONCE_INIT;
    unsafe {
        ONCE.call_once(|| {
            let timedb = TimeDB {
                times: Arc::new(Mutex::new(HashMap::new())),
            };
            TIMEDB = mem::transmute(box timedb);

            // Make sure to free it at exit
            rt::at_exit(|| {
                mem::transmute::<_, Box<TimeDB>>(TIMEDB);
                TIMEDB = 0 as *const _;
            });
        });
        (*TIMEDB).clone()
    }
}

#[derive(Copy)]
struct InvocationTracking {
    count: u64,
    total_time: u64,
}

impl fmt::Show for InvocationTracking {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let avg_time = match self.count == 0 {
            true => 0.0f64,
            false => self.total_time as f64 / self.count as f64,
        };
        write!(f, "{} | {} ns/call", self.count, avg_time)
    }
}

impl InvocationTracking {
    fn new(t: &TimeIt) -> InvocationTracking {
        let mut i = InvocationTracking {
            count: 0,
            total_time: 0,
        };
        i.add_time(t);
        return i;
    }
    fn add_time(&mut self, t: &TimeIt) {
        let dur = precise_time_ns() - t.start_time;
        self.count += 1;
        self.total_time += dur;
    }
}

impl TimeDB {
    fn add_time(&mut self, time: &TimeIt) {
        let ref mut m = self.times.lock().unwrap();
        if !m.contains_key(time.name) {
            m.insert(time.name, InvocationTracking::new(time));
        } else {
            m.get_mut(time.name).unwrap().add_time(time);
        }
    }
}

impl fmt::Show for TimeDB {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ref m = self.times.lock().unwrap();
        for (name, res) in m.iter() {
            try!(writeln!(f, "{} => {}", name, res));
        }
        write!(f, "")
    }
}

pub struct TimeIt {
    start_time: u64,
    name: &'static str,
}

impl TimeIt {
    pub fn new(name: &'static str) -> TimeIt {
        TimeIt {
            start_time: precise_time_ns(),
            name: name,
        }
    }
}

impl Drop for TimeIt {
    fn drop(&mut self) {
        time_db().add_time(self);
    }
}

pub struct TimeFileSave {
    file_name: &'static str,
}

impl Drop for TimeFileSave {
    fn drop(&mut self) {
        match File::create(&Path::new(self.file_name)) {
            Err(_) => {}
            Ok(mut f) => {
                let m1 : TimeDB = time_db();
                let _ = write!(&mut f, "{}", m1);
            }
        };
    }
}

impl TimeFileSave {
    pub fn new(file_name: &'static str) -> TimeFileSave {
        TimeFileSave {
            file_name: file_name,
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use TimeIt;
    use time_db;
    use TimeFileSave;

    #[test]
    fn test_times() {
        {
            time_3();
        }
        {
            TimeFileSave::new("test_result.txt");
        }
        let td = time_db();
        let m = td.times.lock().unwrap();
        assert_eq!(m.get("time_1").unwrap().count, 2);
        assert_eq!(m.get("time_3").unwrap().count, 1);
    }

    fn time_1() -> u64{
        TimeIt::new("time_1");
        let a = 3u64;
        return a * 3;
    }

    fn time_3() {
        TimeIt::new("time_3");
        time_1();
        time_1();
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate libc;
extern crate rust_resemble as resemble;

use libc::{c_double, size_t};
use image::load_from_memory;

#[no_mangle]
pub extern "C" fn compare_images(img1: *const u8,
                                 img1_length: size_t,
                                 img2: *const u8,
                                 img2_length: size_t)
                                 -> c_double {

    let v1;
    let v2;

    unsafe {
        v1 = std::slice::from_raw_parts(img1, img1_length);
        v2 = std::slice::from_raw_parts(img2, img2_length);
    }

    let img1 = load_from_memory(v1).unwrap();
    let img2 = load_from_memory(v2).unwrap();
    let opts = resemble::ComparisonOptions::new().ignore_antialiasing();

    let r = resemble::compare_images(&img1, &img2, &opts);
    r.mismatch_percent
}<commit_msg>attempt to fix an issue with nodejs 7.6<commit_after>extern crate image;
extern crate libc;
extern crate rust_resemble as resemble;

use libc::{c_double, size_t};
use image::load_from_memory;
use std::mem::forget;

#[no_mangle]
pub extern "C" fn compare_images(img1: *const u8,
                                 img1_length: size_t,
                                 img2: *const u8,
                                 img2_length: size_t)
                                 -> c_double {

    let v1;
    let v2;

    unsafe {
        v1 = std::slice::from_raw_parts(img1, img1_length);
        v2 = std::slice::from_raw_parts(img2, img2_length);
    }

    let img1 = load_from_memory(v1).unwrap();
    let img2 = load_from_memory(v2).unwrap();
    let opts = resemble::ComparisonOptions::new().ignore_antialiasing();

    let r = resemble::compare_images(&img1, &img2, &opts);

    forget(img1);   // do not free that memory
    forget(img2);   // do not free that memory

    r.mismatch_percent
}<|endoftext|>


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

#![crate_name = "string_cache"]
#![crate_type = "rlib"]

#![feature(plugin, old_orphan_check)]
#![no_std]
#![deny(warnings)]
#![allow(unstable)]

#[macro_use]
extern crate core;

extern crate alloc;
extern crate collections;

#[cfg(test)]
extern crate test;

extern crate std;

#[plugin]
extern crate phf_mac;
extern crate phf;

#[macro_use]
extern crate lazy_static;

extern crate xxhash;

#[plugin]
#[macro_use]
extern crate string_cache_macros;

#[cfg(feature = "log-events")]
extern crate serialize;

pub use atom::Atom;
pub use namespace::{Namespace, QualName};

#[cfg(feature = "log-events")]
pub mod event;

pub mod atom;
pub mod namespace;

// A private module so that macro-expanded idents like
// `::string_cache::atom::Atom` will also work in this crate.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod string_cache {
    pub use atom;
    pub use namespace;
}
<commit_msg>Don't link plugin crates<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "string_cache"]
#![crate_type = "rlib"]

#![feature(plugin, old_orphan_check)]
#![no_std]
#![deny(warnings)]
#![allow(unstable)]

#[macro_use]
extern crate core;

extern crate alloc;
extern crate collections;

#[cfg(test)]
extern crate test;

extern crate std;

#[plugin] #[no_link]
extern crate phf_mac;
extern crate phf;

#[macro_use]
extern crate lazy_static;

extern crate xxhash;

#[plugin] #[no_link] #[macro_use]
extern crate string_cache_macros;

#[cfg(feature = "log-events")]
extern crate serialize;

pub use atom::Atom;
pub use namespace::{Namespace, QualName};

#[cfg(feature = "log-events")]
pub mod event;

pub mod atom;
pub mod namespace;

// A private module so that macro-expanded idents like
// `::string_cache::atom::Atom` will also work in this crate.
//
// `libstd` uses the same trick.
#[doc(hidden)]
mod string_cache {
    pub use atom;
    pub use namespace;
}
<|endoftext|>