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

#![crate_type = "bin"]

#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;

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

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, 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(), "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(), "proc               : Displays proc 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(), "vendor_id          : Displays processor vendor id");
    writeln!(&mut io::stdout(), "load_avg           : Displays system load average");
    writeln!(&mut io::stdout(), "frequency          : Displays processor frequency");
    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_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            // Note: you should refresh a few times before using this, so that usage statistics can be ascertained
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} KiB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} KiB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} KiB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} KiB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name(), proc_.status());
            }
        }
        "frequency" => {
            writeln!(&mut io::stdout(), "{} MHz", sys.get_processor_list()[0].get_frequency());
        }
        "vendor_id" => {
            writeln!(&mut io::stdout(), "vendor ID: {}", sys.get_processor_list()[0].get_vendor_id());
        }
        "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_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            writeln!(&mut io::stdout(), "input data : {} B", sys.get_network().get_income());
            writeln!(&mut io::stdout(), "output data: {} B", sys.get_network().get_outcome());
        }
        "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);
            }
        }
        "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",
                     days,
                     hours,
                     minutes);
        }
        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);
            }
        }
        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();
    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 as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<commit_msg>Handle CTRL+D 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 sysinfo::{NetworkExt, Pid, ProcessExt, ProcessorExt, Signal, System, SystemExt};
use sysinfo::Signal::*;
use std::io::{self, BufRead, Write};
use std::str::FromStr;

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, 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(), "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(), "proc               : Displays proc 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(), "vendor_id          : Displays processor vendor id");
    writeln!(&mut io::stdout(), "load_avg           : Displays system load average");
    writeln!(&mut io::stdout(), "frequency          : Displays processor frequency");
    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_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            // Note: you should refresh a few times before using this, so that usage statistics can be ascertained
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} KiB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} KiB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} KiB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} KiB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name(), proc_.status());
            }
        }
        "frequency" => {
            writeln!(&mut io::stdout(), "{} MHz", sys.get_processor_list()[0].get_frequency());
        }
        "vendor_id" => {
            writeln!(&mut io::stdout(), "vendor ID: {}", sys.get_processor_list()[0].get_vendor_id());
        }
        "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_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            writeln!(&mut io::stdout(), "input data : {} B", sys.get_network().get_income());
            writeln!(&mut io::stdout(), "output data: {} B", sys.get_network().get_outcome());
        }
        "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);
            }
        }
        "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",
                     days,
                     hours,
                     minutes);
        }
        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);
            }
        }
        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();
    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>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]

#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;

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

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, 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(), "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(), "proc               : Displays proc 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(), "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_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            // Note: you should refresh a few times before using this, so that usage statistics can be ascertained
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} KiB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} KiB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} KiB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} KiB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name(), proc_.status());
            }
        }
        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_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            writeln!(&mut io::stdout(), "input data : {} B", sys.get_network().get_income());
            writeln!(&mut io::stdout(), "output data: {} B", sys.get_network().get_outcome());
        }
        "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);
            }
        }
        "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",
                     days,
                     hours,
                     minutes);
        }
        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);
            }
        }
        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();
    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 as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<commit_msg>Add new methods into examples as well<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

#![crate_type = "bin"]

#![allow(unused_must_use, non_upper_case_globals)]

extern crate sysinfo;

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

const signals: [Signal; 31] = [Hangup, Interrupt, Quit, Illegal, Trap, Abort, Bus,
                               FloatingPointException, Kill, User1, Segv, User2, Pipe, Alarm,
                               Term, Stklft, 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(), "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(), "proc               : Displays proc 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(), "vendor_id          : Displays processor vendor id");
    writeln!(&mut io::stdout(), "load_avg           : Displays system load average");
    writeln!(&mut io::stdout(), "frequency          : Displays processor frequency");
    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_disk_list();
            writeln!(&mut io::stdout(), "Done.");
        }
        "signals" => {
            let mut nb = 1i32;

            for sig in &signals {
                writeln!(&mut io::stdout(), "{:2}:{:?}", nb, sig);
                nb += 1;
            }
        }
        "proc" => {
            // Note: you should refresh a few times before using this, so that usage statistics can be ascertained
            let procs = sys.get_processor_list();

            writeln!(&mut io::stdout(), "total process usage: {}%", procs[0].get_cpu_usage());
            for proc_ in procs.iter().skip(1) {
                writeln!(&mut io::stdout(), "{:?}", proc_);
            }
        }
        "memory" => {
            writeln!(&mut io::stdout(), "total memory: {} KiB", sys.get_total_memory());
            writeln!(&mut io::stdout(), "used memory : {} KiB", sys.get_used_memory());
            writeln!(&mut io::stdout(), "total swap  : {} KiB", sys.get_total_swap());
            writeln!(&mut io::stdout(), "used swap   : {} KiB", sys.get_used_swap());
        }
        "quit" | "exit" => return true,
        "all" => {
            for (pid, proc_) in sys.get_process_list() {
                writeln!(&mut io::stdout(), "{}:{} status={:?}", pid, proc_.name(), proc_.status());
            }
        }
        "frequency" => {
            writeln!(&mut io::stdout(), "{} MHz", sys.get_processor_list()[0].get_frequency());
        }
        "vendor_id" => {
            writeln!(&mut io::stdout(), "vendor ID: {}", sys.get_processor_list()[0].get_vendor_id());
        }
        "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_list() {
                writeln!(&mut io::stdout(), "{:?}", component);
            }
        }
        "network" => {
            writeln!(&mut io::stdout(), "input data : {} B", sys.get_network().get_income());
            writeln!(&mut io::stdout(), "output data: {} B", sys.get_network().get_outcome());
        }
        "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);
            }
        }
        "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",
                     days,
                     hours,
                     minutes);
        }
        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);
            }
        }
        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();
    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 as &str).ends_with('\n') {
            input.pop();
        }
        done = interpret_input(input.as_ref(), &mut t);
    }
}
<|endoftext|>


<commit_before>use ber;
use ber::error::ASN1Error as Error;

use std::io;
use std::io::Write;

use byteorder::BigEndian;
use byteorder::WriteBytesExt;

use ber::common::{self, Tag};

pub struct Encoder<W>
{
    buf: W,
}

impl<W: io::Write> Encoder<W>
{
    pub fn from_writer(wtr: W) -> Encoder<io::BufWriter<W>>
    {
        Encoder::from_writer_raw(io::BufWriter::new(wtr))
    }

    pub fn from_writer_raw(wtr: W) -> Encoder<W>
    {
        Encoder
        {
            buf: wtr,
        }
    }

    pub fn flush(&mut self) -> ber::Result<()>
    {
        try!(self.buf.flush());

        Ok(())
    }

    pub fn encode(&mut self, tag: common::Tag) -> ber::Result<()>
    {
        try!(write_type(tag._type, &mut self.buf));
        try!(write_length(tag._length, &mut self.buf));
        try!(write_value(tag._value, &mut self.buf));

        Ok(())
    }
}

fn write(tag: common::Tag, mut w: &mut Write) -> ber::Result<()>
{
    try!(write_type(tag._type, w));
    try!(write_length(tag._length, w));
    try!(write_value(tag._value, w));

    Ok(())
}

