<commit_before>#![feature(rustc_private)]
extern crate miri;
extern crate getopts;
extern crate rustc;
extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate syntax;

use std::path::{PathBuf, Path};
use std::io::Write;
use std::sync::{Mutex, Arc};
use std::io;

use rustc::session::Session;
use rustc_metadata::cstore::CStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::ty::TyCtxt;
use syntax::ast;

struct MiriCompilerCalls {
    default: Box<RustcDefaultCalls>,
    /// whether we are building for the host
    host_target: bool,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType
    ) -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        trans: &CodegenBackend,
        matches: &getopts::Matches,
        sess: &Session,
        cstore: &CStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
    }
    fn build_controller(self: Box<Self>, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
        let this = *self;
        let mut control = this.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if !this.host_target {
            // only fully compile targets on the host
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (String::from("miri"), syntax::feature_gate::AttributeType::Whitelisted);
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>, &'a CompileState<'a, 'tcx>);
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::ItemKind::Fn(.., body_id) = i.node {
                    if i.attrs.iter().any(|attr| attr.name() == "test") {
                        let did = self.0.hir.body_owner_def_id(body_id);
                        println!("running test: {}", self.0.def_path_debug_str(did));
                        miri::eval_main(self.0, did, None);
                        self.1.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
    } else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        miri::eval_main(tcx, entry_def_id, None);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn main() {
    let path = option_env!("MIRI_RUSTC_TEST")
        .map(String::from)
        .unwrap_or_else(|| {
            std::env::var("MIRI_RUSTC_TEST")
                .expect("need to set MIRI_RUSTC_TEST to path of rustc tests")
        });

    let mut mir_not_found = Vec::new();
    let mut crate_not_found = Vec::new();
    let mut success = 0;
    let mut failed = Vec::new();
    let mut c_abi_fns = Vec::new();
    let mut abi = Vec::new();
    let mut unsupported = Vec::new();
    let mut unimplemented_intrinsic = Vec::new();
    let mut limits = Vec::new();
    let mut files: Vec<_> = std::fs::read_dir(path).unwrap().collect();
    while let Some(file) = files.pop() {
        let file = file.unwrap();
        let path = file.path();
        if file.metadata().unwrap().is_dir() {
            if !path.to_str().unwrap().ends_with("auxiliary") {
                // add subdirs recursively
                files.extend(std::fs::read_dir(path).unwrap());
            }
            continue;
        }
        if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
            continue;
        }
        let stderr = std::io::stderr();
        write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
        let mut host_target = false;
        let mut args: Vec<String> = std::env::args().filter(|arg| {
            if arg == "--miri_host_target" {
                host_target = true;
                false // remove the flag, rustc doesn't know it
            } else {
                true
            }
        }).collect();
        // file to process
        args.push(path.display().to_string());

        let sysroot_flag = String::from("--sysroot");
        if !args.contains(&sysroot_flag) {
            args.push(sysroot_flag);
            args.push(Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST").display().to_string());
        }

        args.push("-Zmir-opt-level=3".to_owned());
        // for auxilary builds in unit tests
        args.push("-Zalways-encode-mir".to_owned());

        // A threadsafe buffer for writing.
        #[derive(Default, Clone)]
        struct BufWriter(Arc<Mutex<Vec<u8>>>);

        impl Write for BufWriter {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.0.lock().unwrap().write(buf)
            }
            fn flush(&mut self) -> io::Result<()> {
                self.0.lock().unwrap().flush()
            }
        }
        let buf = BufWriter::default();
        let output = buf.clone();
        let result = std::panic::catch_unwind(|| {
            rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
                default: Box::new(RustcDefaultCalls),
                host_target,
            }), None, Some(Box::new(buf)));
        });

        match result {
            Ok(()) => {
                success += 1;
                writeln!(stderr.lock(), "ok").unwrap()
            },
            Err(_) => {
                let output = output.0.lock().unwrap();
                let output_err = std::str::from_utf8(&output).unwrap();
                if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                    let end = text.find('`').unwrap();
                    mir_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                    let end = text.find('`').unwrap();
                    crate_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                } else {
                    for text in output_err.split("error: ").skip(1) {
                        let end = text.find('\n').unwrap_or(text.len());
                        let c_abi = "can't call C ABI function: ";
                        let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                        let unsupported_s = "miri does not support ";
                        let abi_s = "can't handle function with ";
                        let limit_s = "reached the configured maximum ";
                        if text.starts_with(c_abi) {
                            c_abi_fns.push(text[c_abi.len()..end].to_string());
                        } else if text.starts_with(unimplemented_intrinsic_s) {
                            unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                        } else if text.starts_with(unsupported_s) {
                            unsupported.push(text[unsupported_s.len()..end].to_string());
                        } else if text.starts_with(abi_s) {
                            abi.push(text[abi_s.len()..end].to_string());
                        } else if text.starts_with(limit_s) {
                            limits.push(text[limit_s.len()..end].to_string());
                        } else if text.find("aborting").is_none() {
                            failed.push(text[..end].to_string());
                        }
                    }
                    writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                }
            }
        }
    }
    let stderr = std::io::stderr();
    let mut stderr = stderr.lock();
    writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                        {} C fn, {} ABI, {} unsupported, {} intrinsic",
                        success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                        c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
    writeln!(stderr, "# The \"other reasons\" errors").unwrap();
    writeln!(stderr, "(sorted, deduplicated)").unwrap();
    print_vec(&mut stderr, failed);

    writeln!(stderr, "# can't call C ABI function").unwrap();
    print_vec(&mut stderr, c_abi_fns);

    writeln!(stderr, "# unsupported ABI").unwrap();
    print_vec(&mut stderr, abi);

    writeln!(stderr, "# unsupported").unwrap();
    print_vec(&mut stderr, unsupported);

    writeln!(stderr, "# unimplemented intrinsics").unwrap();
    print_vec(&mut stderr, unimplemented_intrinsic);

    writeln!(stderr, "# mir not found").unwrap();
    print_vec(&mut stderr, mir_not_found);

    writeln!(stderr, "# crate not found").unwrap();
    print_vec(&mut stderr, crate_not_found);
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        for next in &mut v {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<commit_msg>fix rustc_test compilation<commit_after>#![feature(rustc_private)]
extern crate miri;
extern crate getopts;
extern crate rustc;
extern crate rustc_metadata;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_codegen_utils;
extern crate syntax;

use std::path::{PathBuf, Path};
use std::io::Write;
use std::sync::{Mutex, Arc};
use std::io;

use rustc::session::Session;
use rustc_metadata::cstore::CStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc::ty::TyCtxt;
use syntax::ast;

struct MiriCompilerCalls {
    default: Box<RustcDefaultCalls>,
    /// whether we are building for the host
    host_target: bool,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType
    ) -> Compilation {
        self.default.early_callback(matches, sopts, cfg, descriptions, output)
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(matches, sopts, cfg, odir, ofile, descriptions)
    }
    fn late_callback(
        &mut self,
        trans: &CodegenBackend,
        matches: &getopts::Matches,
        sess: &Session,
        cstore: &CStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
    }
    fn build_controller(self: Box<Self>, sess: &Session, matches: &getopts::Matches) -> CompileController<'a> {
        let this = *self;
        let mut control = this.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if !this.host_target {
            // only fully compile targets on the host
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (String::from("miri"), syntax::feature_gate::AttributeType::Whitelisted);
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>, &'a CompileState<'a, 'tcx>);
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::ItemKind::Fn(.., body_id) = i.node {
                    if i.attrs.iter().any(|attr| attr.name() == "test") {
                        let did = self.0.hir.body_owner_def_id(body_id);
                        println!("running test: {}", self.0.def_path_debug_str(did));
                        miri::eval_main(self.0, did, None, /*validate*/true);
                        self.1.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
    } else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        miri::eval_main(tcx, entry_def_id, None, /*validate*/true);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn main() {
    let path = option_env!("MIRI_RUSTC_TEST")
        .map(String::from)
        .unwrap_or_else(|| {
            std::env::var("MIRI_RUSTC_TEST")
                .expect("need to set MIRI_RUSTC_TEST to path of rustc tests")
        });

    let mut mir_not_found = Vec::new();
    let mut crate_not_found = Vec::new();
    let mut success = 0;
    let mut failed = Vec::new();
    let mut c_abi_fns = Vec::new();
    let mut abi = Vec::new();
    let mut unsupported = Vec::new();
    let mut unimplemented_intrinsic = Vec::new();
    let mut limits = Vec::new();
    let mut files: Vec<_> = std::fs::read_dir(path).unwrap().collect();
    while let Some(file) = files.pop() {
        let file = file.unwrap();
        let path = file.path();
        if file.metadata().unwrap().is_dir() {
            if !path.to_str().unwrap().ends_with("auxiliary") {
                // add subdirs recursively
                files.extend(std::fs::read_dir(path).unwrap());
            }
            continue;
        }
        if !file.metadata().unwrap().is_file() || !path.to_str().unwrap().ends_with(".rs") {
            continue;
        }
        let stderr = std::io::stderr();
        write!(stderr.lock(), "test [miri-pass] {} ... ", path.display()).unwrap();
        let mut host_target = false;
        let mut args: Vec<String> = std::env::args().filter(|arg| {
            if arg == "--miri_host_target" {
                host_target = true;
                false // remove the flag, rustc doesn't know it
            } else {
                true
            }
        }).collect();
        // file to process
        args.push(path.display().to_string());

        let sysroot_flag = String::from("--sysroot");
        if !args.contains(&sysroot_flag) {
            args.push(sysroot_flag);
            args.push(Path::new(&std::env::var("HOME").unwrap()).join(".xargo").join("HOST").display().to_string());
        }

        args.push("-Zmir-opt-level=3".to_owned());
        // for auxilary builds in unit tests
        args.push("-Zalways-encode-mir".to_owned());

        // A threadsafe buffer for writing.
        #[derive(Default, Clone)]
        struct BufWriter(Arc<Mutex<Vec<u8>>>);

        impl Write for BufWriter {
            fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
                self.0.lock().unwrap().write(buf)
            }
            fn flush(&mut self) -> io::Result<()> {
                self.0.lock().unwrap().flush()
            }
        }
        let buf = BufWriter::default();
        let output = buf.clone();
        let result = std::panic::catch_unwind(|| {
            rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
                default: Box::new(RustcDefaultCalls),
                host_target,
            }), None, Some(Box::new(buf)));
        });

        match result {
            Ok(()) => {
                success += 1;
                writeln!(stderr.lock(), "ok").unwrap()
            },
            Err(_) => {
                let output = output.0.lock().unwrap();
                let output_err = std::str::from_utf8(&output).unwrap();
                if let Some(text) = output_err.splitn(2, "no mir for `").nth(1) {
                    let end = text.find('`').unwrap();
                    mir_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "NO MIR FOR `{}`", &text[..end]).unwrap();
                } else if let Some(text) = output_err.splitn(2, "can't find crate for `").nth(1) {
                    let end = text.find('`').unwrap();
                    crate_not_found.push(text[..end].to_string());
                    writeln!(stderr.lock(), "CAN'T FIND CRATE FOR `{}`", &text[..end]).unwrap();
                } else {
                    for text in output_err.split("error: ").skip(1) {
                        let end = text.find('\n').unwrap_or(text.len());
                        let c_abi = "can't call C ABI function: ";
                        let unimplemented_intrinsic_s = "unimplemented intrinsic: ";
                        let unsupported_s = "miri does not support ";
                        let abi_s = "can't handle function with ";
                        let limit_s = "reached the configured maximum ";
                        if text.starts_with(c_abi) {
                            c_abi_fns.push(text[c_abi.len()..end].to_string());
                        } else if text.starts_with(unimplemented_intrinsic_s) {
                            unimplemented_intrinsic.push(text[unimplemented_intrinsic_s.len()..end].to_string());
                        } else if text.starts_with(unsupported_s) {
                            unsupported.push(text[unsupported_s.len()..end].to_string());
                        } else if text.starts_with(abi_s) {
                            abi.push(text[abi_s.len()..end].to_string());
                        } else if text.starts_with(limit_s) {
                            limits.push(text[limit_s.len()..end].to_string());
                        } else if text.find("aborting").is_none() {
                            failed.push(text[..end].to_string());
                        }
                    }
                    writeln!(stderr.lock(), "stderr: \n {}", output_err).unwrap();
                }
            }
        }
    }
    let stderr = std::io::stderr();
    let mut stderr = stderr.lock();
    writeln!(stderr, "{} success, {} no mir, {} crate not found, {} failed, \
                        {} C fn, {} ABI, {} unsupported, {} intrinsic",
                        success, mir_not_found.len(), crate_not_found.len(), failed.len(),
                        c_abi_fns.len(), abi.len(), unsupported.len(), unimplemented_intrinsic.len()).unwrap();
    writeln!(stderr, "# The \"other reasons\" errors").unwrap();
    writeln!(stderr, "(sorted, deduplicated)").unwrap();
    print_vec(&mut stderr, failed);

    writeln!(stderr, "# can't call C ABI function").unwrap();
    print_vec(&mut stderr, c_abi_fns);

    writeln!(stderr, "# unsupported ABI").unwrap();
    print_vec(&mut stderr, abi);

    writeln!(stderr, "# unsupported").unwrap();
    print_vec(&mut stderr, unsupported);

    writeln!(stderr, "# unimplemented intrinsics").unwrap();
    print_vec(&mut stderr, unimplemented_intrinsic);

    writeln!(stderr, "# mir not found").unwrap();
    print_vec(&mut stderr, mir_not_found);

    writeln!(stderr, "# crate not found").unwrap();
    print_vec(&mut stderr, crate_not_found);
}

