<commit_before>use std::collections::BTreeMap;
use std::string::String;
use std::vec::Vec;
use std::boxed::Box;
use std::fs::File;
use std::io::{stdout, Read, Write};
use std::env;
use std::process;

use self::to_num::ToNum;
use self::input_editor::readln;
use self::tokenizer::{Token, tokenize};
use self::expansion::expand_tokens;
use self::parser::{parse, Job};

pub mod builtin;
pub mod to_num;
pub mod input_editor;
pub mod tokenizer;
pub mod parser;
pub mod expansion;

/// Structure which represents a Terminal's command.
/// This command structure contains a name, and the code which run the
/// functionnality associated to this one, with zero, one or several argument(s).
/// # Example
/// ```
/// let my_command = Command {
///     name: "my_command",
///     help: "Describe what my_command does followed by a newline showing usage",
///     main: box|args: &[String]| {
///         println!("Say 'hello' to my command! :-D");
///     }
/// }
/// ```
pub struct Command {
    pub name: &'static str,
    pub help: &'static str,
    pub main: Box<Fn(&[String], &mut Shell)>,
}

/// This struct will contain all of the data structures related to this
/// instance of the shell.
pub struct Shell {
    pub variables: BTreeMap<String, String>,
    pub modes: Vec<Mode>,
}

impl Command {
    /// Return the map from command names to commands
    pub fn map() -> BTreeMap<String, Self> {
        let mut commands: BTreeMap<String, Self> = BTreeMap::new();

        commands.insert("cat".to_string(),
                        Command {
                            name: "cat",
                            help: "To display a file in the output\n    cat <your_file>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::cat(args);
                            }),
                        });

        commands.insert("cd".to_string(),
                        Command {
                            name: "cd",
                            help: "To change the current directory\n    cd <your_destination>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::cd(args);
                            }),
                        });

        commands.insert("echo".to_string(),
                        Command {
                            name: "echo",
                            help: "To display some text in the output\n    echo Hello world!",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::echo(args);
                            }),
                        });

        commands.insert("exit".to_string(),
                        Command {
                            name: "exit",
                            help: "To exit the curent session",
                            main: Box::new(|_: &[String], _: &mut Shell| {}),
                        });

        commands.insert("free".to_string(),
                        Command {
                            name: "free",
                            help: "Show memory information\n    free",
                            main: Box::new(|_: &[String], _: &mut Shell| {
                                builtin::free();
                            }),
                        });

        commands.insert("ls".to_string(),
                        Command {
                            name: "ls",
                            help: "To list the content of the current directory\n    ls",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::ls(args);
                            }),
                        });

        commands.insert("mkdir".to_string(),
                        Command {
                            name: "mkdir",
                            help: "To create a directory in the current directory\n    mkdir \
                                   <my_new_directory>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::mkdir(args);
                            }),
                        });

        commands.insert("poweroff".to_string(),
                        Command {
                            name: "poweroff",
                            help: "poweroff utility has the machine remove power, if \
                                   possible\n\tpoweroff",
                            main: Box::new(|_: &[String], _: &mut Shell| {
                                builtin::poweroff();
                            }),
                        });

        commands.insert("ps".to_string(),
                        Command {
                            name: "ps",
                            help: "Show process list\n    ps",
                            main: Box::new(|_: &[String], _: &mut Shell| {
                                builtin::ps();
                            }),
                        });

        commands.insert("pwd".to_string(),
                        Command {
                            name: "pwd",
                            help: "To output the path of the current directory\n    pwd",
                            main: Box::new(|_: &[String], _: &mut Shell| {
                                builtin::pwd();
                            }),
                        });

        commands.insert("read".to_string(),
                        Command {
                            name: "read",
                            help: "To read some variables\n    read <my_variable>",
                            main: Box::new(|args: &[String], shell: &mut Shell| {
                                builtin::read(args, &mut shell.variables);
                            }),
                        });

        commands.insert("rm".to_string(),
                        Command {
                            name: "rm",
                            help: "Remove a file\n    rm <file>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::rm(args);
                            }),
                        });

        commands.insert("rmdir".to_string(),
                        Command {
                            name: "rmdir",
                            help: "Remove a directory\n    rmdir <directory>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::rmdir(args);
                            }),
                        });

        commands.insert("run".to_string(),
                        Command {
                            name: "run",
                            help: "Run a script\n    run <script>",
                            main: Box::new(|args: &[String], shell: &mut Shell| {
                                builtin::run(args, &mut shell.variables);
                            }),
                        });

        commands.insert("sleep".to_string(),
                        Command {
                            name: "sleep",
                            help: "Make a sleep in the current session\n    sleep \
                                   <number_of_seconds>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::sleep(args);
                            }),
                        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.insert("touch".to_string(),
                        Command {
                            name: "touch",
                            help: "To create a file, in the current directory\n    touch <my_file>",
                            main: Box::new(|args: &[String], _: &mut Shell| {
                                builtin::touch(args);
                            }),
                        });

        // TODO: Someone should implement FromIterator for HashMap before
        //       changing the type back to HashMap
        let command_helper: BTreeMap<String, String> = commands.iter()
                                                               .map(|(k, v)| {
                                                                   (k.to_string(),
                                                                    v.help.to_string())
                                                               })
                                                               .collect();

        commands.insert("help".to_string(),
                        Command {
                            name: "help",
                            help: "Display a little helper for a given command\n    help ls",
                            main: Box::new(move |args: &[String], _: &mut Shell| {
                                if let Some(command) = args.get(1) {
                                    if command_helper.contains_key(command) {
                                        match command_helper.get(command) {
                                            Some(help) => println!("{}", help),
                                            None => {
                                                println!("Command helper not found [run 'help']...")
                                            }
                                        }
                                    } else {
                                        println!("Command helper not found [run 'help']...");
                                    }
                                } else {
                                    for (command, _help) in command_helper.iter() {
                                        println!("{}", command);
                                    }
                                }
                            }),
                        });

        commands
    }
}

pub struct Mode {
    value: bool,
}

fn on_command(command_string: &str, commands: &BTreeMap<String, Command>, shell: &mut Shell) {
    // Show variables
    if command_string == "$" {
        for (key, value) in shell.variables.iter() {
            println!("{}={}", key, value);
        }
        return;
    }

    let mut tokens: Vec<Token> = expand_tokens(&mut tokenize(command_string), &mut shell.variables);
    let jobs: Vec<Job> = parse(&mut tokens);

    // Execute commands
    for job in jobs.iter() {
        if job.command == "if" {
            let mut value = false;

            if let Some(left) = job.args.get(0) {
                if let Some(cmp) = job.args.get(1) {
                    if let Some(right) = job.args.get(2) {
                        if cmp == "==" {
                            value = *left == *right;
                        } else if cmp == "!=" {
                            value = *left != *right;
                        } else if cmp == ">" {
                            value = left.to_num_signed() > right.to_num_signed();
                        } else if cmp == ">=" {
                            value = left.to_num_signed() >= right.to_num_signed();
                        } else if cmp == "<" {
                            value = left.to_num_signed() < right.to_num_signed();
                        } else if cmp == "<=" {
                            value = left.to_num_signed() <= right.to_num_signed();
                        } else {
                            println!("Unknown comparison: {}", cmp);
                        }
                    } else {
                        println!("No right hand side");
                    }
                } else {
                    println!("No comparison operator");
                }
            } else {
                println!("No left hand side");
            }

            shell.modes.insert(0, Mode { value: value });
            continue;
        }

        if job.command == "else" {
            let mut syntax_error = false;
            match shell.modes.get_mut(0) {
                Some(mode) => mode.value = !mode.value,
                None => syntax_error = true,
            }
            if syntax_error {
                println!("Syntax error: else found with no previous if");
            }
            continue;
        }

        if job.command == "fi" {
            let mut syntax_error = false;
            if !shell.modes.is_empty() {
                shell.modes.remove(0);
            } else {
                syntax_error = true;
            }
            if syntax_error {
                println!("Syntax error: fi found with no previous if");
            }
            continue;
        }

        let mut skipped: bool = false;
        for mode in shell.modes.iter() {
            if !mode.value {
                skipped = true;
                break;
            }
        }
        if skipped {
            continue;
        }

        // Set variables
        if let Some(i) = job.command.find('=') {
            let name = job.command[0..i].trim();
            let mut value = job.command[i + 1..job.command.len()].trim().to_string();

            for i in 0..job.args.len() {
                if let Some(arg) = job.args.get(i) {
                    value = value + " " + &arg;
                }
            }

            set_var(&mut shell.variables, name, &value);
            continue;
        }

        // Commands
        let mut args = job.args.clone();
        args.insert(0, job.command.clone());
        if let Some(command) = commands.get(&job.command) {
            (*command.main)(&args, shell);
        } else {
            run_external_commmand(args, &mut shell.variables);
        }
    }
}

