<commit_before>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::file::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command {
    pub name: String,
    pub main: Box<Fn(&Vec<String>)>,
}

impl Command {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo".to_string(),
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send".to_string(),
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex".to_string(),
            main: box |args: &Vec<String>| {
                let path;
                match args.get(1) {
                    Some(arg) => path = arg.clone(),
                    None => path = String::new(),
                }

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + &c.name) + " exit";

        commands.push(Command {
            name: "help".to_string(),
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application {
    commands: Vec<Command>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl Application {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &String) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if *command_string == "$" {
            let mut variables = String::new();
            for variable in self.variables.iter() {
                variables = variables + "\n" + &variable.name + "=" + &variable.value;
            }
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if arg.len() > 0 {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            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);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.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");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if self.modes.len() > 0 {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

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

                if name.len() == 0 {
                    return;
                }

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

                if value.len() == 0 {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if command.len() > 0 {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<commit_msg>Minor cleanup<commit_after>use redox::ops::DerefMut;
use redox::string::*;
use redox::vec::Vec;
use redox::boxed::Box;
use redox::fs::file::*;
use redox::io::*;
use redox::console::*;
use redox::env::*;
use redox::to_num::*;

/* Magic Macros { */
static mut application: *mut Application = 0 as *mut Application;

/// Execute a command
macro_rules! exec {
    ($cmd:expr) => ({
        unsafe {
            (*application).on_command(&$cmd.to_string());
        }
    })
}
/* } Magic Macros */

/// A command
pub struct Command {
    pub name: String,
    pub main: Box<Fn(&Vec<String>)>,
}

impl Command {
    /// Return the vector of the commands
    // TODO: Use a more efficient collection instead
    pub fn vec() -> Vec<Self> {
        let mut commands: Vec<Self> = Vec::new();
        commands.push(Command {
            name: "echo".to_string(),
            main: box |args: &Vec<String>| {
                let echo = args.iter()
                    .skip(1)
                    .fold(String::new(), |string, arg| string + " " + arg);
                println!("{}", echo.trim());
            },
        });

        commands.push(Command {
            name: "open".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(arg) = args.get(1) {
                    File::exec(arg);
                }
            },
        });

        commands.push(Command {
            name: "run".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(path) = args.get(1) {

                    let mut commands = String::new();
                    if let Some(mut file) = File::open(path) {
                        println!("URL: {:?}", file.path());

                        file.read_to_string(&mut commands);
                    }

                    for command in commands.split('\n') {
                        exec!(command);
                    }
                }
            },
        });

        commands.push(Command {
            name: "send".to_string(),
            main: box |args: &Vec<String>| {
                if args.len() < 3 {
                    println!("Error: incorrect arguments");
                    println!("Usage: send [url] [data]");
                    return;
                }

                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let string: String = args.iter()
                        .skip(2)
                        .fold(String::new(), |s, arg| s + " " + arg)
                        + "\r\n\r\n";

                    match file.write(string.trim_left().as_bytes()) {
                        Some(size) => println!("Wrote {} bytes", size),
                        None => println!("Failed to write"),
                    }

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url".to_string(),
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut string = String::new();
                    match file.read_to_string(&mut string) {
                        Some(_) => println!("{}", string),
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "url_hex".to_string(),
            main: box |args: &Vec<String>| {
                let path = {
                    match args.get(1) {
                        Some(arg) => arg.clone(),
                        None => String::new(),
                    }
                };

                if let Some(mut file) = File::open(&path) {
                    println!("URL: {:?}", file.path());

                    let mut vec: Vec<u8> = Vec::new();
                    match file.read_to_end(&mut vec) {
                        Some(_) => {
                            let mut line = "HEX:".to_string();
                            for byte in vec.iter() {
                                line = line + " " + &format!("{:X}", *byte);
                            }
                            println!("{}", line);
                        }
                        None => println!("Failed to read"),
                    }
                }
            },
        });

        commands.push(Command {
            name: "wget".to_string(),
            main: box |args: &Vec<String>| {
                if let Some(host) = args.get(1) {
                    if let Some(req) = args.get(2) {
                        if let Some(mut con) = File::open(&("tcp://".to_string() + host)) {
                            con.write(("GET ".to_string() + req + " HTTP/1.1").as_bytes());

                            let mut res = Vec::new();
                            con.read_to_end(&mut res);

                            if let Some(mut file) = File::open(&req) {
                                file.write(&res);
                            }
                        }
                    } else {
                        println!("No request given");
                    }
                } else {
                    println!("No url given");
                }
            },
        });

        let command_list = commands.iter().fold(String::new(), |l , c| l + " " + &c.name) + " exit";

        commands.push(Command {
            name: "help".to_string(),
            main: box move |args: &Vec<String>| {
                println!("Commands:{}", command_list);
            },
         });

        commands
    }
}

/// A (env) variable
pub struct Variable {
    pub name: String,
    pub value: String,
}

pub struct Mode {
    value: bool,
}

/// An application
pub struct Application {
    commands: Vec<Command>,
    variables: Vec<Variable>,
    modes: Vec<Mode>,
}

impl Application {
    /// Create a new empty application
    pub fn new() -> Self {
        return Application {
            commands: Command::vec(),
            variables: Vec::new(),
            modes: Vec::new(),
        };
    }

    fn on_command(&mut self, command_string: &String) {
        //Comment
        if command_string.starts_with('#') {
            return;
        }

        //Show variables
        if *command_string == "$" {
            let mut variables = String::new();
            for variable in self.variables.iter() {
                variables = variables + "\n" + &variable.name + "=" + &variable.value;
            }
            println!("{}", variables);
            return;
        }

        //Explode into arguments, replace variables
        let mut args: Vec<String> = Vec::<String>::new();
        for arg in command_string.split(' ') {
            if arg.len() > 0 {
                if arg.starts_with('$') {
                    let name = arg[1 .. arg.len()].to_string();
                    for variable in self.variables.iter() {
                        if variable.name == name {
                            args.push(variable.value.clone());
                            break;
                        }
                    }
                } else {
                    args.push(arg.to_string());
                }
            }
        }

        //Execute commands
        if let Some(cmd) = args.get(0) {
            if cmd == "if" {
                let mut value = false;

                if let Some(left) = args.get(1) {
                    if let Some(cmp) = args.get(2) {
                        if let Some(right) = args.get(3) {
                            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);
                            }
                        }
                    }
                }

                self.modes.insert(0, Mode { value: value });
                return;
            }

            if cmd == "else" {
                let mut syntax_error = false;
                match self.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");
                }
                return;
            }

            if cmd == "fi" {
                let mut syntax_error = false;
                if self.modes.len() > 0 {
                    self.modes.remove(0);
                } else {
                    syntax_error = true;
                }
                if syntax_error {
                    println!("Syntax error: fi found with no previous if");
                }
                return;
            }

            for mode in self.modes.iter() {
                if !mode.value {
                    return;
                }
            }

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

                if name.len() == 0 {
                    return;
                }

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

                if value.len() == 0 {
                    let mut remove = -1;
                    for i in 0..self.variables.len() {
                        match self.variables.get(i) {
                            Some(variable) => if variable.name == name {
                                remove = i as isize;
                                break;
                            },
                            None => break,
                        }
                    }

                    if remove >= 0 {
                        self.variables.remove(remove as usize);
                    }
                } else {
                    for variable in self.variables.iter_mut() {
                        if variable.name == name {
                            variable.value = value;
                            return;
                        }
                    }

                    self.variables.push(Variable {
                        name: name,
                        value: value,
                    });
                }
                return;
            }

            //Commands
            for command in self.commands.iter() {
                if &command.name == cmd {
                    (*command.main)(&args);
                    return;
                }
            }

            println!("Unknown command: '{}'", cmd);
        }
    }

    /// Run the application
    pub fn main(&mut self) {
        console_title("Terminal");

        println!("Type help for a command list");
        if let Some(arg) = args().get(1) {
            let command = "run ".to_string() + arg;
            println!("# {}", command);
            self.on_command(&command);
        }

        while let Some(command) = readln!() {
            println!("# {}", command);
            if command == "exit" {
                break;
            } else if command.len() > 0 {
                self.on_command(&command);
            }
        }
    }
}

pub fn main() {
    unsafe {
        let mut app = box Application::new();
        application = app.deref_mut();
        app.main();
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(unboxed_closures)]

#[plugin]
extern crate glium_macros;

extern crate glutin;
extern crate glium;

use glium::Surface;

mod support;

#[test]
fn min_blending() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        blending_function: Some(glium::BlendingFunction::Min),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 0.2, 0.3, 1.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(0, 0, 0, 255));
        }
    }