fn write_type(tagtype: common::Type, mut w: &mut Write) -> ber::Result<()>
{
    let class_number = match tagtype.class
    {
        common::Class::Universal(_) => common::ClassNumber::Universal,
        common::Class::Application(_) => common::ClassNumber::Application,
        common::Class::ContextSpecific(_) => common::ClassNumber::ContextSpecific,
        common::Class::Private(_) => common::ClassNumber::Private,
    };

    let mut extended_tag: Option<Vec<u8>> = None;

    let type_byte =
            // First two bits: Class
            (class_number as u8) << 6 |
            // Bit 6: Primitive/Constructed
            (tagtype.structure as u8) << 5 |
            // Bit 5-1: Tag Number
            match tagtype.class
            {
                // tag will never be bigger than 30 so this is ok
                common::Class::Universal(tag) => (tag as u8),
                common::Class::Application(tag) |
                common::Class::ContextSpecific(tag) |
                common::Class::Private(tag) =>
                {
                    if tag > 30
                    {
                        let mut tagbytes: Vec<u8> = Vec::new();

                        let mut tag = tag;
                        while tag > 0
                        {
                            let mut byte = (tag & 0x7F) as u8;

                            tag >>= 7;

                            tagbytes.push(byte);
                        }

                        extended_tag = Some(tagbytes);

                        // This means we need to set the 5 tag bits to 11111, so 31 or 0x1F
                        31
                    }
                    else
                    {
                        extended_tag = None;
                        (tag as u8)
                    }
                },
            }; // let type_byte

    try!(w.write_u8(type_byte));

    let mut written = 1;

    if let Some(mut ext_bytes) = extended_tag
    {
        for _ in 0..ext_bytes.len()-1
        {
            let mut byte = ext_bytes.pop().unwrap();

            // Set the first bit
            byte |= 0x80;

            w.write_u8(byte);
        }

        let byte = ext_bytes.pop().unwrap();
        w.write_u8(byte);
    }

    Ok(())
}

// Yes I know you could overflow the length in theory. But, do you have 2^64 bytes of memory?
fn write_length(mut length: u64, mut w: &mut Write) -> ber::Result<()>
{
    // Short form
    if length < 128
    {
        try!(w.write_u8(length as u8));

        Ok(())
    }
    // Long form
    else
    {
        let mut count = 0u8;
        let mut len = length;
        while {count += 1; len >>= 8; len > 0 }{}

        try!(w.write_u8(count | 0x80));
        w.write_uint::<BigEndian>(length, count as usize);

        Ok(())
    }
}

fn write_value(payload: common::Payload, mut w: &mut Write) -> ber::Result<()>
{
    match payload
    {
        common::Payload::Primitive(ref value) =>
        {
            try!(w.write_all(value));
            Ok(())
        },
        common::Payload::Constructed(tags) =>
        {
            for tag in tags
            {
                try!(write(tag, w));
            }
            Ok(())
        }
    }
}

#[cfg(test)]
mod test
{
    use super::*;
    use ber::common;
    use std::io::Cursor;

    use byteorder::WriteBytesExt;
    use byteorder::BigEndian;

    #[test]
    fn encode_simple_tag()
    {
        let mut payload: Vec<u8> = Vec::new();
        payload.write_i16::<BigEndian>(1616);

        let class = common::Class::Universal(common::UniversalTypes::Integer);
        let pl = common::Payload::Primitive(payload);

        let tag = common::construct(class, pl);

        let mut buf = Vec::<u8>::new();
        super::write(tag, &mut buf).unwrap();

        println!("{:?}", buf);

        assert!(buf == vec![0x2, 0x2, 0x06, 0x50]);
    }

    #[test]
    fn encode_constructed_tag()
    {
        let child =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("Hello World!".to_string().into_bytes());

            common::construct(class, pl)
        };

        println!("{:?}", child);

