<commit_before>
//! main entry for `gerrit-rust`

extern crate clap;
extern crate curl;
extern crate gerritlib;
extern crate git2;
extern crate rustc_serialize;
extern crate toml_config;

pub mod changes;
pub mod config;
pub mod topic;

use clap::Arg;
use clap::App;
use clap::SubCommand;
use std::error::Error;

fn main() {
    let mut app = App::new("gerrit-rust")
        .author("Silvio Fricke <silvio.fricke@gmail.com>")
        .about("some gerrit tools")
        .subcommand(SubCommand::with_name("topic")
                    .about("topic management")
                    .subcommand(SubCommand::with_name("create")
                                .help("Create topic branches")
                                .arg(Arg::with_name("branchname")
                                     .help("branch name to create")
                                     .required(true)
                                     .index(1)
                                )
                                .arg(Arg::with_name("repo")
                                     .short("r")
                                     .long("repo")
                                     .help("Create topic branch on this repository. \
                                            Use <repo>[:<git-reference>] to point to a specific repository. \
                                            Current repository is '.' \
                                            '<git-reference>' defaults to HEAD. \
                                            Example: -r .:origin/master -r test -r project:4d6d711")
                                     .next_line_help(true)
                                     .required(true)
                                     .multiple(true)
                                     .takes_value(true)
                                )
                    )
                    .subcommand(SubCommand::with_name("forget")
                                .help("Delete topic branch")
                                .arg(Arg::with_name("branchname")
                                     .help("branch name to delete")
                                     .required(true)
                                     .index(1)
                                )
                                .arg(Arg::with_name("recursive")
                                     .help("recursive remove of branch")
                                     .short("R")
                                )
                    )
        )
        .subcommand(SubCommand::with_name("changes")
                    .about("changes management")
                    .subcommand(SubCommand::with_name("query")
                                .help("queries changes")
                                .arg(Arg::with_name("fields")
                                     .help("select fields to print,\
                                            default is project,subject,topic")
                                     .short("f")
                                     .takes_value(true)
                                )
                                .arg(Arg::with_name("userquery")
                                     .help("user query for changes")
                                     .required(true)
                                     .multiple(true)
                                     .takes_value(true)
                                )
                    )
        )
        .subcommand(SubCommand::with_name("config")
                    .about("config management for ggr")
                    .subcommand(SubCommand::with_name("list")
                                .help("List all config options")
                    )
        )
        ;

    let matches = app.clone().get_matches();

    let out = match matches.subcommand() {
        ("topic", Some(x)) => { topic::manage(x) },
        ("changes", Some(x)) => { changes::manage(x) },
        ("config", Some(x)) => { config::manage(x) },
        _ => { let _ = app.print_help(); Ok(()) },
    };

    match out {
        Ok(_) => {},
        Err(e) => {
            println!("Error: {}", e.description())
        },
    }
}
<commit_msg>bin: use about instead of help for subcommands<commit_after>
//! main entry for `gerrit-rust`

extern crate clap;
extern crate curl;
extern crate gerritlib;
extern crate git2;
extern crate rustc_serialize;
extern crate toml_config;

pub mod changes;
pub mod config;
pub mod topic;

use clap::Arg;
use clap::App;
use clap::SubCommand;
use std::error::Error;

fn main() {
    let mut app = App::new("gerrit-rust")
        .author("Silvio Fricke <silvio.fricke@gmail.com>")
        .about("some gerrit tools")
        .subcommand(SubCommand::with_name("topic")
                    .about("topic management")
                    .subcommand(SubCommand::with_name("create")
                                .about("Create topic branch")
                                .arg(Arg::with_name("branchname")
                                     .help("branch name to create")
                                     .required(true)
                                     .index(1)
                                )
                                .arg(Arg::with_name("repo")
                                     .short("r")
                                     .long("repo")
                                     .help("Create topic branch on this repository. \
                                            Use <repo>[:<git-reference>] to point to a specific repository. \
                                            Current repository is '.' \
                                            '<git-reference>' defaults to HEAD. \
                                            Example: -r .:origin/master -r test -r project:4d6d711")
                                     .next_line_help(true)
                                     .required(true)
                                     .multiple(true)
                                     .takes_value(true)
                                )
                    )
                    .subcommand(SubCommand::with_name("forget")
                                .about("Delete topic branch")
                                .arg(Arg::with_name("branchname")
                                     .help("branch name to delete")
                                     .required(true)
                                     .index(1)
                                )
                                .arg(Arg::with_name("recursive")
                                     .help("recursive remove of branch")
                                     .short("R")
                                )
                    )
        )
        .subcommand(SubCommand::with_name("changes")
                    .about("changes management")
                    .subcommand(SubCommand::with_name("query")
                                .about("queries changes")
                                .arg(Arg::with_name("fields")
                                     .help("select fields to print,\
                                            default is project,subject,topic")
                                     .short("f")
                                     .takes_value(true)
                                )
                                .arg(Arg::with_name("userquery")
                                     .help("user query for changes")
                                     .required(true)
                                     .multiple(true)
                                     .takes_value(true)
                                )
                    )
        )
        .subcommand(SubCommand::with_name("config")
                    .about("config management for ggr")
                    .subcommand(SubCommand::with_name("list")
                                .help("List all config options")
                    )
        )
        ;

    let matches = app.clone().get_matches();

    let out = match matches.subcommand() {
        ("topic", Some(x)) => { topic::manage(x) },
        ("changes", Some(x)) => { changes::manage(x) },
        ("config", Some(x)) => { config::manage(x) },
        _ => { let _ = app.print_help(); Ok(()) },
    };

    match out {
        Ok(_) => {},
        Err(e) => {
            println!("Error: {}", e.description())
        },
    }
}
<|endoftext|>


<commit_before>extern crate crossbeam;
extern crate multiqueue;
extern crate time;

use multiqueue::{MultiReader, MultiWriter, multiqueue};
use std::sync::mpsc::TryRecvError;

use crossbeam::scope;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread::spawn;

const EACH_READER: usize = 100;
const MAX_READERS: usize = 60;
const WRITERS: usize = 20;

#[inline(never)]
fn recv(reader: MultiReader<u64>, how_many_r: Arc<AtomicUsize>) -> u64 {
    let mut cur = 0;
    for _ in 0..2 {
        'outer: for _ in 0..EACH_READER {
            for _ in 0..100000 {
            match reader.try_recv() {
                Ok(_) => {
                    cur += 1;
                    continue 'outer;
                },
                Err(TryRecvError::Disconnected) => return cur,
                _ => (),
               }
           }
           panic!("Couldn't read from queue");
        }
        if how_many_r.load(Ordering::SeqCst) < MAX_READERS {
            let new_reader = reader.add_reader();
            how_many_r.fetch_add(1, Ordering::SeqCst);
            let newr = how_many_r.clone();
            spawn(move || { recv(new_reader, newr)});
        }
    }
    let current = how_many_r.load(Ordering::SeqCst);
    if current <= 10 {
        let new_reader = reader.add_reader();
        spawn(move || { recv(new_reader, how_many_r) });
    }
    return cur;
}

fn send(writer: MultiWriter<u64>, num_push: usize) {
    'outer: for i in 0..num_push as u64 {
        for _ in 0..100000 {
            let topush = i;
            if let Ok(_) =  writer.try_send(topush) {
                continue 'outer;
            }
        }
        panic!("Couldn't write to queue");
    }
}

fn main() {
    let num_do = 10000000;
    let mytest = Arc::new(AtomicUsize::new(1));
    let (writer, reader) = multiqueue(200);
    scope(|scope| {
        for _ in 0..WRITERS {
            let cwriter = writer.clone();
            scope.spawn(move || {
                send(cwriter, num_do);
            });
        }
        writer.unsubscribe();
        recv(reader, mytest);
    });
}
<commit_msg>Removed pointless mem stress test, use existing ones<commit_after><|endoftext|>


<commit_before>#![feature(phase, macro_rules)]

extern crate serialize;
extern crate libc;
#[phase(plugin, link)] extern crate log;

extern crate argparse;
extern crate quire;
#[phase(plugin, link)] extern crate lithos;

use std::os::{set_exit_status, getenv};
use std::io::stderr;
use std::default::Default;
use std::collections::TreeMap;

use argparse::{ArgumentParser, Store};
use quire::parse_config;

use lithos::tree_config::TreeConfig;
use lithos::container_config::{ContainerConfig, Readonly, Persistent, Tmpfs};
use lithos::container_config::{parse_volume};
use lithos::container::{Command};
use lithos::mount::{bind_mount, mount_ro_recursive, mount_tmpfs, mount_private};
use lithos::mount::{mount_pseudo};
use lithos::monitor::{Monitor, Executor};
use lithos::signal;

struct Target {
    name: String,
    global: TreeConfig,
    local: ContainerConfig,
}