    display.assert_no_error();
}

#[test]
fn max_blending() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        blending_function: Some(glium::BlendingFunction::Max),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.4, 1.0, 1.0, 0.2);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(255, 255, 255, 255));
        }
    }

    display.assert_no_error();
}

#[test]
fn one_plus_one() {
    let display = support::build_display();

    let params = glium::DrawParameters {
        blending_function: Some(glium::BlendingFunction::Addition {
            source: glium::LinearBlendingFactor::One,
            destination: glium::LinearBlendingFactor::One,
        }),
        .. std::default::Default::default()
    };

    let (vb, ib, program) = support::build_fullscreen_red_pipeline(&display);

    let texture = support::build_renderable_texture(&display);
    texture.as_surface().clear_color(0.0, 1.0, 1.0, 0.0);
    texture.as_surface().draw(&vb, &ib, &program, &glium::uniforms::EmptyUniforms, &params).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = texture.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(255, 255, 255, 255));
        }
    }

    display.assert_no_error();
}
<commit_msg>Change blending tests to use a macro instead<commit_after>#![feature(plugin)]
#![feature(unboxed_closures)]

#[plugin]
extern crate glium_macros;

extern crate glutin;

#[macro_use]
extern crate glium;

use glium::Surface;

mod support;

macro_rules! blending_test {
    ($name:ident, $func:expr, $source:expr, $dest:expr, $result:expr) => (
        #[test]
        fn $name() {
            let display = support::build_display();

            let params = glium::DrawParameters {
                blending_function: Some($func),
                .. std::default::Default::default()
            };

            let (vb, ib) = support::build_rectangle_vb_ib(&display);

            let program = glium::Program::from_source(&display,
                "
                    #version 110

                    attribute vec2 position;

                    void main() {
                        gl_Position = vec4(position, 0.0, 1.0);
                    }
                ",
                "
                    #version 110

                    uniform vec4 color;

                    void main() {
                        gl_FragColor = color;
                    }
                ",
                None).unwrap();

            let texture = support::build_renderable_texture(&display);
            texture.as_surface().clear(Some($source), None, None);
            texture.as_surface().draw(&vb, &ib, &program, &uniform!{ color: $dest },
                                      &params).unwrap();

            let data: Vec<Vec<(f32, f32, f32, f32)>> = texture.read();
            for row in data.iter() {
                for pixel in row.iter() {
                    assert_eq!(pixel, &$result);
                }
            }

            display.assert_no_error();
        }
    )
}