pub fn set_var(variables: &mut BTreeMap<String, String>, name: &str, value: &str) {
    if name.is_empty() {
        return;
    }

    if value.is_empty() {
        variables.remove(&name.to_string());
    } else {
        variables.insert(name.to_string(), value.to_string());
    }
}

fn print_prompt(modes: &Vec<Mode>) {
    for mode in modes.iter().rev() {
        if mode.value {
            print!("+ ");
        } else {
            print!("- ");
        }
    }

    let cwd = match env::current_dir() {
        Ok(path) => {
            match path.to_str() {
                Some(path_str) => path_str.to_string(),
                None => "?".to_string(),
            }
        }
        Err(_) => "?".to_string(),
    };

    print!("ion:{}# ", cwd);
    if let Err(message) = stdout().flush() {
        println!("{}: failed to flush prompt to stdout", message);
    }
}

fn run_external_commmand(args: Vec<String>, variables: &mut BTreeMap<String, String>) {
    if let Some(path) = args.get(0) {
        let mut command = process::Command::new(path);
        for i in 1..args.len() {
            if let Some(arg) = args.get(i) {
                command.arg(arg);
            }
        }
        match command.spawn() {
            Ok(mut child) => {
                match child.wait() {
                    Ok(status) => {
                        if let Some(code) = status.code() {
                            set_var(variables, "?", &format!("{}", code));
                        } else {
                            println!("{}: No child exit code", path);
                        }
                    }
                    Err(err) => println!("{}: Failed to wait: {}", path, err),
                }
            }
            Err(err) => println!("{}: Failed to execute: {}", path, err),
        }
    }
}

fn main() {
    let commands = Command::map();
    let mut shell = Shell {
        variables: BTreeMap::new(),
        modes: vec![],
    };

    for arg in env::args().skip(1) {
        let mut command_list = String::new();
        if let Ok(mut file) = File::open(&arg) {
            if let Err(message) = file.read_to_string(&mut command_list) {
                println!("{}: Failed to read {}", message, arg);
            }
        }
        on_command(&command_list, &commands, &mut shell);

        return;
    }

    loop {

        print_prompt(&shell.modes);

        if let Some(command_original) = readln() {
            let command = command_original.trim();
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                on_command(&command, &commands, &mut shell);
            }
        } else {
            break;
        }
    }
}
<commit_msg>Use box syntax instead of Box::new<commit_after>#![feature(box_syntax)]

use std::collections::BTreeMap;
use std::string::String;
use std::vec::Vec;
use std::boxed::Box;
use std::fs::File;
use std::io::{stdout, Read, Write};
use std::env;
use std::process;

use self::to_num::ToNum;
use self::input_editor::readln;
use self::tokenizer::{Token, tokenize};
use self::expansion::expand_tokens;
use self::parser::{parse, Job};

pub mod builtin;
pub mod to_num;
pub mod input_editor;
pub mod tokenizer;
pub mod parser;
pub mod expansion;

/// Structure which represents a Terminal's command.
/// This command structure contains a name, and the code which run the
/// functionnality associated to this one, with zero, one or several argument(s).
/// # Example
/// ```
/// let my_command = Command {
///     name: "my_command",
///     help: "Describe what my_command does followed by a newline showing usage",
///     main: box|args: &[String]| {
///         println!("Say 'hello' to my command! :-D");
///     }
/// }
/// ```
pub struct Command {
    pub name: &'static str,
    pub help: &'static str,
    pub main: Box<Fn(&[String], &mut Shell)>,
}

/// This struct will contain all of the data structures related to this
/// instance of the shell.
pub struct Shell {
    pub variables: BTreeMap<String, String>,
    pub modes: Vec<Mode>,
}

impl Command {
    /// Return the map from command names to commands
    pub fn map() -> BTreeMap<String, Self> {
        let mut commands: BTreeMap<String, Self> = BTreeMap::new();

        commands.insert("cat".to_string(),
                        Command {
                            name: "cat",
                            help: "To display a file in the output\n    cat <your_file>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::cat(args);
                            },
                        });

        commands.insert("cd".to_string(),
                        Command {
                            name: "cd",
                            help: "To change the current directory\n    cd <your_destination>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::cd(args);
                            },
                        });

        commands.insert("echo".to_string(),
                        Command {
                            name: "echo",
                            help: "To display some text in the output\n    echo Hello world!",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::echo(args);
                            },
                        });

        commands.insert("exit".to_string(),
                        Command {
                            name: "exit",
                            help: "To exit the curent session",
                            main: box |_: &[String], _: &mut Shell| {},
                        });

        commands.insert("free".to_string(),
                        Command {
                            name: "free",
                            help: "Show memory information\n    free",
                            main: box |_: &[String], _: &mut Shell| {
                                builtin::free();
                            },
                        });

        commands.insert("ls".to_string(),
                        Command {
                            name: "ls",
                            help: "To list the content of the current directory\n    ls",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::ls(args);
                            },
                        });

        commands.insert("mkdir".to_string(),
                        Command {
                            name: "mkdir",
                            help: "To create a directory in the current directory\n    mkdir \
                                   <my_new_directory>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::mkdir(args);
                            },
                        });

        commands.insert("poweroff".to_string(),
                        Command {
                            name: "poweroff",
                            help: "poweroff utility has the machine remove power, if \
                                   possible\n\tpoweroff",
                            main: box |_: &[String], _: &mut Shell| {
                                builtin::poweroff();
                            },
                        });

        commands.insert("ps".to_string(),
                        Command {
                            name: "ps",
                            help: "Show process list\n    ps",
                            main: box |_: &[String], _: &mut Shell| {
                                builtin::ps();
                            },
                        });

        commands.insert("pwd".to_string(),
                        Command {
                            name: "pwd",
                            help: "To output the path of the current directory\n    pwd",
                            main: box |_: &[String], _: &mut Shell| {
                                builtin::pwd();
                            },
                        });

        commands.insert("read".to_string(),
                        Command {
                            name: "read",
                            help: "To read some variables\n    read <my_variable>",
                            main: box |args: &[String], shell: &mut Shell| {
                                builtin::read(args, &mut shell.variables);
                            },
                        });

        commands.insert("rm".to_string(),
                        Command {
                            name: "rm",
                            help: "Remove a file\n    rm <file>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::rm(args);
                            },
                        });

        commands.insert("rmdir".to_string(),
                        Command {
                            name: "rmdir",
                            help: "Remove a directory\n    rmdir <directory>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::rmdir(args);
                            },
                        });

        commands.insert("run".to_string(),
                        Command {
                            name: "run",
                            help: "Run a script\n    run <script>",
                            main: box |args: &[String], shell: &mut Shell| {
                                builtin::run(args, &mut shell.variables);
                            },
                        });

        commands.insert("sleep".to_string(),
                        Command {
                            name: "sleep",
                            help: "Make a sleep in the current session\n    sleep \
                                   <number_of_seconds>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::sleep(args);
                            },
                        });

        // Simple command to create a file, in the current directory
        // The file has got the name given as the first argument of the command
        // If the command have no arguments, the command don't create the file
        commands.insert("touch".to_string(),
                        Command {
                            name: "touch",
                            help: "To create a file, in the current directory\n    touch <my_file>",
                            main: box |args: &[String], _: &mut Shell| {
                                builtin::touch(args);
                            },
                        });

        // TODO: Someone should implement FromIterator for HashMap before
        //       changing the type back to HashMap
        let command_helper: BTreeMap<String, String> = commands.iter()
                                                               .map(|(k, v)| {
                                                                   (k.to_string(),
                                                                    v.help.to_string())
                                                               })
                                                               .collect();

        commands.insert("help".to_string(),
                        Command {
                            name: "help",
                            help: "Display a little helper for a given command\n    help ls",
                            main: box move |args: &[String], _: &mut Shell| {
                                if let Some(command) = args.get(1) {
                                    if command_helper.contains_key(command) {
                                        match command_helper.get(command) {
                                            Some(help) => println!("{}", help),
                                            None => {
                                                println!("Command helper not found [run 'help']...")
                                            }
                                        }
                                    } else {
                                        println!("Command helper not found [run 'help']...");
                                    }
                                } else {
                                    for (command, _help) in command_helper.iter() {
                                        println!("{}", command);
                                    }
                                }
                            },
                        });

        commands
    }
}