fn print_vec<W: std::io::Write>(stderr: &mut W, v: Vec<String>) {
    writeln!(stderr, "```").unwrap();
    for (n, s) in vec_to_hist(v).into_iter().rev() {
        writeln!(stderr, "{:4} {}", n, s).unwrap();
    }
    writeln!(stderr, "```").unwrap();
}

fn vec_to_hist<T: PartialEq + Ord>(mut v: Vec<T>) -> Vec<(usize, T)> {
    v.sort();
    let mut v = v.into_iter();
    let mut result = Vec::new();
    let mut current = v.next();
    'outer: while let Some(current_val) = current {
        let mut n = 1;
        for next in &mut v {
            if next == current_val {
                n += 1;
            } else {
                result.push((n, current_val));
                current = Some(next);
                continue 'outer;
            }
        }
        result.push((n, current_val));
        break;
    }
    result.sort();
    result
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]
#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;

use std::io::{self, BufRead, Write};
use std::str::FromStr;
use sysinfo::Signal::*;
use sysinfo::{
    NetworkExt, NetworksExt, Pid, ProcessExt, ProcessorExt, Signal, System, SystemExt, UserExt,
};

const signals: &[Signal] = &[
    Hangup,
    Interrupt,
    Quit,
    Illegal,
    Trap,
    Abort,
    Bus,
    FloatingPointException,
    Kill,
    User1,
    Segv,
    User2,
    Pipe,
    Alarm,
    Term,
    Child,
    Continue,
    Stop,
    TSTP,
    TTIN,
    TTOU,
    Urgent,
    XCPU,
    XFSZ,
    VirtualAlarm,
    Profiling,
    Winch,
    IO,
    Power,
    Sys,
];

fn print_help() {
    writeln!(&mut io::stdout(), "== Help menu ==");
    writeln!(&mut io::stdout(), "help               : show this menu");
    writeln!(
        &mut io::stdout(),
        "signals            : show the available signals"
    );
    writeln!(
        &mut io::stdout(),
        "refresh            : reloads all processes' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh [pid]      : reloads corresponding process' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh_disks      : reloads only disks' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh_users      : reloads only users' information"
    );
    writeln!(
        &mut io::stdout(),
        "show [pid | name]  : show information of the given process \
         corresponding to [pid | name]"
    );
    writeln!(
        &mut io::stdout(),
        "kill [pid] [signal]: send [signal] to the process with this \
         [pid]. 0 < [signal] < 32"
    );
    writeln!(
        &mut io::stdout(),
        "processors         : Displays processors state"
    );
    writeln!(
        &mut io::stdout(),
        "memory             : Displays memory state"
    );
    writeln!(
        &mut io::stdout(),
        "temperature        : Displays components' temperature"
    );
    writeln!(
        &mut io::stdout(),
        "disks              : Displays disks' information"
    );
    writeln!(
        &mut io::stdout(),
        "network            : Displays network' information"
    );
    writeln!(
        &mut io::stdout(),
        "all                : Displays all process name and pid"
    );
    writeln!(
        &mut io::stdout(),
        "uptime             : Displays system uptime"
    );
    writeln!(
        &mut io::stdout(),
        "boot_time          : Displays system boot time"
    );
    writeln!(
        &mut io::stdout(),
        "vendor_id          : Displays processor vendor id"
    );
    writeln!(
        &mut io::stdout(),
        "brand              : Displays processor brand"
    );
    writeln!(
        &mut io::stdout(),
        "load_avg           : Displays system load average"
    );
    writeln!(
        &mut io::stdout(),
        "frequency          : Displays processor frequency"
    );
    writeln!(&mut io::stdout(), "users              : Displays all users");
    writeln!(
        &mut io::stdout(),
        "system             : Displays system information (such as name, version and hostname)"
    );
    writeln!(
        &mut io::stdout(),
        "pid                : Display this example's PID"
    );
    writeln!(&mut io::stdout(), "quit               : Exit the program");
}

