<commit_before>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

mod utils;

use clap::Clap;
use utils::*;

#[derive(Clap, PartialEq, Debug)]
enum Opt {
    /// Fetch stuff from GitHub
    Fetch {
        #[clap(long)]
        all: bool,
        #[clap(short, long)]
        /// Overwrite local branches.
        force: bool,
        repo: String,
    },

    Add {
        #[clap(short, long)]
        interactive: bool,
        #[clap(short, long)]
        verbose: bool,
    },
}

#[test]
fn test_fetch() {
    assert_eq!(
        Opt::Fetch {
            all: true,
            force: false,
            repo: "origin".to_string()
        },
        Opt::parse_from(&["test", "fetch", "--all", "origin"])
    );
    assert_eq!(
        Opt::Fetch {
            all: false,
            force: true,
            repo: "origin".to_string()
        },
        Opt::parse_from(&["test", "fetch", "-f", "origin"])
    );
}

#[test]
fn test_add() {
    assert_eq!(
        Opt::Add {
            interactive: false,
            verbose: false
        },
        Opt::parse_from(&["test", "add"])
    );
    assert_eq!(
        Opt::Add {
            interactive: true,
            verbose: true
        },
        Opt::parse_from(&["test", "add", "-i", "-v"])
    );
}

#[test]
fn test_no_parse() {
    let result = Opt::try_parse_from(&["test", "badcmd", "-i", "-v"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test", "add", "--badoption"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test"]);
    assert!(result.is_err());
}

#[derive(Clap, PartialEq, Debug)]
enum Opt2 {
    DoSomething { arg: String },
}

#[test]
/// This test is specifically to make sure that hyphenated subcommands get
/// processed correctly.
fn test_hyphenated_subcommands() {
    assert_eq!(
        Opt2::DoSomething {
            arg: "blah".to_string()
        },
        Opt2::parse_from(&["test", "do-something", "blah"])
    );
}

#[derive(Clap, PartialEq, Debug)]
enum Opt3 {
    Add,
    Init,
    Fetch,
}

#[test]
fn test_null_commands() {
    assert_eq!(Opt3::Add, Opt3::parse_from(&["test", "add"]));
    assert_eq!(Opt3::Init, Opt3::parse_from(&["test", "init"]));
    assert_eq!(Opt3::Fetch, Opt3::parse_from(&["test", "fetch"]));
}

#[derive(Clap, PartialEq, Debug)]
#[clap(about = "Not shown")]
struct Add {
    file: String,
}
/// Not shown
#[derive(Clap, PartialEq, Debug)]
struct Fetch {
    remote: String,
}
#[derive(Clap, PartialEq, Debug)]
enum Opt4 {
    // Not shown
    /// Add a file
    Add(Add),
    Init,
    /// download history from remote
    Fetch(Fetch),
}

#[test]
fn test_tuple_commands() {
    assert_eq!(
        Opt4::Add(Add {
            file: "f".to_string()
        }),
        Opt4::parse_from(&["test", "add", "f"])
    );
    assert_eq!(Opt4::Init, Opt4::parse_from(&["test", "init"]));
    assert_eq!(
        Opt4::Fetch(Fetch {
            remote: "origin".to_string()
        }),
        Opt4::parse_from(&["test", "fetch", "origin"])
    );

    let output = get_long_help::<Opt4>();

    assert!(output.contains("download history from remote"));
    assert!(output.contains("Add a file"));
    assert!(!output.contains("Not shown"));
}

#[test]
fn global_passed_down() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(global = true, long)]
        other: bool,
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        Add,
        Global(GlobalCmd),
    }

    #[derive(Debug, PartialEq, Clap)]
    struct GlobalCmd {
        #[clap(from_global)]
        other: bool,
    }

    assert_eq!(
        Opt::parse_from(&["test", "global"]),
        Opt {
            other: false,
            sub: Subcommands::Global(GlobalCmd { other: false })
        }
    );

    assert_eq!(
        Opt::parse_from(&["test", "global", "--other"]),
        Opt {
            other: true,
            sub: Subcommands::Global(GlobalCmd { other: true })
        }
    );
}

#[test]
fn external_subcommand() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        Add,
        Remove,
        #[clap(external_subcommand)]
        Other(Vec<String>),
    }

    assert_eq!(
        Opt::parse_from(&["test", "add"]),
        Opt {
            sub: Subcommands::Add
        }
    );

    assert_eq!(
        Opt::parse_from(&["test", "remove"]),
        Opt {
            sub: Subcommands::Remove
        }
    );

    assert!(Opt::try_parse_from(&["test"]).is_err());

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Subcommands::Other(vec!["git".into(), "status".into()])
        }
    );
}

#[test]
fn external_subcommand_os_string() {
    use std::ffi::OsString;

    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        #[clap(external_subcommand)]
        Other(Vec<OsString>),
    }

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Subcommands::Other(vec!["git".into(), "status".into()])
        }
    );

    assert!(Opt::try_parse_from(&["test"]).is_err());
}

#[test]
fn external_subcommand_optional() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Option<Subcommands>,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        #[clap(external_subcommand)]
        Other(Vec<String>),
    }

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Some(Subcommands::Other(vec!["git".into(), "status".into()]))
        }
    );

    assert_eq!(Opt::try_parse_from(&["test"]).unwrap(), Opt { sub: None });
}