blending_test!(min_blending, glium::BlendingFunction::Min,
               (0.0, 0.2, 0.3, 1.0), (1.0, 0.0, 0.0, 1.0), (0.0, 0.0, 0.0, 1.0));

blending_test!(max_blending, glium::BlendingFunction::Max,
               (0.4, 1.0, 1.0, 0.2), (1.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0));

blending_test!(one_plus_one, glium::BlendingFunction::Addition {
                   source: glium::LinearBlendingFactor::One,
                   destination: glium::LinearBlendingFactor::One,
               },
               (0.0, 1.0, 1.0, 0.0), (1.0, 0.0, 0.0, 1.0), (1.0, 1.0, 1.0, 1.0));
<|endoftext|>


<commit_before><commit_msg>Upgrade Rust.<commit_after><|endoftext|>


<commit_before><commit_msg>guards added to pattern matching<commit_after><|endoftext|>


<commit_before><commit_msg>factor out songs output in example<commit_after><|endoftext|>


<commit_before><commit_msg>Error in test vector for Keystore unittest. Fixed test.<commit_after><|endoftext|>


<commit_before><commit_msg>take seed by ref<commit_after><|endoftext|>


<commit_before><commit_msg>Strip down parser<commit_after>use nom::{self,Needed,is_digit};
use nom::IResult::*;
use nom::Err::*;

use helper::*;
use super::{Date,Time};

named!(take_4_digits, take_n_filter!(4, is_digit));
named!(take_2_digits, take_n_filter!(2, is_digit));

named!(year_prefix, alt!(tag!("+") | tag!("-")));
named!(positive_year  <&[u8], i32>, map!(call!(take_4_digits), buf_to_i32));
named!(pub year <&[u8], i32>, chain!(
        pref: opt!(year_prefix) ~
        y: positive_year
        ,
        || {
            match pref {
                Some(b"-") => -y,
                _ => y
            }
        }));

named!(pub month <&[u8], u32>, map!(call!(take_2_digits), buf_to_u32));
named!(pub day   <&[u8], u32>, map!(call!(take_2_digits), buf_to_u32));

named!(pub date <&[u8], Date>, chain!(
        y: year ~ tag!("-") ~ m: month ~ tag!("-") ~ d: day
        , || { Date{ year: y, month: m, day: d }
        }
        ));

named!(pub hour   <&[u8], u32>, map!(call!(take_2_digits), buf_to_u32));
named!(pub minute <&[u8], u32>, map!(call!(take_2_digits), buf_to_u32));
named!(pub second <&[u8], u32>, map!(call!(take_2_digits), buf_to_u32));

named!(pub time <&[u8], Time>, chain!(
        h: hour ~
        tag!(":") ~
        m: minute ~
        s: empty_or!(chain!(
                tag!(":") ~ s:second , || { s }))
        ,
        || { Time{ hour: h,
                   minute: m,
                   second: s.unwrap_or(0),
                   tz_offset: 0 }
           }
        ));

#[test]
fn easy_parse_date() {
    assert_eq!(Done(&[][..], Date{ year: 2015, month: 6, day: 26 }), date(b"2015-06-26"));
    assert_eq!(Done(&[][..], Date{ year: -333, month: 7, day: 11 }), date(b"-0333-07-11"));

    assert!(date(b"201").is_incomplete());
    assert!(date(b"2015p00p00").is_err());
    assert!(date(b"pppp").is_err());
}

#[test]
fn easy_parse_time() {
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}), time(b"16:43:16"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second:  0, tz_offset: 0}), time(b"16:43"));

    assert!(time(b"20:").is_incomplete());
    assert!(time(b"20p42p16").is_err());
    assert!(time(b"pppp").is_err());
}
<|endoftext|>


<commit_before><commit_msg>Small comment<commit_after><|endoftext|>


<commit_before><commit_msg>Much smarter solver, completes board now<commit_after><|endoftext|>


<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<'a> {
    pub variables: &'a mut BTreeMap<String, String>,
    pub modes: &'a mut 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, 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, 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), 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(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, 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: &mut BTreeMap::new(),
        modes: &mut 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>Make Shell own values instead of borrow<commit_after>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;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add a simple testcase<commit_after><|endoftext|>


<commit_before><commit_msg>Receiving added.<commit_after><|endoftext|>


<commit_before><commit_msg>Encapsulated encode function in the EncodeResult struct for organization.<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use collections::borrow::ToOwned;
use net_traits::image::base::{Image, load_from_memory};
use net_traits::image_cache_task::{ImageState, ImageCacheTask, ImageCacheChan, ImageCacheCommand, ImageCacheResult};
use net_traits::load_whole_resource;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::mem;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver, Select};
use util::resource_files::resources_dir_path;
use util::task::spawn_named;
use util::taskpool::TaskPool;
use url::Url;
use net_traits::{AsyncResponseTarget, ControlMsg, LoadData, ResponseAction, ResourceTask, LoadConsumer};
use net_traits::image_cache_task::ImageResponder;