fn interpret_input(input: &str, sys: &mut System) -> bool {
    match input.trim() {
        "help" => print_help(),
        "refresh_disks" => {
            writeln!(&mut io::stdout(), "Refreshing disk list...");
            sys.refresh_disks_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "refresh_users" => {
            writeln!(&mut io::stdout(), "Refreshing user list...");
            sys.refresh_users_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "processors" => {
            // Note: you should refresh a few times before using this, so that usage statistics
            // can be ascertained
            writeln!(
                &mut io::stdout(),
                "total process usage: {}%",
                sys.get_global_processor_info().get_cpu_usage()
            );
            for proc_ in sys.get_processors() {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(
                &mut io::stdout(),
                "total memory: {} KB",
                sys.get_total_memory()
            );
            writeln!(
                &mut io::stdout(),
                "used memory : {} KB",
                sys.get_used_memory()
            );
            writeln!(
                &mut io::stdout(),
                "total swap  : {} KB",
                sys.get_total_swap()
            );
            writeln!(
                &mut io::stdout(),
                "used swap   : {} KB",
                sys.get_used_swap()
            );
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_processes() {
                writeln!(
                    &mut io::stdout(),
                    "{}:{} status={:?}",
                    pid,
                    proc_.name(),
                    proc_.status()
                );
            }
        }
        "frequency" => {
            writeln!(
                &mut io::stdout(),
                "{} MHz",
                sys.get_processors()[0].get_frequency()
            );
        }
        "vendor_id" => {
            writeln!(
                &mut io::stdout(),
                "vendor ID: {}",
                sys.get_processors()[0].get_vendor_id()
            );
        }
        "brand" => {
            writeln!(
                &mut io::stdout(),
                "brand: {}",
                sys.get_processors()[0].get_brand()
            );
        }
        "load_avg" => {
            let load_avg = sys.get_load_average();
            writeln!(&mut io::stdout(), "one minute     : {}%", load_avg.one);
            writeln!(&mut io::stdout(), "five minutes   : {}%", load_avg.five);
            writeln!(&mut io::stdout(), "fifteen minutes: {}%", load_avg.fifteen);
        }
        e if e.starts_with("show ") => {
            let tmp: Vec<&str> = e.split(' ').collect();

            if tmp.len() != 2 {
                writeln!(
                    &mut io::stdout(),
                    "show command takes a pid or a name in parameter!"
                );
                writeln!(&mut io::stdout(), "example: show 1254");
            } else if let Ok(pid) = Pid::from_str(tmp[1]) {
                match sys.get_process(pid) {
                    Some(p) => writeln!(&mut io::stdout(), "{:?}", *p),
                    None => writeln!(&mut io::stdout(), "pid \"{:?}\" not found", pid),
                };
            } else {
                let proc_name = tmp[1];
                for proc_ in sys.get_process_by_name(proc_name) {
                    writeln!(&mut io::stdout(), "==== {} ====", proc_.name());
                    writeln!(&mut io::stdout(), "{:?}", proc_);
                }
            }
        }
        "temperature" => {
            for component in sys.get_components() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            for (interface_name, data) in sys.get_networks().iter() {
                writeln!(
                    &mut io::stdout(),
                    "{}:\n  input data  (new / total): {} / {} B\n  output data (new / total): {} / {} B",
                    interface_name,
                    data.get_received(),
                    data.get_total_received(),
                    data.get_transmitted(),
                    data.get_total_transmitted(),
                );
            }
        }
        "show" => {
            writeln!(
                &mut io::stdout(),
                "'show' command expects a pid number or a process name"
            );
        }
        e if e.starts_with("kill ") => {
            let tmp: Vec<&str> = e.split(' ').collect();

            if tmp.len() != 3 {
                writeln!(
                    &mut io::stdout(),
                    "kill command takes the pid and a signal number in parameter !"
                );
                writeln!(&mut io::stdout(), "example: kill 1254 9");
            } else {
                let pid = Pid::from_str(tmp[1]).unwrap();
                let signal = i32::from_str(tmp[2]).unwrap();

                if signal < 1 || signal > 31 {
                    writeln!(
                        &mut io::stdout(),
                        "Signal must be between 0 and 32 ! See the signals list with the \
                         signals command"
                    );
                } else {
                    match sys.get_process(pid) {
                        Some(p) => {
                            writeln!(
                                &mut io::stdout(),
                                "kill: {}",
                                p.kill(*signals.get(signal as usize - 1).unwrap())
                            );
                        }
                        None => {
                            writeln!(&mut io::stdout(), "pid not found");
                        }
                    };
                }
            }
        }
        "disks" => {
            for disk in sys.get_disks() {
                writeln!(&mut io::stdout(), "{:?}", disk);
            }
        }
        "users" => {
            for user in sys.get_users() {
                writeln!(&mut io::stdout(), "{:?}", user.get_name());
            }
        }
        "boot_time" => {
            writeln!(&mut io::stdout(), "{} seconds", sys.get_boot_time());
        }
        "uptime" => {
            let up = sys.get_uptime();
            let mut uptime = sys.get_uptime();
            let days = uptime / 86400;
            uptime -= days * 86400;
            let hours = uptime / 3600;
            uptime -= hours * 3600;
            let minutes = uptime / 60;
            writeln!(
                &mut io::stdout(),
                "{} days {} hours {} minutes ({} seconds in total)",
                days,
                hours,
                minutes,
                up,
            );
        }
        x if x.starts_with("refresh") => {
            if x == "refresh" {
                writeln!(&mut io::stdout(), "Getting processes' information...");
                sys.refresh_all();
                writeln!(&mut io::stdout(), "Done.");
            } else if x.starts_with("refresh ") {
                writeln!(&mut io::stdout(), "Getting process' information...");
                if let Some(pid) = x
                    .split(' ')
                    .filter_map(|pid| pid.parse().ok())
                    .take(1)
                    .next()
                {
                    if sys.refresh_process(pid) {
                        writeln!(&mut io::stdout(), "Process `{}` updated successfully", pid);
                    } else {
                        writeln!(
                            &mut io::stdout(),
                            "Process `{}` couldn't be updated...",
                            pid
                        );
                    }
                } else {
                    writeln!(&mut io::stdout(), "Invalid [pid] received...");
                }
            } else {
                writeln!(
                    &mut io::stdout(),
                    "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                     list.",
                    x
                );
            }
        }
        "pid" => {
            writeln!(
                &mut io::stdout(),
                "PID: {}",
                sysinfo::get_current_pid().expect("failed to get PID")
            );
        }
        "system" => {
            writeln!(
                &mut io::stdout(),
                "System name:           {}\n\
                System kernel version: {}\n\
                System OS version:     {}\n\
                System host name:      {}",
                sys.get_name().unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_kernel_version()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_os_version()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_host_name()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
            );
        }
        e => {
            writeln!(
                &mut io::stdout(),
                "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                 list.",
                e
            );
        }
    }
    false
}

fn main() {
    println!("Getting processes' information...");
    let mut t = System::new_all();
    println!("Done.");
    let t_stin = io::stdin();
    let mut stin = t_stin.lock();
    let mut done = false;

    println!("To get the commands' list, enter 'help'.");
    while !done {
        let mut input = String::new();
        write!(&mut io::stdout(), "> ");
        io::stdout().flush();

        stin.read_line(&mut input);
        if input.is_empty() {
            // The string is empty, meaning there is no '\n', meaning
            // that the user used CTRL+D so we can just quit!
            println!("\nLeaving, bye!");
            break;
        }
        if (&input as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<commit_msg>Add physical core count information to processor command in example<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]
#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;

use std::io::{self, BufRead, Write};
use std::str::FromStr;
use sysinfo::Signal::*;
use sysinfo::{
    NetworkExt, NetworksExt, Pid, ProcessExt, ProcessorExt, Signal, System, SystemExt, UserExt,
};

const signals: &[Signal] = &[
    Hangup,
    Interrupt,
    Quit,
    Illegal,
    Trap,
    Abort,
    Bus,
    FloatingPointException,
    Kill,
    User1,
    Segv,
    User2,
    Pipe,
    Alarm,
    Term,
    Child,
    Continue,
    Stop,
    TSTP,
    TTIN,
    TTOU,
    Urgent,
    XCPU,
    XFSZ,
    VirtualAlarm,
    Profiling,
    Winch,
    IO,
    Power,
    Sys,
];

fn print_help() {
    writeln!(&mut io::stdout(), "== Help menu ==");
    writeln!(&mut io::stdout(), "help               : show this menu");
    writeln!(
        &mut io::stdout(),
        "signals            : show the available signals"
    );
    writeln!(
        &mut io::stdout(),
        "refresh            : reloads all processes' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh [pid]      : reloads corresponding process' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh_disks      : reloads only disks' information"
    );
    writeln!(
        &mut io::stdout(),
        "refresh_users      : reloads only users' information"
    );
    writeln!(
        &mut io::stdout(),
        "show [pid | name]  : show information of the given process \
         corresponding to [pid | name]"
    );
    writeln!(
        &mut io::stdout(),
        "kill [pid] [signal]: send [signal] to the process with this \
         [pid]. 0 < [signal] < 32"
    );
    writeln!(
        &mut io::stdout(),
        "processors         : Displays processors state"
    );
    writeln!(
        &mut io::stdout(),
        "memory             : Displays memory state"
    );
    writeln!(
        &mut io::stdout(),
        "temperature        : Displays components' temperature"
    );
    writeln!(
        &mut io::stdout(),
        "disks              : Displays disks' information"
    );
    writeln!(
        &mut io::stdout(),
        "network            : Displays network' information"
    );
    writeln!(
        &mut io::stdout(),
        "all                : Displays all process name and pid"
    );
    writeln!(
        &mut io::stdout(),
        "uptime             : Displays system uptime"
    );
    writeln!(
        &mut io::stdout(),
        "boot_time          : Displays system boot time"
    );
    writeln!(
        &mut io::stdout(),
        "vendor_id          : Displays processor vendor id"
    );
    writeln!(
        &mut io::stdout(),
        "brand              : Displays processor brand"
    );
    writeln!(
        &mut io::stdout(),
        "load_avg           : Displays system load average"
    );
    writeln!(
        &mut io::stdout(),
        "frequency          : Displays processor frequency"
    );
    writeln!(&mut io::stdout(), "users              : Displays all users");
    writeln!(
        &mut io::stdout(),
        "system             : Displays system information (such as name, version and hostname)"
    );
    writeln!(
        &mut io::stdout(),
        "pid                : Display this example's PID"
    );
    writeln!(&mut io::stdout(), "quit               : Exit the program");
}

fn interpret_input(input: &str, sys: &mut System) -> bool {
    match input.trim() {
        "help" => print_help(),
        "refresh_disks" => {
            writeln!(&mut io::stdout(), "Refreshing disk list...");
            sys.refresh_disks_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "refresh_users" => {
            writeln!(&mut io::stdout(), "Refreshing user list...");
            sys.refresh_users_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "processors" => {
            // Note: you should refresh a few times before using this, so that usage statistics
            // can be ascertained
            writeln!(
                &mut io::stdout(),
                "number of physical cores: {}",
                sys.get_physical_core_count()
                    .map(|c| c.to_string())
                    .unwrap_or_else(|| "Unknown".to_owned()),
            );
            writeln!(
                &mut io::stdout(),
                "total process usage: {}%",
                sys.get_global_processor_info().get_cpu_usage()
            );
            for proc_ in sys.get_processors() {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(
                &mut io::stdout(),
                "total memory: {} KB",
                sys.get_total_memory()
            );
            writeln!(
                &mut io::stdout(),
                "used memory : {} KB",
                sys.get_used_memory()
            );
            writeln!(
                &mut io::stdout(),
                "total swap  : {} KB",
                sys.get_total_swap()
            );
            writeln!(
                &mut io::stdout(),
                "used swap   : {} KB",
                sys.get_used_swap()
            );
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_processes() {
                writeln!(
                    &mut io::stdout(),
                    "{}:{} status={:?}",
                    pid,
                    proc_.name(),
                    proc_.status()
                );
            }
        }
        "frequency" => {
            writeln!(
                &mut io::stdout(),
                "{} MHz",
                sys.get_processors()[0].get_frequency()
            );
        }
        "vendor_id" => {
            writeln!(
                &mut io::stdout(),
                "vendor ID: {}",
                sys.get_processors()[0].get_vendor_id()
            );
        }
        "brand" => {
            writeln!(
                &mut io::stdout(),
                "brand: {}",
                sys.get_processors()[0].get_brand()
            );
        }
        "load_avg" => {
            let load_avg = sys.get_load_average();
            writeln!(&mut io::stdout(), "one minute     : {}%", load_avg.one);
            writeln!(&mut io::stdout(), "five minutes   : {}%", load_avg.five);
            writeln!(&mut io::stdout(), "fifteen minutes: {}%", load_avg.fifteen);
        }
        e if e.starts_with("show ") => {
            let tmp: Vec<&str> = e.split(' ').collect();

            if tmp.len() != 2 {
                writeln!(
                    &mut io::stdout(),
                    "show command takes a pid or a name in parameter!"
                );
                writeln!(&mut io::stdout(), "example: show 1254");
            } else if let Ok(pid) = Pid::from_str(tmp[1]) {
                match sys.get_process(pid) {
                    Some(p) => writeln!(&mut io::stdout(), "{:?}", *p),
                    None => writeln!(&mut io::stdout(), "pid \"{:?}\" not found", pid),
                };
            } else {
                let proc_name = tmp[1];
                for proc_ in sys.get_process_by_name(proc_name) {
                    writeln!(&mut io::stdout(), "==== {} ====", proc_.name());
                    writeln!(&mut io::stdout(), "{:?}", proc_);
                }
            }
        }
        "temperature" => {
            for component in sys.get_components() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            for (interface_name, data) in sys.get_networks().iter() {
                writeln!(
                    &mut io::stdout(),
                    "{}:\n  input data  (new / total): {} / {} B\n  output data (new / total): {} / {} B",
                    interface_name,
                    data.get_received(),
                    data.get_total_received(),
                    data.get_transmitted(),
                    data.get_total_transmitted(),
                );
            }
        }
        "show" => {
            writeln!(
                &mut io::stdout(),
                "'show' command expects a pid number or a process name"
            );
        }
        e if e.starts_with("kill ") => {
            let tmp: Vec<&str> = e.split(' ').collect();

            if tmp.len() != 3 {
                writeln!(
                    &mut io::stdout(),
                    "kill command takes the pid and a signal number in parameter !"
                );
                writeln!(&mut io::stdout(), "example: kill 1254 9");
            } else {
                let pid = Pid::from_str(tmp[1]).unwrap();
                let signal = i32::from_str(tmp[2]).unwrap();

                if signal < 1 || signal > 31 {
                    writeln!(
                        &mut io::stdout(),
                        "Signal must be between 0 and 32 ! See the signals list with the \
                         signals command"
                    );
                } else {
                    match sys.get_process(pid) {
                        Some(p) => {
                            writeln!(
                                &mut io::stdout(),
                                "kill: {}",
                                p.kill(*signals.get(signal as usize - 1).unwrap())
                            );
                        }
                        None => {
                            writeln!(&mut io::stdout(), "pid not found");
                        }
                    };
                }
            }
        }
        "disks" => {
            for disk in sys.get_disks() {
                writeln!(&mut io::stdout(), "{:?}", disk);
            }
        }
        "users" => {
            for user in sys.get_users() {
                writeln!(&mut io::stdout(), "{:?}", user.get_name());
            }
        }
        "boot_time" => {
            writeln!(&mut io::stdout(), "{} seconds", sys.get_boot_time());
        }
        "uptime" => {
            let up = sys.get_uptime();
            let mut uptime = sys.get_uptime();
            let days = uptime / 86400;
            uptime -= days * 86400;
            let hours = uptime / 3600;
            uptime -= hours * 3600;
            let minutes = uptime / 60;
            writeln!(
                &mut io::stdout(),
                "{} days {} hours {} minutes ({} seconds in total)",
                days,
                hours,
                minutes,
                up,
            );
        }
        x if x.starts_with("refresh") => {
            if x == "refresh" {
                writeln!(&mut io::stdout(), "Getting processes' information...");
                sys.refresh_all();
                writeln!(&mut io::stdout(), "Done.");
            } else if x.starts_with("refresh ") {
                writeln!(&mut io::stdout(), "Getting process' information...");
                if let Some(pid) = x
                    .split(' ')
                    .filter_map(|pid| pid.parse().ok())
                    .take(1)
                    .next()
                {
                    if sys.refresh_process(pid) {
                        writeln!(&mut io::stdout(), "Process `{}` updated successfully", pid);
                    } else {
                        writeln!(
                            &mut io::stdout(),
                            "Process `{}` couldn't be updated...",
                            pid
                        );
                    }
                } else {
                    writeln!(&mut io::stdout(), "Invalid [pid] received...");
                }
            } else {
                writeln!(
                    &mut io::stdout(),
                    "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                     list.",
                    x
                );
            }
        }
        "pid" => {
            writeln!(
                &mut io::stdout(),
                "PID: {}",
                sysinfo::get_current_pid().expect("failed to get PID")
            );
        }
        "system" => {
            writeln!(
                &mut io::stdout(),
                "System name:           {}\n\
                System kernel version: {}\n\
                System OS version:     {}\n\
                System host name:      {}",
                sys.get_name().unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_kernel_version()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_os_version()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
                sys.get_host_name()
                    .unwrap_or_else(|| "<unknown>".to_owned()),
            );
        }
        e => {
            writeln!(
                &mut io::stdout(),
                "\"{}\": Unknown command. Enter 'help' if you want to get the commands' \
                 list.",
                e
            );
        }
    }
    false
}

fn main() {
    println!("Getting processes' information...");
    let mut t = System::new_all();
    println!("Done.");
    let t_stin = io::stdin();
    let mut stin = t_stin.lock();
    let mut done = false;

    println!("To get the commands' list, enter 'help'.");
    while !done {
        let mut input = String::new();
        write!(&mut io::stdout(), "> ");
        io::stdout().flush();

        stin.read_line(&mut input);
        if input.is_empty() {
            // The string is empty, meaning there is no '\n', meaning
            // that the user used CTRL+D so we can just quit!
            println!("\nLeaving, bye!");
            break;
        }
        if (&input as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<|endoftext|>


<commit_before>extern crate cgmath;
extern crate froggy;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use gfx::format::{I8Norm, U8Norm};

pub type ColorFormat = gfx::format::Srgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 4] = "a_Pos",
        normal: [I8Norm; 4] = "a_Normal",
    }

    vertex Instance {
        offset_scale: [f32; 4] = "a_OffsetScale",
        rotation: [f32; 4] = "a_Rotation",
        color: [U8Norm; 4] = "a_Color",
    }

    constant Globals {
        light_pos: [f32; 4] = "u_LightPos",
        light_color: [f32; 4] = "u_LightColor",
    }

    pipeline pipe {
        vert_buf: gfx::VertexBuffer<Vertex> = (),
        inst_buf: gfx::InstanceBuffer<Instance> = (),
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

fn vertex(x: i8, y: i8, z: i8, nx: i8, ny: i8, nz: i8) -> Vertex {
    Vertex {
        pos: [x as f32, y as f32, z as f32, 1.0],
        normal: I8Norm::cast4([nx, ny, nz, 0]),
    }
}

const CODE_VS: &'static [u8] = b"
    #version 150 core
    in vec4 a_Pos;

    vec3 rotate_vector(vec4 quat, vec3 vec)
    {
        return vec + 2.0 * cross(cross(vec, quat.xyz) + quat.w * vec, quat.xyz);
    }

    void main() {
        gl_Position = a_Pos;
    }
";

const CODE_FS: &'static [u8] = b"
    #version 150 core
    void main() {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
";

fn main() {
    use gfx::traits::{Device, FactoryExt};

    let builder = glutin::WindowBuilder::new()
        .with_title("Froggy Cubes demo".to_string())
        .with_vsync();
    let (window, mut device, mut factory, main_color, _main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);

    let mut encoder = gfx::Encoder::from(factory.create_command_buffer());
    let pso = factory.create_pipeline_simple(CODE_VS, CODE_FS, pipe::new()).unwrap();

    'main: loop {
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => (),
            }
        }
        // draw -- start
        encoder.clear(&main_color, [0.1, 0.2, 0.3, 1.0]);
        // draw -- end
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<commit_msg>Cubes - cgmath hookup and cube construction<commit_after>extern crate cgmath;
extern crate froggy;
#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use cgmath::{EuclideanSpace, Transform};
use gfx::traits::{Device, Factory, FactoryExt};

pub type ColorFormat = gfx::format::Srgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_defines!{
    vertex Vertex {
        pos: [f32; 4] = "a_Pos",
        normal: [i8; 4] = "a_Normal",
    }

    vertex Instance {
        offset_scale: [f32; 4] = "a_OffsetScale",
        rotation: [f32; 4] = "a_Rotation",
        color: [f32; 4] = "a_Color",
    }

    constant Globals {
        projection: [[f32; 4]; 4] = "u_Projection",
        light_pos: [f32; 4] = "u_LightPos",
        light_color: [f32; 4] = "u_LightColor",
    }

    pipeline pipe {
        vert_buf: gfx::VertexBuffer<Vertex> = (),
        inst_buf: gfx::InstanceBuffer<Instance> = (),
        globals: gfx::ConstantBuffer<Globals> = "b_Globals",
        out_color: gfx::RenderTarget<ColorFormat> = "Target0",
        out_depth: gfx::DepthTarget<DepthFormat> = gfx::preset::depth::LESS_EQUAL_WRITE,
    }
}

fn vertex(x: i8, y: i8, z: i8, nx: i8, ny: i8, nz: i8) -> Vertex {
    Vertex {
        pos: [x as f32, y as f32, z as f32, 1.0],
        normal: [nx, ny, nz, 0],
    }
}

const CODE_VS: &'static [u8] = b"
    #version 150 core
    in vec4 a_Pos;

    uniform b_Globals {
        mat4 u_Projection;
        vec4 u_LightPos;
        vec4 u_LightColor;
    };

    vec3 rotate_vector(vec4 quat, vec3 vec) {
        return vec + 2.0 * cross(cross(vec, quat.xyz) + quat.w * vec, quat.xyz);
    }

    void main() {
        gl_Position = u_Projection * a_Pos;
    }
";

const CODE_FS: &'static [u8] = b"
    #version 150 core
    void main() {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
";

fn create_cube<R: gfx::Resources, F: gfx::Factory<R>>(factory: &mut F)
               -> (gfx::handle::Buffer<R, Vertex>, gfx::Slice<R>)
{
    let vertices = [
        // bottom
        vertex(1, 1, -1, 0, 0, -1),
        vertex(1, -1, -1, 0, 0, -1),
        vertex(-1, -1, -1, 0, 0, -1),
        vertex(-1, 1, -1, 0, 0, -1),
        // top
        vertex(1, 1, 1, 0, 0, 1),
        vertex(1, -1, 1, 0, 0, 1),
        vertex(-1, -1, 1, 0, 0, 1),
        vertex(-1, 1, 1, 0, 0, 1),
        // left
        vertex(-1, 1, 1, -1, 0, 0),
        vertex(-1, 1, -1, -1, 0, 0),
        vertex(-1, -1, -1, -1, 0, 0),
        vertex(-1, -1, 1, -1, 0, 0),
        // right
        vertex(1, 1, 1, 1, 0, 0),
        vertex(1, 1, -1, 1, 0, 0),
        vertex(1, -1, -1, 1, 0, 0),
        vertex(1, -1, 1, 1, 0, 0),
        // front
        vertex(1, -1, 1, 0, -1, 0),
        vertex(1, -1, -1, 0, -1, 0),
        vertex(-1, -1, -1, 0, -1, 0),
        vertex(-1, -1, 1, 0, -1, 0),
        // back
        vertex(1, 1, 1, 0, 1, 0),
        vertex(1, 1, -1, 0, 1, 0),
        vertex(-1, 1, -1, 0, 1, 0),
        vertex(-1, 1, 1, 0, 1, 0),
    ];

    let indices = [
        0u16, 1, 2, 0, 2, 3,
        4, 5, 6, 4, 6, 7,
        8, 9, 10, 8, 10, 11,
        12, 13, 14, 12, 14, 15,
        16, 17, 18, 16, 18, 19,
        20, 21, 22, 20, 22, 23,
    ];

    factory.create_vertex_buffer_with_slice(&vertices, &indices[..])
}

fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_title("Froggy Cubes demo".to_string())
        .with_vsync();
    let (window, mut device, mut factory, main_color, main_depth) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let mut encoder = gfx::Encoder::from(factory.create_command_buffer());

    let (cube_vbuf, cube_slice) = create_cube(&mut factory);
    let instances = [
        Instance {
            offset_scale: [0.0, 0.0, 0.0, 1.0],
            rotation: [0.0, 0.0, 0.0, 1.0],
            color: [1.0, 1.0, 1.0, 1.0],
        },
    ];
    let cube_ibuf = factory.create_buffer(1, gfx::buffer::Role::Vertex,
        gfx::memory::Usage::Dynamic, gfx::Bind::empty()).unwrap();
    encoder.update_buffer(&cube_ibuf, &instances, 0).unwrap();

    let mx_proj = {
        let (w, h, _, _) = main_color.get_dimensions();
        let fovy = cgmath::Deg(60.0);
        let aspect = w as f32 / h as f32;
        let perspective = cgmath::perspective(fovy, aspect, 1.0, 100.0);
        let view: cgmath::Matrix4<f32> = Transform::look_at(
            cgmath::Point3::new(-2.0, -10.0, 4.0),
            cgmath::Point3::origin(),
            cgmath::Vector3::unit_z());
        perspective * view
    };
    let global_buf = factory.create_constant_buffer(1);
    encoder.update_constant_buffer(&global_buf, &Globals {
        projection: mx_proj.into(),
        light_pos: [10.0, 10.0, 10.0, 1.0],
        light_color: [1.0, 1.0, 0.0, 1.0],
    });

    let pso = factory.create_pipeline_simple(CODE_VS, CODE_FS, pipe::new()).unwrap();
    let data = pipe::Data {
        vert_buf: cube_vbuf,
        inst_buf: cube_ibuf,
        globals: global_buf,
        out_color: main_color,
        out_depth: main_depth,
    };

    'main: loop {
        for event in window.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => (),
            }
        }
        // draw -- start
        encoder.clear_depth(&data.out_depth, 1.0);
        encoder.clear(&data.out_color, [0.1, 0.2, 0.3, 1.0]);
        encoder.draw(&cube_slice, &pso, &data);
        // draw -- end
        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon and Hound to decode a
// flac file. This can be done more efficiently, but it is also more verbose.
// See the `decode` example for that.

extern crate claxon;
extern crate walkdir;
extern crate time;

use time::PreciseTime;
use std::io::{Seek, SeekFrom};

fn main() {
    use std::ffi::OsStr;
    let mut file_times_us = Vec::new();
    let mut bytes_per_sec = Vec::new();

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok())
        .take(1024);

    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            let epoch = PreciseTime::now();

            let reader = claxon::FlacReader::open(path).unwrap();

            // Note that these are not optimized away even though the results
            // are not used, because the expectation may fail.
            reader.get_tag("DATE").next().expect("DATE");
            reader.get_tag("ORIGINALDATE").next().expect("ORIGINALDATE");
            reader.get_tag("TITLE").next().expect("TITLE");
            reader.get_tag("ALBUM").next().expect("ALBUM");
            reader.get_tag("ALBUMARTIST").next().expect("ALBUMARTIST");
            reader.get_tag("MUSICBRAINZ_TRACKID").next().expect("MUSICBRAINZ_TRACKID");
            reader.get_tag("MUSICBRAINZ_ALBUMID").next().expect("MUSICBRAINZ_ALBUMID");
            reader.get_tag("MUSICBRAINZ_ARTISTID").next().expect("MUSICBRAINZ_ARTISTID");

            let bytes = reader.into_inner().seek(SeekFrom::Current(0)).unwrap();
            let duration_ns = epoch.to(PreciseTime::now()).num_nanoseconds().unwrap();
            file_times_us.push(duration_ns as f64 / 1000.0);
            bytes_per_sec.push(bytes as f64 / (duration_ns as f64 / 1.0e9));
        }
    }

    file_times_us.sort_by(|x, y| x.partial_cmp(y).unwrap());
    bytes_per_sec.sort_by(|x, y| x.partial_cmp(y).unwrap());

    let p10 = file_times_us[10 * file_times_us.len() / 100];
    let p50 = file_times_us[50 * file_times_us.len() / 100];
    let p90 = file_times_us[90 * file_times_us.len() / 100];
    let mean = file_times_us.iter().sum::<f64>() / (file_times_us.len() as f64);
    let p10_mibs = bytes_per_sec[10 * bytes_per_sec.len() / 100] / (1024.0 * 1024.0);

    // Output numbers compatible with tools/compare_benches.r.
    println!("{:>6.2} {:>6.2} {:>6.2} {:>6.2} {:>6.2}", p10, p50, p90, mean, p10_mibs);
}
<commit_msg>Amortize walkdir cost in metadata benchmark<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2017 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

// This file contains a minimal example of using Claxon and Hound to decode a
// flac file. This can be done more efficiently, but it is also more verbose.
// See the `decode` example for that.

extern crate claxon;
extern crate walkdir;
extern crate time;

use time::PreciseTime;
use std::io::{Seek, SeekFrom};

fn main() {
    use std::ffi::OsStr;
    let mut file_times_us = Vec::new();
    let mut bytes_per_sec = Vec::new();

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok())
        .take(1024);

    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            let epoch = PreciseTime::now();
            let mut bytes = 0;

            // Read the file multiple times to amortize the walkdir cost.
            for _ in 0..10 {
                let reader = claxon::FlacReader::open(path).unwrap();

                // Note that these are not optimized away even though the results
                // are not used, because the expectation may fail.
                reader.get_tag("DATE").next().expect("DATE");
                reader.get_tag("ORIGINALDATE").next().expect("ORIGINALDATE");
                reader.get_tag("TITLE").next().expect("TITLE");
                reader.get_tag("ALBUM").next().expect("ALBUM");
                reader.get_tag("ALBUMARTIST").next().expect("ALBUMARTIST");
                reader.get_tag("MUSICBRAINZ_TRACKID").next().expect("MUSICBRAINZ_TRACKID");
                reader.get_tag("MUSICBRAINZ_ALBUMID").next().expect("MUSICBRAINZ_ALBUMID");
                reader.get_tag("MUSICBRAINZ_ARTISTID").next().expect("MUSICBRAINZ_ARTISTID");
                bytes += reader.into_inner().seek(SeekFrom::Current(0)).unwrap();
            }

            let duration_ns = epoch.to(PreciseTime::now()).num_nanoseconds().unwrap();
            file_times_us.push(duration_ns as f64 / 1000.0 / 10.0);
            bytes_per_sec.push(bytes as f64 / (duration_ns as f64 / 1.0e9) / 10.0);
        }
    }

    file_times_us.sort_by(|x, y| x.partial_cmp(y).unwrap());
    bytes_per_sec.sort_by(|x, y| x.partial_cmp(y).unwrap());

    let p10 = file_times_us[10 * file_times_us.len() / 100];
    let p50 = file_times_us[50 * file_times_us.len() / 100];
    let p90 = file_times_us[90 * file_times_us.len() / 100];
    let mean = file_times_us.iter().sum::<f64>() / (file_times_us.len() as f64);
    let p10_mibs = bytes_per_sec[10 * bytes_per_sec.len() / 100] / (1024.0 * 1024.0);

    // Output numbers compatible with tools/compare_benches.r.
    println!("{:>6.2} {:>6.2} {:>6.2} {:>6.2} {:>6.2}", p10, p50, p90, mean, p10_mibs);
}
<|endoftext|>


<commit_before>use color_eyre::eyre::{bail, Result};
use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
    process::Command,
};

use crate::Config;

#[derive(Default, Debug)]
pub struct Dependencies {
    /// All paths that must be imported with `-L dependency=`. This is for
    /// finding proc macros run on the host and dependencies for the target.
    pub import_paths: Vec<PathBuf>,
    /// The name as chosen in the `Cargo.toml` and its corresponding rmeta file.
    pub dependencies: Vec<(String, PathBuf)>,
}

/// Compiles dependencies and returns the crate names and corresponding rmeta files.
pub fn build_dependencies(config: &Config) -> Result<Dependencies> {
    let manifest_path = match &config.dependencies_crate_manifest_path {
        Some(path) => path,
        None => return Ok(Default::default()),
    };
    let (program, args, envs): (&Path, &[_], &[_]) = match &config.dependency_builder {
        Some(db) => (&db.program, &db.args, &db.envs),
        None => (Path::new("cargo"), &[], &[]),
    };
    let mut build = Command::new(program);
    build.args(args);
    // HACK: we're using `cargo run` (or `cargo miri run`), because the latter does not
    // support `cargo miri build` yet.
    build.arg("run");

    if let Some(target) = &config.target {
        build.arg(format!("--target={target}"));
    }

    // Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
    let setup_command = |cmd: &mut Command| {
        cmd.envs(envs.iter().map(|(k, v)| (k, v)));
        cmd.arg("--manifest-path").arg(manifest_path);
    };

    setup_command(&mut build);
    build.arg("--message-format=json");

    let output = build.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to compile dependencies:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    // Collect all artifacts generated
    let output = output.stdout;
    let output = String::from_utf8(output)?;
    let mut import_paths: HashSet<PathBuf> = HashSet::new();
    let mut artifacts: HashMap<_, _> = output
        .lines()
        .filter_map(|line| {
            let message = serde_json::from_str::<cargo_metadata::Message>(line).ok()?;
            if let cargo_metadata::Message::CompilerArtifact(artifact) = message {
                for filename in &artifact.filenames {
                    import_paths.insert(filename.parent().unwrap().into());
                }
                let filename = artifact
                    .filenames
                    .into_iter()
                    .find(|filename| filename.extension() == Some("rmeta"))?;
                Some((artifact.package_id, filename.into_std_path_buf()))
            } else {
                None
            }
        })
        .collect();

    // Check which crates are mentioned in the crate itself
    let mut metadata = cargo_metadata::MetadataCommand::new().cargo_command();
    setup_command(&mut metadata);
    let output = metadata.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to run cargo-metadata:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    let output = output.stdout;
    let output = String::from_utf8(output)?;

    for line in output.lines() {
        if !line.starts_with('{') {
            continue;
        }
        let metadata: cargo_metadata::Metadata = serde_json::from_str(line)?;
        // Only take artifacts that are defined in the Cargo.toml

        // First, find the root artifact
        let root = metadata
            .packages
            .iter()
            .find(|package| {
                package.manifest_path.as_std_path().canonicalize().unwrap()
                    == manifest_path.canonicalize().unwrap()
            })
            .unwrap();

        // Then go over all of its dependencies
        let dependencies = root
            .dependencies
            .iter()
            .map(|package| {
                // Get the id for the package matching the version requirement of the dep
                let id = &metadata
                    .packages
                    .iter()
                    .find(|&dep| dep.name == package.name && package.req.matches(&dep.version))
                    .expect("dependency does not exist")
                    .id;
                // Return the name chosen in `Cargo.toml` and the path to the corresponding artifact
                (
                    package.rename.clone().unwrap_or_else(|| package.name.clone()),
                    artifacts.remove(id).expect("package without artifact"),
                )
            })
            .collect();
        let import_paths = import_paths.into_iter().collect();
        return Ok(Dependencies { dependencies, import_paths });
    }

    bail!("no json found in cargo-metadata output")
}
<commit_msg>Auto merge of #2434 - RalfJung:ui-test-locked, r=oli-obk<commit_after>use color_eyre::eyre::{bail, Result};
use std::{
    collections::{HashMap, HashSet},
    path::{Path, PathBuf},
    process::Command,
};

use crate::{Config, OutputConflictHandling};

#[derive(Default, Debug)]
pub struct Dependencies {
    /// All paths that must be imported with `-L dependency=`. This is for
    /// finding proc macros run on the host and dependencies for the target.
    pub import_paths: Vec<PathBuf>,
    /// The name as chosen in the `Cargo.toml` and its corresponding rmeta file.
    pub dependencies: Vec<(String, PathBuf)>,
}

/// Compiles dependencies and returns the crate names and corresponding rmeta files.
pub fn build_dependencies(config: &Config) -> Result<Dependencies> {
    let manifest_path = match &config.dependencies_crate_manifest_path {
        Some(path) => path,
        None => return Ok(Default::default()),
    };
    let (program, args, envs): (&Path, &[_], &[_]) = match &config.dependency_builder {
        Some(db) => (&db.program, &db.args, &db.envs),
        None => (Path::new("cargo"), &[], &[]),
    };
    let mut build = Command::new(program);
    build.args(args);
    // HACK: we're using `cargo run` (or `cargo miri run`), because the latter does not
    // support `cargo miri build` yet.
    build.arg("run");

    if let Some(target) = &config.target {
        build.arg(format!("--target={target}"));
    }

    // Reusable closure for setting up the environment both for artifact generation and `cargo_metadata`
    let setup_command = |cmd: &mut Command| {
        cmd.envs(envs.iter().map(|(k, v)| (k, v)));
        cmd.arg("--manifest-path").arg(manifest_path);
        if matches!(config.output_conflict_handling, OutputConflictHandling::Error) {
            cmd.arg("--locked");
        }
    };

    setup_command(&mut build);
    build.arg("--message-format=json");

    let output = build.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to compile dependencies:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    // Collect all artifacts generated
    let output = output.stdout;
    let output = String::from_utf8(output)?;
    let mut import_paths: HashSet<PathBuf> = HashSet::new();
    let mut artifacts: HashMap<_, _> = output
        .lines()
        .filter_map(|line| {
            let message = serde_json::from_str::<cargo_metadata::Message>(line).ok()?;
            if let cargo_metadata::Message::CompilerArtifact(artifact) = message {
                for filename in &artifact.filenames {
                    import_paths.insert(filename.parent().unwrap().into());
                }
                let filename = artifact
                    .filenames
                    .into_iter()
                    .find(|filename| filename.extension() == Some("rmeta"))?;
                Some((artifact.package_id, filename.into_std_path_buf()))
            } else {
                None
            }
        })
        .collect();

    // Check which crates are mentioned in the crate itself
    let mut metadata = cargo_metadata::MetadataCommand::new().cargo_command();
    setup_command(&mut metadata);
    let output = metadata.output()?;

    if !output.status.success() {
        let stdout = String::from_utf8(output.stdout)?;
        let stderr = String::from_utf8(output.stderr)?;
        bail!("failed to run cargo-metadata:\nstderr:\n{stderr}\n\nstdout:{stdout}");
    }

    let output = output.stdout;
    let output = String::from_utf8(output)?;

    for line in output.lines() {
        if !line.starts_with('{') {
            continue;
        }
        let metadata: cargo_metadata::Metadata = serde_json::from_str(line)?;
        // Only take artifacts that are defined in the Cargo.toml

        // First, find the root artifact
        let root = metadata
            .packages
            .iter()
            .find(|package| {
                package.manifest_path.as_std_path().canonicalize().unwrap()
                    == manifest_path.canonicalize().unwrap()
            })
            .unwrap();

        // Then go over all of its dependencies
        let dependencies = root
            .dependencies
            .iter()
            .map(|package| {
                // Get the id for the package matching the version requirement of the dep
                let id = &metadata
                    .packages
                    .iter()
                    .find(|&dep| dep.name == package.name && package.req.matches(&dep.version))
                    .expect("dependency does not exist")
                    .id;
                // Return the name chosen in `Cargo.toml` and the path to the corresponding artifact
                (
                    package.rename.clone().unwrap_or_else(|| package.name.clone()),
                    artifacts.remove(id).expect("package without artifact"),
                )
            })
            .collect();
        let import_paths = import_paths.into_iter().collect();
        return Ok(Dependencies { dependencies, import_paths });
    }

    bail!("no json found in cargo-metadata output")
}
<|endoftext|>


<commit_before>macro_rules! bench_digest {
    ($name:ident, $engine:path, $blocks:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            use octavo::digest::Digest;

            let bs = <$engine>::block_size();

            let mut d = <$engine>::default();
            let data = vec![0; bs];

            b.iter(|| {
                for _ in 0..$blocks {
                    d.update(&data[..]);
                }
            });

            b.bytes = bs as u64 * $blocks;
        }
    };

    ($engine:path) => {
        bench_digest!(_1x_block_size,   $engine,   1);
        bench_digest!(_10x_block_size,  $engine,  10);
        bench_digest!(_100x_block_size, $engine, 100);
    }
}

#[cfg(feature = "md4")] #[macro_use] mod md4;
#[cfg(feature = "md5")] #[macro_use] mod md5;
#[cfg(feature = "sha1")] #[macro_use] mod sha1;
#[cfg(feature = "sha2")] #[macro_use] mod sha2;
#[cfg(feature = "sha3")] #[macro_use] mod sha3;
#[cfg(feature = "tiger")] #[macro_use] mod tiger;
<commit_msg>bench(digest): Do not use slices if not needed<commit_after>macro_rules! bench_digest {
    ($name:ident, $engine:path, $blocks:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            use octavo::digest::Digest;

            let bs = <$engine>::block_size();

            let mut d = <$engine>::default();
            let data = vec![0; bs];

            b.iter(|| {
                for _ in 0..$blocks {
                    d.update(&data);
                }
            });

            b.bytes = bs as u64 * $blocks;
        }
    };

    ($engine:path) => {
        bench_digest!(_1x_block_size,   $engine,   1);
        bench_digest!(_10x_block_size,  $engine,  10);
        bench_digest!(_100x_block_size, $engine, 100);
    }
}