#[test]
fn enum_in_enum_subsubcommand() {
    #[derive(Clap, Debug, PartialEq)]
    pub enum Opt {
        #[clap(subcommand)]
        Daemon(DaemonCommand),
    }

    #[derive(Clap, Debug, PartialEq)]
    pub enum DaemonCommand {
        Start,
        Stop,
    }

    let result = Opt::try_parse_from(&["test"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test", "daemon"]);
    assert!(result.is_err());

    let result = Opt::parse_from(&["test", "daemon", "start"]);
    assert_eq!(Opt::Daemon(DaemonCommand::Start), result);
}

#[test]
fn update_subcommands() {
    #[derive(Clap, PartialEq, Debug)]
    enum Opt {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command1 {
        arg1: i32,
        arg2: i32,
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command2 {
        arg2: i32,
    }

    // Full subcommand update
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command1", "42", "44"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "command1", "42", "44"]), opt);

    // Partial subcommand update
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command1", "42"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "command1", "42", "14"]), opt);

    // Change subcommand
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command2", "43"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "command2", "43"]), opt);
}

#[test]
fn update_sub_subcommands() {
    #[derive(Clap, PartialEq, Debug)]
    enum Opt {
        #[clap(subcommand)]
        Child1(Child1),
        #[clap(subcommand)]
        Child2(Child2),
    }

    #[derive(Clap, PartialEq, Debug)]
    enum Child1 {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    enum Child2 {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command1 {
        arg1: i32,
        arg2: i32,
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command2 {
        arg2: i32,
    }

    // Full subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command1", "42", "44"])
        .unwrap();
    assert_eq!(
        Opt::parse_from(&["test", "child1", "command1", "42", "44"]),
        opt
    );

    // Partial subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command1", "42"])
        .unwrap();
    assert_eq!(
        Opt::parse_from(&["test", "child1", "command1", "42", "14"]),
        opt
    );

    // Partial subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command2", "43"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "child1", "command2", "43"]), opt);

    // Change subcommand
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child2", "command2", "43"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "child2", "command2", "43"]), opt);
}
<commit_msg>test: Cover external subcommand updates<commit_after>// Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
// Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
// Andrew Hobden (@hoverbear) <andrew@hoverbear.org>
//
// 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.
//
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
// MIT/Apache 2.0 license.

mod utils;

use clap::Clap;
use utils::*;

#[derive(Clap, PartialEq, Debug)]
enum Opt {
    /// Fetch stuff from GitHub
    Fetch {
        #[clap(long)]
        all: bool,
        #[clap(short, long)]
        /// Overwrite local branches.
        force: bool,
        repo: String,
    },

    Add {
        #[clap(short, long)]
        interactive: bool,
        #[clap(short, long)]
        verbose: bool,
    },
}

#[test]
fn test_fetch() {
    assert_eq!(
        Opt::Fetch {
            all: true,
            force: false,
            repo: "origin".to_string()
        },
        Opt::parse_from(&["test", "fetch", "--all", "origin"])
    );
    assert_eq!(
        Opt::Fetch {
            all: false,
            force: true,
            repo: "origin".to_string()
        },
        Opt::parse_from(&["test", "fetch", "-f", "origin"])
    );
}

#[test]
fn test_add() {
    assert_eq!(
        Opt::Add {
            interactive: false,
            verbose: false
        },
        Opt::parse_from(&["test", "add"])
    );
    assert_eq!(
        Opt::Add {
            interactive: true,
            verbose: true
        },
        Opt::parse_from(&["test", "add", "-i", "-v"])
    );
}

#[test]
fn test_no_parse() {
    let result = Opt::try_parse_from(&["test", "badcmd", "-i", "-v"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test", "add", "--badoption"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test"]);
    assert!(result.is_err());
}

#[derive(Clap, PartialEq, Debug)]
enum Opt2 {
    DoSomething { arg: String },
}

#[test]
/// This test is specifically to make sure that hyphenated subcommands get
/// processed correctly.
fn test_hyphenated_subcommands() {
    assert_eq!(
        Opt2::DoSomething {
            arg: "blah".to_string()
        },
        Opt2::parse_from(&["test", "do-something", "blah"])
    );
}

#[derive(Clap, PartialEq, Debug)]
enum Opt3 {
    Add,
    Init,
    Fetch,
}

#[test]
fn test_null_commands() {
    assert_eq!(Opt3::Add, Opt3::parse_from(&["test", "add"]));
    assert_eq!(Opt3::Init, Opt3::parse_from(&["test", "init"]));
    assert_eq!(Opt3::Fetch, Opt3::parse_from(&["test", "fetch"]));
}

#[derive(Clap, PartialEq, Debug)]
#[clap(about = "Not shown")]
struct Add {
    file: String,
}
/// Not shown
#[derive(Clap, PartialEq, Debug)]
struct Fetch {
    remote: String,
}
#[derive(Clap, PartialEq, Debug)]
enum Opt4 {
    // Not shown
    /// Add a file
    Add(Add),
    Init,
    /// download history from remote
    Fetch(Fetch),
}

#[test]
fn test_tuple_commands() {
    assert_eq!(
        Opt4::Add(Add {
            file: "f".to_string()
        }),
        Opt4::parse_from(&["test", "add", "f"])
    );
    assert_eq!(Opt4::Init, Opt4::parse_from(&["test", "init"]));
    assert_eq!(
        Opt4::Fetch(Fetch {
            remote: "origin".to_string()
        }),
        Opt4::parse_from(&["test", "fetch", "origin"])
    );

    let output = get_long_help::<Opt4>();

    assert!(output.contains("download history from remote"));
    assert!(output.contains("Add a file"));
    assert!(!output.contains("Not shown"));
}

#[test]
fn global_passed_down() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(global = true, long)]
        other: bool,
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        Add,
        Global(GlobalCmd),
    }

    #[derive(Debug, PartialEq, Clap)]
    struct GlobalCmd {
        #[clap(from_global)]
        other: bool,
    }

    assert_eq!(
        Opt::parse_from(&["test", "global"]),
        Opt {
            other: false,
            sub: Subcommands::Global(GlobalCmd { other: false })
        }
    );

    assert_eq!(
        Opt::parse_from(&["test", "global", "--other"]),
        Opt {
            other: true,
            sub: Subcommands::Global(GlobalCmd { other: true })
        }
    );
}

#[test]
fn external_subcommand() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        Add,
        Remove,
        #[clap(external_subcommand)]
        Other(Vec<String>),
    }

    assert_eq!(
        Opt::parse_from(&["test", "add"]),
        Opt {
            sub: Subcommands::Add
        }
    );

    assert_eq!(
        Opt::parse_from(&["test", "remove"]),
        Opt {
            sub: Subcommands::Remove
        }
    );

    assert!(Opt::try_parse_from(&["test"]).is_err());

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Subcommands::Other(vec!["git".into(), "status".into()])
        }
    );
}

#[test]
fn external_subcommand_os_string() {
    use std::ffi::OsString;

    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Subcommands,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        #[clap(external_subcommand)]
        Other(Vec<OsString>),
    }

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Subcommands::Other(vec!["git".into(), "status".into()])
        }
    );

    assert!(Opt::try_parse_from(&["test"]).is_err());
}

#[test]
fn external_subcommand_optional() {
    #[derive(Debug, PartialEq, Clap)]
    struct Opt {
        #[clap(subcommand)]
        sub: Option<Subcommands>,
    }

    #[derive(Debug, PartialEq, Clap)]
    enum Subcommands {
        #[clap(external_subcommand)]
        Other(Vec<String>),
    }

    assert_eq!(
        Opt::try_parse_from(&["test", "git", "status"]).unwrap(),
        Opt {
            sub: Some(Subcommands::Other(vec!["git".into(), "status".into()]))
        }
    );

    assert_eq!(Opt::try_parse_from(&["test"]).unwrap(), Opt { sub: None });
}

#[test]
fn enum_in_enum_subsubcommand() {
    #[derive(Clap, Debug, PartialEq)]
    pub enum Opt {
        #[clap(subcommand)]
        Daemon(DaemonCommand),
    }

    #[derive(Clap, Debug, PartialEq)]
    pub enum DaemonCommand {
        Start,
        Stop,
    }

    let result = Opt::try_parse_from(&["test"]);
    assert!(result.is_err());

    let result = Opt::try_parse_from(&["test", "daemon"]);
    assert!(result.is_err());

    let result = Opt::parse_from(&["test", "daemon", "start"]);
    assert_eq!(Opt::Daemon(DaemonCommand::Start), result);
}

#[test]
fn update_subcommands() {
    #[derive(Clap, PartialEq, Debug)]
    enum Opt {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command1 {
        arg1: i32,
        arg2: i32,
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command2 {
        arg2: i32,
    }

    // Full subcommand update
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command1", "42", "44"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "command1", "42", "44"]), opt);

    // Partial subcommand update
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command1", "42"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "command1", "42", "14"]), opt);

    // Change subcommand
    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "command2", "43"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "command2", "43"]), opt);
}

#[test]
fn update_sub_subcommands() {
    #[derive(Clap, PartialEq, Debug)]
    enum Opt {
        #[clap(subcommand)]
        Child1(Child1),
        #[clap(subcommand)]
        Child2(Child2),
    }

    #[derive(Clap, PartialEq, Debug)]
    enum Child1 {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    enum Child2 {
        Command1(Command1),
        Command2(Command2),
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command1 {
        arg1: i32,
        arg2: i32,
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command2 {
        arg2: i32,
    }

    // Full subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command1", "42", "44"])
        .unwrap();
    assert_eq!(
        Opt::parse_from(&["test", "child1", "command1", "42", "44"]),
        opt
    );

    // Partial subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command1", "42"])
        .unwrap();
    assert_eq!(
        Opt::parse_from(&["test", "child1", "command1", "42", "14"]),
        opt
    );

    // Partial subcommand update
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child1", "command2", "43"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "child1", "command2", "43"]), opt);

    // Change subcommand
    let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 }));
    opt.try_update_from(&["test", "child2", "command2", "43"])
        .unwrap();
    assert_eq!(Opt::parse_from(&["test", "child2", "command2", "43"]), opt);
}

#[test]
fn update_ext_subcommand() {
    #[derive(Clap, PartialEq, Debug)]
    enum Opt {
        Command1(Command1),
        Command2(Command2),
        #[clap(external_subcommand)]
        Ext(Vec<String>),
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command1 {
        arg1: i32,
        arg2: i32,
    }

    #[derive(Clap, PartialEq, Debug)]
    struct Command2 {
        arg2: i32,
    }

    // Full subcommand update
    let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
    opt.try_update_from(&["test", "ext", "42", "44"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "ext", "42", "44"]), opt);

    // No partial subcommand update
    let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
    opt.try_update_from(&["test", "ext", "42"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "ext", "42"]), opt);

    // Change subcommand
    let mut opt = Opt::Ext(vec!["12".into(), "14".into()]);
    opt.try_update_from(&["test", "command2", "43"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "command2", "43"]), opt);

    let mut opt = Opt::Command1(Command1 { arg1: 12, arg2: 14 });
    opt.try_update_from(&["test", "ext", "42", "44"]).unwrap();
    assert_eq!(Opt::parse_from(&["test", "ext", "42", "44"]), opt);
}
<|endoftext|>


<commit_before>// Build mcuboot as a library, based on the requested features.

extern crate cc;