        let parent =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![child]);

            common::construct(class, pl)
        };

        println!("{:?}", parent);

        let mut buf = Vec::<u8>::new();
        super::write(parent, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![48, 14, 128, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
    }

    #[test]
    fn encode_extended_type_tags()
    {

        let tag = {
            let class = common::Class::ContextSpecific(1000);
            let pl = common::Payload::Primitive("second".to_string().into_bytes());

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(tag, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![0x9F,0x87,0x68,0x06,0x73,0x65,0x63,0x6F,0x6E,0x64]);
    }

    #[test]
    fn encode_long_length_tags()
    {
        let name =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("JustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let value =
        {
            let class = common::Class::ContextSpecific(1);
            let pl = common::Payload::Primitive("JustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let seq =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![name, value]);

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(seq, &mut buf);

        println!("{:?}", buf);
        assert!(buf == vec![
            0x30, 0x82, 0x01, 0x01,
            0x80, 0x0C, 0x4A, 0x75,
            0x73, 0x74, 0x41, 0x4C,
            0x6F, 0x6E, 0x67, 0x54,
            0x61, 0x67, 0x81, 0x81,
            0xF0, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67,
        ]);
    }
}
<commit_msg>Encoder only requires a pointer to a tag now<commit_after>use ber;
use ber::error::ASN1Error as Error;

use std::io;
use std::io::Write;

use byteorder::BigEndian;
use byteorder::WriteBytesExt;

use ber::common::{self, Tag};

pub struct Encoder<W>
{
    buf: W,
}

impl<W: io::Write> Encoder<W>
{
    pub fn from_writer(wtr: W) -> Encoder<io::BufWriter<W>>
    {
        Encoder::from_writer_raw(io::BufWriter::new(wtr))
    }

    pub fn from_writer_raw(wtr: W) -> Encoder<W>
    {
        Encoder
        {
            buf: wtr,
        }
    }

    pub fn flush(&mut self) -> ber::Result<()>
    {
        try!(self.buf.flush());

        Ok(())
    }

    pub fn encode(&mut self, tag: &common::Tag) -> ber::Result<()>
    {
        try!(write_type(tag._type, &mut self.buf));
        try!(write_length(tag._length, &mut self.buf));
        try!(write_value(&tag._value, &mut self.buf));

        Ok(())
    }
}

fn write(tag: &common::Tag, mut w: &mut Write) -> ber::Result<()>
{
    try!(write_type(tag._type, w));
    try!(write_length(tag._length, w));
    try!(write_value(&tag._value, w));

    Ok(())
}

fn write_type(tagtype: common::Type, mut w: &mut Write) -> ber::Result<()>
{
    let class_number = match tagtype.class
    {
        common::Class::Universal(_) => common::ClassNumber::Universal,
        common::Class::Application(_) => common::ClassNumber::Application,
        common::Class::ContextSpecific(_) => common::ClassNumber::ContextSpecific,
        common::Class::Private(_) => common::ClassNumber::Private,
    };

    let mut extended_tag: Option<Vec<u8>> = None;

    let type_byte =
            // First two bits: Class
            (class_number as u8) << 6 |
            // Bit 6: Primitive/Constructed
            (tagtype.structure as u8) << 5 |
            // Bit 5-1: Tag Number
            match tagtype.class
            {
                // tag will never be bigger than 30 so this is ok
                common::Class::Universal(tag) => (tag as u8),
                common::Class::Application(tag) |
                common::Class::ContextSpecific(tag) |
                common::Class::Private(tag) =>
                {
                    if tag > 30
                    {
                        let mut tagbytes: Vec<u8> = Vec::new();

                        let mut tag = tag;
                        while tag > 0
                        {
                            let mut byte = (tag & 0x7F) as u8;

                            tag >>= 7;

                            tagbytes.push(byte);
                        }

                        extended_tag = Some(tagbytes);

                        // This means we need to set the 5 tag bits to 11111, so 31 or 0x1F
                        31
                    }
                    else
                    {
                        extended_tag = None;
                        (tag as u8)
                    }
                },
            }; // let type_byte

    try!(w.write_u8(type_byte));

    let mut written = 1;

    if let Some(mut ext_bytes) = extended_tag
    {
        for _ in 0..ext_bytes.len()-1
        {
            let mut byte = ext_bytes.pop().unwrap();

            // Set the first bit
            byte |= 0x80;

            w.write_u8(byte);
        }

        let byte = ext_bytes.pop().unwrap();
        w.write_u8(byte);
    }

    Ok(())
}

// Yes I know you could overflow the length in theory. But, do you have 2^64 bytes of memory?
fn write_length(mut length: u64, mut w: &mut Write) -> ber::Result<()>
{
    // Short form
    if length < 128
    {
        try!(w.write_u8(length as u8));

        Ok(())
    }
    // Long form
    else
    {
        let mut count = 0u8;
        let mut len = length;
        while {count += 1; len >>= 8; len > 0 }{}

        try!(w.write_u8(count | 0x80));
        w.write_uint::<BigEndian>(length, count as usize);

        Ok(())
    }
}

fn write_value(payload: &common::Payload, mut w: &mut Write) -> ber::Result<()>
{
    match *payload
    {
        common::Payload::Primitive(ref value) =>
        {
            try!(w.write_all(value));
            Ok(())
        },
        common::Payload::Constructed(ref tags) =>
        {
            for tag in tags
            {
                try!(write(tag, w));
            }
            Ok(())
        }
    }
}

#[cfg(test)]
mod test
{
    use super::*;
    use ber::common;
    use std::io::Cursor;

    use byteorder::WriteBytesExt;
    use byteorder::BigEndian;

    #[test]
    fn encode_simple_tag()
    {
        let mut payload: Vec<u8> = Vec::new();
        payload.write_i16::<BigEndian>(1616);

        let class = common::Class::Universal(common::UniversalTypes::Integer);
        let pl = common::Payload::Primitive(payload);

        let tag = common::construct(class, pl);

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf).unwrap();

        println!("{:?}", buf);

        assert!(buf == vec![0x2, 0x2, 0x06, 0x50]);
    }

    #[test]
    fn encode_constructed_tag()
    {
        let child =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("Hello World!".to_string().into_bytes());

            common::construct(class, pl)
        };

        println!("{:?}", child);

        let parent =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![child]);

            common::construct(class, pl)
        };

        println!("{:?}", parent);

        let mut buf = Vec::<u8>::new();
        super::write(&parent, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![48, 14, 128, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])
    }

    #[test]
    fn encode_extended_type_tags()
    {

        let tag = {
            let class = common::Class::ContextSpecific(1000);
            let pl = common::Payload::Primitive("second".to_string().into_bytes());

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&tag, &mut buf);

        println!("{:?}", buf);

        assert!(buf == vec![0x9F,0x87,0x68,0x06,0x73,0x65,0x63,0x6F,0x6E,0x64]);
    }

    #[test]
    fn encode_long_length_tags()
    {
        let name =
        {
            let class = common::Class::ContextSpecific(0);
            let pl = common::Payload::Primitive("JustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let value =
        {
            let class = common::Class::ContextSpecific(1);
            let pl = common::Payload::Primitive("JustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTagJustALongTag".to_string().into_bytes());

            common::construct(class, pl)
        };

        let seq =
        {
            let class = common::Class::Universal(common::UniversalTypes::Sequence);
            let pl = common::Payload::Constructed(vec![name, value]);

            common::construct(class, pl)
        };

        let mut buf = Vec::<u8>::new();
        super::write(&seq, &mut buf);

        println!("{:?}", buf);
        assert!(buf == vec![
            0x30, 0x82, 0x01, 0x01,
            0x80, 0x0C, 0x4A, 0x75,
            0x73, 0x74, 0x41, 0x4C,
            0x6F, 0x6E, 0x67, 0x54,
            0x61, 0x67, 0x81, 0x81,
            0xF0, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67, 0x4A, 0x75, 0x73,
            0x74, 0x41, 0x4C, 0x6F,
            0x6E, 0x67, 0x54, 0x61,
            0x67,
        ]);
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate rustfmt_nightly as rustfmt;

use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;

use getopts::{Matches, Options};

use rustfmt::{run, Input};
use rustfmt::config;

fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> {
    let prefixes: Vec<_> = files
        .iter()
        .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs"))
        .map(|f| &f[..f.len() - 6])
        .collect();

    let mut pruned_prefixes = vec![];
    for p1 in prefixes.into_iter() {
        let mut include = true;
        if !p1.starts_with("src/bin/") {
            for p2 in pruned_prefixes.iter() {
                if p1.starts_with(p2) {
                    include = false;
                    break;
                }
            }
        }
        if include {
            pruned_prefixes.push(p1);
        }
    }
    debug!("prefixes: {:?}", pruned_prefixes);

    files
        .into_iter()
        .filter(|f| {
            let mut include = true;
            if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") {
                return true;
            }
            for pp in pruned_prefixes.iter() {
                if f.starts_with(pp) {
                    include = false;
                    break;
                }
            }
            include
        })
        .collect()
}

fn git_diff(commits: String) -> String {
    let mut cmd = Command::new("git");
    cmd.arg("diff");
    if commits != "0" {
        cmd.arg(format!("HEAD~{}", commits));
    }
    let output = cmd.output().expect("Couldn't execute `git diff`");
    String::from_utf8_lossy(&output.stdout).into_owned()
}

fn get_files(input: &str) -> Vec<&str> {
    input
        .lines()
        .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs"))
        .map(|line| &line[6..])
        .collect()
}

fn fmt_files(files: &[&str]) -> i32 {
    let (config, _) = config::Config::from_resolved_toml_path(Path::new("."))
        .unwrap_or_else(|_| (config::Config::default(), None));

    let mut exit_code = 0;
    for file in files {
        let summary = run(Input::File(PathBuf::from(file)), &config);
        if !summary.has_no_errors() {
            exit_code = 1;
        }
    }
    exit_code
}

fn uncommitted_files() -> Vec<String> {
    let mut cmd = Command::new("git");
    cmd.arg("ls-files");
    cmd.arg("--others");
    cmd.arg("--modified");
    cmd.arg("--exclude-standard");
    let output = cmd.output().expect("Couldn't execute Git");
    let stdout = String::from_utf8_lossy(&output.stdout);
    stdout.lines().filter(|s| s.ends_with(".rs")).map(|s| s.to_owned()).collect()
}

fn check_uncommitted() {
    let uncommitted = uncommitted_files();
    debug!("uncommitted files: {:?}", uncommitted);
    if !uncommitted.is_empty() {
        println!("Found untracked changes:");
        for f in uncommitted.iter() {
            println!("  {}", f);
        }
        println!("Commit your work, or run with `-u`.");
        println!("Exiting.");
        std::process::exit(1);
    }
}

fn make_opts() -> Options {
    let mut opts = Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("c", "check", "check only, don't format (unimplemented)");
    opts.optflag("u", "uncommitted", "format uncommitted files");
    opts
}

struct Config {
    commits: String,
    uncommitted: bool,
    check: bool,
}

impl Config {
    fn from_args(matches: &Matches, opts: &Options) -> Config {
        // `--help` display help message and quit
        if matches.opt_present("h") {
            let message = format!(
                "\nusage: {} <commits> [options]\n\n\
                 commits: number of commits to format, default: 1",
                env::args_os().next().unwrap().to_string_lossy()
            );
            println!("{}", opts.usage(&message));
            std::process::exit(0);
        }

        let mut config = Config {
            commits: "1".to_owned(),
            uncommitted: false,
            check: false,
        };

        if matches.opt_present("c") {
            config.check = true;
            unimplemented!();
        }

        if matches.opt_present("u") {
            config.uncommitted = true;
        }

        if matches.free.len() > 1 {
            panic!("unknown arguments, use `-h` for usage");
        }
        if matches.free.len() == 1 {
            let commits = matches.free[0].trim();
            if let Err(_) = u32::from_str(&commits) {
                panic!("Couldn't parse number of commits");
            }
            config.commits = commits.to_owned();
        }

        config
    }
}

fn main() {
    let _ = env_logger::init();

    let opts = make_opts();
    let matches = opts.parse(env::args().skip(1))
        .expect("Couldn't parse command line");
    let config = Config::from_args(&matches, &opts);

    if !config.uncommitted {
        check_uncommitted();
    }

    let stdout = git_diff(config.commits);
    let files = get_files(&stdout);
    debug!("files: {:?}", files);
    let files = prune_files(files);
    debug!("pruned files: {:?}", files);
    let exit_code = fmt_files(&files);
    std::process::exit(exit_code);
}
<commit_msg>Fix formatting in git-fmt<commit_after>extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate rustfmt_nightly as rustfmt;

use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;

use getopts::{Matches, Options};

use rustfmt::{run, Input};
use rustfmt::config;

fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> {
    let prefixes: Vec<_> = files
        .iter()
        .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs"))
        .map(|f| &f[..f.len() - 6])
        .collect();

    let mut pruned_prefixes = vec![];
    for p1 in prefixes.into_iter() {
        let mut include = true;
        if !p1.starts_with("src/bin/") {
            for p2 in pruned_prefixes.iter() {
                if p1.starts_with(p2) {
                    include = false;
                    break;
                }
            }
        }
        if include {
            pruned_prefixes.push(p1);
        }
    }
    debug!("prefixes: {:?}", pruned_prefixes);

    files
        .into_iter()
        .filter(|f| {
            let mut include = true;
            if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") {
                return true;
            }
            for pp in pruned_prefixes.iter() {
                if f.starts_with(pp) {
                    include = false;
                    break;
                }
            }
            include
        })
        .collect()
}

fn git_diff(commits: String) -> String {
    let mut cmd = Command::new("git");
    cmd.arg("diff");
    if commits != "0" {
        cmd.arg(format!("HEAD~{}", commits));
    }
    let output = cmd.output().expect("Couldn't execute `git diff`");
    String::from_utf8_lossy(&output.stdout).into_owned()
}

fn get_files(input: &str) -> Vec<&str> {
    input
        .lines()
        .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs"))
        .map(|line| &line[6..])
        .collect()
}

fn fmt_files(files: &[&str]) -> i32 {
    let (config, _) = config::Config::from_resolved_toml_path(Path::new("."))
        .unwrap_or_else(|_| (config::Config::default(), None));

    let mut exit_code = 0;
    for file in files {
        let summary = run(Input::File(PathBuf::from(file)), &config);
        if !summary.has_no_errors() {
            exit_code = 1;
        }
    }
    exit_code
}

fn uncommitted_files() -> Vec<String> {
    let mut cmd = Command::new("git");
    cmd.arg("ls-files");
    cmd.arg("--others");
    cmd.arg("--modified");
    cmd.arg("--exclude-standard");
    let output = cmd.output().expect("Couldn't execute Git");
    let stdout = String::from_utf8_lossy(&output.stdout);
    stdout
        .lines()
        .filter(|s| s.ends_with(".rs"))
        .map(|s| s.to_owned())
        .collect()
}

fn check_uncommitted() {
    let uncommitted = uncommitted_files();
    debug!("uncommitted files: {:?}", uncommitted);
    if !uncommitted.is_empty() {
        println!("Found untracked changes:");
        for f in uncommitted.iter() {
            println!("  {}", f);
        }
        println!("Commit your work, or run with `-u`.");
        println!("Exiting.");
        std::process::exit(1);
    }
}

fn make_opts() -> Options {
    let mut opts = Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("c", "check", "check only, don't format (unimplemented)");
    opts.optflag("u", "uncommitted", "format uncommitted files");
    opts
}

struct Config {
    commits: String,
    uncommitted: bool,
    check: bool,
}

impl Config {
    fn from_args(matches: &Matches, opts: &Options) -> Config {
        // `--help` display help message and quit
        if matches.opt_present("h") {
            let message = format!(
                "\nusage: {} <commits> [options]\n\n\
                 commits: number of commits to format, default: 1",
                env::args_os().next().unwrap().to_string_lossy()
            );
            println!("{}", opts.usage(&message));
            std::process::exit(0);
        }

        let mut config = Config {
            commits: "1".to_owned(),
            uncommitted: false,
            check: false,
        };

        if matches.opt_present("c") {
            config.check = true;
            unimplemented!();
        }

        if matches.opt_present("u") {
            config.uncommitted = true;
        }

        if matches.free.len() > 1 {
            panic!("unknown arguments, use `-h` for usage");
        }
        if matches.free.len() == 1 {
            let commits = matches.free[0].trim();
            if let Err(_) = u32::from_str(&commits) {
                panic!("Couldn't parse number of commits");
            }
            config.commits = commits.to_owned();
        }

        config
    }
}

fn main() {
    let _ = env_logger::init();

    let opts = make_opts();
    let matches = opts.parse(env::args().skip(1))
        .expect("Couldn't parse command line");
    let config = Config::from_args(&matches, &opts);

    if !config.uncommitted {
        check_uncommitted();
    }

    let stdout = git_diff(config.commits);
    let files = get_files(&stdout);
    debug!("files: {:?}", files);
    let files = prune_files(files);
    debug!("pruned files: {:?}", files);
    let exit_code = fmt_files(&files);
    std::process::exit(exit_code);
}
<|endoftext|>


<commit_before>use criterion::{black_box, criterion_group, criterion_main, Criterion};
use git_brws::argv::Parsed;
use git_brws::url::build_url;
use std::ffi::OsStr;

struct DummyArgs<'a>(Vec<&'a OsStr>);

impl<'a> DummyArgs<'a> {
    fn new(args: &'a [&'a str]) -> DummyArgs<'a> {
        DummyArgs(args.iter().map(AsRef::as_ref).collect())
    }
}