impl Executor for Target {
    fn command(&self) -> Command
    {
        let mut cmd = Command::new(self.name.clone(),
            self.local.executable.as_slice());
        cmd.set_user_id(self.local.user_id);
        cmd.chroot(&Path::new(self.global.mount_dir.as_slice()));

        // Should we propagate TERM?
        cmd.set_env("TERM".to_string(),
                    getenv("TERM").unwrap_or("dumb".to_string()));
        cmd.update_env(self.local.environ.iter());
        cmd.set_env("LITHOS_NAME".to_string(), self.name.clone());

        cmd.args(self.local.arguments.as_slice());

        return cmd;
    }
}

fn map_dir(dir: &Path, dirs: &TreeMap<String, String>) -> Option<Path> {
    for (prefix, real_dir) in dirs.iter() {
        let dir_prefix = Path::new(prefix.as_slice());
        match dir.path_relative_from(&dir_prefix) {
            Some(tail) => {
                return Some(Path::new(real_dir.as_slice()).join(tail));
            }
            None => continue,
        }
    }
    return None;
}

fn setup_filesystem(global: &TreeConfig, local: &ContainerConfig)
    -> Result<(), String>
{
    let mntdir = Path::new(global.mount_dir.as_slice());
    assert!(mntdir.is_absolute());

    let mut volumes: Vec<(&String, &String)> = local.volumes.iter().collect();
    volumes.sort_by(|&(mp1, _), &(mp2, _)| mp1.len().cmp(&mp2.len()));

    for &(mp_str, volume_str) in volumes.iter() {
        let tmp_mp = Path::new(mp_str.as_slice());
        assert!(tmp_mp.is_absolute());  // should be checked earlier

        let dest = mntdir.join(
            tmp_mp.path_relative_from(&Path::new("/")).unwrap());
        match try_str!(parse_volume(volume_str.as_slice())) {
            Readonly(dir) => {
                let path = match map_dir(&dir, &global.readonly_paths).or(
                                 map_dir(&dir, &global.writable_paths)) {
                    None => {
                        return Err(format!(concat!("Can't find volume for {},",
                            " probably missing entry in readonly-paths"),
                            dir.display()));
                    }
                    Some(path) => path,
                };
                try!(bind_mount(&path, &dest));
                try!(mount_ro_recursive(&dest));
            }
            Persistent(dir) => {
                let path = match map_dir(&dir, &global.writable_paths) {
                    None => {
                        return Err(format!(concat!("Can't find volume for {},",
                            " probably missing entry in writable-paths"),
                            dir.display()));
                    }
                    Some(path) => path,
                };
                try!(bind_mount(&path, &dest));
                try_str!(mount_private(&dest));
            }
            Tmpfs(opt) => {
                try!(mount_tmpfs(&dest, opt.as_slice()));
            }
        }
    }
    let devdir = mntdir.join("dev");
    try!(bind_mount(&Path::new(global.devfs_dir.as_slice()), &devdir));
    try!(mount_ro_recursive(&devdir));
    try!(mount_pseudo(&mntdir.join("sys"), "sysfs", "", true));
    try!(mount_pseudo(&mntdir.join("proc"), "proc", "", false));

    return Ok(());
}

fn run(name: String, global_cfg: Path, local_cfg: Path) -> Result<(), String> {
    let global: TreeConfig = try_str!(parse_config(&global_cfg,
        TreeConfig::validator(), Default::default()));
    let local: ContainerConfig = try_str!(parse_config(&local_cfg,
        ContainerConfig::validator(), Default::default()));

    info!("[{:s}] Starting container", name);

    try!(setup_filesystem(&global, &local));

    let mut mon = Monitor::new(name.clone());
    let name = name + ".main";
    mon.add(name.clone(), box Target {
        name: name,
        global: global,
        local: local,
    }, None);
    mon.run();

    return Ok(());
}

fn main() {

    signal::block_all();

    let mut global_config = Path::new("/etc/lithos.yaml");
    let mut container_config = Path::new("");
    let mut name = "".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tree of processes");
        ap.refer(&mut name)
          .add_option(["--name"], box Store::<String>,
            "The process name");
        ap.refer(&mut global_config)
          .add_option(["--global-config"], box Store::<Path>,
            "Name of the global configuration file (default /etc/lithos.yaml)")
          .metavar("FILE");
        ap.refer(&mut container_config)
          .add_option(["--container-config"], box Store::<Path>,
            "Name of the container configuration file")
          .required()
          .metavar("FILE");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                set_exit_status(x);
                return;
            }
        }
    }
    match run(name, global_config, container_config) {
        Ok(()) => {
            set_exit_status(0);
        }
        Err(e) => {
            (write!(stderr(), "Fatal error: {}\n", e)).ok();
            set_exit_status(1);
        }
    }
}
<commit_msg>Fix mapping child paths<commit_after>#![feature(phase, macro_rules)]

extern crate serialize;
extern crate libc;
#[phase(plugin, link)] extern crate log;

extern crate argparse;
extern crate quire;
#[phase(plugin, link)] extern crate lithos;

use std::os::{set_exit_status, getenv};
use std::io::stderr;
use std::default::Default;
use std::collections::TreeMap;

use argparse::{ArgumentParser, Store};
use quire::parse_config;

use lithos::tree_config::TreeConfig;
use lithos::container_config::{ContainerConfig, Readonly, Persistent, Tmpfs};
use lithos::container_config::{parse_volume};
use lithos::container::{Command};
use lithos::mount::{bind_mount, mount_ro_recursive, mount_tmpfs, mount_private};
use lithos::mount::{mount_pseudo};
use lithos::monitor::{Monitor, Executor};
use lithos::signal;

struct Target {
    name: String,
    global: TreeConfig,
    local: ContainerConfig,
}

impl Executor for Target {
    fn command(&self) -> Command
    {
        let mut cmd = Command::new(self.name.clone(),
            self.local.executable.as_slice());
        cmd.set_user_id(self.local.user_id);
        cmd.chroot(&Path::new(self.global.mount_dir.as_slice()));

        // Should we propagate TERM?
        cmd.set_env("TERM".to_string(),
                    getenv("TERM").unwrap_or("dumb".to_string()));
        cmd.update_env(self.local.environ.iter());
        cmd.set_env("LITHOS_NAME".to_string(), self.name.clone());

        cmd.args(self.local.arguments.as_slice());

        return cmd;
    }
}

fn map_dir(dir: &Path, dirs: &TreeMap<String, String>) -> Option<Path> {
    assert!(dir.is_absolute());
    for (prefix, real_dir) in dirs.iter() {
        let dir_prefix = Path::new(prefix.as_slice());
        if dir_prefix.is_ancestor_of(dir) {
            match dir.path_relative_from(&dir_prefix) {
                Some(tail) => {
                    assert!(!tail.is_absolute());
                    return Some(Path::new(real_dir.as_slice()).join(tail));
                }
                None => continue,
            }
        }
    }
    return None;
}

fn setup_filesystem(global: &TreeConfig, local: &ContainerConfig)
    -> Result<(), String>
{
    let mntdir = Path::new(global.mount_dir.as_slice());
    assert!(mntdir.is_absolute());

    let mut volumes: Vec<(&String, &String)> = local.volumes.iter().collect();
    volumes.sort_by(|&(mp1, _), &(mp2, _)| mp1.len().cmp(&mp2.len()));

    for &(mp_str, volume_str) in volumes.iter() {
        let tmp_mp = Path::new(mp_str.as_slice());
        assert!(tmp_mp.is_absolute());  // should be checked earlier

        let dest = mntdir.join(
            tmp_mp.path_relative_from(&Path::new("/")).unwrap());
        match try_str!(parse_volume(volume_str.as_slice())) {
            Readonly(dir) => {
                let path = match map_dir(&dir, &global.readonly_paths).or_else(
                                 || map_dir(&dir, &global.writable_paths)) {
                    None => {
                        return Err(format!(concat!("Can't find volume for {},",
                            " probably missing entry in readonly-paths"),
                            dir.display()));
                    }
                    Some(path) => path,
                };
                try!(bind_mount(&path, &dest));
                try!(mount_ro_recursive(&dest));
            }
            Persistent(dir) => {
                let path = match map_dir(&dir, &global.writable_paths) {
                    None => {
                        return Err(format!(concat!("Can't find volume for {},",
                            " probably missing entry in writable-paths"),
                            dir.display()));
                    }
                    Some(path) => path,
                };
                try!(bind_mount(&path, &dest));
                try_str!(mount_private(&dest));
            }
            Tmpfs(opt) => {
                try!(mount_tmpfs(&dest, opt.as_slice()));
            }
        }
    }
    let devdir = mntdir.join("dev");
    try!(bind_mount(&Path::new(global.devfs_dir.as_slice()), &devdir));
    try!(mount_ro_recursive(&devdir));
    try!(mount_pseudo(&mntdir.join("sys"), "sysfs", "", true));
    try!(mount_pseudo(&mntdir.join("proc"), "proc", "", false));

    return Ok(());
}