use std::env;
use std::fs;
use std::io;
use std::path::Path;

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_rsa3072 = env::var("CARGO_FEATURE_SIG_RSA3072").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
    let validate_primary_slot =
                  env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
    let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
    let enc_x25519 = env::var("CARGO_FEATURE_ENC_X25519").is_ok();
    let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
    let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
    let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_HAVE_LOGGING", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
    conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));

    if downgrade_prevention && !overwrite_only {
        panic!("Downgrade prevention requires overwrite only");
    }

    if bootstrap {
        conf.define("MCUBOOT_BOOTSTRAP", None);
    }

    if validate_primary_slot {
        conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
    }

    if downgrade_prevention {
        conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
    }

    // Currently no more than one sig type can be used simultaneously.
    if vec![sig_rsa, sig_rsa3072, sig_ecdsa, sig_ed25519].iter()
        .fold(0, |sum, &v| sum + v as i32) > 1 {
        panic!("mcuboot does not support more than one sig type at the same time");
    }

    if sig_rsa || sig_rsa3072 {
        conf.define("MCUBOOT_SIGN_RSA", None);
        // The Kconfig style defines must be added here as well because
        // they are used internally by "config-rsa.h"
        if sig_rsa {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
        } else {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
        }
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        if !enc_kw {
            conf.include("../../ext/mbedtls-asn1/include");
        }
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if sig_ed25519 {
        conf.define("MCUBOOT_SIGN_ED25519", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");
        conf.include("../../ext/mbedtls-asn1/include");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("csupport/keys.c");
        conf.file("../../ext/fiat/src/curve25519.c");
        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if !enc_ec256 && !enc_x25519 {
        // No signature type, only sha256 validation. The default
        // configuration file bundled with mbedTLS is sufficient.
        // When using ECIES-P256 rely on Tinycrypt.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if swap_move {
        conf.define("MCUBOOT_SWAP_USING_MOVE", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");

        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa_internal.c");
        conf.file("../../ext/mbedtls/crypto/library/md.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        if sig_rsa || sig_rsa3072 {
            conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        }

        /* Simulator uses Mbed-TLS to wrap keys */
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/nist_kw.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher_wrap.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");

        if sig_ecdsa {
            conf.define("MCUBOOT_USE_TINYCRYPT", None);

            conf.include("../../ext/tinycrypt/lib/include");

            conf.file("../../ext/tinycrypt/lib/source/utils.c");
            conf.file("../../ext/tinycrypt/lib/source/sha256.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        }

        if sig_ed25519 {
            panic!("ed25519 does not support image encryption with KW yet");
        }
    }

    if enc_ec256 {
        conf.define("MCUBOOT_ENCRYPT_EC256", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");

        /* FIXME: fail with other signature schemes ? */

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
    }

    if enc_x25519 {
        conf.define("MCUBOOT_ENCRYPT_X25519", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");

        conf.file("../../ext/fiat/src/curve25519.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
    }

    if sig_rsa && enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
    } else if sig_rsa || sig_rsa3072 || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if (sig_ecdsa || enc_ec256) && !enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if sig_ed25519 || enc_x25519 {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa || sig_rsa3072 {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    } else if sig_ed25519 {
        conf.file("../../boot/bootutil/src/image_ed25519.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/swap_misc.c");
    conf.file("../../boot/bootutil/src/swap_scratch.c");
    conf.file("../../boot/bootutil/src/swap_move.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("../../boot/bootutil/src/tlv.c");
    conf.file("../../boot/bootutil/src/fault_injection_hardening.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls-asn1").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("../../ext/mbedtls/crypto/include").unwrap();
    walk_dir("../../ext/mbedtls/crypto/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<commit_msg>sim: change MCUBOOT_OVERWRITE_ONLY_FAST usage<commit_after>// Build mcuboot as a library, based on the requested features.

extern crate cc;

use std::env;
use std::fs;
use std::io;
use std::path::Path;

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_rsa3072 = env::var("CARGO_FEATURE_SIG_RSA3072").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let sig_ed25519 = env::var("CARGO_FEATURE_SIG_ED25519").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let swap_move = env::var("CARGO_FEATURE_SWAP_MOVE").is_ok();
    let validate_primary_slot =
                  env::var("CARGO_FEATURE_VALIDATE_PRIMARY_SLOT").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();
    let enc_ec256 = env::var("CARGO_FEATURE_ENC_EC256").is_ok();
    let enc_x25519 = env::var("CARGO_FEATURE_ENC_X25519").is_ok();
    let bootstrap = env::var("CARGO_FEATURE_BOOTSTRAP").is_ok();
    let multiimage = env::var("CARGO_FEATURE_MULTIIMAGE").is_ok();
    let downgrade_prevention = env::var("CARGO_FEATURE_DOWNGRADE_PREVENTION").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_HAVE_LOGGING", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));
    conf.define("MCUBOOT_IMAGE_NUMBER", Some(if multiimage { "2" } else { "1" }));

    if downgrade_prevention && !overwrite_only {
        panic!("Downgrade prevention requires overwrite only");
    }

    if bootstrap {
        conf.define("MCUBOOT_BOOTSTRAP", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if validate_primary_slot {
        conf.define("MCUBOOT_VALIDATE_PRIMARY_SLOT", None);
    }

    if downgrade_prevention {
        conf.define("MCUBOOT_DOWNGRADE_PREVENTION", None);
    }

    // Currently no more than one sig type can be used simultaneously.
    if vec![sig_rsa, sig_rsa3072, sig_ecdsa, sig_ed25519].iter()
        .fold(0, |sum, &v| sum + v as i32) > 1 {
        panic!("mcuboot does not support more than one sig type at the same time");
    }

    if sig_rsa || sig_rsa3072 {
        conf.define("MCUBOOT_SIGN_RSA", None);
        // The Kconfig style defines must be added here as well because
        // they are used internally by "config-rsa.h"
        if sig_rsa {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "2048");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "2048");
        } else {
            conf.define("MCUBOOT_SIGN_RSA_LEN", "3072");
            conf.define("CONFIG_BOOT_SIGNATURE_TYPE_RSA_LEN", "3072");
        }
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        if !enc_kw {
            conf.include("../../ext/mbedtls-asn1/include");
        }
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if sig_ed25519 {
        conf.define("MCUBOOT_SIGN_ED25519", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");
        conf.include("../../ext/mbedtls-asn1/include");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt-sha512/lib/source/sha512.c");
        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("csupport/keys.c");
        conf.file("../../ext/fiat/src/curve25519.c");
        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");
    } else if !enc_ec256 && !enc_x25519 {
        // No signature type, only sha256 validation. The default
        // configuration file bundled with mbedTLS is sufficient.
        // When using ECIES-P256 rely on Tinycrypt.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
    }

    if swap_move {
        conf.define("MCUBOOT_SWAP_USING_MOVE", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/sha256.c");

        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa.c");
        conf.file("../../ext/mbedtls/crypto/library/rsa_internal.c");
        conf.file("../../ext/mbedtls/crypto/library/md.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");
        conf.file("../../ext/mbedtls/crypto/library/bignum.c");
        conf.file("../../ext/mbedtls/crypto/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        if sig_rsa || sig_rsa3072 {
            conf.file("../../ext/mbedtls/crypto/library/sha256.c");
        }

        /* Simulator uses Mbed-TLS to wrap keys */
        conf.include("../../ext/mbedtls/crypto/include");
        conf.file("../../ext/mbedtls/crypto/library/platform.c");
        conf.file("../../ext/mbedtls/crypto/library/platform_util.c");
        conf.file("../../ext/mbedtls/crypto/library/nist_kw.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher.c");
        conf.file("../../ext/mbedtls/crypto/library/cipher_wrap.c");
        conf.file("../../ext/mbedtls/crypto/library/aes.c");

        if sig_ecdsa {
            conf.define("MCUBOOT_USE_TINYCRYPT", None);

            conf.include("../../ext/tinycrypt/lib/include");

            conf.file("../../ext/tinycrypt/lib/source/utils.c");
            conf.file("../../ext/tinycrypt/lib/source/sha256.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
            conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        }

        if sig_ed25519 {
            panic!("ed25519 does not support image encryption with KW yet");
        }
    }

    if enc_ec256 {
        conf.define("MCUBOOT_ENCRYPT_EC256", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");

        /* FIXME: fail with other signature schemes ? */

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dh.c");
    }

    if enc_x25519 {
        conf.define("MCUBOOT_ENCRYPT_X25519", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);
        conf.define("MCUBOOT_SWAP_SAVE_ENCTLV", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("../../ext/mbedtls-asn1/include");
        conf.include("../../ext/tinycrypt/lib/include");
        conf.include("../../ext/tinycrypt-sha512/lib/include");

        conf.file("../../ext/fiat/src/curve25519.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");

        conf.file("../../ext/mbedtls-asn1/src/platform_util.c");
        conf.file("../../ext/mbedtls-asn1/src/asn1parse.c");

        conf.file("../../ext/tinycrypt/lib/source/aes_encrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/aes_decrypt.c");
        conf.file("../../ext/tinycrypt/lib/source/ctr_mode.c");
        conf.file("../../ext/tinycrypt/lib/source/hmac.c");
    }

    if sig_rsa && enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa-kw.h>"));
    } else if sig_rsa || sig_rsa3072 || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if (sig_ecdsa || enc_ec256) && !enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if sig_ed25519 || enc_x25519 {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa || sig_rsa3072 {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    } else if sig_ed25519 {
        conf.file("../../boot/bootutil/src/image_ed25519.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/swap_misc.c");
    conf.file("../../boot/bootutil/src/swap_scratch.c");
    conf.file("../../boot/bootutil/src/swap_move.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("../../boot/bootutil/src/tlv.c");
    conf.file("../../boot/bootutil/src/fault_injection_hardening.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls-asn1").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("../../ext/mbedtls/crypto/include").unwrap();
    walk_dir("../../ext/mbedtls/crypto/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr;
use std::rc::Rc;

use gl;
use gltf;
use gltf::mesh::{ Indices, TexCoords, Colors };
use gltf::json::mesh::Mode;

use render::math::*;
use render::{Material, Scene};
use shader::Shader;

#[repr(C)]
#[derive(Debug)]
pub struct Vertex {
    pub position: Vector3,
    pub normal: Vector3,
    pub tangent: Vector4,
    pub tex_coord_0: Vector2,
    pub tex_coord_1: Vector2,
    pub color_0: Vector3, // TODO: vec4 support
    // TODO: joints, weights
    // pub joints_0: Vector4,
    // pub weights_0: Vector4,
}

impl Default for Vertex {
    fn default() -> Self {
        Vertex {
            position: Vector3::zero(),
            normal: Vector3::zero(),
            tangent: Vector4::zero(),
            tex_coord_0: Vector2::zero(),
            tex_coord_1: Vector2::zero(),
            color_0: Vector3::zero(),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Texture {
    pub id: u32,
    pub type_: String,
    pub path: String,
}

pub struct Primitive {
    vao: u32,
    vbo: u32,

    ebo: u32,
    num_indices: u32,

    material: Rc<Material>,
    // TODO!: mode, targets
}

impl Primitive {
    pub fn new(vertices: Vec<Vertex>, indices: Vec<u32>, material: Rc<Material>) -> Primitive {
        let mut prim = Primitive {
            num_indices: indices.len() as u32,
            vao: 0, vbo: 0, ebo: 0,
            material,
        };

        // now that we have all the required data, set the vertex buffers and its attribute pointers.
        unsafe { prim.setup_primitive(vertices, indices) }
        prim
    }

    pub fn from_gltf(
        g_primitive: gltf::mesh::Primitive,
        primitive_index: usize,
        mesh_index: usize,
        scene: &mut Scene) -> Primitive
    {
        // positions
        let positions = g_primitive.positions()
            .expect(&format!("primitives must have the POSITION attribute (mesh: {}, primitive: {})",
                mesh_index, primitive_index));
        let mut vertices: Vec<Vertex> = positions
            .map(|position| {
                Vertex {
                    position: Vector3::from(position),
                    ..Vertex::default()
                }
            }).collect();

        // normals
        if let Some(normals) = g_primitive.normals() {
            for (i, normal) in normals.enumerate() {
                vertices[i].normal = Vector3::from(normal);
            }
        }
        else {
            println!("WARNING: found no NORMALs for primitive {} of mesh {} \
                      (flat normal calculation not implemented yet)", primitive_index, mesh_index);
        }

        // tangents
        if let Some(tangents) = g_primitive.tangents() {
            for (i, tangent) in tangents.enumerate() {
                vertices[i].tangent = Vector4::from(tangent);
            }
        }

        // texture coordinates
        let mut tex_coord_set = 0;
        while let Some(tex_coords) = g_primitive.tex_coords(tex_coord_set) {
            if tex_coord_set > 1 {
                println!("WARNING: Ignoring texture coordinate set {}, \
                          only supporting 2 sets at the moment. (mesh: {}, primitive: {})",
                          tex_coord_set, mesh_index, primitive_index);
                tex_coord_set += 1;
                continue;
            }
            let tex_coords = match tex_coords {
                TexCoords::F32(tc) => tc,
                // TODO! TexCoords::U8/U16
                TexCoords::U8(_) => unimplemented!(),
                TexCoords::U16(_) => unimplemented!(),
            };
            for (i, tex_coord) in tex_coords.enumerate() {
                match tex_coord_set {
                    0 => vertices[i].tex_coord_0 = Vector2::from(tex_coord),
                    1 => vertices[i].tex_coord_1 = Vector2::from(tex_coord),
                    _ => unreachable!()
                }
            }
            tex_coord_set += 1;
        }

        // colors
        let mut color_set = 0;
        while let Some(colors) = g_primitive.colors(color_set) {
            if color_set > 0 {
                println!("WARNING: Ignoring color set {}, \
                          only supporting 1 set at the moment. (mesh: {}, primitive: {})",
                          color_set, mesh_index, primitive_index);
                color_set += 1;
                continue;
            }
            let colors = match colors {
                // TODO!: support other color formats
                // Colors::RgbU8(Iter<'a, [u8; 3]>),
                // Colors::RgbaU8(Iter<'a, [u8; 4]>),
                // Colors::RgbU16(Iter<'a, [u16; 3]>),
                // Colors::RgbaU16(Iter<'a, [u16; 4]>),
                Colors::RgbF32(c) => c,
                // Colors::RgbaF32(c),
                _ => unimplemented!()
            };
            for (i, color) in colors.enumerate() {
                vertices[i].color_0 = Vector3::from(color);
            }
            color_set += 1;
        }

        let indices = g_primitive.indices()
            .expect("not yet implemented: Indices required at the moment!");

        // convert indices to u32 if necessary
        // TODO?: use indices as they are?
        let indices: Vec<u32> = match indices {
            Indices::U8(indices) => indices.map(|i| i as u32).collect(),
            Indices::U16(indices) => indices.map(|i| i as u32).collect(),
            Indices::U32(indices) => indices.collect(),
        };

        assert_eq!(g_primitive.mode(), Mode::Triangles, "not yet implemented: primitive mode must be Triangles.");

        // TODO!!: unwraps for Triangle, SimpleMeshes, Cameras, AnimatedTriangle
        let g_material = g_primitive.material()
            .unwrap(); // NOTE: tmp - see https://github.com/alteous/gltf/issues/57

        let mut material = None;
        if let Some(mat) = scene.materials.iter().find(|m| (***m).index == g_material.index()) {
            material = mat.clone().into()
        }

        if material.is_none() { // no else due to borrow checker madness
            let mat = Rc::new(Material::from_gltf(&g_material, scene));
            scene.materials.push(mat.clone());
            material = mat.into();
        };

        Primitive::new(vertices, indices, material.unwrap())
    }

    /// render the mesh
    pub unsafe fn draw(&self, shader: &mut Shader) {
        // TODO: fully cache uniform locations
        let loc = shader.uniform_location("base_color_factor");
        shader.set_vector4(loc, &self.material.base_color_factor);
        if let Some(ref base_color_texture) = self.material.base_color_texture {
            let loc = shader.uniform_location("base_color_texture");
            shader.set_int(loc, 0);
            gl::ActiveTexture(gl::TEXTURE0);
            gl::BindTexture(gl::TEXTURE_2D, base_color_texture.id);
        }

        // draw mesh
        gl::BindVertexArray(self.vao);
        gl::DrawElements(gl::TRIANGLES, self.num_indices as i32, gl::UNSIGNED_INT, ptr::null());
        gl::BindVertexArray(0);

        // always good practice to set everything back to defaults once configured.
        gl::ActiveTexture(gl::TEXTURE0);
    }

    unsafe fn setup_primitive(&mut self, vertices: Vec<Vertex>, indices: Vec<u32>) {
        // create buffers/arrays
        gl::GenVertexArrays(1, &mut self.vao);
        gl::GenBuffers(1, &mut self.vbo);
        gl::GenBuffers(1, &mut self.ebo);

        gl::BindVertexArray(self.vao);
        // load data into vertex buffers
        gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
        // A great thing about structs with repr(C) is that their memory layout is sequential for all its items.
        // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
        // again translates to 3/2 floats which translates to a byte array.
        let size = (vertices.len() * size_of::<Vertex>()) as isize;
        let data = &vertices[0] as *const Vertex as *const c_void;
        gl::BufferData(gl::ARRAY_BUFFER, size, data, gl::STATIC_DRAW);

        gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, self.ebo);
        let size = (indices.len() * size_of::<u32>()) as isize;
        let data = &indices[0] as *const u32 as *const c_void;
        gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, size, data, gl::STATIC_DRAW);

        // set the vertex attribute pointers
        let size = size_of::<Vertex>() as i32;
        // POSITION
        gl::EnableVertexAttribArray(0);
        gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, position) as *const c_void);
        // NORMAL
        gl::EnableVertexAttribArray(1);
        gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, normal) as *const c_void);
        // TANGENT
        gl::EnableVertexAttribArray(2);
        gl::VertexAttribPointer(2, 4, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tangent) as *const c_void);
        // TEXCOORD_0
        gl::EnableVertexAttribArray(3);
        gl::VertexAttribPointer(3, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tex_coord_0) as *const c_void);
        // TEXCOORD_1
        gl::EnableVertexAttribArray(4);
        gl::VertexAttribPointer(4, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tex_coord_1) as *const c_void);
        // COLOR_0
        gl::EnableVertexAttribArray(5);
        gl::VertexAttribPointer(5, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, color_0) as *const c_void);

        gl::BindVertexArray(0);
    }
}
<commit_msg>add support for non-indexed meshes (drawArrays)<commit_after>use std::mem::size_of;
use std::os::raw::c_void;
use std::ptr;
use std::rc::Rc;

use gl;
use gltf;
use gltf::mesh::{ Indices, TexCoords, Colors };
use gltf::json::mesh::Mode;

use render::math::*;
use render::{Material, Scene};
use shader::Shader;

#[repr(C)]
#[derive(Debug)]
pub struct Vertex {
    pub position: Vector3,
    pub normal: Vector3,
    pub tangent: Vector4,
    pub tex_coord_0: Vector2,
    pub tex_coord_1: Vector2,
    pub color_0: Vector3, // TODO: vec4 support
    // TODO: joints, weights
    // pub joints_0: Vector4,
    // pub weights_0: Vector4,
}

impl Default for Vertex {
    fn default() -> Self {
        Vertex {
            position: Vector3::zero(),
            normal: Vector3::zero(),
            tangent: Vector4::zero(),
            tex_coord_0: Vector2::zero(),
            tex_coord_1: Vector2::zero(),
            color_0: Vector3::zero(),
        }
    }
}

#[derive(Clone, Debug)]
pub struct Texture {
    pub id: u32,
    pub type_: String,
    pub path: String,
}

pub struct Primitive {
    vao: u32,
    vbo: u32,
    num_vertices: u32,

    ebo: Option<u32>,
    num_indices: u32,

    material: Rc<Material>,
    // TODO!: mode, targets
}

impl Primitive {
    pub fn new(vertices: Vec<Vertex>, indices: Option<Vec<u32>>, material: Rc<Material>) -> Primitive {
        let num_indices = indices.as_ref().map(|i| i.len()).unwrap_or(0);
        let mut prim = Primitive {
            num_vertices: vertices.len() as u32,
            num_indices: num_indices as u32,
            vao: 0, vbo: 0, ebo: None,
            material,
        };

        // now that we have all the required data, set the vertex buffers and its attribute pointers.
        unsafe { prim.setup_primitive(vertices, indices) }
        prim
    }

    pub fn from_gltf(
        g_primitive: gltf::mesh::Primitive,
        primitive_index: usize,
        mesh_index: usize,
        scene: &mut Scene) -> Primitive
    {
        // positions
        let positions = g_primitive.positions()
            .expect(&format!("primitives must have the POSITION attribute (mesh: {}, primitive: {})",
                mesh_index, primitive_index));
        let mut vertices: Vec<Vertex> = positions
            .map(|position| {
                Vertex {
                    position: Vector3::from(position),
                    ..Vertex::default()
                }
            }).collect();

        // normals
        if let Some(normals) = g_primitive.normals() {
            for (i, normal) in normals.enumerate() {
                vertices[i].normal = Vector3::from(normal);
            }
        }
        else {
            println!("WARNING: found no NORMALs for primitive {} of mesh {} \
                      (flat normal calculation not implemented yet)", primitive_index, mesh_index);
        }

        // tangents
        if let Some(tangents) = g_primitive.tangents() {
            for (i, tangent) in tangents.enumerate() {
                vertices[i].tangent = Vector4::from(tangent);
            }
        }

        // texture coordinates
        let mut tex_coord_set = 0;
        while let Some(tex_coords) = g_primitive.tex_coords(tex_coord_set) {
            if tex_coord_set > 1 {
                println!("WARNING: Ignoring texture coordinate set {}, \
                          only supporting 2 sets at the moment. (mesh: {}, primitive: {})",
                          tex_coord_set, mesh_index, primitive_index);
                tex_coord_set += 1;
                continue;
            }
            let tex_coords = match tex_coords {
                TexCoords::F32(tc) => tc,
                // TODO! TexCoords::U8/U16
                TexCoords::U8(_) => unimplemented!(),
                TexCoords::U16(_) => unimplemented!(),
            };
            for (i, tex_coord) in tex_coords.enumerate() {
                match tex_coord_set {
                    0 => vertices[i].tex_coord_0 = Vector2::from(tex_coord),
                    1 => vertices[i].tex_coord_1 = Vector2::from(tex_coord),
                    _ => unreachable!()
                }
            }
            tex_coord_set += 1;
        }

        // colors
        let mut color_set = 0;
        while let Some(colors) = g_primitive.colors(color_set) {
            if color_set > 0 {
                println!("WARNING: Ignoring color set {}, \
                          only supporting 1 set at the moment. (mesh: {}, primitive: {})",
                          color_set, mesh_index, primitive_index);
                color_set += 1;
                continue;
            }
            let colors = match colors {
                // TODO!: support other color formats
                // Colors::RgbU8(Iter<'a, [u8; 3]>),
                // Colors::RgbaU8(Iter<'a, [u8; 4]>),
                // Colors::RgbU16(Iter<'a, [u16; 3]>),
                // Colors::RgbaU16(Iter<'a, [u16; 4]>),
                Colors::RgbF32(c) => c,
                // Colors::RgbaF32(c),
                _ => unimplemented!()
            };
            for (i, color) in colors.enumerate() {
                vertices[i].color_0 = Vector3::from(color);
            }
            color_set += 1;
        }

        let mut indices: Option<Vec<u32>> = None;
        if let Some(g_indices) = g_primitive.indices() {
            // convert indices to u32 if necessary
            indices = Some(match g_indices {
                Indices::U8(indices) => indices.map(|i| i as u32).collect(),
                Indices::U16(indices) => indices.map(|i| i as u32).collect(),
                Indices::U32(indices) => indices.collect(),
            });
        }

        assert_eq!(g_primitive.mode(), Mode::Triangles, "not yet implemented: primitive mode must be Triangles.");

        // TODO!!: unwraps for Triangle, SimpleMeshes, Cameras, AnimatedTriangle
        let g_material = g_primitive.material()
            .expect("not yet implemented: default material, need an explicit one");
            // NOTE: tmp - see https://github.com/alteous/gltf/issues/57

        let mut material = None;
        if let Some(mat) = scene.materials.iter().find(|m| (***m).index == g_material.index()) {
            material = mat.clone().into()
        }

        if material.is_none() { // no else due to borrow checker madness
            let mat = Rc::new(Material::from_gltf(&g_material, scene));
            scene.materials.push(mat.clone());
            material = mat.into();
        };

        Primitive::new(vertices, indices, material.unwrap())
    }

    /// render the mesh
    pub unsafe fn draw(&self, shader: &mut Shader) {
        // TODO: fully cache uniform locations
        let loc = shader.uniform_location("base_color_factor");
        shader.set_vector4(loc, &self.material.base_color_factor);
        if let Some(ref base_color_texture) = self.material.base_color_texture {
            let loc = shader.uniform_location("base_color_texture");
            shader.set_int(loc, 0);
            gl::ActiveTexture(gl::TEXTURE0);
            gl::BindTexture(gl::TEXTURE_2D, base_color_texture.id);
        }

        // draw mesh
        gl::BindVertexArray(self.vao);
        if self.ebo.is_some() {
            gl::DrawElements(gl::TRIANGLES, self.num_indices as i32, gl::UNSIGNED_INT, ptr::null());
        }
        else {
            gl::DrawArrays(gl::TRIANGLES, 0, self.num_vertices as i32)
        }
        gl::BindVertexArray(0);

        // always good practice to set everything back to defaults once configured.
        gl::ActiveTexture(gl::TEXTURE0);
    }

    unsafe fn setup_primitive(&mut self, vertices: Vec<Vertex>, indices: Option<Vec<u32>>) {
        // create buffers/arrays
        gl::GenVertexArrays(1, &mut self.vao);
        gl::GenBuffers(1, &mut self.vbo);
        if indices.is_some() {
            let mut ebo = 0;
            gl::GenBuffers(1, &mut ebo);
            self.ebo = Some(ebo);
        }

        gl::BindVertexArray(self.vao);
        // load data into vertex buffers
        gl::BindBuffer(gl::ARRAY_BUFFER, self.vbo);
        // A great thing about structs with repr(C) is that their memory layout is sequential for all its items.
        // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
        // again translates to 3/2 floats which translates to a byte array.
        let size = (vertices.len() * size_of::<Vertex>()) as isize;
        let data = &vertices[0] as *const Vertex as *const c_void;
        gl::BufferData(gl::ARRAY_BUFFER, size, data, gl::STATIC_DRAW);

        if let Some(ebo) = self.ebo {
            let indices = indices.unwrap();
            gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo);
            let size = (indices.len() * size_of::<u32>()) as isize;
            let data = &indices[0] as *const u32 as *const c_void;
            gl::BufferData(gl::ELEMENT_ARRAY_BUFFER, size, data, gl::STATIC_DRAW);
        }

        // set the vertex attribute pointers
        let size = size_of::<Vertex>() as i32;
        // POSITION
        gl::EnableVertexAttribArray(0);
        gl::VertexAttribPointer(0, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, position) as *const c_void);
        // NORMAL
        gl::EnableVertexAttribArray(1);
        gl::VertexAttribPointer(1, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, normal) as *const c_void);
        // TANGENT
        gl::EnableVertexAttribArray(2);
        gl::VertexAttribPointer(2, 4, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tangent) as *const c_void);
        // TEXCOORD_0
        gl::EnableVertexAttribArray(3);
        gl::VertexAttribPointer(3, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tex_coord_0) as *const c_void);
        // TEXCOORD_1
        gl::EnableVertexAttribArray(4);
        gl::VertexAttribPointer(4, 2, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, tex_coord_1) as *const c_void);
        // COLOR_0
        gl::EnableVertexAttribArray(5);
        gl::VertexAttribPointer(5, 3, gl::FLOAT, gl::FALSE, size, offset_of!(Vertex, color_0) as *const c_void);

        gl::BindVertexArray(0);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate sysinfo;
extern crate test;

use sysinfo::SystemExt;

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    let pid = *s.get_process_list().iter().take(1).next().unwrap().0;
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disk_lists(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disk_list();
    });
}

#[bench]
fn bench_refresh_network(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_network();
    });
}
<commit_msg>Add more benchmarks<commit_after>#![feature(test)]

extern crate sysinfo;
extern crate test;

use sysinfo::SystemExt;

#[bench]
fn bench_new(b: &mut test::Bencher) {
    b.iter(|| {
        sysinfo::System::new();
    });
}

#[bench]
fn bench_refresh_all(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_all();
    });
}

#[bench]
fn bench_refresh_system(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_system();
    b.iter(move || {
        s.refresh_system();
    });
}

#[bench]
fn bench_refresh_processes(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_processes();
    });
}

#[bench]
fn bench_refresh_process(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    s.refresh_all();
    let pid = *s.get_process_list().iter().take(1).next().unwrap().0;
    b.iter(move || {
        s.refresh_process(pid);
    });
}

#[bench]
fn bench_refresh_disks(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disks();
    });
}