#[cfg(feature = "md4")] #[macro_use] mod md4;
#[cfg(feature = "md5")] #[macro_use] mod md5;
#[cfg(feature = "sha1")] #[macro_use] mod sha1;
#[cfg(feature = "sha2")] #[macro_use] mod sha2;
#[cfg(feature = "sha3")] #[macro_use] mod sha3;
#[cfg(feature = "tiger")] #[macro_use] mod tiger;
<|endoftext|>


<commit_before>use gmp::mpq::Mpq;
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::vec::Vec;

struct BallotState {
    prev: usize,
    edge_flow: Box<[Mpq]>,
    count: i32,
}

#[derive(Clone)]
struct CandidateState {
    prev: (usize, usize),
    count: i32,
}

pub fn strength<Ballot>(num_seats: usize, ballots: &[(Ballot, Mpq)]) -> Mpq
    where Ballot: Borrow<[usize]>
{
    let candidate_ballots = &mut vec![Vec::new(); num_seats][..];
    for (b, &(ref cs, _)) in ballots.iter().enumerate() {
        for (i, &c) in cs.borrow().iter().enumerate() {
            candidate_ballots[c].push((b, i));
        }
    }
    let ballot_states = &mut ballots.iter()
        .map(|&(ref cs, ref w)| {
            let mut edge_flow = vec![Mpq::zero(); 1 + cs.borrow().len()].into_boxed_slice();
            edge_flow[0] = w.clone();
            BallotState {
                prev: !0,
                edge_flow: edge_flow,
                count: 0,
            }
        })
        .collect::<Vec<_>>()[..];
    let candidate_states = &mut vec![CandidateState {
        prev: (!0, !0),
        count: 0,
    }; num_seats][..];

    let mut total_flow = Mpq::zero();
    let mut queue = VecDeque::new();

    loop {
        for (b, bs) in ballot_states.iter_mut().enumerate() {
            if !bs.edge_flow[0].is_zero() {
                bs.prev = 0;
                queue.push_back(b);
            }
        }

        let mut found = Vec::new();
        'search: loop {
            match queue.pop_front() {
                None => {
                    return total_flow;
                }
                Some(b) => {
                    let (ref cs, _) = ballots[b];
                    for (i, &c) in cs.borrow().iter().enumerate() {
                        if candidate_states[c].prev != (!0, !0) {
                            continue;
                        }
                        candidate_states[c].prev = (b, i);
                        found.push(c);
                        if found.len() == num_seats {
                            break 'search;
                        }
                        for &(b1, i1) in &candidate_ballots[c] {
                            if ballot_states[b1].edge_flow[i1 + 1].is_zero() ||
                               ballot_states[b1].prev != !0 {
                                continue;
                            }
                            ballot_states[b1].prev = i1 + 1;
                            queue.push_back(b1);
                        }
                    }
                }
            }
        }

        let mut sunk = 0;
        for &c in found.iter().rev() {
            let (b, _) = candidate_states[c].prev;
            let count = candidate_states[c].count + 1;
            ballot_states[b].count += count;
            let i1 = ballot_states[b].prev;
            if i1 == 0 {
                sunk += count;
            } else {
                let (ref cs, _) = ballots[b];
                candidate_states[cs.borrow()[i1 - 1]].count += count;
            }
        }
        debug_assert_eq!(sunk, num_seats as i32);

        let flow = found.iter()
            .map(|&c| {
                let (b, _) = candidate_states[c].prev;
                &ballot_states[b].edge_flow[ballot_states[b].prev] /
                Mpq::from(ballot_states[b].count as i64)
            })
            .min()
            .unwrap();
        debug_assert!(!flow.is_zero());
        total_flow = total_flow + &flow;

        for c in found {
            let (b, i) = candidate_states[c].prev;
            {
                let edge_flow = &mut ballot_states[b].edge_flow[i + 1];
                *edge_flow = &*edge_flow + &flow * Mpq::from(candidate_states[c].count as i64 + 1);
            }
            if ballot_states[b].count != 0 {
                let edge_flow = &mut ballot_states[b].edge_flow[ballot_states[b].prev];
                *edge_flow = &*edge_flow - &flow * Mpq::from(ballot_states[b].count as i64);
                ballot_states[b].count = 0;
            }

            candidate_states[c].prev = (!0, !0);
            candidate_states[c].count = 0;
        }

        for bs in &mut *ballot_states {
            bs.prev = !0;
            debug_assert_eq!(bs.count, 0);
        }
        queue.clear();
    }
}