fn run(name: String, global_cfg: Path, local_cfg: Path) -> Result<(), String> {
    let global: TreeConfig = try_str!(parse_config(&global_cfg,
        TreeConfig::validator(), Default::default()));
    let local: ContainerConfig = try_str!(parse_config(&local_cfg,
        ContainerConfig::validator(), Default::default()));

    info!("[{:s}] Starting container", name);

    try!(setup_filesystem(&global, &local));

    let mut mon = Monitor::new(name.clone());
    let name = name + ".main";
    mon.add(name.clone(), box Target {
        name: name,
        global: global,
        local: local,
    }, None);
    mon.run();

    return Ok(());
}

fn main() {

    signal::block_all();

    let mut global_config = Path::new("/etc/lithos.yaml");
    let mut container_config = Path::new("");
    let mut name = "".to_string();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Runs tree of processes");
        ap.refer(&mut name)
          .add_option(["--name"], box Store::<String>,
            "The process name");
        ap.refer(&mut global_config)
          .add_option(["--global-config"], box Store::<Path>,
            "Name of the global configuration file (default /etc/lithos.yaml)")
          .metavar("FILE");
        ap.refer(&mut container_config)
          .add_option(["--container-config"], box Store::<Path>,
            "Name of the container configuration file")
          .required()
          .metavar("FILE");
        match ap.parse_args() {
            Ok(()) => {}
            Err(x) => {
                set_exit_status(x);
                return;
            }
        }
    }
    match run(name, global_config, container_config) {
        Ok(()) => {
            set_exit_status(0);
        }
        Err(e) => {
            (write!(stderr(), "Fatal error: {}\n", e)).ok();
            set_exit_status(1);
        }
    }
}
<|endoftext|>


<commit_before>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[crate_id="bloomfilter#0.1"];
#[crate_type = "rlib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern crate collections;
extern crate extra;

use std::cmp;
use std::hash::Hash;
use std::num;
use std::rand;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use std::rand::Rng;
use collections::bitv;

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>Only use use std::rand::Rng in test mode<commit_after>// (C)opyleft 2013,2014 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[crate_id="bloomfilter#0.1"];
#[crate_type = "rlib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern crate collections;
extern crate extra;

use std::cmp;
use std::hash::Hash;
use std::num;
use std::rand;
use std::hash::sip::SipHasher;
use std::hash::Hasher;
use collections::bitv;

#[cfg(test)]
use std::rand::Rng;

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv sips: [SipHasher, ..2]
}

impl Bloom {
/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let sips = [ Bloom::sip_new(), Bloom::sip_new() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            sips: sips
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let sip = self.sips[k_i];
            let hash = sip.hash(item);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }

    fn sip_new() -> SipHasher {
        let mut rng = rand::task_rng();
        SipHasher::new_with_keys(rand::Rand::rand(& mut rng),
                                 rand::Rand::rand(& mut rng))
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>


<commit_before>use crate::aliased_command;
use cargo::util::errors::CargoResult;
use cargo::Config;
use cargo_util::paths::resolve_executable;
use flate2::read::GzDecoder;
use std::ffi::OsString;
use std::io::Read;
use std::io::Write;
use std::path::Path;

const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz"));

/// Checks if the `help` command is being issued.
///
/// This runs before clap processing, because it needs to intercept the `help`
/// command if a man page is available.
///
/// Returns `true` if a man page was displayed. In this case, Cargo should
/// exit.
pub fn handle_embedded_help(config: &Config) -> bool {
    match try_help(config) {
        Ok(true) => true,
        Ok(false) => false,
        Err(e) => {
            log::warn!("man failed: {:?}", e);
            false
        }
    }
}

fn try_help(config: &Config) -> CargoResult<bool> {
    let mut args = std::env::args_os()
        .skip(1)
        .skip_while(|arg| arg.to_str().map_or(false, |s| s.starts_with('-')));
    if !args
        .next()
        .map_or(false, |arg| arg.to_str() == Some("help"))
    {
        return Ok(false);
    }
    let subcommand = match args.next() {
        Some(arg) => arg,
        None => return Ok(false),
    };
    let subcommand = match subcommand.to_str() {
        Some(s) => s,
        None => return Ok(false),
    };
    // Check if this is a built-in command (or alias);
    let subcommand = match check_alias(config, subcommand) {
        Some(s) => s,
        None => return Ok(false),
    };
    if resolve_executable(Path::new("man")).is_ok() {
        let man = match extract_man(&subcommand, "1") {
            Some(man) => man,
            None => return Ok(false),
        };
        write_and_spawn(&man, "man")?;
    } else {
        let txt = match extract_man(&subcommand, "txt") {
            Some(txt) => txt,
            None => return Ok(false),
        };
        if resolve_executable(Path::new("less")).is_ok() {
            write_and_spawn(&txt, "less")?;
        } else if resolve_executable(Path::new("more")).is_ok() {
            write_and_spawn(&txt, "more")?;
        } else {
            drop(std::io::stdout().write_all(&txt));
        }
    }
    Ok(true)
}

/// Checks if the given subcommand is a built-in command (possibly via an alias).
///
/// Returns None if it is not a built-in command.
fn check_alias(config: &Config, subcommand: &str) -> Option<String> {
    if super::builtin_exec(subcommand).is_some() {
        return Some(subcommand.to_string());
    }
    match aliased_command(config, subcommand) {
        Ok(Some(alias)) => {
            let alias = alias.into_iter().next()?;
            if super::builtin_exec(&alias).is_some() {
                Some(alias)
            } else {
                None
            }
        }
        _ => None,
    }
}

/// Extracts the given man page from the compressed archive.
///
/// Returns None if the command wasn't found.
fn extract_man(subcommand: &str, extension: &str) -> Option<Vec<u8>> {
    let extract_name = OsString::from(format!("cargo-{}.{}", subcommand, extension));
    let gz = GzDecoder::new(COMPRESSED_MAN);
    let mut ar = tar::Archive::new(gz);
    // Unwraps should be safe here, since this is a static archive generated
    // by our build script. It should never be an invalid format!
    for entry in ar.entries().unwrap() {
        let mut entry = entry.unwrap();
        let path = entry.path().unwrap();
        if path.file_name().unwrap() != extract_name {
            continue;
        }
        let mut result = Vec::new();
        entry.read_to_end(&mut result).unwrap();
        return Some(result);
    }
    None
}

/// Write the contents of a man page to disk and spawn the given command to
/// display it.
fn write_and_spawn(contents: &[u8], command: &str) -> CargoResult<()> {
    let mut tmp = tempfile::Builder::new().prefix("cargo-man").tempfile()?;
    let f = tmp.as_file_mut();
    f.write_all(contents)?;
    f.flush()?;
    let mut cmd = std::process::Command::new(command)
        .arg(tmp.path())
        .spawn()?;
    drop(cmd.wait());
    Ok(())
}
<commit_msg>Auto merge of #9378 - ehuss:help-windows, r=alexcrichton<commit_after>use crate::aliased_command;
use cargo::util::errors::CargoResult;
use cargo::Config;
use cargo_util::paths::resolve_executable;
use flate2::read::GzDecoder;
use std::ffi::OsString;
use std::io::Read;
use std::io::Write;
use std::path::Path;

const COMPRESSED_MAN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/man.tgz"));

/// Checks if the `help` command is being issued.
///
/// This runs before clap processing, because it needs to intercept the `help`
/// command if a man page is available.
///
/// Returns `true` if a man page was displayed. In this case, Cargo should
/// exit.
pub fn handle_embedded_help(config: &Config) -> bool {
    match try_help(config) {
        Ok(true) => true,
        Ok(false) => false,
        Err(e) => {
            log::warn!("man failed: {:?}", e);
            false
        }
    }
}

fn try_help(config: &Config) -> CargoResult<bool> {
    let mut args = std::env::args_os()
        .skip(1)
        .skip_while(|arg| arg.to_str().map_or(false, |s| s.starts_with('-')));
    if !args
        .next()
        .map_or(false, |arg| arg.to_str() == Some("help"))
    {
        return Ok(false);
    }
    let subcommand = match args.next() {
        Some(arg) => arg,
        None => return Ok(false),
    };
    let subcommand = match subcommand.to_str() {
        Some(s) => s,
        None => return Ok(false),
    };
    // Check if this is a built-in command (or alias);
    let subcommand = match check_alias(config, subcommand) {
        Some(s) => s,
        None => return Ok(false),
    };
    if resolve_executable(Path::new("man")).is_ok() {
        let man = match extract_man(&subcommand, "1") {
            Some(man) => man,
            None => return Ok(false),
        };
        write_and_spawn(&subcommand, &man, "man")?;
    } else {
        let txt = match extract_man(&subcommand, "txt") {
            Some(txt) => txt,
            None => return Ok(false),
        };
        if resolve_executable(Path::new("less")).is_ok() {
            write_and_spawn(&subcommand, &txt, "less")?;
        } else if resolve_executable(Path::new("more")).is_ok() {
            write_and_spawn(&subcommand, &txt, "more")?;
        } else {
            drop(std::io::stdout().write_all(&txt));
        }
    }
    Ok(true)
}

/// Checks if the given subcommand is a built-in command (possibly via an alias).
///
/// Returns None if it is not a built-in command.
fn check_alias(config: &Config, subcommand: &str) -> Option<String> {
    if super::builtin_exec(subcommand).is_some() {
        return Some(subcommand.to_string());
    }
    match aliased_command(config, subcommand) {
        Ok(Some(alias)) => {
            let alias = alias.into_iter().next()?;
            if super::builtin_exec(&alias).is_some() {
                Some(alias)
            } else {
                None
            }
        }
        _ => None,
    }
}

/// Extracts the given man page from the compressed archive.
///
/// Returns None if the command wasn't found.
fn extract_man(subcommand: &str, extension: &str) -> Option<Vec<u8>> {
    let extract_name = OsString::from(format!("cargo-{}.{}", subcommand, extension));
    let gz = GzDecoder::new(COMPRESSED_MAN);
    let mut ar = tar::Archive::new(gz);
    // Unwraps should be safe here, since this is a static archive generated
    // by our build script. It should never be an invalid format!
    for entry in ar.entries().unwrap() {
        let mut entry = entry.unwrap();
        let path = entry.path().unwrap();
        if path.file_name().unwrap() != extract_name {
            continue;
        }
        let mut result = Vec::new();
        entry.read_to_end(&mut result).unwrap();
        return Some(result);
    }
    None
}

/// Write the contents of a man page to disk and spawn the given command to
/// display it.
fn write_and_spawn(name: &str, contents: &[u8], command: &str) -> CargoResult<()> {
    let prefix = format!("cargo-{}.", name);
    let mut tmp = tempfile::Builder::new().prefix(&prefix).tempfile()?;
    let f = tmp.as_file_mut();
    f.write_all(contents)?;
    f.flush()?;
    let path = tmp.path();
    // Use a path relative to the temp directory so that it can work on
    // cygwin/msys systems which don't handle windows-style paths.
    let mut relative_name = std::ffi::OsString::from("./");
    relative_name.push(path.file_name().unwrap());
    let mut cmd = std::process::Command::new(command)
        .arg(relative_name)
        .current_dir(path.parent().unwrap())
        .spawn()?;
    drop(cmd.wait());
    Ok(())
}
<|endoftext|>


<commit_before>use core::prelude::*;
use core::intrinsics;
use hil::{adc};
use pm::{self, Clock, PBAClock};

/* This is a first cut at an implementation of the SAM4L ADC.
   It only allows a single sample at a time, and has three known bugs,
   all serious:
     1) It has not yet been tested (I have no hardware)
     2) Interrupts are not hooked up yet
     3) You cannot request a sample in a callback.

    I've added it mostly as an example of how we might implement
    these services.
*/

#[repr(C, packed)]
#[allow(dead_code,missing_copy_implementations)]
pub struct AdcRegisters { // From page 1005 of SAM4L manual
    cr:        usize,   // Control               (0x00)
    cfg:       usize,   // Configuration         (0x04)
    sr:        usize,   // Status                (0x08)
    scr:       usize,   // Status clear          (0x0c)
    pad:       usize,   // padding/reserved
    seqcfg:    usize,   // Sequencer config      (0x14)
    cdma:      usize,   // Config DMA            (0x18)
    tim:       usize,   // Timing config         (0x1c)
    itimer:    usize,   // Internal timer        (0x20)
    wcfg:      usize,   // Window config         (0x24)
    wth:       usize,   // Window threshold      (0x28)
    lcv:       usize,   // Last converted value  (0x2c)
    ier:       usize,   // Interrupt enable      (0x30)
    idr:       usize,   // Interrupt disable     (0x34)
    imr:       usize,   // Interrupt mask        (0x38)
    calib:     usize,   // Calibration           (0x3c)
    version:   usize,   // Version               (0x40)
    parameter: usize,   // Parameter             (0x44)
}

// Page 59 of SAM4L data sheet
pub const BASE_ADDRESS: usize = 0x40038000;

pub struct Adc {
  registers: &'static mut AdcRegisters,
  enabled: bool,
  request: Option<&'static mut adc::Request>
}

impl Adc {
    pub fn new() -> Adc {
        let address = BASE_ADDRESS;
        Adc {
            registers: unsafe { intrinsics::transmute(address) },
            enabled: false,
            request: None
        }
    }
}

impl adc::AdcInternal for Adc {
    fn initialize(&mut self) -> bool {
        if !self.enabled {
            self.enabled = true;
            unsafe {pm::enable_clock(Clock::PBA(PBAClock::ADCIFE));}
            volatile!(self.registers.cr |= 1 << 8);  // Enable ADC
            volatile!(self.registers.cr |= 1 << 10); // Enable bandgap buffer
            volatile!(self.registers.cr |= 1 << 4);  // Enable reference buffer
            if (volatile!(self.registers.sr) & (1 << 24)) != 0 { // ADC is enabled
                // Setting all 0s in the configuration register sets
                //   - the clock divider to be 4,
                //   - the source to be the Generic clock,
                //   - the max speed to be 300 ksps, and
                //   - the reference voltage to be 1.0V
                volatile!(self.registers.cfg = 0);
            }
        }
        return true;
    }

    fn sample(&mut self, request: &'static mut adc::Request) -> bool {
        if self.enabled || request.channel > 14 {
            return false;
        } else {
            self.enabled = true;
            self.request = Some(request);

            // This configuration sets the ADC to use Pad Ground as the
            // negative input, and the ADC channel as the positive. Since
            // this is a single-ended sample, the bipolar bit is set to zero.
            // Trigger select is set to zero because this denotes a software
            // sample. Gain is 1x (set to 0). Resolution is set to 12 bits
            // (set to 0). The one trick is that the half word left adjust
            // (HWLA) is set to 1. This means that both 12-bit and 8-bit
            // samples are left justified to the lower 16 bits. So they share
            // the same most significant bit but for 8 bit samples the lower
            // 8 bits are zero and for 12 bits the lower 4 bits are zero.

            let mut channel:usize = request.channel as usize;
            channel = channel << 16;
            volatile!(self.registers.seqcfg = 0x00708081 | channel);
/*                    00708081 =  7      << 20 | // MUXNEG
                                  channel << 16 | // MUXPOS
                                  2       << 14 | // Internal
                                  0       << 12 | // Resolution
                                  0       << 8  | // TRGSEL
                                  1       << 7  | // GCOMP
                                  0       << 4  | // GAIN
                                  0       << 2  | // BIPOLAR
                                  1));*/
            // Enable end of conversion interrupt
            volatile!(self.registers.ier = 1);
            // Initiate conversion
            volatile!(self.registers.cr = 2);
            return true;
        }
    }

    fn handle_interrupt(&mut self) {
        // Disable further interrupts
        volatile!(self.registers.idr = 1);
        match self.request {
            Some(ref mut request) => {
                let val = volatile!(self.registers.lcv) & 0xffff;
                request.callback.read_done(val as u16);
            }
            None => {}

        }
        self.request = None;
    }
}
<commit_msg>Explain why ADC readings are masked with 0xFFFF.<commit_after>use core::prelude::*;
use core::intrinsics;
use hil::{adc};
use pm::{self, Clock, PBAClock};

/* This is a first cut at an implementation of the SAM4L ADC.
   It only allows a single sample at a time, and has three known bugs,
   all serious:
     1) It has not yet been tested (I have no hardware)
     2) Interrupts are not hooked up yet
     3) You cannot request a sample in a callback.

    I've added it mostly as an example of how we might implement
    these services.
*/

#[repr(C, packed)]
#[allow(dead_code,missing_copy_implementations)]
pub struct AdcRegisters { // From page 1005 of SAM4L manual
    cr:        usize,   // Control               (0x00)
    cfg:       usize,   // Configuration         (0x04)
    sr:        usize,   // Status                (0x08)
    scr:       usize,   // Status clear          (0x0c)
    pad:       usize,   // padding/reserved
    seqcfg:    usize,   // Sequencer config      (0x14)
    cdma:      usize,   // Config DMA            (0x18)
    tim:       usize,   // Timing config         (0x1c)
    itimer:    usize,   // Internal timer        (0x20)
    wcfg:      usize,   // Window config         (0x24)
    wth:       usize,   // Window threshold      (0x28)
    lcv:       usize,   // Last converted value  (0x2c)
    ier:       usize,   // Interrupt enable      (0x30)
    idr:       usize,   // Interrupt disable     (0x34)
    imr:       usize,   // Interrupt mask        (0x38)
    calib:     usize,   // Calibration           (0x3c)
    version:   usize,   // Version               (0x40)
    parameter: usize,   // Parameter             (0x44)
}

// Page 59 of SAM4L data sheet
pub const BASE_ADDRESS: usize = 0x40038000;

pub struct Adc {
  registers: &'static mut AdcRegisters,
  enabled: bool,
  request: Option<&'static mut adc::Request>
}

impl Adc {
    pub fn new() -> Adc {
        let address = BASE_ADDRESS;
        Adc {
            registers: unsafe { intrinsics::transmute(address) },
            enabled: false,
            request: None
        }
    }
}

impl adc::AdcInternal for Adc {
    fn initialize(&mut self) -> bool {
        if !self.enabled {
            self.enabled = true;
            unsafe {pm::enable_clock(Clock::PBA(PBAClock::ADCIFE));}
            volatile!(self.registers.cr |= 1 << 8);  // Enable ADC
            volatile!(self.registers.cr |= 1 << 10); // Enable bandgap buffer
            volatile!(self.registers.cr |= 1 << 4);  // Enable reference buffer
            if (volatile!(self.registers.sr) & (1 << 24)) != 0 { // ADC is enabled
                // Setting all 0s in the configuration register sets
                //   - the clock divider to be 4,
                //   - the source to be the Generic clock,
                //   - the max speed to be 300 ksps, and
                //   - the reference voltage to be 1.0V
                volatile!(self.registers.cfg = 0);
            }
        }
        return true;
    }

    fn sample(&mut self, request: &'static mut adc::Request) -> bool {
        if self.enabled || request.channel > 14 {
            return false;
        } else {
            self.enabled = true;
            self.request = Some(request);

            // This configuration sets the ADC to use Pad Ground as the
            // negative input, and the ADC channel as the positive. Since
            // this is a single-ended sample, the bipolar bit is set to zero.
            // Trigger select is set to zero because this denotes a software
            // sample. Gain is 1x (set to 0). Resolution is set to 12 bits
            // (set to 0). The one trick is that the half word left adjust
            // (HWLA) is set to 1. This means that both 12-bit and 8-bit
            // samples are left justified to the lower 16 bits. So they share
            // the same most significant bit but for 8 bit samples the lower
            // 8 bits are zero and for 12 bits the lower 4 bits are zero.

            let mut channel:usize = request.channel as usize;
            channel = channel << 16;
            volatile!(self.registers.seqcfg = 0x00708081 | channel);
/*                    00708081 =  7      << 20 | // MUXNEG
                                  channel << 16 | // MUXPOS
                                  2       << 14 | // Internal
                                  0       << 12 | // Resolution
                                  0       << 8  | // TRGSEL
                                  1       << 7  | // GCOMP
                                  0       << 4  | // GAIN
                                  0       << 2  | // BIPOLAR
                                  1               // HWLA ));*/
            // Enable end of conversion interrupt
            volatile!(self.registers.ier = 1);
            // Initiate conversion
            volatile!(self.registers.cr = 2);
            return true;
        }
    }

    fn handle_interrupt(&mut self) {
        // Disable further interrupts
        volatile!(self.registers.idr = 1);
        match self.request {
            Some(ref mut request) => {
                // Because HWLA is set to 1, most significant bit is
                // of reading is left justified to bit 15r
                let val = volatile!(self.registers.lcv) & 0xffff;
                request.callback.read_done(val as u16);
            }
            None => {}

        }
        self.request = None;
    }
}
<|endoftext|>


<commit_before>use codegen::buffer::*;
use codegen::info;
use codegen::x64::reg::*;
use codegen::x64::reg::Reg::*;
use codegen::x64::emit::*;

use parser::ast::ctxt::*;
use parser::ast::*;
use parser::ast::Expr::*;
use parser::ast::Stmt::*;
use parser::ast::visit::*;

use sym::BuiltinType;

pub struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
    fct: &'ast Function,
    buf: Buffer,

    stacksize: u32,
    lbl_break: Option<Label>,
    lbl_continue: Option<Label>,
}

impl<'a, 'ast> CodeGen<'a, 'ast> where 'ast: 'a {
    pub fn new(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> CodeGen<'a, 'ast> {
        CodeGen {
            ctxt: ctxt,
            fct: fct,
            buf: Buffer::new(),

            stacksize: ctxt.function(fct.id, |fct| fct.stacksize),
            lbl_break: None,
            lbl_continue: None
        }
    }

    pub fn generate(mut self) -> Buffer {
        info::generate(self.ctxt, self.fct);

        self.emit_prolog();
        self.store_params();
        self.visit_fct(self.fct);
        self.emit_epilog();

        self.buf
    }

    fn store_params(&mut self) {
        let params_len = self.fct.params.len();
        if params_len == 0 { return; }

        let defs = self.ctxt.defs.borrow();

        for (reg, p) in PARAM_REGS.iter().zip(&self.fct.params) {
            let varid = *defs.get(&p.id).unwrap();
            self.emit_var_store(*reg, varid);
        }
    }

    fn emit_prolog(&mut self) {
        emit_pushq_reg(&mut self.buf, Reg::RBP);
        emit_movq_reg_reg(&mut self.buf, Reg::RSP, Reg::RBP);

        if self.stacksize > 0 {
            emit_subq_imm_reg(&mut self.buf, self.stacksize as i32, RSP);
        }
    }

    fn emit_epilog(&mut self) {
        if self.stacksize > 0 {
            emit_addq_imm_reg(&mut self.buf, self.stacksize as i32, RSP);
        }

        emit_popq_reg(&mut self.buf, Reg::RBP);
        emit_retq(&mut self.buf);
    }

    fn emit_stmt_return(&mut self, s: &'ast StmtReturnType) {
        if let Some(ref expr) = s.expr {
            self.visit_expr(expr);
        }

        self.emit_epilog();
    }

    fn emit_stmt_while(&mut self, s: &'ast StmtWhileType) {
        let lbl_start = self.buf.create_label();
        let lbl_end = self.buf.create_label();

        self.buf.define_label(lbl_start);

        // execute condition, when condition is false jump to
        // end of while
        self.visit_expr(&s.cond);
        emit_testl_reg_reg(&mut self.buf, RAX, RAX);
        emit_jz(&mut self.buf, lbl_end);

        self.save_label_state(lbl_end, lbl_start, |this| {
            // execute while body, then jump back to condition
            this.visit_stmt(&s.block);
            emit_jmp(&mut this.buf, lbl_start);
        });

        self.buf.define_label(lbl_end);
    }

    fn emit_stmt_loop(&mut self, s: &'ast StmtLoopType) {
        let lbl_start = self.buf.create_label();
        let lbl_end = self.buf.create_label();
        self.buf.define_label(lbl_start);

        self.save_label_state(lbl_end, lbl_start, |this| {
            this.visit_stmt(&s.block);
        });

        self.buf.define_label(lbl_end);

        emit_jmp(&mut self.buf, lbl_start);
    }

    fn save_label_state<F>(&mut self, lbl_break: Label, lbl_continue: Label, f: F)
            where F: FnOnce(&mut CodeGen<'a, 'ast>) {
        let old_lbl_break = self.lbl_break;
        let old_lbl_continue = self.lbl_continue;

        self.lbl_break = Some(lbl_break);
        self.lbl_continue = Some(lbl_continue);

        f(self);

        self.lbl_break = old_lbl_break;
        self.lbl_continue = old_lbl_continue;
    }

    fn emit_stmt_if(&mut self, s: &'ast StmtIfType) {
        let lbl_end = self.buf.create_label();
        let lbl_else = if let Some(_) = s.else_block {
            self.buf.create_label()
        } else {
            lbl_end
        };

        self.visit_expr(&s.cond);
        emit_testl_reg_reg(&mut self.buf, RAX, RAX);
        emit_jz(&mut self.buf, lbl_else);

        self.visit_stmt(&s.then_block);

        if let Some(ref else_block) = s.else_block {
            emit_jmp(&mut self.buf, lbl_end);
            self.buf.define_label(lbl_else);

            self.visit_stmt(else_block);
        }

        self.buf.define_label(lbl_end);
    }

    fn emit_stmt_break(&mut self, s: &'ast StmtBreakType)  {
        emit_jmp(&mut self.buf, self.lbl_break.unwrap());
    }

    fn emit_stmt_continue(&mut self, s: &'ast StmtContinueType) {
        emit_jmp(&mut self.buf, self.lbl_continue.unwrap());
    }

    fn emit_stmt_expr(&mut self, s: &'ast StmtExprType) {
        self.visit_expr(&s.expr);
    }

    fn emit_stmt_block(&mut self, s: &'ast StmtBlockType) {
        for stmt in &s.stmts {
            self.visit_stmt(stmt);
        }
    }

    fn emit_stmt_var(&mut self, s: &'ast StmtVarType) {
        if let Some(ref expr) = s.expr {
            self.visit_expr(expr);

            let defs = self.ctxt.defs.borrow();
            let varid = *defs.get(&s.id).unwrap();

            self.emit_var_store(RAX, varid);
        }
    }

    fn emit_expr_lit_int(&mut self, lit: &'ast ExprLitIntType) {
        emit_movl_imm_reg(&mut self.buf, lit.value as u32, Reg::RAX);
    }

    fn emit_expr_lit_bool(&mut self, lit: &'ast ExprLitBoolType) {
        let value : u32 = if lit.value { 1 } else { 0 };
        emit_movl_imm_reg(&mut self.buf, value, Reg::RAX);
    }

    fn emit_expr_ident(&mut self, e: &'ast ExprIdentType) {
        let defs = self.ctxt.defs.borrow();
        let varid = *defs.get(&e.id).unwrap();

        self.emit_var_load(varid, RAX);
    }

    fn emit_expr_un(&mut self, e: &'ast ExprUnType) {
        self.visit_expr(&e.opnd);

        match e.op {
            UnOp::Plus => {},
            _ => unreachable!(),
        }
    }

    fn emit_var_store(&mut self, src: Reg, var: VarInfoId) {
        let var_infos = self.ctxt.var_infos.borrow();
        let var = &var_infos[var.0];

        match var.data_type {
            BuiltinType::Bool => emit_movb_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Int => emit_movl_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Str => emit_movq_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Unit => {},
        }
    }

    fn emit_var_load(&mut self, var: VarInfoId, dest: Reg) {
        let var_infos = self.ctxt.var_infos.borrow();
        let var = &var_infos[var.0];

        match var.data_type {
            BuiltinType::Bool => emit_movb_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Int => emit_movl_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Str => emit_movq_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Unit => {},
        }
    }
}

impl<'a, 'ast> visit::Visitor<'ast> for CodeGen<'a, 'ast> {
    fn visit_stmt(&mut self, s: &'ast Stmt) {
        match *s {
            StmtExpr(ref stmt) => self.emit_stmt_expr(stmt),
            StmtIf(ref stmt) => self.emit_stmt_if(stmt),
            StmtLoop(ref stmt) => self.emit_stmt_loop(stmt),
            StmtWhile(ref stmt) => self.emit_stmt_while(stmt),
            StmtReturn(ref stmt) => self.emit_stmt_return(stmt),
            StmtBreak(ref stmt) => self.emit_stmt_break(stmt),
            StmtContinue(ref stmt) => self.emit_stmt_continue(stmt),
            StmtBlock(ref stmt) => self.emit_stmt_block(stmt),
            StmtVar(ref stmt) => self.emit_stmt_var(stmt),
        }
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        match *e {
            ExprLitInt(ref expr) => self.emit_expr_lit_int(expr),
            ExprLitBool(ref expr) => self.emit_expr_lit_bool(expr),
            ExprIdent(ref expr) => self.emit_expr_ident(expr),
            ExprUn(ref expr) => self.emit_expr_un(expr),
            _ => unreachable!()
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;

    use codegen;
    use driver;
    use mem::CodeMemory;
    use semck;
    use test;

    use super::*;

    fn compile(code: &'static str) -> CodeMemory {
        test::parse(code, |ctxt| {
            // generate code for first function
            let fct = ctxt.ast.elements[0].to_function().unwrap();
            let buffer = codegen::generate(ctxt, fct);

            driver::dump_asm(&buffer, &ctxt.interner.str(fct.name));

            CodeMemory::new(&buffer)
        })
    }

    fn run<T>(code: &'static str) -> T {
        let mem = compile(code);
        let compiled_fct : extern "C" fn() -> T = unsafe { mem::transmute(mem.ptr()) };

        compiled_fct()
    }

    fn fct1<T>(code: &'static str) -> (CodeMemory, extern "C" fn(T) -> T) {
        let m = compile(code);
        let ptr = m.ptr();

        (m, unsafe { mem::transmute(ptr) })
    }

    #[test]
    fn test_lit_int() {
        assert_eq!(1i32, run("fn f() -> int { return 1; }"));
        assert_eq!(2i32, run("fn f() -> int { return 2; }"));
        assert_eq!(3i32, run("fn f() -> int { return 3; }"));
    }

    #[test]
    fn test_expr_un_plus() {
        let (mem, f) = fct1("fn f(a: int) -> int { return +a; }");

        assert_eq!(-1i32, f(-1));
        assert_eq!(0, f(0));
        assert_eq!(1, f(1));
    }

    #[test]
    fn test_param() {
        let (mem, f) = fct1("fn f(a: int) -> int { return a; }");

        assert_eq!(0i32, f(0));
        assert_eq!(1, f(1));
        assert_eq!(2, f(2));
    }

    #[test]
    fn test_lit_bool() {
        assert_eq!(true, run("fn f() -> bool { return true; }"));
        assert_eq!(false, run("fn f() -> bool { return false; }"));
    }

    #[test]
    fn test_if() {
        assert_eq!(1i32, run("fn f() -> int { if true { return 1; } else { return 2; } }"));
        assert_eq!(1i32, run("fn f() -> int { if true { return 1; } return 2; }"));
        assert_eq!(2i32, run("fn f() -> int { if false { return 1; } else { return 2; } }"));
        assert_eq!(2i32, run("fn f() -> int { if false { return 1; } return 2; }"));
    }

    #[test]
    fn test_ident_load_and_store() {
        assert_eq!(4711, run("fn f() -> int { var a = 4711; return a; }"));
        assert_eq!(true, run("fn f() -> bool { var a = true; return a; }"));
        assert_eq!(false, run("fn f() -> bool { var a = false; return a; }"));
    }
}
<commit_msg>codegen: implemented neg and not<commit_after>use codegen::buffer::*;
use codegen::info;
use codegen::x64::reg::*;
use codegen::x64::reg::Reg::*;
use codegen::x64::emit::*;

use parser::ast::ctxt::*;
use parser::ast::*;
use parser::ast::Expr::*;
use parser::ast::Stmt::*;
use parser::ast::visit::*;

use sym::BuiltinType;

pub struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a Context<'a, 'ast>,
    fct: &'ast Function,
    buf: Buffer,

    stacksize: u32,
    lbl_break: Option<Label>,
    lbl_continue: Option<Label>,
}

impl<'a, 'ast> CodeGen<'a, 'ast> where 'ast: 'a {
    pub fn new(ctxt: &'a Context<'a, 'ast>, fct: &'ast Function) -> CodeGen<'a, 'ast> {
        CodeGen {
            ctxt: ctxt,
            fct: fct,
            buf: Buffer::new(),

            stacksize: ctxt.function(fct.id, |fct| fct.stacksize),
            lbl_break: None,
            lbl_continue: None
        }
    }