#[bench]
fn bench_refresh_disk_lists(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_disk_list();
    });
}

#[bench]
fn bench_refresh_network(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_network();
    });
}

#[bench]
fn bench_refresh_memory(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_memory();
    });
}

#[bench]
fn bench_refresh_cpu(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_cpu();
    });
}

#[bench]
fn bench_refresh_temperatures(b: &mut test::Bencher) {
    let mut s = sysinfo::System::new();

    b.iter(move || {
        s.refresh_temperatures();
    });
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate rustc_serialize;

// use csv;
use std::collections::HashMap;

// fn adjusted_cosine(vec_feat_1: Vec<f32>, vec_feat_2: Vec<f32>) -> f32 {
//     if vec_feat_1.len() != vec_feat_2.len() {
//         panic!("Should compare vectors of same size");
//     }

//     let n_users = vec_feat_1.len();

//     let mut usr_pref = 0.0;
//     let mut feat_1_sqr = 0.0;
//     let mut feat_2_sqr = 0.0;

//     for i in 0..n_users {
//         if vec_feat_1[i] > 0.0 && vec_feat_2[i] > 0.0 {
//             let name = db["names"].as_array().unwrap()[i as usize]
//                 .as_str()
//                 .unwrap();
//             let avg = db["scores"][name].as_array().unwrap()[0]
//                 .as_f64()
//                 .unwrap() as f32;
//             let feat_1_inf = vec_feat_1[i] - avg;
//             let feat_2_inf = vec_feat_2[i] - avg;
//             usr_pref += feat_1_inf * feat_2_inf;
//             feat_1_sqr += feat_1_inf.powf(2.0);
//             feat_2_sqr += feat_2_inf.powf(2.0);
//         }
//     }

//     usr_pref / (feat_1_sqr.sqrt() * feat_2_sqr.sqrt())
// }

fn get_feature_vector(records: &(HashMap<String, u32>, HashMap<String, u32>, Vec<f32>),
                      feat: &str)
                      -> Vec<f32> {
    let mut vec = Vec::new();
    let indx = records.0.get(feat).unwrap();
    let i = records.0.len();
    let j = records.1.len();

    for y in 0..j {
        vec.push(records.2[(y * i + *indx as usize) as usize]);
    }

    vec
}

fn load_database(path: &str) -> (HashMap<String, u32>, HashMap<String, u32>, Vec<f32>) {
    let mut rdr = csv::Reader::from_file(path).unwrap().has_headers(true);
    let mut headers: HashMap<String, u32> = HashMap::new();
    let mut names: HashMap<String, u32> = HashMap::new();
    let mut records: Vec<f32> = Vec::new();

    let mut i = 0;
    let mut j = 0;

    loop {
        match rdr.next_bytes() {
            csv::NextField::Data(data) => {
                let d_string = String::from_utf8(data.to_vec()).unwrap();
                match j {
                    0 => {
                        /***********HEADERS***********/
                        if i > 0 {
                            headers.insert(d_string, i - 1);
                        }
                    }
                    _ => {
                        /***********RECORDS***********/
                        match i {
                            0 => {
                                /***********NAMES***********/
                                names.insert(d_string, j - 1);
                            }
                            _ => {
                                /***********VALUES***********/
                                records.push(d_string.parse::<f32>().unwrap());
                            }
                        }
                    }
                }
                i += 1;
            }
            csv::NextField::EndOfRecord => {
                j += 1;
                i = 0;
            }
            csv::NextField::EndOfCsv => break,
            csv::NextField::Error(err) => panic!(err),
        }
    }

    // for y in 0..5 {
    //     for x in 0..j {
    //         print!("{}, ", records[(y * j + x) as usize]);
    //     }
    //     println!("");
    // }
    (headers, names, records)
}

fn item_similarity(feat_1: &str, feat_2: &str) -> f32 {
    let records = load_database("./data/db1.csv");

    let v_feat_1 = get_feature_vector(&records, feat_1);
    let v_feat_2 = get_feature_vector(&records, feat_2);

    println!("{:?}", v_feat_1);
    println!("{:?}", v_feat_2);

    3.1416
}

fn main() {
    println!("Sim: {}", item_similarity("Kacey Musgraves", "Daft Punk"));
    println!("Hello, world!");
}
<commit_msg>Minor changes<commit_after>extern crate csv;
extern crate rustc_serialize;

use std::collections::HashMap;

fn adjusted_cosine(vec_feat_1: Vec<f32>, vec_feat_2: Vec<f32>, vec_avg: Vec<f32>) -> f32 {
    if vec_feat_1.len() != vec_feat_2.len() {
        panic!("Should compare vectors of same size");
    }

    let n_users = vec_feat_1.len();

    let mut usr_pref = 0.0;
    let mut feat_1_sqr = 0.0;
    let mut feat_2_sqr = 0.0;

    for i in 0..n_users {
        if vec_feat_1[i] > 0.0 && vec_feat_2[i] > 0.0 {
            let feat_1_inf = vec_feat_1[i] - vec_avg[i];
            let feat_2_inf = vec_feat_2[i] - vec_avg[i];
            usr_pref += feat_1_inf * feat_2_inf;
            feat_1_sqr += feat_1_inf.powf(2.0);
            feat_2_sqr += feat_2_inf.powf(2.0);
        }
    }

    usr_pref / (feat_1_sqr.sqrt() * feat_2_sqr.sqrt())
}

fn get_user_vector(records: &(HashMap<String, u32>, HashMap<String, u32>, Vec<f32>),
                   name: &str)
                   -> Vec<f32> {
    let mut vec = Vec::new();
    let indx = records.1.get(name).unwrap();
    let i = records.0.len();

    for x in 0..i {
        vec.push(records.2[(*indx as usize * i + x) as usize]);
    }

    vec
}

fn get_feature_vector(records: &(HashMap<String, u32>, HashMap<String, u32>, Vec<f32>),
                      feat: &str)
                      -> Vec<f32> {
    let mut vec = Vec::new();
    let indx = records.0.get(feat).unwrap();
    let i = records.0.len();
    let j = records.1.len();

    for y in 0..j {
        vec.push(records.2[(y * i + *indx as usize) as usize]);
    }

    vec
}

fn normalize(vect: Vec<f32>) -> Vec<f32> {
    let mut normd_vec = Vec::with_capacity(vect.len());

    let mut max = vect[0];
    let mut min = vect[0];

    for rating in vect.iter() {
        if *rating > max {
            max = *rating;
        }
        if *rating != 0.0 && *rating < min {
            min = *rating;
        }
    }

    for rating in vect.iter() {
        let norm = (2.0 * (rating - min) - (max - min)) / (max - min);
        normd_vec.push(norm);
    }

    normd_vec
}

fn load_database(path: &str) -> (HashMap<String, u32>, HashMap<String, u32>, Vec<f32>) {
    let mut rdr = csv::Reader::from_file(path).unwrap().has_headers(true);
    let mut headers: HashMap<String, u32> = HashMap::new();
    let mut names: HashMap<String, u32> = HashMap::new();
    let mut records: Vec<f32> = Vec::new();

    let mut i = 0;
    let mut j = 0;

    loop {
        match rdr.next_bytes() {
            csv::NextField::Data(data) => {
                let d_string = String::from_utf8(data.to_vec()).unwrap();
                match j {
                    0 => {
                        /***********HEADERS***********/
                        if i > 0 {
                            headers.insert(d_string, i - 1);
                        }
                    }
                    _ => {
                        /***********RECORDS***********/
                        match i {
                            0 => {
                                /***********NAMES***********/
                                names.insert(d_string, j - 1);
                            }
                            _ => {
                                /***********VALUES***********/
                                records.push(d_string.parse::<f32>().unwrap());
                            }
                        }
                    }
                }
                i += 1;
            }
            csv::NextField::EndOfRecord => {
                j += 1;
                i = 0;
            }
            csv::NextField::EndOfCsv => break,
            csv::NextField::Error(err) => panic!(err),
        }
    }

    (headers, names, records)
}

fn item_similarity(records: &(HashMap<String, u32>, HashMap<String, u32>, Vec<f32>),
                   feat_1: &str,
                   feat_2: &str)
                   -> f32 {
    let v_feat_1 = get_feature_vector(&records, feat_1);
    let v_feat_2 = get_feature_vector(&records, feat_2);
    let v_avg = get_feature_vector(&records, "average");

    adjusted_cosine(v_feat_1, v_feat_2, v_avg)
}

fn prediction(name: &str, feature: &str) -> f32 {
    let records = load_database("./data/db1.csv");

    println!("{}",
             item_similarity(&records, "Daft Punk", "Kacey Musgraves"));
    println!("{:?}", normalize(get_user_vector(&records, "David")));
    3.1416
}

fn main() {
    println!("Prediction: {}", prediction("David", "Kacey Musgraves"));
}
<|endoftext|>


<commit_before>extern crate document;
extern crate xpath;

use std::cmp::min;
use std::collections::HashMap;
use std::io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory};
use xpath::expression::Expression;

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn main() {
    let mut args = std::os::args();

    args.remove(0); // Executable name

    let filename = args.remove(0).expect("File required");
    let xpath_str = args.remove(0).expect("XPath required");

    let factory = Factory::new();

    let expr = match factory.build(xpath_str.as_slice()) {
        Err(x) => panic!("Unable to compile XPath: {}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    };

    let p = Parser::new();

    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    let package = match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    };

    let d = package.as_document();

    let mut functions = HashMap::new();
    xpath::function::register_core_functions(& mut functions);
    let variables = HashMap::new();
    let mut namespaces = HashMap::new();

    for pair in args.as_slice().chunks(2) {
        namespaces.insert(pair[0].clone(), pair[1].clone());
    }

    let mut context = EvaluationContext::new(d.root().to_node(),
                                             &functions,
                                             &variables,
                                             &namespaces);
    context.next(d.root().to_node());

    let res = expr.evaluate(&context);

    println!("{}", res);
}
<commit_msg>Reorganize command line tool and provide a usage method<commit_after>extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::collections::HashMap;
use std::io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory};
use xpath::expression::Expression;

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options] FILE...", program);
    print!("{}", usage(brief.as_slice(), opts));
}