pub struct Mode {
    value: bool,
}

fn on_command(command_string: &str, commands: &BTreeMap<String, Command>, shell: &mut Shell) {
    // Show variables
    if command_string == "$" {
        for (key, value) in shell.variables.iter() {
            println!("{}={}", key, value);
        }
        return;
    }

    let mut tokens: Vec<Token> = expand_tokens(&mut tokenize(command_string), &mut shell.variables);
    let jobs: Vec<Job> = parse(&mut tokens);

    // Execute commands
    for job in jobs.iter() {
        if job.command == "if" {
            let mut value = false;

            if let Some(left) = job.args.get(0) {
                if let Some(cmp) = job.args.get(1) {
                    if let Some(right) = job.args.get(2) {
                        if cmp == "==" {
                            value = *left == *right;
                        } else if cmp == "!=" {
                            value = *left != *right;
                        } else if cmp == ">" {
                            value = left.to_num_signed() > right.to_num_signed();
                        } else if cmp == ">=" {
                            value = left.to_num_signed() >= right.to_num_signed();
                        } else if cmp == "<" {
                            value = left.to_num_signed() < right.to_num_signed();
                        } else if cmp == "<=" {
                            value = left.to_num_signed() <= right.to_num_signed();
                        } else {
                            println!("Unknown comparison: {}", cmp);
                        }
                    } else {
                        println!("No right hand side");
                    }
                } else {
                    println!("No comparison operator");
                }
            } else {
                println!("No left hand side");
            }

            shell.modes.insert(0, Mode { value: value });
            continue;
        }

        if job.command == "else" {
            let mut syntax_error = false;
            match shell.modes.get_mut(0) {
                Some(mode) => mode.value = !mode.value,
                None => syntax_error = true,
            }
            if syntax_error {
                println!("Syntax error: else found with no previous if");
            }
            continue;
        }

        if job.command == "fi" {
            let mut syntax_error = false;
            if !shell.modes.is_empty() {
                shell.modes.remove(0);
            } else {
                syntax_error = true;
            }
            if syntax_error {
                println!("Syntax error: fi found with no previous if");
            }
            continue;
        }

        let mut skipped: bool = false;
        for mode in shell.modes.iter() {
            if !mode.value {
                skipped = true;
                break;
            }
        }
        if skipped {
            continue;
        }

        // Set variables
        if let Some(i) = job.command.find('=') {
            let name = job.command[0..i].trim();
            let mut value = job.command[i + 1..job.command.len()].trim().to_string();

            for i in 0..job.args.len() {
                if let Some(arg) = job.args.get(i) {
                    value = value + " " + &arg;
                }
            }

            set_var(&mut shell.variables, name, &value);
            continue;
        }

        // Commands
        let mut args = job.args.clone();
        args.insert(0, job.command.clone());
        if let Some(command) = commands.get(&job.command) {
            (*command.main)(&args, shell);
        } else {
            run_external_commmand(args, &mut shell.variables);
        }
    }
}

pub fn set_var(variables: &mut BTreeMap<String, String>, name: &str, value: &str) {
    if name.is_empty() {
        return;
    }

    if value.is_empty() {
        variables.remove(&name.to_string());
    } else {
        variables.insert(name.to_string(), value.to_string());
    }
}

fn print_prompt(modes: &Vec<Mode>) {
    for mode in modes.iter().rev() {
        if mode.value {
            print!("+ ");
        } else {
            print!("- ");
        }
    }

    let cwd = match env::current_dir() {
        Ok(path) => {
            match path.to_str() {
                Some(path_str) => path_str.to_string(),
                None => "?".to_string(),
            }
        }
        Err(_) => "?".to_string(),
    };

    print!("ion:{}# ", cwd);
    if let Err(message) = stdout().flush() {
        println!("{}: failed to flush prompt to stdout", message);
    }
}

fn run_external_commmand(args: Vec<String>, variables: &mut BTreeMap<String, String>) {
    if let Some(path) = args.get(0) {
        let mut command = process::Command::new(path);
        for i in 1..args.len() {
            if let Some(arg) = args.get(i) {
                command.arg(arg);
            }
        }
        match command.spawn() {
            Ok(mut child) => {
                match child.wait() {
                    Ok(status) => {
                        if let Some(code) = status.code() {
                            set_var(variables, "?", &format!("{}", code));
                        } else {
                            println!("{}: No child exit code", path);
                        }
                    }
                    Err(err) => println!("{}: Failed to wait: {}", path, err),
                }
            }
            Err(err) => println!("{}: Failed to execute: {}", path, err),
        }
    }
}