    pub fn generate(mut self) -> Buffer {
        info::generate(self.ctxt, self.fct);

        self.emit_prolog();
        self.store_params();
        self.visit_fct(self.fct);
        self.emit_epilog();

        self.buf
    }

    fn store_params(&mut self) {
        let params_len = self.fct.params.len();
        if params_len == 0 { return; }

        let defs = self.ctxt.defs.borrow();

        for (reg, p) in PARAM_REGS.iter().zip(&self.fct.params) {
            let varid = *defs.get(&p.id).unwrap();
            self.emit_var_store(*reg, varid);
        }
    }

    fn emit_prolog(&mut self) {
        emit_pushq_reg(&mut self.buf, Reg::RBP);
        emit_movq_reg_reg(&mut self.buf, Reg::RSP, Reg::RBP);

        if self.stacksize > 0 {
            emit_subq_imm_reg(&mut self.buf, self.stacksize as i32, RSP);
        }
    }

    fn emit_epilog(&mut self) {
        if self.stacksize > 0 {
            emit_addq_imm_reg(&mut self.buf, self.stacksize as i32, RSP);
        }

        emit_popq_reg(&mut self.buf, Reg::RBP);
        emit_retq(&mut self.buf);
    }

    fn emit_stmt_return(&mut self, s: &'ast StmtReturnType) {
        if let Some(ref expr) = s.expr {
            self.visit_expr(expr);
        }

        self.emit_epilog();
    }