fn pretty_error(xml: &str, position: uint) -> &str {
    let s = xml.slice_from(position);
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<xpath::expression::Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(data.as_slice()) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(data.as_slice(), point)),
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>() -> xpath::Variables<'a> {
    HashMap::new()
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();
    for ns_defn in arguments.opt_strs("namespace").iter() {
        let parts: Vec<_> = ns_defn.splitn(2, ':').collect();
        if parts.len() < 2 {
            panic!("Namespace definition '{}' is malformed", ns_defn);
        }

        namespaces.insert(parts[0].to_string(), parts[1].to_string());
    }
    namespaces
}

fn main() {
    let args = std::os::args();
    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name.as_slice(), opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(xpath_str.as_slice());

    for filename in arguments.free.iter() {
        let package = load_xml(filename.as_slice());
        let doc = package.as_document();
        let root = doc.root().to_node();

        let functions = build_functions();
        let variables = build_variables();
        let namespaces = build_namespaces(&arguments);

        let mut context = EvaluationContext::new(root,
                                                 &functions,
                                                 &variables,
                                                 &namespaces);
        context.next(root);

        let res = xpath.evaluate(&context);

        println!("{}", res);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate futures;
extern crate test;

use futures::Async;
use futures::executor;
use futures::executor::{Notify, NotifyHandle};
use futures::sync::BiLock;

use test::Bencher;

fn notify_noop() -> NotifyHandle {
    struct Noop;

    impl Notify for Noop {
        fn notify(&self, _id: usize) {}
    }

    const NOOP : &'static Noop = &Noop;

    NotifyHandle::from(NOOP)
}

#[bench]
fn contended(b: &mut Bencher) {
    b.iter(|| {
        let mut t = BiLock::new(1);
        for _ in 0..1000 {
            let (x, y) = t;
            let x_lock = match executor::spawn(x.lock()).poll_future_notify(&notify_noop(), 11).unwrap() {
                Async::Ready(lock) => lock,
                Async::NotReady => panic!(),
            };

            // Try poll second lock while first lock still holds the lock
            let mut y = executor::spawn(y.lock());
            match y.poll_future_notify(&notify_noop(), 11).unwrap() {
                Async::Ready(_) => panic!(),
                Async::NotReady => (),
            };

            let x = x_lock.unlock();

            let y_lock = match y.poll_future_notify(&notify_noop(), 11).unwrap() {
                Async::Ready(lock) => lock,
                Async::NotReady => panic!(),
            };

            let y = y_lock.unlock();
            t = (x, y);
        }
        t
    });
}

#[bench]
fn lock_unlock(b: &mut Bencher) {
    b.iter(|| {
        let mut t = BiLock::new(1);
        for _ in 0..1000 {
            let (x, y) = t;
            let x_lock = match executor::spawn(x.lock()).poll_future_notify(&notify_noop(), 11).unwrap() {
                Async::Ready(lock) => lock,
                Async::NotReady => panic!(),
            };

            let x = x_lock.unlock();

            let mut y = executor::spawn(y.lock());
            let y_lock = match y.poll_future_notify(&notify_noop(), 11).unwrap() {
                Async::Ready(lock) => lock,
                Async::NotReady => panic!(),
            };

            let y = y_lock.unlock();
            t = (x, y);
        }
        t
    })
}
<commit_msg>Bench BiLock without overhead of executor::spawn<commit_after>#![feature(test)]

extern crate futures;
extern crate test;

use futures::{Async, Poll};
use futures::executor;
use futures::executor::{Notify, NotifyHandle};
use futures::sync::BiLock;
use futures::sync::BiLockAcquire;
use futures::sync::BiLockAcquired;
use futures::future::Future;
use futures::stream::Stream;

use test::Bencher;

fn notify_noop() -> NotifyHandle {
    struct Noop;

    impl Notify for Noop {
        fn notify(&self, _id: usize) {}
    }

    const NOOP : &'static Noop = &Noop;

    NotifyHandle::from(NOOP)
}

/// Pseudo-stream which simply calls `lock.poll()` on `poll`
struct LockStream {
    lock: BiLockAcquire<u32>,
}

impl LockStream {
    fn new(lock: BiLock<u32>) -> LockStream {
        LockStream {
            lock: lock.lock()
        }
    }

    /// Release a lock after it was acquired in `poll`,
    /// so `poll` could be called again.
    fn release_lock(&mut self, guard: BiLockAcquired<u32>) {
        self.lock = guard.unlock().lock()
    }
}

impl Stream for LockStream {
    type Item = BiLockAcquired<u32>;
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        self.lock.poll().map(|a| match a {
            Async::Ready(a) => Async::Ready(Some(a)),
            Async::NotReady => Async::NotReady,
        })
    }
}

#[bench]
fn contended(b: &mut Bencher) {
    b.iter(|| {
        let (x, y) = BiLock::new(1);

        let mut x = executor::spawn(LockStream::new(x));
        let mut y = executor::spawn(LockStream::new(y));

        for _ in 0..1000 {
            let x_guard = match x.poll_stream_notify(&notify_noop(), 11) {
                Ok(Async::Ready(Some(guard))) => guard,
                _ => panic!(),
            };

            // Try poll second lock while first lock still holds the lock
            match y.poll_stream_notify(&notify_noop(), 11) {
                Ok(Async::NotReady) => (),
                _ => panic!(),
            };

            x.get_mut().release_lock(x_guard);

            let y_guard = match y.poll_stream_notify(&notify_noop(), 11) {
                Ok(Async::Ready(Some(guard))) => guard,
                _ => panic!(),
            };

            y.get_mut().release_lock(y_guard);
        }
        (x, y)
    });
}

#[bench]
fn lock_unlock(b: &mut Bencher) {
    b.iter(|| {
        let (x, y) = BiLock::new(1);

        let mut x = executor::spawn(LockStream::new(x));
        let mut y = executor::spawn(LockStream::new(y));

        for _ in 0..1000 {
            let x_guard = match x.poll_stream_notify(&notify_noop(), 11) {
                Ok(Async::Ready(Some(guard))) => guard,
                _ => panic!(),
            };

            x.get_mut().release_lock(x_guard);

            let y_guard = match y.poll_stream_notify(&notify_noop(), 11) {
                Ok(Async::Ready(Some(guard))) => guard,
                _ => panic!(),
            };

            y.get_mut().release_lock(y_guard);
        }
        (x, y)
    })
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate rle_vec;

use std::iter::FromIterator;
use std::iter::repeat;
use test::Bencher;
use rle_vec::RleVec;

#[bench]
fn rle_insert_middle_non_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let mut rle = RleVec::from_iter(iter);
    let middle_value = rle[5_000];

    b.iter(|| {
        rle.insert(5_000, middle_value); // ???
    })
}

#[bench]
fn rle_insert_middle_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let mut rle = RleVec::from_iter(iter);

    b.iter(|| {
        rle.insert(5_000, 424242); // ???
    })
}