///
/// TODO(gw): Remaining work on image cache:
///     * Make use of the prefetch support in various parts of the code.
///     * Experiment with changing the image 'key' from being a url to a resource id
///         This might be a decent performance win and/or memory saving in some cases (esp. data urls)
///     * Profile time in GetImageIfAvailable - might be worth caching these results per paint / layout task.
///

/// Represents an image that is either being loaded
/// by the resource task, or decoded by a worker thread.
struct PendingLoad {
    bytes: Vec<u8>,
    result: Option<Result<(), String>>,
    listeners: Vec<ImageListener>,
}

impl PendingLoad {
    fn new() -> PendingLoad {
        PendingLoad {
            bytes: vec!(),
            result: None,
            listeners: vec!(),
        }
    }

    fn add_listener(&mut self, listener: ImageListener) {
        self.listeners.push(listener);
    }
}

/// Represents an image that has completed loading.
/// Images that fail to load (due to network or decode
/// failure) are still stored here, so that they aren't
/// fetched again.
struct CompletedLoad {
    image: Option<Arc<Image>>,
}

impl CompletedLoad {
    fn new(image: Option<Arc<Image>>) -> CompletedLoad {
        CompletedLoad {
            image: image,
        }
    }
}

/// Stores information to notify a client when the state
/// of an image changes.
struct ImageListener {
    sender: ImageCacheChan,
    responder: Option<Box<ImageResponder>>,
}

impl ImageListener {
    fn new(sender: ImageCacheChan, responder: Option<Box<ImageResponder>>) -> ImageListener {
        ImageListener {
            sender: sender,
            responder: responder,
        }
    }

    fn notify(self, image: Option<Arc<Image>>) {
        let ImageCacheChan(ref sender) = self.sender;
        let msg = ImageCacheResult {
            responder: self.responder,
            image: image,
        };
        sender.send(msg).ok();
    }
}

struct ResourceLoadInfo {
    action: ResponseAction,
    url: Url,
}

struct ResourceListener {
    url: Url,
    sender: Sender<ResourceLoadInfo>,
}

impl AsyncResponseTarget for ResourceListener {
    fn invoke_with_listener(&self, action: ResponseAction) {
        self.sender.send(ResourceLoadInfo {
            action: action,
            url: self.url.clone(),
        }).unwrap();
    }
}

/// Implementation of the image cache
struct ImageCache {
    // Receive commands from clients
    cmd_receiver: Receiver<ImageCacheCommand>,

    // Receive notifications from the resource task
    progress_receiver: Receiver<ResourceLoadInfo>,
    progress_sender: Sender<ResourceLoadInfo>,

    // Receive notifications from the decoder thread pool
    decoder_receiver: Receiver<DecoderMsg>,
    decoder_sender: Sender<DecoderMsg>,

    // Worker threads for decoding images.
    task_pool: TaskPool,

    // Resource task handle
    resource_task: ResourceTask,

    // Images that are loading over network, or decoding.
    pending_loads: HashMap<Url, PendingLoad>,

    // Images that have finished loading (successful or not)
    completed_loads: HashMap<Url, CompletedLoad>,

    // The placeholder image used when an image fails to load
    placeholder_image: Option<Arc<Image>>,
}

/// Message that the decoder worker threads send to main image cache task.
struct DecoderMsg {
    url: Url,
    image: Option<Image>,
}

/// The types of messages that the main image cache task receives.
enum SelectResult {
    Command(ImageCacheCommand),
    Progress(ResourceLoadInfo),
    Decoder(DecoderMsg),
}

impl ImageCache {
    fn run(&mut self) {
        let mut exit_sender: Option<Sender<()>> = None;

        loop {
            let result = {
                let sel = Select::new();

                let mut cmd_handle = sel.handle(&self.cmd_receiver);
                let mut progress_handle = sel.handle(&self.progress_receiver);
                let mut decoder_handle = sel.handle(&self.decoder_receiver);

                unsafe {
                    cmd_handle.add();
                    progress_handle.add();
                    decoder_handle.add();
                }

                let ret = sel.wait();

                if ret == cmd_handle.id() {
                    SelectResult::Command(self.cmd_receiver.recv().unwrap())
                } else if ret == decoder_handle.id() {
                    SelectResult::Decoder(self.decoder_receiver.recv().unwrap())
                } else {
                    SelectResult::Progress(self.progress_receiver.recv().unwrap())
                }
            };

            match result {
                SelectResult::Command(cmd) => {
                    exit_sender = self.handle_cmd(cmd);
                }
                SelectResult::Progress(msg) => {
                    self.handle_progress(msg);
                }
                SelectResult::Decoder(msg) => {
                    self.handle_decoder(msg);
                }
            }

            // Can only exit when all pending loads are complete.
            if let Some(ref exit_sender) = exit_sender {
                if self.pending_loads.len() == 0 {
                    exit_sender.send(()).unwrap();
                    break;
                }
            }
        }
    }