    fn emit_stmt_while(&mut self, s: &'ast StmtWhileType) {
        let lbl_start = self.buf.create_label();
        let lbl_end = self.buf.create_label();

        self.buf.define_label(lbl_start);

        // execute condition, when condition is false jump to
        // end of while
        self.visit_expr(&s.cond);
        emit_testl_reg_reg(&mut self.buf, RAX, RAX);
        emit_jz(&mut self.buf, lbl_end);

        self.save_label_state(lbl_end, lbl_start, |this| {
            // execute while body, then jump back to condition
            this.visit_stmt(&s.block);
            emit_jmp(&mut this.buf, lbl_start);
        });

        self.buf.define_label(lbl_end);
    }

    fn emit_stmt_loop(&mut self, s: &'ast StmtLoopType) {
        let lbl_start = self.buf.create_label();
        let lbl_end = self.buf.create_label();
        self.buf.define_label(lbl_start);

        self.save_label_state(lbl_end, lbl_start, |this| {
            this.visit_stmt(&s.block);
        });

        self.buf.define_label(lbl_end);

        emit_jmp(&mut self.buf, lbl_start);
    }

    fn save_label_state<F>(&mut self, lbl_break: Label, lbl_continue: Label, f: F)
            where F: FnOnce(&mut CodeGen<'a, 'ast>) {
        let old_lbl_break = self.lbl_break;
        let old_lbl_continue = self.lbl_continue;

        self.lbl_break = Some(lbl_break);
        self.lbl_continue = Some(lbl_continue);

        f(self);

        self.lbl_break = old_lbl_break;
        self.lbl_continue = old_lbl_continue;
    }