#[bench]
fn vec_insert_middle_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let mut vec = Vec::from_iter(iter);
    let middle_value = vec[5_000];

    b.iter(|| {
        vec.insert(5_000, middle_value);
    })
}
<commit_msg>bench: Add RleVec creation to the benches to make them valid<commit_after>#![feature(test)]

extern crate test;
extern crate rle_vec;

use std::iter::FromIterator;
use std::iter::repeat;
use test::Bencher;
use rle_vec::RleVec;

#[bench]
fn rle_insert_middle_non_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);
    let vec: Vec<_> = iter.collect();

    b.iter(|| {
        let mut rle = RleVec::from(&vec[..]);
        let middle_value = rle[5_000];
        rle.insert(5_000, middle_value);
    })
}

#[bench]
fn rle_insert_middle_breaking_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);
    let vec: Vec<_> = iter.collect();

    b.iter(|| {
        let mut rle = RleVec::from(&vec[..]);
        rle.insert(5_000, 424242);
    })
}

#[bench]
fn vec_insert_middle_10_000_runs_of_10_values(b: &mut Bencher) {
    let zeros = repeat(0).take(10);
    let ones = repeat(1).take(10);
    let iter = repeat(zeros.chain(ones)).flat_map(|x| x).take(10_000);

    let tmp_vec = Vec::from_iter(iter);

    b.iter(|| {
        let mut vec = tmp_vec.clone();
        let middle_value = vec[5_000];
        vec.insert(5_000, middle_value);
    })
}
<|endoftext|>