impl<'a> IntoIterator for DummyArgs<'a> {
    type Item = &'a OsStr;
    type IntoIter = std::vec::IntoIter<Self::Item>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

fn criterion_benchmark(c: &mut Criterion) {
    c.bench_function("no argument", |b| {
        b.iter(|| {
            let args = DummyArgs::new(&[]);
            if let Parsed::OpenPage(cfg) = Parsed::from_iter(args).unwrap() {
                build_url(black_box(&cfg)).unwrap();
            } else {
                assert!(false);
            }
        })
    });
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<commit_msg>add more benchmark test cases<commit_after>use criterion::{criterion_group, criterion_main, Criterion};
use git_brws::argv::Parsed;
use git_brws::url::build_url;

fn criterion_benchmark(c: &mut Criterion) {
    macro_rules! bench_function {
        ($bench_name:expr, $args:expr) => {
            c.bench_function($bench_name, |b| {
                b.iter(|| {
                    let parsed = Parsed::from_iter($args.iter()).unwrap();
                    if let Parsed::OpenPage(cfg) = parsed {
                        build_url(&cfg).unwrap();
                    } else {
                        assert!(false);
                    }
                })
            });
        };
    }

    bench_function!("no argument", ["git-brws"]);
    bench_function!("commit", ["git-brws", "c6c470c"]);
    bench_function!("diff", ["git-brws", "25d500f..c6c470c"]);
    bench_function!("file", ["git-brws", "README.md"]);
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
<|endoftext|>


<commit_before>// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Axis-aligned bounding boxes

use point::{Point, Point2, Point3};
use vector::{Vector, Vec2, Vec3};
use array::build;
use std::fmt;
use std::num::{zero, one};
use std::iter::Iterator;

pub trait Aabb
<
    S: Primitive,
    V: Vector<S, Slice>,
    P: Point<S, V, Slice>,
    Slice
> {
    fn new(p1: &P, p2: &P) -> Self;
    fn min<'a>(&'a self) -> &'a P;
    fn max<'a>(&'a self) -> &'a P;
    #[inline] fn dim(&self) -> V { self.max().sub_p(self.min()) }
    #[inline] fn volume(&self) -> S { self.dim().comp_mul() }
    #[inline] fn center(&self) -> P {
        let two = one::<S>() + one::<S>();
        self.min().add_v(&self.dim().div_s(two))
    }