#[cfg(test)]
mod tests {
    use super::strength;
    use gmp::mpq::Mpq;

    const Q: fn(i64) -> Mpq = Mpq::from;

    #[test]
    fn test_strength_1() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] =
            &[(&[0], Q(12)), (&[1], Q(0)), (&[0, 1], Q(51)), (&[], Q(27))];
        assert_eq!(strength(2, ballots), Q(63) / Q(2));
    }

    #[test]
    fn test_strength_2() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] = &[(&[0], Q(38)), (&[1], Q(27)), (&[0, 1], Q(12))];
        assert_eq!(strength(2, ballots), Q(77) / Q(2));
    }

    #[test]
    fn test_strength_3() {
        // Schulze’s calcul02.pdf
        let ballots: &[(&[usize], Mpq)] = &[(&[0, 1, 2, 3], Q(36_597383) / Q(1_000000)),
                                            (&[0, 1, 2], Q(5_481150) / Q(1_000000)),
                                            (&[0, 1, 3], Q(13_279131) / Q(1_000000)),
                                            (&[0, 1], Q(4_859413) / Q(1_000000)),
                                            (&[0, 2, 3], Q(35_425375) / Q(1_000000)),
                                            (&[0, 2], Q(5_490934) / Q(1_000000)),
                                            (&[0, 3], Q(22_855333) / Q(1_000000)),
                                            (&[0], Q(19_835570) / Q(1_000000)),
                                            (&[1, 2, 3], Q(22_928716) / Q(1_000000)),
                                            (&[1, 2], Q(5_538309) / Q(1_000000)),
                                            (&[1, 3], Q(13_130227) / Q(1_000000)),
                                            (&[1], Q(6_056291) / Q(1_000000)),
                                            (&[2, 3], Q(23_992772) / Q(1_000000)),
                                            (&[2], Q(16_699207) / Q(1_000000)),
                                            (&[3], Q(98_165759) / Q(1_000000)),
                                            (&[], Q(129_664430) / Q(1_000000))];
        assert_eq!(strength(4, ballots), Q(77_389937) / Q(1_000000));
    }
}
<commit_msg>vote_management: Add ballot_candidates indexing into candidates_ballots<commit_after>use gmp::mpq::Mpq;
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::vec::Vec;