fn main() {
    let commands = Command::map();
    let mut shell = Shell {
        variables: BTreeMap::new(),
        modes: vec![],
    };

    for arg in env::args().skip(1) {
        let mut command_list = String::new();
        if let Ok(mut file) = File::open(&arg) {
            if let Err(message) = file.read_to_string(&mut command_list) {
                println!("{}: Failed to read {}", message, arg);
            }
        }
        on_command(&command_list, &commands, &mut shell);

        return;
    }

    loop {

        print_prompt(&shell.modes);

        if let Some(command_original) = readln() {
            let command = command_original.trim();
            if command == "exit" {
                break;
            } else if !command.is_empty() {
                on_command(&command, &commands, &mut shell);
            }
        } else {
            break;
        }
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libzou;
extern crate num_cpus;

use clap::{App, Arg};
use libzou::cargo_helper::get_cargo_info;
use libzou::download::download_chunks;
use libzou::filesize::format_filesize;
use libzou::protocol::{get_protocol, Protocol};
use libzou::util::prompt_user;
use libzou::write::OutputFileWriter;
#[macro_use]
mod logs;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

fn main() {

    // Parse arguments

    let argparse = App::new("Zou")
        .about("Zou, a simple and fast download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("mirrors")
                 .long("mirrors")
                 .short("m")
                 .multiple(true)
                 .takes_value(true)
                 .help("Download using a list of mirrors - the list of mirrors is used WITH the original URL"))
        .arg(Arg::with_name("ssl_support")
                .long("ssl_support")
                .short("s")
                .help("Switch to an SSL client"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    // Get the URL as a Path structure
    let url = Path::new(argparse.value_of("url").unwrap());

    // Get the path filename
    let filename = url.file_name().unwrap().to_str().unwrap();

    // Check if multi-threaded download is possible
    let mut threads: usize = value_t!(argparse, "threads", usize)
        .and_then(|v| if v != 0 {
            Ok(v)
        } else {
            Err(clap::Error::with_description(
                "Cannot download a file using 0 thread",
                clap::ErrorKind::InvalidValue,
            ))
        })
        .unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        info!(&format!("version: {}", crate_version!()));
        info!(&format!("file: {}", filename));
        info!(&format!("threads: {}", threads));
    }

    let local_path = Path::new(&filename);

    if local_path.exists() {
        if local_path.is_dir() {
            epanic!(
                "The local path to store the remote content is already exists, \
                        and is a directory!"
            );
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(
                "The path to store the file already exists! \
                                          Do you want to override it? [y/N]",
            );
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            warning!(
                "The path to store the file already exists! \
                                 It is going to be overriden."
            );
        }
    }

    // Get automaticaly the protocol from the given URL
    let ssl_support = match get_protocol(url.to_str().unwrap()) {
        Some(protocol) => match protocol {
            // If the protocol is HTTP, return the user decision for the HTTPS client
            Protocol::HTTP => argparse.is_present("ssl_support"),
            // Force to use HTTPS client
            Protocol::HTTPS => true,
        },
        None => epanic!("Unknown protocol!"),
    };

    let cargo_info =
        get_cargo_info(url.to_str().unwrap(), ssl_support).expect("fail to parse url");
    info!(&format!(
        "Remote content length: {}",
        format_filesize(cargo_info.file.content_length)
    ));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(cargo_info.file.content_length).expect(
        "Cannot extend local file !",
    );
    let out_file = OutputFileWriter::new(local_file);

    // If the server does not accept PartialContent status, download the remote file
    // using only one thread
    if !cargo_info.accept_partialcontent {
        warning!(
            "The remote server does not accept PartialContent status! \
                             Downloading the remote file using one thread."
        );
        threads = 1;
    }

    if download_chunks(cargo_info, out_file, threads as u64, filename, ssl_support) {
        ok!(&format!(
            "Your download is available in {}",
            local_path.to_str().unwrap()
        ));
    } else {
        // If the file is not ok, delete it from the file system
        error!("Download failed! An error occured - erasing file... ");
        if remove_file(local_path).is_err() {
            error!("Cannot remove downloaded file!");
        }
    }

}
<commit_msg>Change import statements, and main function code<commit_after>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libzou;
extern crate num_cpus;

use clap::{App, Arg};
use libzou::cargo_helper::get_remote_server_informations;
use libzou::download::download_chunks;
use libzou::filesize::StringFileType;
use libzou::protocol::{get_protocol, Protocol};
use libzou::util::prompt_user;
use libzou::write::OutputFileWriter;
#[macro_use]
mod logs;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

fn main() {

    // Parse arguments

    let argparse = App::new("Zou")
        .about("Zou, a simple and fast download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("mirrors")
                 .long("mirrors")
                 .short("m")
                 .multiple(true)
                 .takes_value(true)
                 .help("Download using a list of mirrors - the list of mirrors is used WITH the original URL"))
        .arg(Arg::with_name("ssl_support")
                .long("ssl_support")
                .short("s")
                .help("Switch to an SSL client"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    // Get the URL as a Path structure
    let url = Path::new(argparse.value_of("url").unwrap());
    let url_str = url.to_str().unwrap();

    // Get the path filename
    let filename = url.file_name().unwrap().to_str().unwrap();

    // Check if multi-threaded download is possible
    let mut threads: usize = value_t!(argparse, "threads", usize)
        .and_then(|v| if v != 0 {
            Ok(v)
        } else {
            Err(clap::Error::with_description(
                "Cannot download a file using 0 thread",
                clap::ErrorKind::InvalidValue,
            ))
        })
        .unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        info!(&format!("version: {}", crate_version!()));
        info!(&format!("file: {}", filename));
        info!(&format!("threads: {}", threads));
    }

    let local_path = Path::new(&filename);

    if local_path.exists() {
        if local_path.is_dir() {
            epanic!(
                "The local path to store the remote content is already exists, \
                        and is a directory!"
            );
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(
                "The path to store the file already exists! \
                                          Do you want to override it? [y/N]",
            );
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            warning!(
                "The path to store the file already exists! \
                                 It is going to be overriden."
            );
        }
    }

    // Get automaticaly the protocol from the given URL
    let ssl_support = match get_protocol(url.to_str().unwrap()) {
        Some(protocol) => match protocol {
            // If the protocol is HTTP, return the user decision for the HTTPS client
            Protocol::HTTP => argparse.is_present("ssl_support"),
            // Force to use HTTPS client
            Protocol::HTTPS => true,
        },
        None => epanic!("Unknown protocol!"),
    };

    // Get remote server informations in order to perform the best download strategy as possible
    let remote_server_informations = match get_remote_server_informations(url_str, ssl_support) {
        Ok(informations) => informations,
        Err(err) => panic!(err),
    };

    info!(
        &format!("Remote content length: {}", StringFileType::from(remote_server_informations.file.content_length))
    );

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(remote_server_informations.file.content_length).expect(
        "Cannot extend local file !",
    );
    let out_file = OutputFileWriter::new(local_file);

    // If the server does not accept PartialContent status, download the remote file
    // using only one thread
    if !remote_server_informations.accept_partialcontent {
        warning!(
            "The remote server does not accept PartialContent status! \
                             Downloading the remote file using one thread."
        );
        threads = 1;
    }

    if download_chunks(remote_server_informations, out_file, threads as u64, filename, ssl_support) {
        ok!(&format!(
            "Your download is available in {}",
            local_path.to_str().unwrap()
        ));
    } else {
        // If the file is not ok, delete it from the file system
        error!("Download failed! An error occured - erasing file... ");
        if remove_file(local_path).is_err() {
            error!("Cannot delete downloaded file!");
        }
    }

}
<|endoftext|>


<commit_before>pub mod miniml_grammar;
pub mod ast;

use ast::{Type, Expr, TopLevelCmd};
type Name = String;

use std::collections::HashMap;
use std::fmt;
use std::io;
use std::io::Write;

/////////  type_check.ml ////////////////

fn check(ctx: &mut HashMap<Name,Type>, t: &Type, e: &Expr) -> Result<(), String> {
    let t_ctx = try!(type_of(ctx, e));
    if *t == t_ctx {
        Ok(())
    } else {
        Err(format!("{} has type of {} but is used as if it has type {}.", e, t, t_ctx))
    }
}

fn type_of<'a, 'b>(ctx: &'a mut HashMap<Name,Type>, e: &'b Expr) -> Result<Type, String> {
    match *e {
        Expr::Var(ref name) => {
            if let Some(t) = ctx.get(name) {
                Ok(t.clone())
            } else {
                Err(format!("Variable name {} not found.", name))
            }
        },
        Expr::Int(_) => Ok(Type::Int),
        Expr::Bool(_) => Ok(Type::Bool),
        Expr::Times(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Plus(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Minus(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Equal(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Bool) },
        Expr::Less(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Bool) },
        Expr::If(ref e1, ref e2, ref e3) => {
            try!(check(ctx, &Type::Bool, e1));
            let t2 = try!(type_of(ctx, e2));
            try!(check(ctx, &t2, e3));
            Ok(t2)
        },
        Expr::Fn(ref f, ref x, ref ty1, ref ty2, ref e) => {
            ctx.insert((*f).clone(), Type::Arrow(Box::new((*ty1).clone()), Box::new((*ty2).clone())));
            ctx.insert((*x).clone(), (*ty1).clone());
            try!(check(ctx, ty2, e));
            Ok(Type::Arrow(Box::new((*ty1).clone()), Box::new((*ty2).clone())))
        },
        Expr::Apply(ref e1, ref e2) => {
            let ty = try!(type_of(ctx, e1));
            match ty {
                Type::Arrow(ref ty1, ref ty2) => {
                    try!(check(ctx, ty1, e2));
                    Ok((**ty2).clone())
                },
                wrong_type => Err(format!("{} is used as a function but its type is {}", e1, wrong_type))
            }
        }
    }
}

///////// end type check ////////////

///////// machine.ml ///////////////

// type Name = String above
type Frame = Vec<Instr>;
type Environ = HashMap<Name, Mvalue>;

#[derive(Clone, Debug)]
enum Mvalue {
    Int(i64),
    Bool(bool),
    Closure(Name, Frame, Environ)
}

impl fmt::Display for Mvalue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Mvalue::Int(i) => write!(f, "{}", i),
            Mvalue::Bool(b) => write!(f, "{}", b),
            Mvalue::Closure(_, _, _) => write!(f, "<fun>")
        }
    }
}

#[derive(Clone, Debug)]
enum Instr {
    Mult,
    Add,
    Sub,
    Equal,
    Less,
    Var(Name),
    Int(i64),
    Bool(bool),
    Closure(Name, Name, Frame),
    Branch(Frame, Frame),
    Call,
    PopEnv,
}

fn lookup(x: &Name, envs: &mut Vec<Environ>) -> Result<Mvalue, String> {
    if let Some(env) = envs.get_mut(0) {
        if let Some(v) = env.get(x) {
            Ok((*v).clone())
        } else {
            Err(format!("Variable {} not found in environment!", x))
        }
    } else {
        return Err("Can't look up. No environment in stack".to_string())
    }
}

fn pop_bool(s: &mut Vec<Mvalue>) -> Result<bool, String> {
    if let Some(val) = s.pop() {
        match val {
            Mvalue::Bool(b) => Ok(b),
            _ => Err(format!("Bool expected, but got {}", val))
        }
    } else {
        Err("No values on stack.".to_string())
    }
}

fn pop_app(s: &mut Vec<Mvalue>) -> Result<(Name, Frame, Environ, Mvalue), String> {
    if let (Some(v1), Some(v2)) = (s.pop(), s.pop()) {
        match v2 {
            Mvalue::Closure(n, f, e) => Ok((n, f, e, v1)),
            _ => Err(format!("Value and closure expected, got {} and {}", v1, v2))
        }
    } else {
        Err("Two elements expected on stack, but were not there.".to_string())
    }
}

fn mult(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1*i2));
        Ok(())
    } else {
        Err("To ints expected for mult, but not on stack".to_string())
    }
}

fn add(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1+i2));
        Ok(())
    } else {
        Err("To ints expected for add, but not on stack".to_string())
    }
}