    // Handle a request from a client
    fn handle_cmd(&mut self, cmd: ImageCacheCommand) -> Option<Sender<()>> {
        match cmd {
            ImageCacheCommand::Exit(sender) => {
                return Some(sender);
            }
            ImageCacheCommand::RequestImage(url, result_chan, responder) => {
                self.request_image(url, result_chan, responder);
            }
            ImageCacheCommand::GetImageIfAvailable(url, consumer) => {
                let result = match self.completed_loads.get(&url) {
                    Some(completed_load) => {
                        completed_load.image.clone().ok_or(ImageState::LoadError)
                    }
                    None => {
                        let pending_load = self.pending_loads.get(&url);
                        Err(pending_load.map_or(ImageState::NotRequested, |_| ImageState::Pending))
                    }
                };
                consumer.send(result).unwrap();
            }
        };

        None
    }

    // Handle progress messages from the resource task
    fn handle_progress(&mut self, msg: ResourceLoadInfo) {
        match msg.action {
            ResponseAction::HeadersAvailable(_) => {}
            ResponseAction::DataAvailable(data) => {
                let pending_load = self.pending_loads.get_mut(&msg.url).unwrap();
                pending_load.bytes.push_all(&data);
            }
            ResponseAction::ResponseComplete(result) => {
                match result {
                    Ok(()) => {
                        let pending_load = self.pending_loads.get_mut(&msg.url).unwrap();
                        pending_load.result = Some(result);

                        let bytes = mem::replace(&mut pending_load.bytes, vec!());
                        let url = msg.url.clone();
                        let sender = self.decoder_sender.clone();

                        self.task_pool.execute(move || {
                            let image = load_from_memory(&bytes);
                            let msg = DecoderMsg {
                                url: url,
                                image: image
                            };
                            sender.send(msg).unwrap();
                        });
                    }
                    Err(_) => {
                        let placeholder_image = self.placeholder_image.clone();
                        self.complete_load(msg.url, placeholder_image);
                    }
                }
            }
        }
    }

    // Handle a message from one of the decoder worker threads
    fn handle_decoder(&mut self, msg: DecoderMsg) {
        let image = msg.image.map(Arc::new);
        self.complete_load(msg.url, image);
    }

    // Change state of a url from pending -> loaded.
    fn complete_load(&mut self, url: Url, image: Option<Arc<Image>>) {
        let pending_load = self.pending_loads.remove(&url).unwrap();

        let completed_load = CompletedLoad::new(image.clone());
        self.completed_loads.insert(url, completed_load);

        for listener in pending_load.listeners.into_iter() {
            listener.notify(image.clone());
        }
    }

    // Request an image from the cache
    fn request_image(&mut self, url: Url, result_chan: ImageCacheChan, responder: Option<Box<ImageResponder>>) {
        let image_listener = ImageListener::new(result_chan, responder);

        // Check if already completed
        match self.completed_loads.get(&url) {
            Some(completed_load) => {
                // It's already completed, return a notify straight away
                image_listener.notify(completed_load.image.clone());
            }
            None => {
                // Check if the load is already pending
                match self.pending_loads.entry(url.clone()) {
                    Occupied(mut e) => {
                        // It's pending, so add the listener for state changes
                        let pending_load = e.get_mut();
                        pending_load.add_listener(image_listener);
                    }
                    Vacant(e) => {
                        // A new load request! Add the pending load and request
                        // it from the resource task.
                        let mut pending_load = PendingLoad::new();
                        pending_load.add_listener(image_listener);
                        e.insert(pending_load);

                        let load_data = LoadData::new(url.clone(), None);
                        let listener = box ResourceListener {
                            url: url,
                            sender: self.progress_sender.clone(),
                        };
                        self.resource_task.send(ControlMsg::Load(load_data, LoadConsumer::Listener(listener))).unwrap();
                    }
                }
            }
        }
    }
}

/// Create a new image cache.
pub fn new_image_cache_task(resource_task: ResourceTask) -> ImageCacheTask {
    let (cmd_sender, cmd_receiver) = channel();
    let (progress_sender, progress_receiver) = channel();
    let (decoder_sender, decoder_receiver) = channel();

    spawn_named("ImageCacheThread".to_owned(), move || {

        // Preload the placeholder image, used when images fail to load.
        let mut placeholder_url = resources_dir_path();
        // TODO (Savago): replace for a prettier one.
        placeholder_url.push("rippy.jpg");
        let url = Url::from_file_path(&*placeholder_url).unwrap();
        let placeholder_image = match load_whole_resource(&resource_task, url) {
            Err(..) => {
                debug!("image_cache_task: failed loading the placeholder.");
                None
            }
            Ok((_, image_data)) => {
                Some(Arc::new(load_from_memory(&image_data).unwrap()))
            }
        };

        let mut cache = ImageCache {
            cmd_receiver: cmd_receiver,
            progress_sender: progress_sender,
            progress_receiver: progress_receiver,
            decoder_sender: decoder_sender,
            decoder_receiver: decoder_receiver,
            task_pool: TaskPool::new(4),
            pending_loads: HashMap::new(),
            completed_loads: HashMap::new(),
            resource_task: resource_task,
            placeholder_image: placeholder_image,
        };

        cache.run();
    });

    ImageCacheTask::new(cmd_sender)
}
<commit_msg>This was done already on #5783, maybe was reintroduced by mistake.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use collections::borrow::ToOwned;
use net_traits::image::base::{Image, load_from_memory};
use net_traits::image_cache_task::{ImageState, ImageCacheTask, ImageCacheChan, ImageCacheCommand, ImageCacheResult};
use net_traits::load_whole_resource;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::mem;
use std::sync::Arc;
use std::sync::mpsc::{channel, Sender, Receiver, Select};
use util::resource_files::resources_dir_path;
use util::task::spawn_named;
use util::taskpool::TaskPool;
use url::Url;
use net_traits::{AsyncResponseTarget, ControlMsg, LoadData, ResponseAction, ResourceTask, LoadConsumer};
use net_traits::image_cache_task::ImageResponder;