struct BallotState {
    prev: usize,
    edge_flow: Box<[Mpq]>,
    count: i32,
}

#[derive(Clone)]
struct CandidateState {
    prev: (usize, usize),
    count: i32,
}

pub fn strength<Ballot>(num_seats: usize, ballots: &[(Ballot, Mpq)]) -> Mpq
    where Ballot: Borrow<[usize]>
{
    let ballot_candidates = &mut vec![Vec::new(); ballots.len()][..];
    let candidate_ballots = &mut vec![Vec::new(); num_seats][..];
    for (b, &(ref cs, _)) in ballots.iter().enumerate() {
        ballot_candidates[b].push((!0, !0));
        for (i, &c) in cs.borrow().iter().enumerate() {
            ballot_candidates[b].push((c, candidate_ballots[c].len()));
            candidate_ballots[c].push((b, i + 1));
        }
    }
    let ballot_states = &mut ballots.iter()
        .map(|&(ref cs, ref w)| {
            let mut edge_flow = vec![Mpq::zero(); 1 + cs.borrow().len()].into_boxed_slice();
            edge_flow[0] = w.clone();
            BallotState {
                prev: !0,
                edge_flow: edge_flow,
                count: 0,
            }
        })
        .collect::<Vec<_>>()[..];
    let candidate_states = &mut vec![CandidateState {
        prev: (!0, !0),
        count: 0,
    }; num_seats][..];

    let mut total_flow = Mpq::zero();
    let mut queue = VecDeque::new();

    loop {
        for (b, bs) in ballot_states.iter_mut().enumerate() {
            if !bs.edge_flow[0].is_zero() {
                bs.prev = 0;
                queue.push_back(b);
            }
        }

        let mut found = Vec::new();
        'search: loop {
            match queue.pop_front() {
                None => {
                    return total_flow;
                }
                Some(b) => {
                    for (i, &(c, _)) in ballot_candidates[b].iter().enumerate().skip(1) {
                        if candidate_states[c].prev != (!0, !0) {
                            continue;
                        }
                        candidate_states[c].prev = (b, i);
                        found.push(c);
                        if found.len() == num_seats {
                            break 'search;
                        }
                        for &(b1, i1) in &candidate_ballots[c] {
                            if ballot_states[b1].edge_flow[i1].is_zero() ||
                               ballot_states[b1].prev != !0 {
                                continue;
                            }
                            ballot_states[b1].prev = i1;
                            queue.push_back(b1);
                        }
                    }
                }
            }
        }

        let mut sunk = 0;
        for &c in found.iter().rev() {
            let (b, _) = candidate_states[c].prev;
            let count = candidate_states[c].count + 1;
            ballot_states[b].count += count;
            let i1 = ballot_states[b].prev;
            if i1 == 0 {
                sunk += count;
            } else {
                let (c1, _) = ballot_candidates[b][i1];
                candidate_states[c1].count += count;
            }
        }
        debug_assert_eq!(sunk, num_seats as i32);

        let flow = found.iter()
            .map(|&c| {
                let (b, _) = candidate_states[c].prev;
                &ballot_states[b].edge_flow[ballot_states[b].prev] /
                Mpq::from(ballot_states[b].count as i64)
            })
            .min()
            .unwrap();
        debug_assert!(!flow.is_zero());
        total_flow = total_flow + &flow;

        for c in found {
            let (b, i) = candidate_states[c].prev;
            {
                let edge_flow = &mut ballot_states[b].edge_flow[i];
                *edge_flow = &*edge_flow + &flow * Mpq::from(candidate_states[c].count as i64 + 1);
            }
            if ballot_states[b].count != 0 {
                let edge_flow = &mut ballot_states[b].edge_flow[ballot_states[b].prev];
                *edge_flow = &*edge_flow - &flow * Mpq::from(ballot_states[b].count as i64);
                ballot_states[b].count = 0;
            }

            candidate_states[c].prev = (!0, !0);
            candidate_states[c].count = 0;
        }

        for bs in &mut *ballot_states {
            bs.prev = !0;
            debug_assert_eq!(bs.count, 0);
        }
        queue.clear();
    }
}