fn sub(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1-i2));
        Ok(())
    } else {
        Err("To ints expected for sub, but not on stack".to_string())
    }
}

fn equal(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Bool(i1 == i2));
        Ok(())
    } else {
        Err("To ints expected for equal, but not on stack".to_string())
    }
}

fn less(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Bool(i1 < i2));
        Ok(())
    } else {
        Err("To ints expected for less, but not on stack".to_string())
    }
}

fn exec(instr: Instr, frms: &mut Vec<Frame>, stack: &mut Vec<Mvalue>, envs: &mut Vec<Environ>) -> Result<(), String> {
    match instr {
        // arithemetic
        Instr::Mult => { mult(stack) }
        Instr::Add => { add(stack) }
        Instr::Sub => { sub(stack) }
        Instr::Equal => { equal(stack) }
        Instr::Less => { less(stack) }

        // pushing values onto stack
        Instr::Var(name) => {
            let val = try!(lookup(&name, envs));
            Ok(stack.push(val))
        }
        Instr::Int(i) => { Ok(stack.push(Mvalue::Int(i))) }
        Instr::Bool(b) => { Ok(stack.push(Mvalue::Bool(b))) }
        Instr::Closure(f, x, frm) => {
            let env = try!((*envs).first().ok_or("No environments in closure.".to_string()));
            let mut c = Mvalue::Closure(x, frm, (*env).clone());
            let c2 = c.clone();

            match c {
                Mvalue::Closure(_, _, ref mut e) => {
                    e.insert(f, c2);
                },
                _ => unreachable!()
            }
            Ok(stack.push(c))
        }
        Instr::Branch(f1, f2) => {
            let b = try!(pop_bool(stack));

            if b {
                Ok(frms.push(f1))
            } else {
                Ok(frms.push(f2))
            }
        }
        Instr::Call => {
            let (x, f, mut e, v) = try!(pop_app(stack));
            (*frms).push(f);
            e.insert(x, v);
            (*envs).push(e);
            Ok(())
        }
        Instr::PopEnv => {
            if let Some(_) = (*envs).pop() {
                Ok(())
            } else {
                Err("No environment to pop.".to_string())
            }
        }
    }
}

fn run(frm: Frame, env: &mut Environ) -> Result<Mvalue, String> {
    let mut frms: Vec<Frame> = vec![frm];
    let mut stack: Vec<Mvalue> = vec![];
    let mut envs: Vec<Environ> = vec![env.clone()];

    loop {
        if frms.len() == 0 && stack.len() == 1 {
            return Ok(stack.pop().unwrap())
        } else if frms.len() >= 1 && frms.first().unwrap().len() >=1 {
            let mut frm = frms.pop().unwrap();
            let i = try!(frm.pop().ok_or("No instructions in this frame."));
            frms.push(frm);
            try!(exec(i, &mut frms, &mut stack, &mut envs));
        } else if frms.len() >= 1 && frms.first().unwrap().len() == 0 {
            frms.pop();
        } else {
            return Err("Illegal end of program.".to_string())
        }
    }
}

/////////////// end machine /////////////////////

///////////// compile.ml ////////////////////

// MiniML compiler Expr -> Instr
fn compile(expr: Expr) -> Vec<Instr> {
    match expr {
        Expr::Var(x) => vec![Instr::Var(x)],
        Expr::Int(k) => vec![Instr::Int(k)],
        Expr::Bool(b) => vec![Instr::Bool(b)],
        Expr::Times(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Mult]);
            instrs
        }
        Expr::Plus(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Add]);
            instrs
        }
        Expr::Minus(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Sub]);
            instrs
        }
        Expr::Equal(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Equal]);
            instrs
        }
        Expr::Less(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Less]);
            instrs
        }
        Expr::If(e1, e2, e3) => {
            let mut cond_instrs = compile(*e1);
            let true_instrs = compile(*e2);
            let false_instrs = compile(*e3);
            cond_instrs.extend(vec![Instr::Branch(true_instrs, false_instrs)]);
            cond_instrs
        }
        Expr::Fn(f, x, _, _, e) => {
            let mut func_body = compile(*e);
            func_body.extend(vec![Instr::PopEnv]);
            vec![Instr::Closure((*f).to_string(), (*x).to_string(), func_body)]
        }

        Expr::Apply(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Call]);
            instrs
        }
    }
}
////////////// end compile /////////////

////////// miniml.ml //////////////

//[exec_cmd (ctx, env) cmd] executes the toplevel command [cmd] and
// returns the new context-environment pair and a string representing the
// result of evaluation.
fn exec_cmd(ctx: &mut HashMap<Name, Type>, env: &mut Environ, cmd: TopLevelCmd) -> Result<String, String> {
    match cmd {
        TopLevelCmd::Expr(e) => {
            let ty = try!(type_of(ctx, &e));
            let frm = compile(e);
            let v = try!(run(frm, env));
            Ok(format!("- : {} = {}", ty, v))
        }
        TopLevelCmd::Def(x, e) => {
            let ty = try!(type_of(ctx, &e));
            let frm = compile(e);
            let v = try!(run(frm, env));
            ctx.insert(x.clone(), ty.clone());
            Ok(format!("{} : {} = {}", x, ty, v))
        }
    }
}

fn exec_cmds(ctx: &mut HashMap<Name, Type>, env: &mut Environ, cmds: Vec<TopLevelCmd>) -> Result<String, String> {
    let mut output: String = String::new();
    for cmd in cmds.into_iter() {
        let o = try!(exec_cmd(ctx, env, cmd));
        output = output + "\n";
        output = output + &o;
    }
    Ok(output)
}

fn shell(ctx: &mut HashMap<Name, Type>, env: &mut Environ) {
    println!("Welcome to MiniML.");
    loop {
        print!("MiniML> ");
        if let Err(x) = io::stdout().flush() {
            println!("could not flush: {}", x);
        }
        let mut input = String::new();
        io::stdin().read_line(&mut input).ok().expect("Could not read line.");
        if let Ok(cmds) = parse(input) {
            if let Ok(out) = exec_cmds(ctx, env, cmds) {
                println!("{}", out)
            }
        }
    }
}

fn parse(input: String) -> Result<Vec<TopLevelCmd>, ()> {
    match miniml_grammar::parse_Toplevel(&input) {
        Ok(ast) => Ok(ast),
        Err(err) => {
            println!("Parse Error: {:?}", err);
            Err(())
        }
    }
}

////////// end miniml ///////////

fn main() {
    let mut ctx: HashMap<Name, Type> = HashMap::new();
    let mut env: Environ = HashMap::new();
    shell(&mut ctx, &mut env);
}

// #[test]
// fn test_parse_type() {
//     println!("{:?}", miniml_grammar::parse_Type("int -> int"));
// }

#[test]
fn calculator1() {
    assert!(miniml_grammar::parse_Term("22").is_ok());
}
<commit_msg>Fix a bug where definition wasn't being added to env<commit_after>pub mod miniml_grammar;
pub mod ast;

use ast::{Type, Expr, TopLevelCmd};
type Name = String;

use std::collections::HashMap;
use std::fmt;
use std::io;
use std::io::Write;

/////////  type_check.ml ////////////////

fn check(ctx: &mut HashMap<Name,Type>, t: &Type, e: &Expr) -> Result<(), String> {
    let t_ctx = try!(type_of(ctx, e));
    if *t == t_ctx {
        Ok(())
    } else {
        Err(format!("{} has type of {} but is used as if it has type {}.", e, t, t_ctx))
    }
}

fn type_of<'a, 'b>(ctx: &'a mut HashMap<Name,Type>, e: &'b Expr) -> Result<Type, String> {
    match *e {
        Expr::Var(ref name) => {
            if let Some(t) = ctx.get(name) {
                Ok(t.clone())
            } else {
                Err(format!("Variable name {} not found.", name))
            }
        },
        Expr::Int(_) => Ok(Type::Int),
        Expr::Bool(_) => Ok(Type::Bool),
        Expr::Times(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Plus(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Minus(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Int) },
        Expr::Equal(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Bool) },
        Expr::Less(ref e1, ref e2) => {try!(check(ctx, &Type::Int, e1)); try!(check(ctx, &Type::Int, e2)); Ok(Type::Bool) },
        Expr::If(ref e1, ref e2, ref e3) => {
            try!(check(ctx, &Type::Bool, e1));
            let t2 = try!(type_of(ctx, e2));
            try!(check(ctx, &t2, e3));
            Ok(t2)
        },
        Expr::Fn(ref f, ref x, ref ty1, ref ty2, ref e) => {
            ctx.insert((*f).clone(), Type::Arrow(Box::new((*ty1).clone()), Box::new((*ty2).clone())));
            ctx.insert((*x).clone(), (*ty1).clone());
            try!(check(ctx, ty2, e));
            Ok(Type::Arrow(Box::new((*ty1).clone()), Box::new((*ty2).clone())))
        },
        Expr::Apply(ref e1, ref e2) => {
            let ty = try!(type_of(ctx, e1));
            match ty {
                Type::Arrow(ref ty1, ref ty2) => {
                    try!(check(ctx, ty1, e2));
                    Ok((**ty2).clone())
                },
                wrong_type => Err(format!("{} is used as a function but its type is {}", e1, wrong_type))
            }
        }
    }
}