    fn emit_stmt_if(&mut self, s: &'ast StmtIfType) {
        let lbl_end = self.buf.create_label();
        let lbl_else = if let Some(_) = s.else_block {
            self.buf.create_label()
        } else {
            lbl_end
        };

        self.visit_expr(&s.cond);
        emit_testl_reg_reg(&mut self.buf, RAX, RAX);
        emit_jz(&mut self.buf, lbl_else);

        self.visit_stmt(&s.then_block);

        if let Some(ref else_block) = s.else_block {
            emit_jmp(&mut self.buf, lbl_end);
            self.buf.define_label(lbl_else);

            self.visit_stmt(else_block);
        }

        self.buf.define_label(lbl_end);
    }

    fn emit_stmt_break(&mut self, s: &'ast StmtBreakType)  {
        emit_jmp(&mut self.buf, self.lbl_break.unwrap());
    }

    fn emit_stmt_continue(&mut self, s: &'ast StmtContinueType) {
        emit_jmp(&mut self.buf, self.lbl_continue.unwrap());
    }

    fn emit_stmt_expr(&mut self, s: &'ast StmtExprType) {
        self.visit_expr(&s.expr);
    }

    fn emit_stmt_block(&mut self, s: &'ast StmtBlockType) {
        for stmt in &s.stmts {
            self.visit_stmt(stmt);
        }
    }

    fn emit_stmt_var(&mut self, s: &'ast StmtVarType) {
        if let Some(ref expr) = s.expr {
            self.visit_expr(expr);

            let defs = self.ctxt.defs.borrow();
            let varid = *defs.get(&s.id).unwrap();

            self.emit_var_store(RAX, varid);
        }
    }

    fn emit_expr_lit_int(&mut self, lit: &'ast ExprLitIntType) {
        emit_movl_imm_reg(&mut self.buf, lit.value as u32, Reg::RAX);
    }

    fn emit_expr_lit_bool(&mut self, lit: &'ast ExprLitBoolType) {
        let value : u32 = if lit.value { 1 } else { 0 };
        emit_movl_imm_reg(&mut self.buf, value, Reg::RAX);
    }

    fn emit_expr_ident(&mut self, e: &'ast ExprIdentType) {
        let defs = self.ctxt.defs.borrow();
        let varid = *defs.get(&e.id).unwrap();

        self.emit_var_load(varid, RAX);
    }

    fn emit_expr_un(&mut self, e: &'ast ExprUnType) {
        self.visit_expr(&e.opnd);

        match e.op {
            UnOp::Plus => {},
            UnOp::Neg => emit_negl_reg(&mut self.buf, RAX),
            UnOp::BitNot => emit_notl_reg(&mut self.buf, RAX),
            _ => unreachable!(),
        }
    }

    fn emit_var_store(&mut self, src: Reg, var: VarInfoId) {
        let var_infos = self.ctxt.var_infos.borrow();
        let var = &var_infos[var.0];

        match var.data_type {
            BuiltinType::Bool => emit_movb_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Int => emit_movl_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Str => emit_movq_reg_memq(&mut self.buf, src, RBP, var.offset),
            BuiltinType::Unit => {},
        }
    }

    fn emit_var_load(&mut self, var: VarInfoId, dest: Reg) {
        let var_infos = self.ctxt.var_infos.borrow();
        let var = &var_infos[var.0];

        match var.data_type {
            BuiltinType::Bool => emit_movb_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Int => emit_movl_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Str => emit_movq_memq_reg(&mut self.buf, RBP, var.offset, dest),
            BuiltinType::Unit => {},
        }
    }
}

impl<'a, 'ast> visit::Visitor<'ast> for CodeGen<'a, 'ast> {
    fn visit_stmt(&mut self, s: &'ast Stmt) {
        match *s {
            StmtExpr(ref stmt) => self.emit_stmt_expr(stmt),
            StmtIf(ref stmt) => self.emit_stmt_if(stmt),
            StmtLoop(ref stmt) => self.emit_stmt_loop(stmt),
            StmtWhile(ref stmt) => self.emit_stmt_while(stmt),
            StmtReturn(ref stmt) => self.emit_stmt_return(stmt),
            StmtBreak(ref stmt) => self.emit_stmt_break(stmt),
            StmtContinue(ref stmt) => self.emit_stmt_continue(stmt),
            StmtBlock(ref stmt) => self.emit_stmt_block(stmt),
            StmtVar(ref stmt) => self.emit_stmt_var(stmt),
        }
    }

    fn visit_expr(&mut self, e: &'ast Expr) {
        match *e {
            ExprLitInt(ref expr) => self.emit_expr_lit_int(expr),
            ExprLitBool(ref expr) => self.emit_expr_lit_bool(expr),
            ExprIdent(ref expr) => self.emit_expr_ident(expr),
            ExprUn(ref expr) => self.emit_expr_un(expr),
            _ => unreachable!()
        }
    }
}

#[cfg(test)]
mod tests {
    use std::mem;

    use codegen;
    use driver;
    use mem::CodeMemory;
    use semck;
    use test;

    use super::*;

    fn compile(code: &'static str) -> CodeMemory {
        test::parse(code, |ctxt| {
            // generate code for first function
            let fct = ctxt.ast.elements[0].to_function().unwrap();
            let buffer = codegen::generate(ctxt, fct);

            driver::dump_asm(&buffer, &ctxt.interner.str(fct.name));

            CodeMemory::new(&buffer)
        })
    }

    fn run<T>(code: &'static str) -> T {
        let mem = compile(code);
        let compiled_fct : extern "C" fn() -> T = unsafe { mem::transmute(mem.ptr()) };

        compiled_fct()
    }

    fn fct1<T>(code: &'static str) -> (CodeMemory, extern "C" fn(T) -> T) {
        let m = compile(code);
        let ptr = m.ptr();

        (m, unsafe { mem::transmute(ptr) })
    }

    #[test]
    fn test_lit_int() {
        assert_eq!(1i32, run("fn f() -> int { return 1; }"));
        assert_eq!(2i32, run("fn f() -> int { return 2; }"));
        assert_eq!(3i32, run("fn f() -> int { return 3; }"));
    }

    #[test]
    fn test_expr_un_plus() {
        let (mem, f) = fct1("fn f(a: int) -> int { return +a; }");

        assert_eq!(-1i32, f(-1));
        assert_eq!(0, f(0));
        assert_eq!(1, f(1));
    }

    #[test]
    fn test_expr_un_neg() {
        let (mem, f) = fct1("fn f(a: int) -> int { return -a; }");

        assert_eq!(1i32, f(-1));
        assert_eq!(0, f(0));
        assert_eq!(-1, f(1));
    }

    #[test]
    fn test_expr_un_bit_not() {
        let (mem, f) = fct1("fn f(a: int) -> int { return ~a; }");

        assert_eq!(0i32, f(-1));
        assert_eq!(-1, f(0));
        assert_eq!(-2, f(1));
    }

    #[test]
    fn test_param() {
        let (mem, f) = fct1("fn f(a: int) -> int { return a; }");

        assert_eq!(0i32, f(0));
        assert_eq!(1, f(1));
        assert_eq!(2, f(2));
    }

    #[test]
    fn test_lit_bool() {
        assert_eq!(true, run("fn f() -> bool { return true; }"));
        assert_eq!(false, run("fn f() -> bool { return false; }"));
    }