#[cfg(test)]
mod tests {
    use super::strength;
    use gmp::mpq::Mpq;

    const Q: fn(i64) -> Mpq = Mpq::from;

    #[test]
    fn test_strength_1() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] =
            &[(&[0], Q(12)), (&[1], Q(0)), (&[0, 1], Q(51)), (&[], Q(27))];
        assert_eq!(strength(2, ballots), Q(63) / Q(2));
    }

    #[test]
    fn test_strength_2() {
        // Wikipedia
        let ballots: &[(&[usize], Mpq)] = &[(&[0], Q(38)), (&[1], Q(27)), (&[0, 1], Q(12))];
        assert_eq!(strength(2, ballots), Q(77) / Q(2));
    }

    #[test]
    fn test_strength_3() {
        // Schulze’s calcul02.pdf
        let ballots: &[(&[usize], Mpq)] = &[(&[0, 1, 2, 3], Q(36_597383) / Q(1_000000)),
                                            (&[0, 1, 2], Q(5_481150) / Q(1_000000)),
                                            (&[0, 1, 3], Q(13_279131) / Q(1_000000)),
                                            (&[0, 1], Q(4_859413) / Q(1_000000)),
                                            (&[0, 2, 3], Q(35_425375) / Q(1_000000)),
                                            (&[0, 2], Q(5_490934) / Q(1_000000)),
                                            (&[0, 3], Q(22_855333) / Q(1_000000)),
                                            (&[0], Q(19_835570) / Q(1_000000)),
                                            (&[1, 2, 3], Q(22_928716) / Q(1_000000)),
                                            (&[1, 2], Q(5_538309) / Q(1_000000)),
                                            (&[1, 3], Q(13_130227) / Q(1_000000)),
                                            (&[1], Q(6_056291) / Q(1_000000)),
                                            (&[2, 3], Q(23_992772) / Q(1_000000)),
                                            (&[2], Q(16_699207) / Q(1_000000)),
                                            (&[3], Q(98_165759) / Q(1_000000)),
                                            (&[], Q(129_664430) / Q(1_000000))];
        assert_eq!(strength(4, ballots), Q(77_389937) / Q(1_000000));
    }
}
<|endoftext|>