///////// end type check ////////////

///////// machine.ml ///////////////

// type Name = String above
type Frame = Vec<Instr>;
type Environ = HashMap<Name, Mvalue>;

#[derive(Clone, Debug)]
enum Mvalue {
    Int(i64),
    Bool(bool),
    Closure(Name, Frame, Environ)
}

impl fmt::Display for Mvalue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Mvalue::Int(i) => write!(f, "{}", i),
            Mvalue::Bool(b) => write!(f, "{}", b),
            Mvalue::Closure(_, _, _) => write!(f, "<fun>")
        }
    }
}

#[derive(Clone, Debug)]
enum Instr {
    Mult,
    Add,
    Sub,
    Equal,
    Less,
    Var(Name),
    Int(i64),
    Bool(bool),
    Closure(Name, Name, Frame),
    Branch(Frame, Frame),
    Call,
    PopEnv,
}

fn lookup(x: &Name, envs: &mut Vec<Environ>) -> Result<Mvalue, String> {
    if let Some(env) = envs.get_mut(0) {
        if let Some(v) = env.get(x) {
            Ok((*v).clone())
        } else {
            Err(format!("Variable {} not found in environment!", x))
        }
    } else {
        return Err("Can't look up. No environment in stack".to_string())
    }
}

fn pop_bool(s: &mut Vec<Mvalue>) -> Result<bool, String> {
    if let Some(val) = s.pop() {
        match val {
            Mvalue::Bool(b) => Ok(b),
            _ => Err(format!("Bool expected, but got {}", val))
        }
    } else {
        Err("No values on stack.".to_string())
    }
}

fn pop_app(s: &mut Vec<Mvalue>) -> Result<(Name, Frame, Environ, Mvalue), String> {
    if let (Some(v1), Some(v2)) = (s.pop(), s.pop()) {
        match v2 {
            Mvalue::Closure(n, f, e) => Ok((n, f, e, v1)),
            _ => Err(format!("Value and closure expected, got {} and {}", v1, v2))
        }
    } else {
        Err("Two elements expected on stack, but were not there.".to_string())
    }
}

fn mult(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1*i2));
        Ok(())
    } else {
        Err("To ints expected for mult, but not on stack".to_string())
    }
}

fn add(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1+i2));
        Ok(())
    } else {
        Err("To ints expected for add, but not on stack".to_string())
    }
}

fn sub(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Int(i1-i2));
        Ok(())
    } else {
        Err("To ints expected for sub, but not on stack".to_string())
    }
}

fn equal(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Bool(i1 == i2));
        Ok(())
    } else {
        Err("To ints expected for equal, but not on stack".to_string())
    }
}

fn less(s: &mut Vec<Mvalue>) -> Result<(), String> {
    if let (Some(Mvalue::Int(i1)), Some(Mvalue::Int(i2))) = (s.pop(), s.pop()) {
        s.push(Mvalue::Bool(i1 < i2));
        Ok(())
    } else {
        Err("To ints expected for less, but not on stack".to_string())
    }
}

fn exec(instr: Instr, frms: &mut Vec<Frame>, stack: &mut Vec<Mvalue>, envs: &mut Vec<Environ>) -> Result<(), String> {
    match instr {
        // arithemetic
        Instr::Mult => { mult(stack) }
        Instr::Add => { add(stack) }
        Instr::Sub => { sub(stack) }
        Instr::Equal => { equal(stack) }
        Instr::Less => { less(stack) }

        // pushing values onto stack
        Instr::Var(name) => {
            let val = try!(lookup(&name, envs));
            Ok(stack.push(val))
        }
        Instr::Int(i) => { Ok(stack.push(Mvalue::Int(i))) }
        Instr::Bool(b) => { Ok(stack.push(Mvalue::Bool(b))) }
        Instr::Closure(f, x, frm) => {
            let env = try!((*envs).first().ok_or("No environments in closure.".to_string()));
            let mut c = Mvalue::Closure(x, frm, (*env).clone());
            let c2 = c.clone();

            match c {
                Mvalue::Closure(_, _, ref mut e) => {
                    e.insert(f, c2);
                },
                _ => unreachable!()
            }
            Ok(stack.push(c))
        }
        Instr::Branch(f1, f2) => {
            let b = try!(pop_bool(stack));

            if b {
                Ok(frms.push(f1))
            } else {
                Ok(frms.push(f2))
            }
        }
        Instr::Call => {
            let (x, f, mut e, v) = try!(pop_app(stack));
            (*frms).push(f);
            e.insert(x, v);
            (*envs).push(e);
            Ok(())
        }
        Instr::PopEnv => {
            if let Some(_) = (*envs).pop() {
                Ok(())
            } else {
                Err("No environment to pop.".to_string())
            }
        }
    }
}

fn run(frm: Frame, env: &mut Environ) -> Result<Mvalue, String> {
    let mut frms: Vec<Frame> = vec![frm];
    let mut stack: Vec<Mvalue> = vec![];
    let mut envs: Vec<Environ> = vec![env.clone()];

    loop {
        if frms.len() == 0 && stack.len() == 1 {
            return Ok(stack.pop().unwrap())
        } else if frms.len() >= 1 && frms.first().unwrap().len() >=1 {
            let mut frm = frms.pop().unwrap();
            let i = try!(frm.pop().ok_or("No instructions in this frame."));
            frms.push(frm);
            try!(exec(i, &mut frms, &mut stack, &mut envs));
        } else if frms.len() >= 1 && frms.first().unwrap().len() == 0 {
            frms.pop();
        } else {
            return Err("Illegal end of program.".to_string())
        }
    }
}

/////////////// end machine /////////////////////

///////////// compile.ml ////////////////////

// MiniML compiler Expr -> Instr
fn compile(expr: Expr) -> Vec<Instr> {
    match expr {
        Expr::Var(x) => vec![Instr::Var(x)],
        Expr::Int(k) => vec![Instr::Int(k)],
        Expr::Bool(b) => vec![Instr::Bool(b)],
        Expr::Times(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Mult]);
            instrs
        }
        Expr::Plus(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Add]);
            instrs
        }
        Expr::Minus(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Sub]);
            instrs
        }
        Expr::Equal(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Equal]);
            instrs
        }
        Expr::Less(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Less]);
            instrs
        }
        Expr::If(e1, e2, e3) => {
            let mut cond_instrs = compile(*e1);
            let true_instrs = compile(*e2);
            let false_instrs = compile(*e3);
            cond_instrs.extend(vec![Instr::Branch(true_instrs, false_instrs)]);
            cond_instrs
        }
        Expr::Fn(f, x, _, _, e) => {
            let mut func_body = compile(*e);
            func_body.extend(vec![Instr::PopEnv]);
            vec![Instr::Closure((*f).to_string(), (*x).to_string(), func_body)]
        }

        Expr::Apply(e1, e2) => {
            let mut instrs = compile(*e1);
            instrs.extend(compile(*e2));
            instrs.extend(vec![Instr::Call]);
            instrs
        }
    }
}
////////////// end compile /////////////

////////// miniml.ml //////////////

//[exec_cmd (ctx, env) cmd] executes the toplevel command [cmd] and
// returns the new context-environment pair and a string representing the
// result of evaluation.
fn exec_cmd(ctx: &mut HashMap<Name, Type>, env: &mut Environ, cmd: TopLevelCmd) -> Result<String, String> {
    match cmd {
        TopLevelCmd::Expr(e) => {
            let ty = try!(type_of(ctx, &e));
            let frm = compile(e);
            let v = try!(run(frm, env));
            Ok(format!("- : {} = {}", ty, v))
        }
        TopLevelCmd::Def(x, e) => {
            let ty = try!(type_of(ctx, &e));
            let frm = compile(e);
            let v = try!(run(frm, env));
            ctx.insert(x.clone(), ty.clone());
            env.insert(x.clone(), v.clone());
            Ok(format!("{} : {} = {}", x, ty, v))
        }
    }
}