///
/// TODO(gw): Remaining work on image cache:
///     * Make use of the prefetch support in various parts of the code.
///     * Experiment with changing the image 'key' from being a url to a resource id
///         This might be a decent performance win and/or memory saving in some cases (esp. data urls)
///     * Profile time in GetImageIfAvailable - might be worth caching these results per paint / layout task.
///

/// Represents an image that is either being loaded
/// by the resource task, or decoded by a worker thread.
struct PendingLoad {
    bytes: Vec<u8>,
    result: Option<Result<(), String>>,
    listeners: Vec<ImageListener>,
}

impl PendingLoad {
    fn new() -> PendingLoad {
        PendingLoad {
            bytes: vec!(),
            result: None,
            listeners: vec!(),
        }
    }

    fn add_listener(&mut self, listener: ImageListener) {
        self.listeners.push(listener);
    }
}

/// Represents an image that has completed loading.
/// Images that fail to load (due to network or decode
/// failure) are still stored here, so that they aren't
/// fetched again.
struct CompletedLoad {
    image: Option<Arc<Image>>,
}

impl CompletedLoad {
    fn new(image: Option<Arc<Image>>) -> CompletedLoad {
        CompletedLoad {
            image: image,
        }
    }
}

/// Stores information to notify a client when the state
/// of an image changes.
struct ImageListener {
    sender: ImageCacheChan,
    responder: Option<Box<ImageResponder>>,
}

impl ImageListener {
    fn new(sender: ImageCacheChan, responder: Option<Box<ImageResponder>>) -> ImageListener {
        ImageListener {
            sender: sender,
            responder: responder,
        }
    }

    fn notify(self, image: Option<Arc<Image>>) {
        let ImageCacheChan(ref sender) = self.sender;
        let msg = ImageCacheResult {
            responder: self.responder,
            image: image,
        };
        sender.send(msg).ok();
    }
}

struct ResourceLoadInfo {
    action: ResponseAction,
    url: Url,
}

struct ResourceListener {
    url: Url,
    sender: Sender<ResourceLoadInfo>,
}

impl AsyncResponseTarget for ResourceListener {
    fn invoke_with_listener(&self, action: ResponseAction) {
        self.sender.send(ResourceLoadInfo {
            action: action,
            url: self.url.clone(),
        }).unwrap();
    }
}

/// Implementation of the image cache
struct ImageCache {
    // Receive commands from clients
    cmd_receiver: Receiver<ImageCacheCommand>,

    // Receive notifications from the resource task
    progress_receiver: Receiver<ResourceLoadInfo>,
    progress_sender: Sender<ResourceLoadInfo>,

    // Receive notifications from the decoder thread pool
    decoder_receiver: Receiver<DecoderMsg>,
    decoder_sender: Sender<DecoderMsg>,

    // Worker threads for decoding images.
    task_pool: TaskPool,

    // Resource task handle
    resource_task: ResourceTask,

    // Images that are loading over network, or decoding.
    pending_loads: HashMap<Url, PendingLoad>,

    // Images that have finished loading (successful or not)
    completed_loads: HashMap<Url, CompletedLoad>,

    // The placeholder image used when an image fails to load
    placeholder_image: Option<Arc<Image>>,
}

/// Message that the decoder worker threads send to main image cache task.
struct DecoderMsg {
    url: Url,
    image: Option<Image>,
}

/// The types of messages that the main image cache task receives.
enum SelectResult {
    Command(ImageCacheCommand),
    Progress(ResourceLoadInfo),
    Decoder(DecoderMsg),
}

impl ImageCache {
    fn run(&mut self) {
        let mut exit_sender: Option<Sender<()>> = None;

        loop {
            let result = {
                let sel = Select::new();

                let mut cmd_handle = sel.handle(&self.cmd_receiver);
                let mut progress_handle = sel.handle(&self.progress_receiver);
                let mut decoder_handle = sel.handle(&self.decoder_receiver);

                unsafe {
                    cmd_handle.add();
                    progress_handle.add();
                    decoder_handle.add();
                }

                let ret = sel.wait();

                if ret == cmd_handle.id() {
                    SelectResult::Command(self.cmd_receiver.recv().unwrap())
                } else if ret == decoder_handle.id() {
                    SelectResult::Decoder(self.decoder_receiver.recv().unwrap())
                } else {
                    SelectResult::Progress(self.progress_receiver.recv().unwrap())
                }
            };

            match result {
                SelectResult::Command(cmd) => {
                    exit_sender = self.handle_cmd(cmd);
                }
                SelectResult::Progress(msg) => {
                    self.handle_progress(msg);
                }
                SelectResult::Decoder(msg) => {
                    self.handle_decoder(msg);
                }
            }

            // Can only exit when all pending loads are complete.
            if let Some(ref exit_sender) = exit_sender {
                if self.pending_loads.len() == 0 {
                    exit_sender.send(()).unwrap();
                    break;
                }
            }
        }
    }