    // Tests whether a point is cointained in the box, inclusive for min corner
    // and exclusive for the max corner.
    #[inline] fn contains(&self, p: &P) -> bool {
        p.sub_p(self.min()).iter().all(|x| *x >= zero::<S>()) &&
        self.max().sub_p(p).iter().all(|x| *x > zero::<S>())
    }

    // Returns a new AABB that is grown to include the given point.
    fn grow(&self, p: &P) -> Self {
        let mn : P = build(|i| self.min().i(i).min(p.i(i)));
        let mx : P = build(|i| self.max().i(i).max(p.i(i)));
        Aabb::new(&mn, &mx)
    }

    // Returns a new AABB that has its points translated by the given vector.
    fn add_v(&self, v: &V) -> Self {
        Aabb::new(&self.min().add_v(v), &self.max().add_v(v))
    }

    fn mul_s(&self, s: S) -> Self {
        Aabb::new(&self.min().mul_s(s.clone()), &self.max().mul_s(s.clone()))
    }

    fn mul_v(&self, v: &V) -> Self {
        let mn : P = Point::from_vec(&self.min().to_vec().mul_v(v));
        let mx : P = Point::from_vec(&self.max().to_vec().mul_v(v));
        Aabb::new(&mn, &mx)
    }
}

#[deriving(Clone, Eq)]
pub struct Aabb2<S> {
    mn: Point2<S>,
    mx: Point2<S>,
}

impl<S: Num + Orderable> Aabb2<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: &Point2<S>, p2: &Point2<S>) -> Aabb2<S> {
        Aabb2 {
            mn: Point2::new(p1.x.min(&p2.x), p1.y.min(&p2.y)),
            mx: Point2::new(p1.x.max(&p2.x), p1.y.max(&p2.y)),
        }
    }
}

impl<S: Primitive> Aabb<S, Vec2<S>, Point2<S>, [S, ..2]> for Aabb2<S> {
    fn new(p1: &Point2<S>, p2: &Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) }
    #[inline] fn min<'a>(&'a self) -> &'a Point2<S> { &self.mn }
    #[inline] fn max<'a>(&'a self) -> &'a Point2<S> { &self.mx }
}

impl<S: fmt::Show> ToStr for Aabb2<S> {
    fn to_str(&self) -> ~str {
        format!("[{} - {}]", self.mn.to_str(), self.mx.to_str())
    }
}

#[deriving(Clone, Eq)]
pub struct Aabb3<S> {
    mn: Point3<S>,
    mx: Point3<S>,
}

impl<S: Num + Orderable> Aabb3<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: &Point3<S>, p2: &Point3<S>) -> Aabb3<S> {
        Aabb3 {
            mn: Point3::new(p1.x.min(&p2.x), p1.y.min(&p2.y), p1.z.min(&p2.z)),
            mx: Point3::new(p1.x.max(&p2.x), p1.y.max(&p2.y), p1.z.max(&p2.z)),
        }
    }
}

impl<S: Primitive> Aabb<S, Vec3<S>, Point3<S>, [S, ..3]> for Aabb3<S> {
    fn new(p1: &Point3<S>, p2: &Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) }
    #[inline] fn min<'a>(&'a self) -> &'a Point3<S> { &self.mn }
    #[inline] fn max<'a>(&'a self) -> &'a Point3<S> { &self.mx }
}

impl<S: fmt::Show> ToStr for Aabb3<S> {
    fn to_str(&self) -> ~str {
        format!("[{} - {}]", self.mn.to_str(), self.mx.to_str())
    }
}
<commit_msg>Don't use abbrevations for the Aabb field names<commit_after>// Copyright 2013 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Axis-aligned bounding boxes

use point::{Point, Point2, Point3};
use vector::{Vector, Vec2, Vec3};
use array::build;
use std::fmt;
use std::num::{zero, one};
use std::iter::Iterator;

pub trait Aabb
<
    S: Primitive,
    V: Vector<S, Slice>,
    P: Point<S, V, Slice>,
    Slice