    #[test]
    fn test_if() {
        assert_eq!(1i32, run("fn f() -> int { if true { return 1; } else { return 2; } }"));
        assert_eq!(1i32, run("fn f() -> int { if true { return 1; } return 2; }"));
        assert_eq!(2i32, run("fn f() -> int { if false { return 1; } else { return 2; } }"));
        assert_eq!(2i32, run("fn f() -> int { if false { return 1; } return 2; }"));
    }

    #[test]
    fn test_ident_load_and_store() {
        assert_eq!(4711, run("fn f() -> int { var a = 4711; return a; }"));
        assert_eq!(true, run("fn f() -> bool { var a = true; return a; }"));
        assert_eq!(false, run("fn f() -> bool { var a = false; return a; }"));
    }
}
<|endoftext|>


<commit_before>extern crate clap;

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

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}", config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}", config.version.unwrap(), config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ()
        },
        Some(_) => profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
            .expect("Could not create source-groonga.ps1"),
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}
<commit_msg>rustfmt<commit_after>extern crate clap;

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

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::Client;
use util;
use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    if !env::home_dir()
        .unwrap()
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = Client::new();
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir)
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::create_profile_source(&config.shim_dir, &groonga_dir, &config.versions_dir)
                .expect("Could not create source-groonga.ps1")
        }
        None => unreachable!(),
    }
}

pub fn versions() {
    let groonga_versioned_dir = util::obtain_groonga_versioned_path();
    let paths = fs::read_dir(&Path::new(&groonga_versioned_dir)).unwrap();

    let names = paths.filter_map(|entry| {
            entry.ok().and_then(|e| {
                e.path()
                    .file_name()
                    .and_then(|n| n.to_str().map(|s| String::from(s)))
            })
        })
        .collect::<Vec<String>>();

    println!("Installed Groonga:");
    println!("\tsystem");
    for entry in names {
        println!("\t{}", entry);
    }
}
<|endoftext|>


<commit_before>use sqlite::{Connection, Statement, State};
use std::mem;
use std::path::Path;

use output::Output;
use streamer::platform::{Platform, Profile};
use streamer::system::{EventKind, Job};
use {Data, Event, Result, System};

pub struct Database {
    #[allow(dead_code)]
    connection: Connection,
    arrivals: Statement<'static>,
    profiles: Statement<'static>,
}

impl Database {
    pub fn new<T: AsRef<Path>>(system: &System, path: T) -> Result<Database> {
        use sql::prelude::*;

        let connection = ok!(Connection::open(path));

        ok!(connection.execute("
            PRAGMA journal_mode = MEMORY;
            PRAGMA synchronous = OFF;
        "));

        ok!(connection.execute({
            ok!(create_table("arrivals").if_not_exists().columns(&[
                "time".float().not_null(),
            ]).compile())
        }));
        ok!(connection.execute({
            ok!(create_table("profiles").if_not_exists().columns(&[
                "time".float().not_null(), "component_id".integer().not_null(),
                "power".float().not_null(), "temperature".float().not_null(),
            ]).compile())
        }));

        ok!(connection.execute(ok!(delete_from("arrivals").compile())));
        ok!(connection.execute(ok!(delete_from("profiles").compile())));

        let arrivals = {
            let statement = ok!(connection.prepare({
                ok!(insert_into("arrivals").columns(&[
                    "time",
                ]).compile())
            }));
            unsafe { mem::transmute(statement) }
        };
        let profiles = {
            let units = system.platform().elements().len();
            let statement = ok!(connection.prepare({
                ok!(insert_into("profiles").columns(&[
                    "time", "component_id", "power", "temperature",
                ]).batch(units).compile())
            }));
            unsafe { mem::transmute(statement) }
        };

        Ok(Database {
            connection: connection,
            arrivals: arrivals,
            profiles: profiles,
        })
    }

    fn write_arrival(&mut self, job: &Job) -> Result<()> {
        let statement = &mut self.arrivals;
        ok!(statement.bind(1, job.arrival));
        if State::Done != ok!(statement.next()) {
            raise!("failed to write into the database");
        }
        Ok(())
    }

    fn write_profile(&mut self, power: &Profile, temperature: &Profile) -> Result<()> {
        let &Profile { units, steps, time, time_step, data: ref power } = power;
        let &Profile { data: ref temperature, .. } = temperature;
        let statement = &mut self.profiles;
        for i in 0..steps {
            let time = time + (i as f64) * time_step;
            ok!(statement.reset());
            let mut k = 0;
            for j in 0..units {
                ok!(statement.bind(k + 1, time));
                ok!(statement.bind(k + 2, j as i64));
                ok!(statement.bind(k + 3, power[i * units + j]));
                ok!(statement.bind(k + 4, temperature[i * units + j]));
                k += 4;
            }
            if State::Done != ok!(statement.next()) {
                raise!("failed to write into the database");
            }
        }
        Ok(())
    }
}

impl Output for Database {
    fn next(&mut self, event: &Event, &(ref power, ref temperature): &Data) -> Result<()> {
        ok!(self.connection.execute("BEGIN TRANSACTION"));
        if let &EventKind::Arrived(ref job) = &event.kind {
            ok!(self.write_arrival(job));
        }
        ok!(self.write_profile(power, temperature));
        ok!(self.connection.execute("END TRANSACTION"));
        Ok(())
    }
}
<commit_msg>bin: fix the dumping of arrival times<commit_after>use sqlite::{Connection, Statement, State};
use std::mem;
use std::path::Path;

use output::Output;
use streamer::platform::{Platform, Profile};
use streamer::system::{EventKind, Job};
use {Data, Event, Result, System};

pub struct Database {
    #[allow(dead_code)]
    connection: Connection,
    arrivals: Statement<'static>,
    profiles: Statement<'static>,
}

impl Database {
    pub fn new<T: AsRef<Path>>(system: &System, path: T) -> Result<Database> {
        use sql::prelude::*;

        let connection = ok!(Connection::open(path));

        ok!(connection.execute("
            PRAGMA journal_mode = MEMORY;
            PRAGMA synchronous = OFF;
        "));

        ok!(connection.execute({
            ok!(create_table("arrivals").if_not_exists().columns(&[
                "time".float().not_null(),
            ]).compile())
        }));
        ok!(connection.execute({
            ok!(create_table("profiles").if_not_exists().columns(&[
                "time".float().not_null(), "component_id".integer().not_null(),
                "power".float().not_null(), "temperature".float().not_null(),
            ]).compile())
        }));

        ok!(connection.execute(ok!(delete_from("arrivals").compile())));
        ok!(connection.execute(ok!(delete_from("profiles").compile())));

        let arrivals = {
            let statement = ok!(connection.prepare({
                ok!(insert_into("arrivals").columns(&[
                    "time",
                ]).compile())
            }));
            unsafe { mem::transmute(statement) }
        };
        let profiles = {
            let units = system.platform().elements().len();
            let statement = ok!(connection.prepare({
                ok!(insert_into("profiles").columns(&[
                    "time", "component_id", "power", "temperature",
                ]).batch(units).compile())
            }));
            unsafe { mem::transmute(statement) }
        };

        Ok(Database {
            connection: connection,
            arrivals: arrivals,
            profiles: profiles,
        })
    }

    fn write_arrival(&mut self, job: &Job) -> Result<()> {
        let statement = &mut self.arrivals;
        ok!(statement.reset());
        ok!(statement.bind(1, job.arrival));
        if State::Done != ok!(statement.next()) {
            raise!("failed to write into the database");
        }
        Ok(())
    }

    fn write_profile(&mut self, power: &Profile, temperature: &Profile) -> Result<()> {
        let &Profile { units, steps, time, time_step, data: ref power } = power;
        let &Profile { data: ref temperature, .. } = temperature;
        let statement = &mut self.profiles;
        for i in 0..steps {
            let time = time + (i as f64) * time_step;
            ok!(statement.reset());
            let mut k = 0;
            for j in 0..units {
                ok!(statement.bind(k + 1, time));
                ok!(statement.bind(k + 2, j as i64));
                ok!(statement.bind(k + 3, power[i * units + j]));
                ok!(statement.bind(k + 4, temperature[i * units + j]));
                k += 4;
            }
            if State::Done != ok!(statement.next()) {
                raise!("failed to write into the database");
            }
        }
        Ok(())
    }
}

impl Output for Database {
    fn next(&mut self, event: &Event, &(ref power, ref temperature): &Data) -> Result<()> {
        ok!(self.connection.execute("BEGIN TRANSACTION"));
        if let &EventKind::Arrived(ref job) = &event.kind {
            ok!(self.write_arrival(job));
        }
        ok!(self.write_profile(power, temperature));
        ok!(self.connection.execute("END TRANSACTION"));
        Ok(())
    }
}
<|endoftext|>