    // Handle a request from a client
    fn handle_cmd(&mut self, cmd: ImageCacheCommand) -> Option<Sender<()>> {
        match cmd {
            ImageCacheCommand::Exit(sender) => {
                return Some(sender);
            }
            ImageCacheCommand::RequestImage(url, result_chan, responder) => {
                self.request_image(url, result_chan, responder);
            }
            ImageCacheCommand::GetImageIfAvailable(url, consumer) => {
                let result = match self.completed_loads.get(&url) {
                    Some(completed_load) => {
                        completed_load.image.clone().ok_or(ImageState::LoadError)
                    }
                    None => {
                        let pending_load = self.pending_loads.get(&url);
                        Err(pending_load.map_or(ImageState::NotRequested, |_| ImageState::Pending))
                    }
                };
                consumer.send(result).unwrap();
            }
        };

        None
    }

    // Handle progress messages from the resource task
    fn handle_progress(&mut self, msg: ResourceLoadInfo) {
        match msg.action {
            ResponseAction::HeadersAvailable(_) => {}
            ResponseAction::DataAvailable(data) => {
                let pending_load = self.pending_loads.get_mut(&msg.url).unwrap();
                pending_load.bytes.push_all(&data);
            }
            ResponseAction::ResponseComplete(result) => {
                match result {
                    Ok(()) => {
                        let pending_load = self.pending_loads.get_mut(&msg.url).unwrap();
                        pending_load.result = Some(result);

                        let bytes = mem::replace(&mut pending_load.bytes, vec!());
                        let url = msg.url.clone();
                        let sender = self.decoder_sender.clone();

                        self.task_pool.execute(move || {
                            let image = load_from_memory(&bytes);
                            let msg = DecoderMsg {
                                url: url,
                                image: image
                            };
                            sender.send(msg).unwrap();
                        });
                    }
                    Err(_) => {
                        let placeholder_image = self.placeholder_image.clone();
                        self.complete_load(msg.url, placeholder_image);
                    }
                }
            }
        }
    }

    // Handle a message from one of the decoder worker threads
    fn handle_decoder(&mut self, msg: DecoderMsg) {
        let image = msg.image.map(Arc::new);
        self.complete_load(msg.url, image);
    }

    // Change state of a url from pending -> loaded.
    fn complete_load(&mut self, url: Url, image: Option<Arc<Image>>) {
        let pending_load = self.pending_loads.remove(&url).unwrap();

        let completed_load = CompletedLoad::new(image.clone());
        self.completed_loads.insert(url, completed_load);

        for listener in pending_load.listeners.into_iter() {
            listener.notify(image.clone());
        }
    }

    // Request an image from the cache
    fn request_image(&mut self, url: Url, result_chan: ImageCacheChan, responder: Option<Box<ImageResponder>>) {
        let image_listener = ImageListener::new(result_chan, responder);

        // Check if already completed
        match self.completed_loads.get(&url) {
            Some(completed_load) => {
                // It's already completed, return a notify straight away
                image_listener.notify(completed_load.image.clone());
            }
            None => {
                // Check if the load is already pending
                match self.pending_loads.entry(url.clone()) {
                    Occupied(mut e) => {
                        // It's pending, so add the listener for state changes
                        let pending_load = e.get_mut();
                        pending_load.add_listener(image_listener);
                    }
                    Vacant(e) => {
                        // A new load request! Add the pending load and request
                        // it from the resource task.
                        let mut pending_load = PendingLoad::new();
                        pending_load.add_listener(image_listener);
                        e.insert(pending_load);

                        let load_data = LoadData::new(url.clone(), None);
                        let listener = box ResourceListener {
                            url: url,
                            sender: self.progress_sender.clone(),
                        };
                        self.resource_task.send(ControlMsg::Load(load_data, LoadConsumer::Listener(listener))).unwrap();
                    }
                }
            }
        }
    }
}

/// Create a new image cache.
pub fn new_image_cache_task(resource_task: ResourceTask) -> ImageCacheTask {
    let (cmd_sender, cmd_receiver) = channel();
    let (progress_sender, progress_receiver) = channel();
    let (decoder_sender, decoder_receiver) = channel();

    spawn_named("ImageCacheThread".to_owned(), move || {

        // Preload the placeholder image, used when images fail to load.
        let mut placeholder_url = resources_dir_path();
        placeholder_url.push("rippy.jpg");
        let url = Url::from_file_path(&*placeholder_url).unwrap();
        let placeholder_image = match load_whole_resource(&resource_task, url) {
            Err(..) => {
                debug!("image_cache_task: failed loading the placeholder.");
                None
            }
            Ok((_, image_data)) => {
                Some(Arc::new(load_from_memory(&image_data).unwrap()))
            }
        };

        let mut cache = ImageCache {
            cmd_receiver: cmd_receiver,
            progress_sender: progress_sender,
            progress_receiver: progress_receiver,
            decoder_sender: decoder_sender,
            decoder_receiver: decoder_receiver,
            task_pool: TaskPool::new(4),
            pending_loads: HashMap::new(),
            completed_loads: HashMap::new(),
            resource_task: resource_task,
            placeholder_image: placeholder_image,
        };

        cache.run();
    });

    ImageCacheTask::new(cmd_sender)
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{Show, Formatter, Error};
use std::collections::HashMap;

trait HasInventory {
    fn getInventory<'s>(&'s self) -> &'s mut Inventory;
    fn addToInventory(&self, item: &Item);
    fn removeFromInventory(&self, itemName: &str) -> bool;
}