<commit_before>use std::io;

static MEM_SIZE: uint = 5000;

pub struct BrainfuckInterpreter
{
    pointer: uint,
    mem: [u8, ..MEM_SIZE],
}

impl BrainfuckInterpreter
{
    pub fn new() -> BrainfuckInterpreter
    {
        BrainfuckInterpreter {
            pointer: 0,
            mem: [0, ..MEM_SIZE],
        }
    }

    pub fn run(&mut self, program: &str)
    {
        let mut pc: uint = 0;
        let mut loops: ~[uint] = ~[];
        let mut input = io::stdin();

        let get_matching_paren = || {
            let mut tmp = pc;

            while tmp < program.len()
            {
                if program[tmp] == ']' as u8
                {
                    return tmp;
                }

                tmp += 1;
            }

            fail!("No matching ']' for index {}", pc);
        };

        while pc < program.len()
        {
            let c = program[pc] as char;
            pc += 1;

            match c
            {
                '>' => {
                    self.pointer += 1;
                    while self.pointer >= MEM_SIZE
                    {
                        self.pointer -= MEM_SIZE;
                    }
                }
                '<' => {
                    self.pointer -= 1;
                    while self.pointer < 0
                    {
                        self.pointer += MEM_SIZE;
                    }
                }
                '+' => {
                    self.mem[self.pointer] += 1;
                }
                '-' => {
                    self.mem[self.pointer] -= 1;
                }
                '.' => {
                    print!("{:c}", self.mem[self.pointer] as char);
                }
                ',' => {
                    self.mem[self.pointer] = do io::io_error::cond.trap(|_| {}).inside {
                        input.read_u8()
                    };
                }
                '[' => {
                    if self.mem[self.pointer] == 0
                    {
                        pc = get_matching_paren();
                    }
                    else
                    {
                        loops.push(pc - 1);
                    }
                }
                ']' => {
                    if self.mem[self.pointer] != 0
                    {
                        if loops.len() == 0
                        {
                            fail!("No matching '[' for index {}", pc);
                        }

                        pc = loops.pop();
                    }
                }
                _ => {}
            }
        }
    }
}
<commit_msg>Fix mem index.<commit_after>use std::io;