fn exec_cmds(ctx: &mut HashMap<Name, Type>, env: &mut Environ, cmds: Vec<TopLevelCmd>) -> Result<String, String> {
    let mut output: String = String::new();
    for cmd in cmds.into_iter() {
        let o = try!(exec_cmd(ctx, env, cmd));
        output = output + "\n";
        output = output + &o;
    }
    Ok(output)
}

fn shell(ctx: &mut HashMap<Name, Type>, env: &mut Environ) {
    println!("Welcome to MiniML.");
    loop {
        print!("MiniML> ");
        if let Err(x) = io::stdout().flush() {
            println!("could not flush: {}", x);
        }
        let mut input = String::new();
        io::stdin().read_line(&mut input).ok().expect("Could not read line.");

        if let Ok(cmds) = parse(input) {
            match exec_cmds(ctx, env, cmds) {
                Ok(out) => println!("{}", out),
                Err(err) => println!("{}", err)
            }
        }
    }
}

fn parse(input: String) -> Result<Vec<TopLevelCmd>, ()> {
    match miniml_grammar::parse_Toplevel(&input) {
        Ok(ast) => Ok(ast),
        Err(err) => {
            println!("Parse Error: {:?}", err);
            Err(())
        }
    }
}

////////// end miniml ///////////

fn main() {
    let mut ctx: HashMap<Name, Type> = HashMap::new();
    let mut env: Environ = HashMap::new();
    shell(&mut ctx, &mut env);
}

// #[test]
// fn test_parse_type() {
//     println!("{:?}", miniml_grammar::parse_Type("int -> int"));
// }

#[test]
fn calculator1() {
    assert!(miniml_grammar::parse_Term("22").is_ok());
}
<|endoftext|>


<commit_before>extern crate pnet;
extern crate clap;

pub mod cli;
pub mod config;

use std::thread;
use std::time::Duration;
use std::net::Ipv4Addr;

use pnet::datalink::{self, NetworkInterface};
use pnet::datalink::Channel;
use pnet::packet::ethernet::MutableEthernetPacket;
use pnet::packet::arp::MutableArpPacket;
use pnet::util::MacAddr;
use pnet::packet::ethernet::EtherTypes;
use pnet::packet::MutablePacket;
use pnet::packet::arp::{ArpHardwareTypes, ArpOperations};

use config::Config;
use cli::cli_main;