trait TraversesWorld {
    fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
        let direction = str_to_direction(directionStr);
        let maybe_room = room.direction_to_room.get(&direction);
        //~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
        match maybe_room {
            Some(entry) => Ok(entry),
            _ => Err("Direction does not exist in room.")
        }
    }
}

#[derive(Debug, Eq, PartialEq, Hash)]
enum RoomDirection {
    West,
    East,
    North,
    South,
    Up,
    Down,
    In,
    Out,

    None
}

struct Room {
    description: String,
    items: Vec<Item>,
    direction_to_room: HashMap<RoomDirection, Room>,
}

impl Room {
    fn new(description: &'static str) -> Room {
        Room {
            description: description.to_string(),
            items: Vec::new(),
            direction_to_room: HashMap::new()
        }
    }

    fn add_direction(&mut self, direction: RoomDirection, room: Room) {
        self.direction_to_room.insert(direction, room);
    }
}

struct Item {
    name: String,
}

struct Inventory {
    items: Vec<Item>,
}

impl Inventory {
    fn new() -> Inventory {
        Inventory {
            items: Vec::new()
        }
    }
}

struct Player {
    name: String,
    inventory: Inventory,
}

impl Player {
    fn new(name: &'static str) -> Player {
        Player {
            name: name.to_string(),
            inventory: Inventory::new()
        }
    }
}

impl TraversesWorld for Player {
}

impl Debug for Player {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
        formatter.write_str("Player{ name:");
        formatter.write_str(self.name.as_slice());
        formatter.write_str(" }");
        Ok(())
    }
}

fn str_to_direction(to_parse: &str) -> RoomDirection {
    match to_parse {
        "w" | "west" => RoomDirection::West,
        "e" | "east" => RoomDirection::East,
        "n" | "north" => RoomDirection::North,
        "s" | "south" => RoomDirection::South,
        "in" => RoomDirection::In,
        "out" => RoomDirection::Out,
        "up" => RoomDirection::Up,
        "down" => RoomDirection::Down,
        _ => None //~ ERROR mismatched types
    }
}

fn main() {
    let mut player = Player::new("Test player");
    let mut room = Room::new("A test room");
    println!("Made a player: {:?}", player);
    println!("Direction parse: {:?}", str_to_direction("east"));
    match player.attemptTraverse(&room, "west") {
        Ok(_) => println!("Was able to move west"),
        Err(msg) => println!("Not able to move west: {}", msg)
    };
}
<commit_msg>fix import in cfail test<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt::{Debug, Formatter, Error};
use std::collections::HashMap;

trait HasInventory {
    fn getInventory<'s>(&'s self) -> &'s mut Inventory;
    fn addToInventory(&self, item: &Item);
    fn removeFromInventory(&self, itemName: &str) -> bool;
}

trait TraversesWorld {
    fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
        let direction = str_to_direction(directionStr);
        let maybe_room = room.direction_to_room.get(&direction);
        //~^ ERROR cannot infer an appropriate lifetime for autoref due to conflicting requirements
        match maybe_room {
            Some(entry) => Ok(entry),
            _ => Err("Direction does not exist in room.")
        }
    }
}

#[derive(Debug, Eq, PartialEq, Hash)]
enum RoomDirection {
    West,
    East,
    North,
    South,
    Up,
    Down,
    In,
    Out,

    None
}

struct Room {
    description: String,
    items: Vec<Item>,
    direction_to_room: HashMap<RoomDirection, Room>,
}

impl Room {
    fn new(description: &'static str) -> Room {
        Room {
            description: description.to_string(),
            items: Vec::new(),
            direction_to_room: HashMap::new()
        }
    }

    fn add_direction(&mut self, direction: RoomDirection, room: Room) {
        self.direction_to_room.insert(direction, room);
    }
}

struct Item {
    name: String,
}

struct Inventory {
    items: Vec<Item>,
}

impl Inventory {
    fn new() -> Inventory {
        Inventory {
            items: Vec::new()
        }
    }
}

struct Player {
    name: String,
    inventory: Inventory,
}

impl Player {
    fn new(name: &'static str) -> Player {
        Player {
            name: name.to_string(),
            inventory: Inventory::new()
        }
    }
}

impl TraversesWorld for Player {
}

impl Debug for Player {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
        formatter.write_str("Player{ name:");
        formatter.write_str(self.name.as_slice());
        formatter.write_str(" }");
        Ok(())
    }
}

fn str_to_direction(to_parse: &str) -> RoomDirection {
    match to_parse {
        "w" | "west" => RoomDirection::West,
        "e" | "east" => RoomDirection::East,
        "n" | "north" => RoomDirection::North,
        "s" | "south" => RoomDirection::South,
        "in" => RoomDirection::In,
        "out" => RoomDirection::Out,
        "up" => RoomDirection::Up,
        "down" => RoomDirection::Down,
        _ => None //~ ERROR mismatched types
    }
}

fn main() {
    let mut player = Player::new("Test player");
    let mut room = Room::new("A test room");
    println!("Made a player: {:?}", player);
    println!("Direction parse: {:?}", str_to_direction("east"));
    match player.attemptTraverse(&room, "west") {
        Ok(_) => println!("Was able to move west"),
        Err(msg) => println!("Not able to move west: {}", msg)
    };
}
<|endoftext|>