static MEM_SIZE: uint = 5000;

pub struct BrainfuckInterpreter
{
    pointer: uint,
    mem: [u8, ..MEM_SIZE],
}

impl BrainfuckInterpreter
{
    pub fn new() -> BrainfuckInterpreter
    {
        BrainfuckInterpreter {
            pointer: 0,
            mem: [0, ..MEM_SIZE],
        }
    }

    pub fn run(&mut self, program: &str)
    {
        let mut pc: uint = 0;
        let mut loops: ~[uint] = ~[];
        let mut input = io::stdin();

        let get_matching_paren = || {
            let mut tmp = pc;

            while tmp < program.len()
            {
                if program[tmp] == ']' as u8
                {
                    return tmp;
                }

                tmp += 1;
            }

            fail!("No matching ']' for index {}", pc);
        };

        while pc < program.len()
        {
            let c = program[pc] as char;
            pc += 1;

            match c
            {
                '>' => {
                    self.pointer += 1;
                    self.pointer = self.pointer % MEM_SIZE;
                }
                '<' => {
                    self.pointer -= 1;
                    self.pointer = self.pointer % MEM_SIZE;
                }
                '+' => {
                    self.mem[self.pointer] += 1;
                }
                '-' => {
                    self.mem[self.pointer] -= 1;
                }
                '.' => {
                    print!("{:c}", self.mem[self.pointer] as char);
                }
                ',' => {
                    self.mem[self.pointer] = do io::io_error::cond.trap(|_| {}).inside {
                        input.read_u8()
                    };
                }
                '[' => {
                    if self.mem[self.pointer] == 0
                    {
                        pc = get_matching_paren();
                    }
                    else
                    {
                        loops.push(pc - 1);
                    }
                }
                ']' => {
                    if self.mem[self.pointer] != 0
                    {
                        if loops.len() == 0
                        {
                            fail!("No matching '[' for index {}", pc);
                        }

                        pc = loops.pop();
                    }
                }
                _ => {}
            }
        }
    }
}
<|endoftext|>