fn send_arp_reply_packet(source_ip: Ipv4Addr, source_mac: MacAddr, target_ip: Ipv4Addr, target_mac: MacAddr) {
    let interfaces = datalink::interfaces();

    // Get en1 interface in osx.
    let interfaces_name_match = |iface: &NetworkInterface| iface.name == "en1";
    let interface = interfaces.into_iter().filter(interfaces_name_match).next().unwrap();

    let(mut tx, _) = match datalink::channel(&interface, Default::default()) {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unknown channel type"),
        Err(e) => panic!("Error happened {}", e),
    };

    /// ethernet_packet = Ethernet {
    ///     destination: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
    ///     source: [0x28, 0xef, 0xf9, 0x5f, 0x8e, 0x2b],
    ///     ethertype: [0x08, 0x06], // Arp(0x0806)
    ///     payload: arp_packet
    /// }
    ///
    /// arp_packet = Arp {
    ///     hardware_type: [0x00, 0x01],
    ///     protocol_type: [0x08, 0x00], // Ipv4(0x0800)
    ///     hw_addr_len: [0x06],
    ///     proto_addr_len: [0x04],
    ///     operation: [0x00, 0x02], // Reply(0x0002)
    ///     sender_hw_addr: [0x28, 0xef, 0xf9, 0x5f, 0x8e, 0x2b],
    ///     sender_proto_addr: [0xc0, 0xa8, 0x00, 0x66], // Ipv4(192.168.0.102)
    ///     target_hw_addr: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff], // Broadcast
    ///     target_proto_addr: [0xc0, 0xa8, 0x00, 0x65], // Ipv4(192.168.0.101)
    ///     payload: [],
    /// }

    let mut ethernet_buffer: &mut [u8] = &mut [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

    let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();
    ethernet_packet.set_destination(target_mac);
    ethernet_packet.set_source(source_mac);
    ethernet_packet.set_ethertype(EtherTypes::Arp);

    let mut arp_buffer: &mut [u8] = &mut [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

    let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

    arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
    arp_packet.set_protocol_type(EtherTypes::Ipv4);
    arp_packet.set_hw_addr_len(6);
    arp_packet.set_proto_addr_len(4);
    arp_packet.set_operation(ArpOperations::Reply);
    arp_packet.set_sender_hw_addr(source_mac);
    arp_packet.set_sender_proto_addr(source_ip);
    arp_packet.set_target_hw_addr(target_mac);
    arp_packet.set_target_proto_addr(target_ip);

    ethernet_packet.set_payload(arp_packet.packet_mut());

    tx.send_to(&ethernet_packet.to_immutable(), Some(interface));
}

fn main() {
    let config: Config = cli_main();
    let mut packet_count: i32 = 0;

    loop {
        send_arp_reply_packet(config.source_ip, config.source_mac, config.target_ip, config.target_mac);

        packet_count += 1;
        println!("Sent {} ARP reply packets.", packet_count);
        thread::sleep(Duration::new(5, 0));
    }
}
<commit_msg>Add option to choose arp operation reply/request<commit_after>extern crate pnet;
extern crate clap;

pub mod cli;
pub mod config;

use std::thread;
use std::time::Duration;
use std::net::Ipv4Addr;

use pnet::datalink::{self, NetworkInterface};
use pnet::datalink::Channel;
use pnet::packet::ethernet::MutableEthernetPacket;
use pnet::packet::arp::MutableArpPacket;
use pnet::util::MacAddr;
use pnet::packet::ethernet::EtherTypes;
use pnet::packet::MutablePacket;
use pnet::packet::arp::{ArpHardwareTypes, ArpOperation};

use config::Config;
use cli::cli_main;

fn send_arp_packet(interface: NetworkInterface, source_ip: Ipv4Addr, source_mac: MacAddr, target_ip: Ipv4Addr, target_mac: MacAddr, arp_operation: ArpOperation) {
    let(mut tx, _) = match datalink::channel(&interface, Default::default()) {
        Ok(Channel::Ethernet(tx, rx)) => (tx, rx),
        Ok(_) => panic!("Unknown channel type"),
        Err(e) => panic!("Error happened {}", e),
    };

    /// ethernet_packet = Ethernet {
    ///     destination: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
    ///     source: [0x28, 0xef, 0xf9, 0x5f, 0x8e, 0x2b],
    ///     ethertype: [0x08, 0x06], // Arp(0x0806)
    ///     payload: arp_packet
    /// }
    ///
    /// arp_packet = Arp {
    ///     hardware_type: [0x00, 0x01],
    ///     protocol_type: [0x08, 0x00], // Ipv4(0x0800)
    ///     hw_addr_len: [0x06],
    ///     proto_addr_len: [0x04],
    ///     operation: [0x00, 0x02], // Reply(0x0002)
    ///     sender_hw_addr: [0x28, 0xef, 0xf9, 0x5f, 0x8e, 0x2b],
    ///     sender_proto_addr: [0xc0, 0xa8, 0x00, 0x66], // Ipv4(192.168.0.102)
    ///     target_hw_addr: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff], // Broadcast
    ///     target_proto_addr: [0xc0, 0xa8, 0x00, 0x65], // Ipv4(192.168.0.101)
    ///     payload: [],
    /// }

    let mut ethernet_buffer: &mut [u8] = &mut [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

    let mut ethernet_packet = MutableEthernetPacket::new(&mut ethernet_buffer).unwrap();
    ethernet_packet.set_destination(target_mac);
    ethernet_packet.set_source(source_mac);
    ethernet_packet.set_ethertype(EtherTypes::Arp);

    let mut arp_buffer: &mut [u8] = &mut [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

    let mut arp_packet = MutableArpPacket::new(&mut arp_buffer).unwrap();

    arp_packet.set_hardware_type(ArpHardwareTypes::Ethernet);
    arp_packet.set_protocol_type(EtherTypes::Ipv4);
    arp_packet.set_hw_addr_len(6);
    arp_packet.set_proto_addr_len(4);
    arp_packet.set_operation(arp_operation);
    arp_packet.set_sender_hw_addr(source_mac);
    arp_packet.set_sender_proto_addr(source_ip);
    arp_packet.set_target_hw_addr(target_mac);
    arp_packet.set_target_proto_addr(target_ip);

    ethernet_packet.set_payload(arp_packet.packet_mut());

    tx.send_to(&ethernet_packet.to_immutable(), Some(interface));
}

fn main() {
    let config: Config = cli_main();
    let mut packet_count: i32 = 0;

    loop {
        let interfaces = datalink::interfaces();

        // Get en1 interface in osx.
        let interfaces_name_match = |iface: &NetworkInterface| iface.name == config.interface;
        let interface = interfaces.into_iter().filter(interfaces_name_match).next().unwrap();

       send_arp_packet(interface, config.source_ip, config.source_mac, config.target_ip, config.target_mac, config.arp_operation);

        packet_count += 1;
        println!("Sent {} ARP {:?} packets.", packet_count, config.arp_operation);
        thread::sleep(Duration::new(5, 0));
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Tyler Neely
//
// 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.
//
extern crate rocksdb;
use rocksdb::{DB, MergeOperands, Options, Writable};

// fn snapshot_test() {
//    let path = "_rust_rocksdb_iteratortest";
//    {
//        let mut db = DB::open_default(path).unwrap();
//        let p = db.put(b"k1", b"v1111");
//        assert!(p.is_ok());
//        let p = db.put(b"k2", b"v2222");
//        assert!(p.is_ok());
//        let p = db.put(b"k3", b"v3333");
//        assert!(p.is_ok());
//        let mut snap = db.snapshot();
//        let mut view1 = snap.iterator();
//        println!("See the output of the first iter");
//        for (k,v) in view1.from_start() {
// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(),
// std::str::from_utf8(v).unwrap());
//        };
//        for (k,v) in view1.from_start() {
// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(),
// std::str::from_utf8(v).unwrap());
//        };
//        for (k,v) in view1.from_end() {
// println!("Hello {}: {}", std::str::from_utf8(k).unwrap(),
// std::str::from_utf8(v).unwrap());
//        };
//    }
//    let opts = Options::default();
//    assert!(DB::destroy(&opts, path).is_ok());
// }

#[cfg(not(feature = "valgrind"))]
fn main() {
    let path = "/tmp/rust-rocksdb";
    let db = DB::open_default(path).unwrap();
    assert!(db.put(b"my key", b"my value").is_ok());
    match db.get(b"my key") {
        Ok(Some(value)) => {
            match value.to_utf8() {
                Some(v) => println!("retrieved utf8 value: {}", v),
                None => println!("did not read valid utf-8 out of the db"),
            }
        }
        Ok(None) => panic!("value not present!"),
        Err(e) => println!("error retrieving value: {}", e),
    }

    assert!(db.delete(b"my key").is_ok());

    custom_merge();
}

fn concat_merge(_: &[u8],
                existing_val: Option<&[u8]>,
                operands: &mut MergeOperands)
                -> Vec<u8> {
    let mut result: Vec<u8> = Vec::with_capacity(operands.size_hint().0);
    if let Some(v) = existing_val {
        for e in v {
            result.push(*e)
        }
    }
    for op in operands {
        for e in op {
            result.push(*e);
        }
    }
    result
}

fn custom_merge() {
    let path = "_rust_rocksdb_mergetest";
    let mut opts = Options::default();
    opts.create_if_missing(true);
    opts.add_merge_operator("test operator", concat_merge);
    {
        let db = DB::open(&opts, path).unwrap();
        db.put(b"k1", b"a").unwrap();
        db.merge(b"k1", b"b").unwrap();
        db.merge(b"k1", b"c").unwrap();
        db.merge(b"k1", b"d").unwrap();
        db.merge(b"k1", b"efg").unwrap();
        db.merge(b"k1", b"h").unwrap();
        match db.get(b"k1") {
            Ok(Some(value)) => {
                match value.to_utf8() {
                    Some(v) => println!("retrieved utf8 value: {}", v),
                    None => println!("did not read valid utf-8 out of the db"),
                }
            }
            Ok(None) => panic!("value not present!"),
            Err(e) => println!("error retrieving value: {}", e),
        }
    }
    DB::destroy(&opts, path).is_ok();
}

#[cfg(feature = "valgrind")]
fn main() {
    let path = "_rust_rocksdb_valgrind";
    let mut opts = Options::default();
    opts.create_if_missing(true);
    opts.add_merge_operator("test operator", concat_merge);
    let db = DB::open(&opts, path).unwrap();
    loop {
        db.put(b"k1", b"a");
        db.merge(b"k1", b"b");
        db.merge(b"k1", b"c");
        db.merge(b"k1", b"d");
        db.merge(b"k1", b"efg");
        db.merge(b"k1", b"h");
        db.get(b"k1")
          .map(|value| {
              match value.to_utf8() {
                  Some(v) => (),
                  None => panic!("value corrupted"),
              }
          })
          .or_else(|e| panic!("error retrieving value: {}", e));
        db.delete(b"k1");
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{BlockBasedOptions, DB, Options};
    use rocksdb::DBCompactionStyle::Universal;

    fn tuned_for_somebody_elses_disk(path: &str,
                                     opts: &mut Options,
                                     blockopts: &mut BlockBasedOptions)
                                     -> DB {
        opts.create_if_missing(true);
        opts.set_max_open_files(10000);
        opts.set_use_fsync(false);
        opts.set_bytes_per_sync(8388608);
        opts.set_disable_data_sync(false);
        opts.set_block_cache_size_mb(1024);
        opts.set_table_cache_num_shard_bits(6);
        opts.set_max_write_buffer_number(32);
        opts.set_write_buffer_size(536870912);
        opts.set_target_file_size_base(1073741824);
        opts.set_min_write_buffer_number_to_merge(4);
        opts.set_level_zero_stop_writes_trigger(2000);
        opts.set_level_zero_slowdown_writes_trigger(0);
        opts.set_compaction_style(Universal);
        opts.set_max_background_compactions(4);
        opts.set_max_background_flushes(4);
        opts.set_filter_deletes(false);
        blockopts.set_block_size(524288);
        opts.set_block_based_table_factory(blockopts);
        opts.set_disable_auto_compactions(true);

        // let filter = new_bloom_filter(10);
        // opts.set_filter(filter);

        DB::open(&opts, path).unwrap()
    }

    // TODO(tyler) unstable
    // #[bench]
    // fn a_writes(b: &mut Bencher) {
    // dirty hack due to parallel tests causing contention.
    // sleep_ms(1000);
    // let path = "_rust_rocksdb_optimizetest";
    // let mut opts = Options::default();
    // let mut blockopts = BlockBasedOptions::default();
    // let mut db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
    // let mut i = 0 as u64;
    // b.iter(|| {
    // db.put(i.to_string().as_bytes(), b"v1111");
    // i += 1;
    // });
    // }
    //
    // #[bench]
    // fn b_reads(b: &mut Bencher) {
    // let path = "_rust_rocksdb_optimizetest";
    // let mut opts = Options::default();
    // let mut blockopts = BlockBasedOptions::default();
    // {
    // let db = tuned_for_somebody_elses_disk(path, &mut opts, &mut blockopts);
    // let mut i = 0 as u64;
    // b.iter(|| {
    // db.get(i.to_string().as_bytes()).on_error( |e| {
    // println!("error: {}", e);
    // e
    // });
    // i += 1;
    // });
    // }
    // DB::destroy(&opts, path).is_ok();
    // }
    //
}
<commit_msg>main.rs is not used<commit_after><|endoftext|>


<commit_before>fn main() {
    println!("Hello World!");
}
<commit_msg>Add main loop.<commit_after>#[macro_use]
extern crate glium;

fn main() {
    use glium::{DisplayBuild, Surface};
    let display = glium::glutin::WindowBuilder::new()
        .with_dimensions(800, 600)
        .with_title(format!("Rusty Gauntlet™"))
        .build_glium()
        .unwrap();

    loop {
        let mut target = display.draw();
        target.clear_color(0.5, 0.6, 0.9, 1.0);
        target.finish().unwrap();

        for ev in display.poll_events() {
            match ev {
                glium::glutin::Event::Closed => return,
                _ => ()
            }
        }
    }
}
<|endoftext|>