> {
    fn new(p1: &P, p2: &P) -> Self;
    fn min<'a>(&'a self) -> &'a P;
    fn max<'a>(&'a self) -> &'a P;
    #[inline] fn dim(&self) -> V { self.max().sub_p(self.min()) }
    #[inline] fn volume(&self) -> S { self.dim().comp_mul() }
    #[inline] fn center(&self) -> P {
        let two = one::<S>() + one::<S>();
        self.min().add_v(&self.dim().div_s(two))
    }

    // Tests whether a point is cointained in the box, inclusive for min corner
    // and exclusive for the max corner.
    #[inline] fn contains(&self, p: &P) -> bool {
        p.sub_p(self.min()).iter().all(|x| *x >= zero::<S>()) &&
        self.max().sub_p(p).iter().all(|x| *x > zero::<S>())
    }

    // Returns a new AABB that is grown to include the given point.
    fn grow(&self, p: &P) -> Self {
        let min : P = build(|i| self.min().i(i).min(p.i(i)));
        let max : P = build(|i| self.max().i(i).max(p.i(i)));
        Aabb::new(&min, &max)
    }

    // Returns a new AABB that has its points translated by the given vector.
    fn add_v(&self, v: &V) -> Self {
        Aabb::new(&self.min().add_v(v), &self.max().add_v(v))
    }

    fn mul_s(&self, s: S) -> Self {
        Aabb::new(&self.min().mul_s(s.clone()), &self.max().mul_s(s.clone()))
    }

    fn mul_v(&self, v: &V) -> Self {
        let min : P = Point::from_vec(&self.min().to_vec().mul_v(v));
        let max : P = Point::from_vec(&self.max().to_vec().mul_v(v));
        Aabb::new(&min, &max)
    }
}

#[deriving(Clone, Eq)]
pub struct Aabb2<S> {
    min: Point2<S>,
    max: Point2<S>,
}

impl<S: Num + Orderable> Aabb2<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: &Point2<S>, p2: &Point2<S>) -> Aabb2<S> {
        Aabb2 {
            min: Point2::new(p1.x.min(&p2.x), p1.y.min(&p2.y)),
            max: Point2::new(p1.x.max(&p2.x), p1.y.max(&p2.y)),
        }
    }
}

impl<S: Primitive> Aabb<S, Vec2<S>, Point2<S>, [S, ..2]> for Aabb2<S> {
    fn new(p1: &Point2<S>, p2: &Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) }
    #[inline] fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
    #[inline] fn max<'a>(&'a self) -> &'a Point2<S> { &self.max }
}

impl<S: fmt::Show> ToStr for Aabb2<S> {
    fn to_str(&self) -> ~str {
        format!("[{} - {}]", self.min.to_str(), self.max.to_str())
    }
}

#[deriving(Clone, Eq)]
pub struct Aabb3<S> {
    min: Point3<S>,
    max: Point3<S>,
}

impl<S: Num + Orderable> Aabb3<S> {
    /// Construct a new axis-aligned bounding box from two points.
    #[inline]
    pub fn new(p1: &Point3<S>, p2: &Point3<S>) -> Aabb3<S> {
        Aabb3 {
            min: Point3::new(p1.x.min(&p2.x), p1.y.min(&p2.y), p1.z.min(&p2.z)),
            max: Point3::new(p1.x.max(&p2.x), p1.y.max(&p2.y), p1.z.max(&p2.z)),
        }
    }
}

impl<S: Primitive> Aabb<S, Vec3<S>, Point3<S>, [S, ..3]> for Aabb3<S> {
    fn new(p1: &Point3<S>, p2: &Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) }
    #[inline] fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
    #[inline] fn max<'a>(&'a self) -> &'a Point3<S> { &self.max }
}

impl<S: fmt::Show> ToStr for Aabb3<S> {
    fn to_str(&self) -> ~str {
        format!("[{} - {}]", self.min.to_str(), self.max.to_str())
    }
}
<|endoftext|>


<commit_before>//! Parsers used by the checker.

use nom::multispace ;

use check::* ;

named!{
  #[doc = "Comment parser."],
  pub cmt, re_bytes_find!(r#"^;.*[\n\r]*"#)
}

named!{
  #[doc = "Parses comments and spaces."],
  pub spc_cmt<()>, map!(
    many0!( alt_complete!(cmt | multispace) ), |_| ()
  )
}

named!{
  #[doc = "Simple ident parser."],
  pub sident<& str>, map_res!(
    re_bytes_find!(r#"^[a-zA-Z~!@\$%^&\*_\-\+=<>\.\?\^/][a-zA-Z0-9~!@\$%^&\*_\-\+=<>\.\?\^/:]*"#),
    |bytes| ::std::str::from_utf8(bytes).chain_err(
      || "could not convert bytes to utf8"
    )
  )
}

named!{
  #[doc = "Quoted ident parser."],
  pub qident<& str>, map_res!(
    re_bytes_find!(r#"^\|[^\|]*\|"#),
    |bytes| ::std::str::from_utf8(bytes).chain_err(
      || "could not convert bytes to utf8"
    )
  )
}

named!{
  #[doc = "Ident parser."],
  pub ident<String>, alt_complete!(
    map!(sident, |s| format!("|{}|", s)) | map!(qident, |s| s.to_string())
  )
}

named!{
  #[doc = "Type parser."],
  pub typ<Typ>, map!(
    map_res!(
      re_bytes_find!("^[A-Z][a-zA-Z]*"),
      |bytes| ::std::str::from_utf8(bytes).chain_err(
        || "could not convert bytes to utf8"
      )
    ), |s| s.to_string()
  )
}

named!{
  #[doc = "Parses a predicate declaration."],
  pub pred_dec<PredDec>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("declare-fun") >>
    spc_cmt >> pred: ident >>
    spc_cmt >> char!('(') >>
    spc_cmt >> sig: many0!(
      terminated!(typ, spc_cmt)
    ) >>
    spc_cmt >> char!(')') >>
    spc_cmt >> typ >>
    spc_cmt >> char!(')') >> (
      PredDec { pred, sig }
    )
  )
}

named!{
  #[doc = "Parses an s-expression."],
  pub s_expr<Term>, alt_complete!(
    // (Un)quoted ident.
    ident |
    // Anything but a space or a paren.
    map!(
      map_res!(
        re_bytes_find!(r#"^[^\s()][^\s()]*"#),
        |bytes| ::std::str::from_utf8(bytes).chain_err(
          || "could not convert bytes to utf8"
        )
      ), |s| s.to_string()
    ) |
    // A sequence of terms between parens.
    do_parse!(
      char!('(') >>
      spc_cmt >> terms: many1!(
        terminated!(s_expr, spc_cmt)
      ) >>
      spc_cmt >> char!(')') >> ({
        let mut s = "( ".to_string() ;
        for term in terms {
          s.push_str(& term) ;
          s.push(' ')
        }
        s.push(')') ;
        s
      })
    )
  )
}

named!{
  #[doc = "Parses some arguments."],
  pub arguments<Args>, do_parse!(
    char!('(') >>
    spc_cmt >> args: many0!(
      do_parse!(
        char!('(') >>
        spc_cmt >> id: ident >>
        spc_cmt >> ty: typ >>
        spc_cmt >> char!(')') >>
        spc_cmt >> (
          (id, ty)
        )
      )
    ) >>
    spc_cmt >> char!(')') >> (args)
  )
}

named!{
  #[doc = "Parses a predicate definition."],
  pub pred_def<PredDef>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("define-fun") >>
    spc_cmt >> pred: ident >>
    spc_cmt >> args: arguments >>
    spc_cmt >> typ >>
    spc_cmt >> body: s_expr >>
    spc_cmt >> char!(')') >> (
      PredDef { pred, args, body }
    )
  )
}

named!{
  #[doc = "Parses a conjunction."],
  pub conjunction< Vec<Term> >, alt_complete!(
    do_parse!(
      char!('(') >>
      spc_cmt >> tag!("and") >>
      spc_cmt >> exprss: many0!(
        terminated!(conjunction, spc_cmt)
      ) >>
      spc_cmt >> char!(')') >> ({
        let mut iter = exprss.into_iter() ;
        if let Some(mut exprs) = iter.next() {
          for es in iter {
            use std::iter::Extend ;
            exprs.extend(es)
          }
          exprs
        } else {
          panic!("nullary `and` application")
        }
      })
    ) |

    map!(s_expr, |s| vec![s])
  )
}

named!{
  #[doc = "Parses a clause."],
  pub clause<Clause>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("assert") >>
    spc_cmt >> char!('(') >>
    spc_cmt >> clause: alt_complete!(

      do_parse!(
        spc_cmt >> tag!("forall") >>
        spc_cmt >> args: arguments >>
        spc_cmt >> lets: many0!(
          do_parse!(
            char!('(') >>
            spc_cmt >> tag!("let") >>
            spc_cmt >> char!('(') >>
            spc_cmt >> bindings: many0!(
              do_parse!(
                char!('(') >>
                spc_cmt >> id: ident >>
                spc_cmt >> term: s_expr >>
                spc_cmt >> char!(')') >>
                spc_cmt >> (
                  (id, term)
                )
              )
            ) >>
            spc_cmt >> char!(')') >>
            spc_cmt >> (
              bindings
            )
          )
        ) >>
        spc_cmt >> char!('(') >>
        spc_cmt >> tag!("=>") >>
        spc_cmt >> lhs: conjunction >>
        spc_cmt >> rhs: s_expr >>
        spc_cmt >> char!(')') >>
        spc_cmt >> many0!(
          terminated!(char!(')'), spc_cmt)
        ) >> (
          Clause { args, lets, lhs, rhs }
        )
      ) |

      do_parse!(
        spc_cmt >> tag!("not") >>
        spc_cmt >> char!('(') >>
        spc_cmt >> tag!("exists") >>
        spc_cmt >> args: arguments >>
        spc_cmt >> lets: many0!(
          do_parse!(
            char!('(') >>
            spc_cmt >> tag!("let") >>
            spc_cmt >> char!('(') >>
            spc_cmt >> bindings: many0!(
              do_parse!(
                char!('(') >>
                spc_cmt >> id: ident >>
                spc_cmt >> term: s_expr >>
                spc_cmt >> char!(')') >> (
                  (id, term)
                )
              )
            ) >>
            spc_cmt >> char!(')') >> (
              bindings
            )
          )
        ) >>
        spc_cmt >> lhs: conjunction >>
        spc_cmt >> many0!(
          terminated!(char!(')'), spc_cmt)
        ) >> (
          Clause { args, lets, lhs, rhs: "false".into() }
        )
      )
    ) >> (
      clause
    )
  )
}

named!{
  #[doc = "Parses the infer command."],
  pub infer<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("check-sat") >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `set-info`."],
  pub set_info<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("set-info") >>
    spc_cmt >> re_bytes_find!(r#"^:[a-zA-Z0-9\-]*"#) >>
    spc_cmt >> alt_complete!(
      re_bytes_find!(r#"^"[^"]*""#) |
      re_bytes_find!(r#"^[^)]*"#)
    ) >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `set-logic`."],
  pub set_logic<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("set-logic") >>
    spc_cmt >> tag!("HORN") >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `hc` file."],
  pub parse_input<Input>, do_parse!(
    spc_cmt >> many0!(
      terminated!(
        alt_complete!( set_info | set_logic ), spc_cmt
      )
    ) >>
    spc_cmt >> pred_decs: many0!(
      terminated!(pred_dec, spc_cmt)
    ) >>
    spc_cmt >> clauses: many0!(
      terminated!(clause, spc_cmt)
    ) >>
    spc_cmt >> infer >>
    spc_cmt >> (
      Input { pred_decs, clauses }
    )
  )
}

named!{
  #[doc = "Parses the output of a horn clause run."],
  pub parse_output<Output>, do_parse!(
    spc_cmt >> tag!("sat") >>
    spc_cmt >> char!('(') >>
    spc_cmt >> tag!("model") >>
    spc_cmt >> pred_defs: many0!(
      terminated!(pred_def, spc_cmt)
    ) >>
    spc_cmt >> char!(')') >>
    spc_cmt >> (
      Output { pred_defs }
    )
  )
}

named!{
  #[doc = "Parses the output of an eldarica run."],
  pub parse_eld_output<Output>, do_parse!(
    spc_cmt >> dbg_dmp!(tag!("sat")) >>
    spc_cmt >> pred_defs: many0!(
      terminated!(dbg_dmp!(pred_def), spc_cmt)
    ) >>
    spc_cmt >> (
      Output { pred_defs }
    )
  )
}<commit_msg>checker fixes<commit_after>//! Parsers used by the checker.

use nom::multispace ;

use check::* ;

named!{
  #[doc = "Comment parser."],
  pub cmt, re_bytes_find!(r#"^;.*[\n\r]*"#)
}

named!{
  #[doc = "Parses comments and spaces."],
  pub spc_cmt<()>, map!(
    many0!( alt_complete!(cmt | multispace) ), |_| ()
  )
}

named!{
  #[doc = "Simple ident parser."],
  pub sident<& str>, map_res!(
    re_bytes_find!(r#"^[a-zA-Z~!@\$%^&\*_\-\+=<>\.\?\^/][a-zA-Z0-9~!@\$%^&\*_\-\+=<>\.\?\^/:]*"#),
    |bytes| ::std::str::from_utf8(bytes).chain_err(
      || "could not convert bytes to utf8"
    )
  )
}

named!{
  #[doc = "Quoted ident parser."],
  pub qident<& str>, map_res!(
    re_bytes_find!(r#"^\|[^\|]*\|"#),
    |bytes| ::std::str::from_utf8(bytes).chain_err(
      || "could not convert bytes to utf8"
    )
  )
}

named!{
  #[doc = "Ident parser."],
  pub ident<String>, alt_complete!(
    map!(sident, |s| format!("|{}|", s)) | map!(qident, |s| s.to_string())
  )
}

named!{
  #[doc = "Type parser."],
  pub typ<Typ>, map!(
    map_res!(
      re_bytes_find!("^[A-Z][a-zA-Z]*"),
      |bytes| ::std::str::from_utf8(bytes).chain_err(
        || "could not convert bytes to utf8"
      )
    ), |s| s.to_string()
  )
}

named!{
  #[doc = "Parses a predicate declaration."],
  pub pred_dec<PredDec>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("declare-fun") >>
    spc_cmt >> pred: ident >>
    spc_cmt >> char!('(') >>
    spc_cmt >> sig: many0!(
      terminated!(typ, spc_cmt)
    ) >>
    spc_cmt >> char!(')') >>
    spc_cmt >> typ >>
    spc_cmt >> char!(')') >> (
      PredDec { pred, sig }
    )
  )
}

named!{
  #[doc = "Parses an s-expression."],
  pub s_expr<Term>, alt_complete!(
    // (Un)quoted ident.
    ident |
    // Anything but a space or a paren.
    map!(
      map_res!(
        re_bytes_find!(r#"^[^\s()][^\s()]*"#),
        |bytes| ::std::str::from_utf8(bytes).chain_err(
          || "could not convert bytes to utf8"
        )
      ), |s| s.to_string()
    ) |
    // A sequence of terms between parens.
    do_parse!(
      char!('(') >>
      spc_cmt >> terms: many1!(
        terminated!(s_expr, spc_cmt)
      ) >>
      spc_cmt >> char!(')') >> ({
        let mut s = "( ".to_string() ;
        for term in terms {
          s.push_str(& term) ;
          s.push(' ')
        }
        s.push(')') ;
        s
      })
    )
  )
}

named!{
  #[doc = "Parses some arguments."],
  pub arguments<Args>, do_parse!(
    char!('(') >>
    spc_cmt >> args: many0!(
      do_parse!(
        char!('(') >>
        spc_cmt >> id: ident >>
        spc_cmt >> ty: typ >>
        spc_cmt >> char!(')') >>
        spc_cmt >> (
          (id, ty)
        )
      )
    ) >>
    spc_cmt >> char!(')') >> (args)
  )
}

named!{
  #[doc = "Parses a predicate definition."],
  pub pred_def<PredDef>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("define-fun") >>
    spc_cmt >> pred: ident >>
    spc_cmt >> args: arguments >>
    spc_cmt >> typ >>
    spc_cmt >> body: s_expr >>
    spc_cmt >> char!(')') >> (
      PredDef { pred, args, body }
    )
  )
}

named!{
  #[doc = "Parses a conjunction."],
  pub conjunction< Vec<Term> >, alt_complete!(
    do_parse!(
      char!('(') >>
      spc_cmt >> tag!("and") >>
      spc_cmt >> exprss: many0!(
        terminated!(conjunction, spc_cmt)
      ) >>
      spc_cmt >> char!(')') >> ({
        let mut iter = exprss.into_iter() ;
        if let Some(mut exprs) = iter.next() {
          for es in iter {
            use std::iter::Extend ;
            exprs.extend(es)
          }
          exprs
        } else {
          panic!("nullary `and` application")
        }
      })
    ) |

    map!(s_expr, |s| vec![s])
  )
}

named!{
  #[doc = "Parses a clause."],
  pub clause<Clause>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("assert") >>
    spc_cmt >> char!('(') >>
    spc_cmt >> clause: alt_complete!(

      do_parse!(
        spc_cmt >> tag!("forall") >>
        spc_cmt >> args: arguments >>
        spc_cmt >> lets: many0!(
          do_parse!(
            char!('(') >>
            spc_cmt >> tag!("let") >>
            spc_cmt >> char!('(') >>
            spc_cmt >> bindings: many0!(
              do_parse!(
                char!('(') >>
                spc_cmt >> id: ident >>
                spc_cmt >> term: s_expr >>
                spc_cmt >> char!(')') >>
                spc_cmt >> (
                  (id, term)
                )
              )
            ) >>
            spc_cmt >> char!(')') >>
            spc_cmt >> (
              bindings
            )
          )
        ) >>
        spc_cmt >> char!('(') >>
        spc_cmt >> clause: alt_complete!(
          do_parse!(
            tag!("not") >>
            spc_cmt >> char!('(') >>
            spc_cmt >> tag!("or") >>
            spc_cmt >> lhs: many0!(
              terminated!(s_expr, spc_cmt)
            ) >>
            spc_cmt >> char!(')') >> (
              Clause {
                args: args.clone(), lets: lets.clone(),
                lhs, rhs: "false".into()
              }
            )
          ) |
          do_parse!(
            tag!("=>") >>
            spc_cmt >> lhs: conjunction >>
            spc_cmt >> rhs: s_expr >> (
              Clause {
                args: args.clone(), lets: lets.clone(),
                lhs, rhs
              }
            )
          )
        ) >>
        spc_cmt >> many0!(
          terminated!(char!(')'), spc_cmt)
        ) >> (
          clause
        )
      ) |

      do_parse!(
        spc_cmt >> tag!("not") >>
        spc_cmt >> char!('(') >>
        spc_cmt >> tag!("exists") >>
        spc_cmt >> args: arguments >>
        spc_cmt >> lets: many0!(
          do_parse!(
            char!('(') >>
            spc_cmt >> tag!("let") >>
            spc_cmt >> char!('(') >>
            spc_cmt >> bindings: many0!(
              do_parse!(
                char!('(') >>
                spc_cmt >> id: ident >>
                spc_cmt >> term: s_expr >>
                spc_cmt >> char!(')') >> (
                  (id, term)
                )
              )
            ) >>
            spc_cmt >> char!(')') >> (
              bindings
            )
          )
        ) >>
        spc_cmt >> lhs: conjunction >>
        spc_cmt >> many0!(
          terminated!(char!(')'), spc_cmt)
        ) >> (
          Clause { args, lets, lhs, rhs: "false".into() }
        )
      )
    ) >> (
      clause
    )
  )
}

named!{
  #[doc = "Parses the infer command."],
  pub infer<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("check-sat") >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `set-info`."],
  pub set_info<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("set-info") >>
    spc_cmt >> re_bytes_find!(r#"^:[a-zA-Z0-9\-]*"#) >>
    spc_cmt >> alt_complete!(
      re_bytes_find!(r#"^"[^"]*""#) |
      re_bytes_find!(r#"^[^)]*"#)
    ) >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `set-logic`."],
  pub set_logic<()>, do_parse!(
    char!('(') >>
    spc_cmt >> tag!("set-logic") >>
    spc_cmt >> tag!("HORN") >>
    spc_cmt >> char!(')') >> (())
  )
}

named!{
  #[doc = "Parses a `hc` file."],
  pub parse_input<Input>, do_parse!(
    spc_cmt >> many0!(
      terminated!(
        alt_complete!( set_info | set_logic ), spc_cmt
      )
    ) >>
    spc_cmt >> pred_decs: many0!(
      terminated!(pred_dec, spc_cmt)
    ) >>
    spc_cmt >> clauses: many0!(
      terminated!(clause, spc_cmt)
    ) >>
    spc_cmt >> infer >>
    spc_cmt >> (
      Input { pred_decs, clauses }
    )
  )
}

named!{
  #[doc = "Parses the output of a horn clause run."],
  pub parse_output<Output>, do_parse!(
    spc_cmt >> tag!("sat") >>
    spc_cmt >> char!('(') >>
    spc_cmt >> tag!("model") >>
    spc_cmt >> pred_defs: many0!(
      terminated!(pred_def, spc_cmt)
    ) >>
    spc_cmt >> char!(')') >>
    spc_cmt >> (
      Output { pred_defs }
    )
  )
}

named!{
  #[doc = "Parses the output of an eldarica run."],
  pub parse_eld_output<Output>, do_parse!(
    spc_cmt >> tag!("sat") >>
    spc_cmt >> pred_defs: many0!(
      terminated!(pred_def, spc_cmt)
    ) >>
    spc_cmt >> (
      Output { pred_defs }
    )
  )
}<|endoftext|>