<commit_before>use std::f32::EPSILON;
use serde_json::value::{Value as Json, from_value};

use lexer::TokenType;
use nodes::Node;
use nodes::SpecificNode::*;
use context::{Context, JsonRender, JsonNumber, JsonTruthy};

// we need to have some data in the renderer for when we are in a ForLoop
// For example, accessing the local variable would fail when
// looking it up in the context
#[derive(Debug)]
struct ForLoop {
    variable_name: String,
    current: usize,
    values: Vec<Json>
}
impl ForLoop {
    pub fn new(local: String, values: Vec<Json>) -> ForLoop {
        ForLoop {
            variable_name: local,
            current: 0,
            values: values
        }
    }

    pub fn increment(&mut self) {
        self.current += 1;
    }

    pub fn get(&self) -> &Json {
        self.values.get(self.current).unwrap()
    }
}

#[derive(Debug)]
pub struct Renderer {
    output: String,
    context: Json,
    ast: Node,
    for_loops: Vec<ForLoop>
}

impl Renderer {
    pub fn new(ast: Node, context: Context) -> Renderer {
        Renderer {
            output: String::new(),
            ast: ast,
            context: context.as_json(),
            for_loops: vec![],
        }
    }

    // Lookup a variable name from the context and takes into
    // account for loops variables
    fn lookup_variable(&self, key: &str) -> Json {
        if self.for_loops.is_empty() {
            // TODO: no unwrap here
            return self.context.lookup(key).cloned().unwrap();
        }

        for for_loop in self.for_loops.iter().rev() {
            if key.starts_with(&for_loop.variable_name) {
                // TODO: no unwrap
                let value = for_loop.get();
                // might be a struct or some nested structure
                if key.contains('.') {
                    let new_key = key.split_terminator('.').skip(1).collect::<Vec<&str>>().join(".");
                    return value.lookup(&new_key).cloned().unwrap();
                } else {
                    return value.clone();
                }
            }
        }

        // TODO: no unwrap here
        self.context.lookup(key).cloned().unwrap()
    }

    fn eval_math(&self, node: &Node) -> f32 {
        match node.specific {
            Identifier(ref s) => {
                // TODO: no unwrap here
                let value = self.context.lookup(s).unwrap();
                value.to_number().unwrap()
            },
            Int(s) => s as f32,
            Float(s) => s,
            Math { ref lhs, ref rhs, ref operator } => {
                let l = self.eval_math(lhs);
                let r = self.eval_math(rhs);
                let mut result = match *operator {
                    TokenType::Multiply => l * r,
                    TokenType::Divide => l / r,
                    TokenType::Add => l + r,
                    TokenType::Substract => l - r,
                    _ => panic!("unexpected operator: {:?}", operator)
                };
                // TODO: fix properly
                // TODO: add tests for float maths arithmetics
                if result.fract() < 0.01 {
                    result = result.round();
                }
                result
            }
            _ => unreachable!()
        }
    }

    // TODO: clean up this, too ugly right now for the == and != nodes
    fn eval_condition(&self, node: &Node) -> bool {
        match node.specific {
            // Simple truthiness check
            Identifier(ref n) => {
                // TODO: no unwrap here
                let value = self.context.lookup(n).unwrap();
                value.is_truthy()
            },
            Logic { ref lhs, ref rhs, ref operator } => {
                match *operator {
                    TokenType::Or => {
                        return self.eval_condition(lhs) || self.eval_condition(rhs);
                    },
                    TokenType::And => {
                        return self.eval_condition(lhs) && self.eval_condition(rhs);
                    },
                    TokenType::GreaterOrEqual | TokenType::Greater
                    | TokenType::LowerOrEqual | TokenType::Lower => {
                        let l = self.eval_math(lhs);
                        let r = self.eval_math(rhs);
                        let result = match *operator {
                            TokenType::GreaterOrEqual => l >= r,
                            TokenType::Greater => l > r,
                            TokenType::LowerOrEqual => l <= r,
                            TokenType::Lower => l < r,
                            _ => unreachable!()
                        };
                        return result;
                    },
                    // This is quite different from the other operators
                    // TODO: clean this up, this is ugly
                    TokenType::Equal | TokenType::NotEqual => {
                        match lhs.specific {
                            Logic { .. } => {
                                // let l = self.eval_condition(lhs);
                                // TODO: rhs MUST be bool like
                                panic!("Unimplemented");
                            },
                            Identifier(ref n) => {
                                let l = self.context.lookup(n).unwrap();
                                // who knows what rhs is
                                // Here goes a whole new level of ugliness
                                match rhs.specific {
                                    Identifier(ref i) => {
                                        let r = self.context.lookup(i).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => l == r,
                                            TokenType::NotEqual => l != r,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    Int(r) => {
                                        // TODO: error handling
                                        let l2: i32 = from_value(l.clone()).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => l2 == r,
                                            TokenType::NotEqual => l2 != r,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    Float(r) => {
                                        let l2: f32 = from_value(l.clone()).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => (l2 - r).abs() < EPSILON,
                                            TokenType::NotEqual => (l2 - r).abs() > EPSILON,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    _ => unreachable!()
                                }
                            },
                            Int(n) => {
                                // rhs MUST be a number
                                let l = n as f32; // TODO: that's going to cause issues
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            Float(l) => {
                                // rhs MUST be a number
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            Math { .. } => {
                                // rhs MUST be a number
                                let l = self.eval_math(lhs);
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            _ => unreachable!()
                        }
                    },
                    _ => unreachable!()
                }
                false
            },
            _ => panic!("Got in eval_condition {:?}", node)
        }
    }

    // eval all the values in a  {{ }} block
    fn render_variable_block(&mut self, node: Node) {
        match node.specific {
            Identifier(ref s) => {
                let value = self.lookup_variable(s);
                self.output.push_str(&value.render());
            },
            Math { .. } => {
                let result = self.eval_math(&node);
                self.output.push_str(&result.to_string());
            }
            _ => unreachable!()
        }
    }

    // evaluates conditions and render bodies accordingly
    fn render_if(&mut self, condition_nodes: Vec<Box<Node>>, else_node: Option<Box<Node>>) {
        let mut skip_else = false;
        for node in condition_nodes {
            match node.specific {
                Conditional {ref condition, ref body } => {
                    if self.eval_condition(condition) {
                        skip_else = true;
                        self.render_node(*body.clone());
                    }
                },
                _ => unreachable!()
            }
        }

        if skip_else {
            return;
        }

        if let Some(e) = else_node {
            self.render_node(*e)
        };
    }

    fn render_for(&mut self, local: Box<Node>, array: Box<Node>, body: Box<Node>) {
        let local_name = match local.specific {
            Identifier(s) => s,
            _ => unreachable!()
        };
        let array_name = match array.specific {
            Identifier(s) => s,
            _ => unreachable!()
        };
        // TODO: no unwrap
        println!("{:?}", array_name);
        let list = self.lookup_variable(&array_name);

        if !list.is_array() {
            panic!("{:?} is not an array! can't iterate on it", list);
        }
        let deserialized = list.as_array().unwrap();
        let length = deserialized.len();
        self.for_loops.push(ForLoop::new(local_name, deserialized.clone()));
        let mut i = 0;
        loop {
            self.render_node(*body.clone());
            self.for_loops.last_mut().unwrap().increment();
            if i == length - 1 {
                break;
            }
            i += 1;
        }
    }

    pub fn render_node(&mut self, node: Node) {
        match node.specific {
            Text(ref s) => self.output.push_str(s),
            VariableBlock(s) => self.render_variable_block(*s),
            If {ref condition_nodes, ref else_node} => {
                self.render_if(condition_nodes.clone(), else_node.clone());
            },
            List(body) => {
                for n in body {
                    self.render_node(*n);
                }
            },
            For {local, array, body} => {
                self.render_for(local, array, body);
            },
            _ => panic!("woo {:?}", node)
        }
    }

    pub fn render(&mut self) -> String {
        for node in self.ast.get_children() {
            self.render_node(*node);
        }

        self.output.clone()
    }
}

#[cfg(test)]
mod tests {
    use template::Template;
    use context::Context;

    #[test]
    fn test_render_simple_string() {
        let result = Template::new("", "
Hello world
").render(Context::new());
        assert_eq!(result, "
Hello world
".to_owned());
    }

    #[test]
    fn test_render_math() {
        let result = Template::new("", "This is {{ 2000 + 16 }}.").render(Context::new());
        assert_eq!(result, "This is 2016.".to_owned());
    }

    #[test]
    fn test_render_basic_variable() {
        let mut context = Context::new();
        context.add("name", &"Vincent");

        let result = Template::new("", "My name is {{ name }}.").render(context);
        assert_eq!(result, "My name is Vincent.".to_owned());
    }

    #[test]
    fn test_render_math_with_variable() {
        let mut context = Context::new();
        context.add("vat_rate", &0.20);

        let result = Template::new("", "Vat: £{{ 100 * vat_rate }}.").render(context);
        assert_eq!(result, "Vat: £20.".to_owned());
    }

    #[test]
    fn test_render_if_simple() {
        let mut context = Context::new();
        context.add("is_admin", &true);

        let result = Template::new("", "{% if is_admin %}Admin{% endif %}").render(context);
        assert_eq!(result, "Admin".to_owned());
    }

    #[test]
    fn test_render_if_or_conditions() {
        let mut context = Context::new();
        context.add("is_adult", &false);
        context.add("age", &18);

        let result = Template::new(
            "",
            "{% if is_adult || age + 1 > 18 %}Adult{% endif %}"
        ).render(context);
        assert_eq!(result, "Adult".to_owned());
    }

    #[test]
    fn test_render_if_and_conditions_with_equality() {
        let mut context = Context::new();
        context.add("is_adult", &true);
        context.add("age", &18);

        let result = Template::new("", "{% if is_adult && age == 18 %}Adult{% endif %}").render(context);
        assert_eq!(result, "Adult".to_owned());
    }

    #[test]
    fn test_render_basic_for() {
        let mut context = Context::new();
        context.add("data", &vec![1,2,3]);

        let result = Template::new("", "{% for i in data %}{{i}}{% endfor %}").render(context);
        assert_eq!(result, "123".to_owned());
    }

}
<commit_msg>Remove random print<commit_after>use std::f32::EPSILON;
use serde_json::value::{Value as Json, from_value};

use lexer::TokenType;
use nodes::Node;
use nodes::SpecificNode::*;
use context::{Context, JsonRender, JsonNumber, JsonTruthy};

// we need to have some data in the renderer for when we are in a ForLoop
// For example, accessing the local variable would fail when
// looking it up in the context
#[derive(Debug)]
struct ForLoop {
    variable_name: String,
    current: usize,
    values: Vec<Json>
}
impl ForLoop {
    pub fn new(local: String, values: Vec<Json>) -> ForLoop {
        ForLoop {
            variable_name: local,
            current: 0,
            values: values
        }
    }

    pub fn increment(&mut self) {
        self.current += 1;
    }

    pub fn get(&self) -> &Json {
        self.values.get(self.current).unwrap()
    }
}

#[derive(Debug)]
pub struct Renderer {
    output: String,
    context: Json,
    ast: Node,
    for_loops: Vec<ForLoop>
}

impl Renderer {
    pub fn new(ast: Node, context: Context) -> Renderer {
        Renderer {
            output: String::new(),
            ast: ast,
            context: context.as_json(),
            for_loops: vec![],
        }
    }

    // Lookup a variable name from the context and takes into
    // account for loops variables
    fn lookup_variable(&self, key: &str) -> Json {
        if self.for_loops.is_empty() {
            // TODO: no unwrap here
            return self.context.lookup(key).cloned().unwrap();
        }

        for for_loop in self.for_loops.iter().rev() {
            if key.starts_with(&for_loop.variable_name) {
                // TODO: no unwrap
                let value = for_loop.get();
                // might be a struct or some nested structure
                if key.contains('.') {
                    let new_key = key.split_terminator('.').skip(1).collect::<Vec<&str>>().join(".");
                    return value.lookup(&new_key).cloned().unwrap();
                } else {
                    return value.clone();
                }
            }
        }

        // TODO: no unwrap here
        self.context.lookup(key).cloned().unwrap()
    }

    fn eval_math(&self, node: &Node) -> f32 {
        match node.specific {
            Identifier(ref s) => {
                // TODO: no unwrap here
                let value = self.context.lookup(s).unwrap();
                value.to_number().unwrap()
            },
            Int(s) => s as f32,
            Float(s) => s,
            Math { ref lhs, ref rhs, ref operator } => {
                let l = self.eval_math(lhs);
                let r = self.eval_math(rhs);
                let mut result = match *operator {
                    TokenType::Multiply => l * r,
                    TokenType::Divide => l / r,
                    TokenType::Add => l + r,
                    TokenType::Substract => l - r,
                    _ => panic!("unexpected operator: {:?}", operator)
                };
                // TODO: fix properly
                // TODO: add tests for float maths arithmetics
                if result.fract() < 0.01 {
                    result = result.round();
                }
                result
            }
            _ => unreachable!()
        }
    }

    // TODO: clean up this, too ugly right now for the == and != nodes
    fn eval_condition(&self, node: &Node) -> bool {
        match node.specific {
            // Simple truthiness check
            Identifier(ref n) => {
                // TODO: no unwrap here
                let value = self.context.lookup(n).unwrap();
                value.is_truthy()
            },
            Logic { ref lhs, ref rhs, ref operator } => {
                match *operator {
                    TokenType::Or => {
                        return self.eval_condition(lhs) || self.eval_condition(rhs);
                    },
                    TokenType::And => {
                        return self.eval_condition(lhs) && self.eval_condition(rhs);
                    },
                    TokenType::GreaterOrEqual | TokenType::Greater
                    | TokenType::LowerOrEqual | TokenType::Lower => {
                        let l = self.eval_math(lhs);
                        let r = self.eval_math(rhs);
                        let result = match *operator {
                            TokenType::GreaterOrEqual => l >= r,
                            TokenType::Greater => l > r,
                            TokenType::LowerOrEqual => l <= r,
                            TokenType::Lower => l < r,
                            _ => unreachable!()
                        };
                        return result;
                    },
                    // This is quite different from the other operators
                    // TODO: clean this up, this is ugly
                    TokenType::Equal | TokenType::NotEqual => {
                        match lhs.specific {
                            Logic { .. } => {
                                // let l = self.eval_condition(lhs);
                                // TODO: rhs MUST be bool like
                                panic!("Unimplemented");
                            },
                            Identifier(ref n) => {
                                let l = self.context.lookup(n).unwrap();
                                // who knows what rhs is
                                // Here goes a whole new level of ugliness
                                match rhs.specific {
                                    Identifier(ref i) => {
                                        let r = self.context.lookup(i).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => l == r,
                                            TokenType::NotEqual => l != r,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    Int(r) => {
                                        // TODO: error handling
                                        let l2: i32 = from_value(l.clone()).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => l2 == r,
                                            TokenType::NotEqual => l2 != r,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    Float(r) => {
                                        let l2: f32 = from_value(l.clone()).unwrap();
                                        let result = match *operator {
                                            TokenType::Equal => (l2 - r).abs() < EPSILON,
                                            TokenType::NotEqual => (l2 - r).abs() > EPSILON,
                                            _ => unreachable!()
                                        };
                                        return result;
                                    },
                                    _ => unreachable!()
                                }
                            },
                            Int(n) => {
                                // rhs MUST be a number
                                let l = n as f32; // TODO: that's going to cause issues
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            Float(l) => {
                                // rhs MUST be a number
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            Math { .. } => {
                                // rhs MUST be a number
                                let l = self.eval_math(lhs);
                                let r = self.eval_math(rhs);
                                let result = match *operator {
                                    TokenType::Equal => (l - r).abs() < EPSILON,
                                    TokenType::NotEqual => (l - r).abs() > EPSILON,
                                    _ => unreachable!()
                                };
                                return result;
                            },
                            _ => unreachable!()
                        }
                    },
                    _ => unreachable!()
                }
                false
            },
            _ => panic!("Got in eval_condition {:?}", node)
        }
    }

    // eval all the values in a  {{ }} block
    fn render_variable_block(&mut self, node: Node) {
        match node.specific {
            Identifier(ref s) => {
                let value = self.lookup_variable(s);
                self.output.push_str(&value.render());
            },
            Math { .. } => {
                let result = self.eval_math(&node);
                self.output.push_str(&result.to_string());
            }
            _ => unreachable!()
        }
    }

    // evaluates conditions and render bodies accordingly
    fn render_if(&mut self, condition_nodes: Vec<Box<Node>>, else_node: Option<Box<Node>>) {
        let mut skip_else = false;
        for node in condition_nodes {
            match node.specific {
                Conditional {ref condition, ref body } => {
                    if self.eval_condition(condition) {
                        skip_else = true;
                        self.render_node(*body.clone());
                    }
                },
                _ => unreachable!()
            }
        }

        if skip_else {
            return;
        }

        if let Some(e) = else_node {
            self.render_node(*e)
        };
    }

    fn render_for(&mut self, local: Box<Node>, array: Box<Node>, body: Box<Node>) {
        let local_name = match local.specific {
            Identifier(s) => s,
            _ => unreachable!()
        };
        let array_name = match array.specific {
            Identifier(s) => s,
            _ => unreachable!()
        };

        let list = self.lookup_variable(&array_name);

        if !list.is_array() {
            panic!("{:?} is not an array! can't iterate on it", list);
        }
        let deserialized = list.as_array().unwrap();
        let length = deserialized.len();
        self.for_loops.push(ForLoop::new(local_name, deserialized.clone()));
        let mut i = 0;
        loop {
            self.render_node(*body.clone());
            self.for_loops.last_mut().unwrap().increment();
            if i == length - 1 {
                break;
            }
            i += 1;
        }
    }

    pub fn render_node(&mut self, node: Node) {
        match node.specific {
            Text(ref s) => self.output.push_str(s),
            VariableBlock(s) => self.render_variable_block(*s),
            If {ref condition_nodes, ref else_node} => {
                self.render_if(condition_nodes.clone(), else_node.clone());
            },
            List(body) => {
                for n in body {
                    self.render_node(*n);
                }
            },
            For {local, array, body} => {
                self.render_for(local, array, body);
            },
            _ => panic!("woo {:?}", node)
        }
    }

    pub fn render(&mut self) -> String {
        for node in self.ast.get_children() {
            self.render_node(*node);
        }

        self.output.clone()
    }
}

#[cfg(test)]
mod tests {
    use template::Template;
    use context::Context;

    #[test]
    fn test_render_simple_string() {
        let result = Template::new("", "
Hello world
").render(Context::new());
        assert_eq!(result, "
Hello world
".to_owned());
    }

    #[test]
    fn test_render_math() {
        let result = Template::new("", "This is {{ 2000 + 16 }}.").render(Context::new());
        assert_eq!(result, "This is 2016.".to_owned());
    }

    #[test]
    fn test_render_basic_variable() {
        let mut context = Context::new();
        context.add("name", &"Vincent");

        let result = Template::new("", "My name is {{ name }}.").render(context);
        assert_eq!(result, "My name is Vincent.".to_owned());
    }

    #[test]
    fn test_render_math_with_variable() {
        let mut context = Context::new();
        context.add("vat_rate", &0.20);

        let result = Template::new("", "Vat: £{{ 100 * vat_rate }}.").render(context);
        assert_eq!(result, "Vat: £20.".to_owned());
    }

    #[test]
    fn test_render_if_simple() {
        let mut context = Context::new();
        context.add("is_admin", &true);

        let result = Template::new("", "{% if is_admin %}Admin{% endif %}").render(context);
        assert_eq!(result, "Admin".to_owned());
    }

    #[test]
    fn test_render_if_or_conditions() {
        let mut context = Context::new();
        context.add("is_adult", &false);
        context.add("age", &18);

        let result = Template::new(
            "",
            "{% if is_adult || age + 1 > 18 %}Adult{% endif %}"
        ).render(context);
        assert_eq!(result, "Adult".to_owned());
    }

    #[test]
    fn test_render_if_and_conditions_with_equality() {
        let mut context = Context::new();
        context.add("is_adult", &true);
        context.add("age", &18);

        let result = Template::new("", "{% if is_adult && age == 18 %}Adult{% endif %}").render(context);
        assert_eq!(result, "Adult".to_owned());
    }

    #[test]
    fn test_render_basic_for() {
        let mut context = Context::new();
        context.add("data", &vec![1,2,3]);

        let result = Template::new("", "{% for i in data %}{{i}}{% endfor %}").render(context);
        assert_eq!(result, "123".to_owned());
    }

}
<|endoftext|>


<commit_before>//! This module contains the parallel iterator types for results
//! (`Result<T, E>`). You will rarely need to interact with it directly
//! unless you have need to name one of the iterator types.

use iter::*;
use iter::plumbing::*;
use std::sync::Mutex;

use option;

/// Parallel iterator over a result
#[derive(Debug, Clone)]
pub struct IntoIter<T: Send> {
    inner: option::IntoIter<T>,
}

impl<T: Send, E> IntoParallelIterator for Result<T, E> {
    type Item = T;
    type Iter = IntoIter<T>;

    fn into_par_iter(self) -> Self::Iter {
        IntoIter { inner: self.ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    IntoIter<T> => T,
    impl<T: Send>
}

/// Parallel iterator over an immutable reference to a result
#[derive(Debug)]
pub struct Iter<'a, T: Sync + 'a> {
    inner: option::IntoIter<&'a T>,
}

impl<'a, T: Sync> Clone for Iter<'a, T> {
    fn clone(&self) -> Self {
        Iter { inner: self.inner.clone() }
    }
}

impl<'a, T: Sync, E> IntoParallelIterator for &'a Result<T, E> {
    type Item = &'a T;
    type Iter = Iter<'a, T>;

    fn into_par_iter(self) -> Self::Iter {
        Iter { inner: self.as_ref().ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    Iter<'a, T> => &'a T,
    impl<'a, T: Sync + 'a>
}

/// Parallel iterator over a mutable reference to a result
#[derive(Debug)]
pub struct IterMut<'a, T: Send + 'a> {
    inner: option::IntoIter<&'a mut T>,
}

impl<'a, T: Send, E> IntoParallelIterator for &'a mut Result<T, E> {
    type Item = &'a mut T;
    type Iter = IterMut<'a, T>;

    fn into_par_iter(self) -> Self::Iter {
        IterMut { inner: self.as_mut().ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    IterMut<'a, T> => &'a mut T,
    impl<'a, T: Send + 'a>
}

/// Collect an arbitrary `Result`-wrapped collection.
///
/// If any item is `Err`, then all previous `Ok` items collected are
/// discarded, and it returns that error.  If there are multiple errors, the
/// one returned is not deterministic.
impl<'a, C, T, E> FromParallelIterator<Result<T, E>> for Result<C, E>
    where C: FromParallelIterator<T>,
          T: Send,
          E: Send
{
    fn from_par_iter<I>(par_iter: I) -> Self
        where I: IntoParallelIterator<Item = Result<T, E>>
    {
        let saved_error = Mutex::new(None);
        let collection = par_iter
            .into_par_iter()
            .map(|item| match item {
                     Ok(item) => Some(item),
                     Err(error) => {
                         if let Ok(mut guard) = saved_error.lock() {
                             *guard = Some(error);
                         }
                         None
                     }
                 })
            .while_some()
            .collect();

        match saved_error.into_inner().unwrap() {
            Some(error) => Err(error),
            None => Ok(collection),
        }
    }
}
<commit_msg>Relax the error locking in collecting results<commit_after>//! This module contains the parallel iterator types for results
//! (`Result<T, E>`). You will rarely need to interact with it directly
//! unless you have need to name one of the iterator types.

use iter::*;
use iter::plumbing::*;
use std::sync::Mutex;

use option;

/// Parallel iterator over a result
#[derive(Debug, Clone)]
pub struct IntoIter<T: Send> {
    inner: option::IntoIter<T>,
}

impl<T: Send, E> IntoParallelIterator for Result<T, E> {
    type Item = T;
    type Iter = IntoIter<T>;

    fn into_par_iter(self) -> Self::Iter {
        IntoIter { inner: self.ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    IntoIter<T> => T,
    impl<T: Send>
}

/// Parallel iterator over an immutable reference to a result
#[derive(Debug)]
pub struct Iter<'a, T: Sync + 'a> {
    inner: option::IntoIter<&'a T>,
}

impl<'a, T: Sync> Clone for Iter<'a, T> {
    fn clone(&self) -> Self {
        Iter { inner: self.inner.clone() }
    }
}

impl<'a, T: Sync, E> IntoParallelIterator for &'a Result<T, E> {
    type Item = &'a T;
    type Iter = Iter<'a, T>;

    fn into_par_iter(self) -> Self::Iter {
        Iter { inner: self.as_ref().ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    Iter<'a, T> => &'a T,
    impl<'a, T: Sync + 'a>
}

/// Parallel iterator over a mutable reference to a result
#[derive(Debug)]
pub struct IterMut<'a, T: Send + 'a> {
    inner: option::IntoIter<&'a mut T>,
}

impl<'a, T: Send, E> IntoParallelIterator for &'a mut Result<T, E> {
    type Item = &'a mut T;
    type Iter = IterMut<'a, T>;

    fn into_par_iter(self) -> Self::Iter {
        IterMut { inner: self.as_mut().ok().into_par_iter() }
    }
}

delegate_indexed_iterator!{
    IterMut<'a, T> => &'a mut T,
    impl<'a, T: Send + 'a>
}

/// Collect an arbitrary `Result`-wrapped collection.
///
/// If any item is `Err`, then all previous `Ok` items collected are
/// discarded, and it returns that error.  If there are multiple errors, the
/// one returned is not deterministic.
impl<'a, C, T, E> FromParallelIterator<Result<T, E>> for Result<C, E>
    where C: FromParallelIterator<T>,
          T: Send,
          E: Send
{
    fn from_par_iter<I>(par_iter: I) -> Self
        where I: IntoParallelIterator<Item = Result<T, E>>
    {
        let saved_error = Mutex::new(None);
        let collection = par_iter
            .into_par_iter()
            .map(|item| match item {
                     Ok(item) => Some(item),
                     Err(error) => {
                         // We don't need a blocking `lock()`, as anybody
                         // else holding the lock will also be writing
                         // `Some(error)`, and then ours is irrelevant.
                         if let Ok(mut guard) = saved_error.try_lock() {
                             if guard.is_none() {
                                 *guard = Some(error);
                             }
                         }
                         None
                     }
                 })
            .while_some()
            .collect();

        match saved_error.into_inner().unwrap() {
            Some(error) => Err(error),
            None => Ok(collection),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;
use iron::modifiers::Redirect;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

pub struct RouterInner {
    // The routers, specialized by method.
    pub routers: Recognizer<HashMap<method::Method, Arc<Handler>>>,
    // Routes that accept any method.
    pub wildcard: Recognizer<Arc<Handler>>,
    // Used in URL generation.
    pub route_ids: HashMap<String, String>
}

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    inner: Arc<RouterInner>
}

impl Router {
    /// Construct a new, empty `Router`.
    ///
    /// ```
    /// # use router::Router;
    /// let router = Router::new();
    /// ```
    pub fn new() -> Router {
        Router {
            inner: Arc::new(RouterInner {
                routers: Recognizer::new(),
                wildcard: Recognizer::new(),
                route_ids: HashMap::new()
            })
        }
    }

    fn mut_inner(&mut self) -> &mut RouterInner {
        Arc::get_mut(&mut self.inner).expect("Cannot modify router at this point.")
    }

    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// let mut router = Router::new();
    /// router.route(method::Get, "/users/:userid/:friendid", controller, "user_friend");
    /// ```
    ///
    /// `route_id` is a unique name for your route, and is used when generating an URL with
    /// `url_for`.
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, method: method::Method, glob: S, handler: H, route_id: I) -> &mut Router {

        let mut hash: HashMap<method::Method, Arc<Handler>>;

        if let Some(s) = self.mut_inner().routers.recognize(glob.as_ref()).ok() {
            hash = s.handler.clone();
        } else {
            hash = HashMap::new();
        }

        hash.insert(method, Arc::new(handler));
        self.mut_inner().routers.add(glob.as_ref(), hash);
        self.route_id(route_id.as_ref(), glob.as_ref());
        self
    }

    fn route_id(&mut self, id: &str, glob: &str) {
        let mut mut_inner = self.mut_inner();
        let ref mut route_ids = mut_inner.route_ids;

        match route_ids.get(id) {
            Some(other_glob) if glob != other_glob => panic!("Duplicate route_id: {}", id),
            _ => ()
        };

        route_ids.insert(id.to_owned(), glob.to_owned());
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Get, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Post, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Put, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Delete, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Head, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Patch, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Options, glob, handler, route_id)
    }

    /// Route will match any method, including gibberish.
    /// In case of ambiguity, handlers specific to methods will be preferred.
    pub fn any<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.mut_inner().wildcard.add(glob.as_ref(), Arc::new(handler));
        self.route_id(route_id.as_ref(), glob.as_ref());
        self
    }

    fn recognize(&self, method: &method::Method, path: &str)
                      -> Result<Match<&Arc<Handler>>, RouterError> {
        let mut found_path = false;
        if let Ok(s) = self.inner.routers.recognize(path) {
            found_path = true;
            if let Some(h) = s.handler.get(method) {
                return Ok(Match::new(h, s.params));
            }
        };

        if let Ok(x) = self.inner.wildcard.recognize(path) {
            return Ok(x)
        };

        Err(if found_path { RouterError::MethodNotAllowed } else { RouterError::NotFound })
    }

    fn handle_options(&self, path: &str) -> Response {
        static METHODS: &'static [method::Method] =
            &[method::Get, method::Post, method::Put,
              method::Delete, method::Head, method::Patch];

        // Get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            if let Ok(s) = self.inner.routers.recognize(path) {
                if let Some(_) = s.handler.get(method) {
                    options.push(method.clone());
                }
            }
        }
        // If GET is there, HEAD is also there.
        if options.contains(&method::Get) && !options.contains(&method::Head) {
            options.push(method::Head);
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        res
    }

    // Tests for a match by adding or removing a trailing slash.
    fn redirect_slash(&self, req: &Request) -> Option<IronError> {
        let mut url = req.url.clone();
        let mut path = url.path().join("/");

        if let Some(last_char) = path.chars().last() {
            {
                let mut path_segments = url.as_mut().path_segments_mut().unwrap();
                if last_char == '/' {
                    // We didn't recognize anything without a trailing slash; try again with one appended.
                    path.pop();
                    path_segments.pop();
                } else {
                    // We didn't recognize anything with a trailing slash; try again without it.
                    path.push('/');
                    path_segments.push("");
                }
            }
        }

        self.recognize(&req.method, &path).ok().and(
            Some(IronError::new(RouterError::TrailingSlash,
                                (status::MovedPermanently, Redirect(url))))
        )
    }

    fn handle_method(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        match self.recognize(&req.method, path) {
            Ok(matched) => {
                req.extensions.insert::<Router>(matched.params);
                req.extensions.insert::<RouterInner>(self.inner.clone());
                matched.handler.handle(req)
            },
            Err(RouterError::MethodNotAllowed) => {
                Err(IronError::new(RouterError::MethodNotAllowed, status::MethodNotAllowed))
            },
            Err(_) => {
                if let Some(err) = self.redirect_slash(req) {
                    return Err(err)
                };

                match req.method {
                    method::Options => Ok(self.handle_options(path)),
                    // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    method::Head => {
                        req.method = method::Get;
                        self.handle_method(req, path)
                    },
                    _ => Err(IronError::new(RouterError::NotFound, status::NotFound))
                }
            }
        }
    }
}

impl Key for Router { type Value = Params; }

impl Key for RouterInner { type Value = Arc<RouterInner>; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path().join("/");
        self.handle_method(req, &path)
    }
}

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug, PartialEq)]
pub enum RouterError {
    /// The error thrown by router if there is no matching method in existing route.
    MethodNotAllowed,
    /// The error thrown by router if there is no matching route.
    NotFound,
    /// The error thrown by router if a request was redirected by adding or removing a trailing slash.
    TrailingSlash
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.description())
    }
}

impl Error for RouterError {
    fn description(&self) -> &str {
        match *self {
            RouterError::MethodNotAllowed => "Method Not Allowed",
            RouterError::NotFound => "No matching route found.",
            RouterError::TrailingSlash => "The request had a trailing slash."
        }
    }
}

/// The error thrown by router if there is no matching route,
/// it is always accompanied by a NotFound response.
#[derive(Debug, PartialEq, Eq)]
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

/// The error thrown by router if a request was redirected
/// by adding or removing a trailing slash.
#[derive(Debug, PartialEq, Eq)]
pub struct TrailingSlash;

impl fmt::Display for TrailingSlash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("The request had a trailing slash.")
    }
}

impl Error for TrailingSlash {
    fn description(&self) -> &str { "Trailing Slash" }
}

#[cfg(test)]
mod test {
    use super::{Router, RouterError};
    use iron::{headers, method, status, Request, Response};

    #[test]
    fn test_handle_options_post() {
        let mut router = Router::new();
        router.post("/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        let resp = router.handle_options("/");
        let headers = resp.headers.get::<headers::Allow>().unwrap();
        let expected = headers::Allow(vec![method::Method::Post]);
        assert_eq!(&expected, headers);
    }

    #[test]
    fn test_handle_options_get_head() {
        let mut router = Router::new();
        router.get("/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        let resp = router.handle_options("/");
        let headers = resp.headers.get::<headers::Allow>().unwrap();
        let expected = headers::Allow(vec![method::Method::Get, method::Method::Head]);
        assert_eq!(&expected, headers);
    }

    #[test]
    fn test_not_allowed_method() {
        let mut router = Router::new();

        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");

        router.get("/post/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "another_route");

        match router.recognize(&method::Get, "/post") {
            Ok(_) => {
                panic!();
            },
            Err(e) => {
                assert_eq!(RouterError::MethodNotAllowed, e);
            }
        }
    }

    #[test]
    fn test_handle_any_ok() {
        let mut router = Router::new();
        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.any("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.put("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.any("/get", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "any");

        assert!(router.recognize(&method::Get, "/post").is_ok());
        assert!(router.recognize(&method::Get, "/get").is_ok());
    }

    #[test]
    fn test_request() {
        let mut router = Router::new();
        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.get("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");

        assert!(router.recognize(&method::Post, "/post").is_ok());
        assert!(router.recognize(&method::Get, "/post").is_ok());
        assert!(router.recognize(&method::Put, "/post").is_err());
        assert!(router.recognize(&method::Get, "/post/").is_err());
    }

    #[test]
    fn test_not_found() {
        let mut router = Router::new();
        router.put("/put", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        match router.recognize(&method::Patch, "/patch") {
            Ok(_) => {
                panic!();
            },
            Err(e) => {
                assert_eq!(RouterError::NotFound, e);
            }
        }
    }

    #[test]
    #[should_panic]
    fn test_same_route_id() {
        let mut router = Router::new();
        router.put("/put", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "my_route_id");
        router.get("/get", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "my_route_id");
    }
}
<commit_msg>testcase<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::sync::Arc;

use iron::{Request, Response, Handler, IronResult, IronError};
use iron::{status, method, headers};
use iron::typemap::Key;
use iron::modifiers::Redirect;

use recognizer::Router as Recognizer;
use recognizer::{Match, Params};

pub struct RouterInner {
    // The routers, specialized by method.
    pub routers: Recognizer<HashMap<method::Method, Arc<Handler>>>,
    // Routes that accept any method.
    pub wildcard: Recognizer<Arc<Handler>>,
    // Used in URL generation.
    pub route_ids: HashMap<String, String>
}

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
pub struct Router {
    inner: Arc<RouterInner>
}

impl Router {
    /// Construct a new, empty `Router`.
    ///
    /// ```
    /// # use router::Router;
    /// let router = Router::new();
    /// ```
    pub fn new() -> Router {
        Router {
            inner: Arc::new(RouterInner {
                routers: Recognizer::new(),
                wildcard: Recognizer::new(),
                route_ids: HashMap::new()
            })
        }
    }

    fn mut_inner(&mut self) -> &mut RouterInner {
        Arc::get_mut(&mut self.inner).expect("Cannot modify router at this point.")
    }

    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports glob patterns: `*` for a single wildcard segment and
    /// `:param` for matching storing that segment of the request url in the `Params`
    /// object, which is stored in the request `extensions`.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// let mut router = Router::new();
    /// router.route(method::Get, "/users/:userid/:friendid", controller, "user_friend");
    /// ```
    ///
    /// `route_id` is a unique name for your route, and is used when generating an URL with
    /// `url_for`.
    ///
    /// The controller provided to route can be any `Handler`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Handler`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, method: method::Method, glob: S, handler: H, route_id: I) -> &mut Router {

        let mut hash: HashMap<method::Method, Arc<Handler>>;

        if let Some(s) = self.mut_inner().routers.recognize(glob.as_ref()).ok() {
            hash = s.handler.clone();
        } else {
            hash = HashMap::new();
        }

        hash.insert(method, Arc::new(handler));
        self.mut_inner().routers.add(glob.as_ref(), hash);
        self.route_id(route_id.as_ref(), glob.as_ref());
        self
    }

    fn route_id(&mut self, id: &str, glob: &str) {
        let mut mut_inner = self.mut_inner();
        let ref mut route_ids = mut_inner.route_ids;

        match route_ids.get(id) {
            Some(other_glob) if glob != other_glob => panic!("Duplicate route_id: {}", id),
            _ => ()
        };

        route_ids.insert(id.to_owned(), glob.to_owned());
    }

    /// Like route, but specialized to the `Get` method.
    pub fn get<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Get, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Post` method.
    pub fn post<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Post, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Put` method.
    pub fn put<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Put, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Delete` method.
    pub fn delete<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Delete, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Head` method.
    pub fn head<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Head, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Patch` method.
    pub fn patch<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Patch, glob, handler, route_id)
    }

    /// Like route, but specialized to the `Options` method.
    pub fn options<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.route(method::Options, glob, handler, route_id)
    }

    /// Route will match any method, including gibberish.
    /// In case of ambiguity, handlers specific to methods will be preferred.
    pub fn any<S: AsRef<str>, H: Handler, I: AsRef<str>>(&mut self, glob: S, handler: H, route_id: I) -> &mut Router {
        self.mut_inner().wildcard.add(glob.as_ref(), Arc::new(handler));
        self.route_id(route_id.as_ref(), glob.as_ref());
        self
    }

    fn recognize(&self, method: &method::Method, path: &str)
                      -> Result<Match<&Arc<Handler>>, RouterError> {
        let mut found_path = false;
        if let Ok(s) = self.inner.routers.recognize(path) {
            found_path = true;
            if let Some(h) = s.handler.get(method) {
                return Ok(Match::new(h, s.params));
            }
        };

        if let Ok(x) = self.inner.wildcard.recognize(path) {
            return Ok(x)
        };

        Err(if found_path { RouterError::MethodNotAllowed } else { RouterError::NotFound })
    }

    fn handle_options(&self, path: &str) -> Response {
        static METHODS: &'static [method::Method] =
            &[method::Get, method::Post, method::Put,
              method::Delete, method::Head, method::Patch];

        // Get all the available methods and return them.
        let mut options = vec![];

        for method in METHODS.iter() {
            if let Ok(s) = self.inner.routers.recognize(path) {
                if let Some(_) = s.handler.get(method) {
                    options.push(method.clone());
                }
            }
        }
        // If GET is there, HEAD is also there.
        if options.contains(&method::Get) && !options.contains(&method::Head) {
            options.push(method::Head);
        }

        let mut res = Response::with(status::Ok);
        res.headers.set(headers::Allow(options));
        res
    }

    // Tests for a match by adding or removing a trailing slash.
    fn redirect_slash(&self, req: &Request) -> Option<IronError> {
        let mut url = req.url.clone();
        let mut path = url.path().join("/");

        if let Some(last_char) = path.chars().last() {
            {
                let mut path_segments = url.as_mut().path_segments_mut().unwrap();
                if last_char == '/' {
                    // We didn't recognize anything without a trailing slash; try again with one appended.
                    path.pop();
                    path_segments.pop();
                } else {
                    // We didn't recognize anything with a trailing slash; try again without it.
                    path.push('/');
                    path_segments.push("");
                }
            }
        }

        self.recognize(&req.method, &path).ok().and(
            Some(IronError::new(RouterError::TrailingSlash,
                                (status::MovedPermanently, Redirect(url))))
        )
    }

    fn handle_method(&self, req: &mut Request, path: &str) -> IronResult<Response> {
        match self.recognize(&req.method, path) {
            Ok(matched) => {
                req.extensions.insert::<Router>(matched.params);
                req.extensions.insert::<RouterInner>(self.inner.clone());
                matched.handler.handle(req)
            },
            Err(RouterError::MethodNotAllowed) => {
                Err(IronError::new(RouterError::MethodNotAllowed, status::MethodNotAllowed))
            },
            Err(_) => {
                if let Some(err) = self.redirect_slash(req) {
                    return Err(err)
                };

                match req.method {
                    method::Options => Ok(self.handle_options(path)),
                    // For HEAD, fall back to GET. Hyper ensures no response body is written.
                    method::Head => {
                        req.method = method::Get;
                        self.handle_method(req, path)
                    },
                    _ => Err(IronError::new(RouterError::NotFound, status::NotFound))
                }
            }
        }
    }
}

impl Key for Router { type Value = Params; }

impl Key for RouterInner { type Value = Arc<RouterInner>; }

impl Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path().join("/");
        self.handle_method(req, &path)
    }
}

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug, PartialEq)]
pub enum RouterError {
    /// The error thrown by router if there is no matching method in existing route.
    MethodNotAllowed,
    /// The error thrown by router if there is no matching route.
    NotFound,
    /// The error thrown by router if a request was redirected by adding or removing a trailing slash.
    TrailingSlash
}

impl fmt::Display for RouterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.description())
    }
}

impl Error for RouterError {
    fn description(&self) -> &str {
        match *self {
            RouterError::MethodNotAllowed => "Method Not Allowed",
            RouterError::NotFound => "No matching route found.",
            RouterError::TrailingSlash => "The request had a trailing slash."
        }
    }
}

/// The error thrown by router if there is no matching route,
/// it is always accompanied by a NotFound response.
#[derive(Debug, PartialEq, Eq)]
pub struct NoRoute;

impl fmt::Display for NoRoute {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("No matching route found.")
    }
}

impl Error for NoRoute {
    fn description(&self) -> &str { "No Route" }
}

/// The error thrown by router if a request was redirected
/// by adding or removing a trailing slash.
#[derive(Debug, PartialEq, Eq)]
pub struct TrailingSlash;

impl fmt::Display for TrailingSlash {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("The request had a trailing slash.")
    }
}

impl Error for TrailingSlash {
    fn description(&self) -> &str { "Trailing Slash" }
}

#[cfg(test)]
mod test {
    use super::{Router, RouterError};
    use iron::{headers, method, status, Request, Response};

    #[test]
    fn test_handle_options_post() {
        let mut router = Router::new();
        router.post("/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        let resp = router.handle_options("/");
        let headers = resp.headers.get::<headers::Allow>().unwrap();
        let expected = headers::Allow(vec![method::Method::Post]);
        assert_eq!(&expected, headers);
    }

    #[test]
    fn test_handle_options_get_head() {
        let mut router = Router::new();
        router.get("/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        let resp = router.handle_options("/");
        let headers = resp.headers.get::<headers::Allow>().unwrap();
        let expected = headers::Allow(vec![method::Method::Get, method::Method::Head]);
        assert_eq!(&expected, headers);
    }

    #[test]
    fn test_not_allowed_method() {
        let mut router = Router::new();

        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");

        router.get("/post/", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "another_route");

        match router.recognize(&method::Get, "/post") {
            Ok(_) => {
                panic!();
            },
            Err(e) => {
                assert_eq!(RouterError::MethodNotAllowed, e);
            }
        }
    }

    #[test]
    fn test_handle_any_ok() {
        let mut router = Router::new();
        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.any("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.put("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.any("/get", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "any");

        assert!(router.recognize(&method::Get, "/post").is_ok());
        assert!(router.recognize(&method::Get, "/get").is_ok());
    }

    #[test]
    fn test_request() {
        let mut router = Router::new();
        router.post("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        router.get("/post", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");

        assert!(router.recognize(&method::Post, "/post").is_ok());
        assert!(router.recognize(&method::Get, "/post").is_ok());
        assert!(router.recognize(&method::Put, "/post").is_err());
        assert!(router.recognize(&method::Get, "/post/").is_err());
    }

    #[test]
    fn test_not_found() {
        let mut router = Router::new();
        router.put("/put", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "");
        match router.recognize(&method::Patch, "/patch") {
            Ok(_) => {
                panic!();
            },
            Err(e) => {
                assert_eq!(RouterError::NotFound, e);
            }
        }
    }

    #[test]
    #[should_panic]
    fn test_same_route_id() {
        let mut router = Router::new();
        router.put("/put", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "my_route_id");
        router.get("/get", |_: &mut Request| {
            Ok(Response::with((status::Ok, "")))
        }, "my_route_id");
    }

    #[test]
    fn test_wildcard_regression() {
        let mut router = Router::new();
        router.options("*", |_: &mut Request| Ok(Response::with((status::Ok, ""))), "id1");
        router.put("/upload/*filename", |_: &mut Request| Ok(Response::with((status::Ok, ""))), "id2");
        assert!(router.recognize(&method::Options, "/foo").is_ok());
        assert!(router.recognize(&method::Put, "/foo").is_err());
        assert!(router.recognize(&method::Put, "/upload/foo").is_ok());
    }
}
<|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 config::Config;
use domain_store::{DomainError, DomainRecord};
use transient_store::{Db, Record};
use errors::*;
use iron::headers::ContentType;
use iron::prelude::*;
use iron::status::{self, Status};
use params::{Params, Value};
use router::Router;
use rustc_serialize::json;
use std::io::Read;
use uuid::Uuid;

fn register(req: &mut Request, config: &Config) -> IronResult<Response> {
    // Get the local IP and optional tunnel url from the body,
    #[derive(RustcDecodable, Debug)]
    struct RegisterBody {
        client: String,
        message: String,
    }

    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();
    let body: RegisterBody = match json::decode(&payload) {
        Ok(body) => body,
        Err(error) => {
            error!("{:?}", error);
            return from_decoder_error(error);
        }
    };

    let message = body.message;
    let client_id = body.client;

    // And the public IP from the socket.
    let public_ip = format!("{}", req.remote_addr.ip());

    info!("POST /register public_ip={} client={} message={}",
          public_ip,
          client_id,
          message);

    // Save this registration in the database.
    // If we already have the same (local, tunnel, public) match, update it,
    // if not create a new match.
    let db = Db::new(config.redis_host.clone(),
                     config.redis_port,
                     config.redis_pass.clone());

    let record = Record {
        public_ip: public_ip.clone(),
        client: client_id.clone(),
        message: message.clone(),
    };

    if let Err(e) = db.set(record) {
        error!("{}", e);
        return EndpointError::with(status::InternalServerError, 501);
    }

    let mut response = Response::with("{\"status\" : \"registered\"}");
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());

    Ok(response)
}

fn ping(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /ping");
    let public_ip = format!("{}", req.remote_addr.ip());

    let mut serialized = String::from("[");

    let db = Db::new(config.redis_host.clone(),
                     config.redis_port,
                     config.redis_pass.clone());
    match db.get(public_ip.clone()) {
        Ok(rvect) => {
            info!("Registrations {:?}", rvect);
            // Serialize the vector.
            let max = rvect.len();
            let mut index = 0;
            for record in rvect {
                match json::encode(&record) {
                    Ok(ref record) => serialized.push_str(record),
                    Err(_) => return EndpointError::with(status::InternalServerError, 501),
                }

                index += 1;
                if index < max {
                    serialized.push_str(",");
                }
            }
        }
        Err(_) => {}
    };

    serialized.push_str("]");
    let mut response = Response::with(serialized);
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());

    Ok(response)
}

fn reserve(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /reserve");

    // Extract the name parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    match map.find(&["name"]) {
        Some(&Value::String(ref name)) => {
            let name = format!("{}.{}", name, config.domain);
            info!("trying to register {}", name);

            let record = config
                .domain_db
                .get_record_by_name(&name)
                .recv()
                .unwrap();
            match record {
                Ok(_) => {
                    // We already have a record for this name, return an error.
                    let mut response = Response::with("{\"error\": \"UnavailableName\"}");
                    response.status = Some(Status::Ok);
                    response.headers.set(ContentType::json());
                    Ok(response)
                }
                Err(DomainError::NoRecord) => {
                    // Create a token, create and store a record and finally return the token.
                    let token = format!("{}", Uuid::new_v4());
                    let record = DomainRecord::new(&name, &token, None);
                    match config.domain_db.add_record(record).recv().unwrap() {
                        Ok(()) => {
                            let mut response = Response::with(format!("{{\"token\": \"{}\"}}", token));
                            response.status = Some(Status::Ok);
                            response.headers.set(ContentType::json());

                            Ok(response)
                        }
                        Err(_) => EndpointError::with(status::InternalServerError, 501),
                    }
                }
                // Other error, like a db issue.
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        // Missing `name` parameter.
        _ => EndpointError::with(status::BadRequest, 400),
    }
}

pub fn create(config: Config) -> Router {
    let mut router = Router::new();

    let config_ = config.clone();
    router.post("register",
                move |req: &mut Request| -> IronResult<Response> { register(req, &config_) },
                "post_message");

    let config_ = config.clone();
    router.get("ping",
               move |req: &mut Request| -> IronResult<Response> { ping(req, &config_) },
               "ping");

    let config_ = config.clone();
    router.get("reserve",
               move |req: &mut Request| -> IronResult<Response> { reserve(req, &config_) },
               "reserve");

    router
}
<commit_msg>Return the name and token in the /reserve response<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 config::Config;
use domain_store::{DomainError, DomainRecord};
use transient_store::{Db, Record};
use errors::*;
use iron::headers::ContentType;
use iron::prelude::*;
use iron::status::{self, Status};
use params::{Params, Value};
use router::Router;
use rustc_serialize::json;
use std::io::Read;
use uuid::Uuid;

fn domain_for_name(name: &str, config: &Config) -> String {
    format!("{}.box.{}", name, config.domain)
}

fn register(req: &mut Request, config: &Config) -> IronResult<Response> {
    // Get the local IP and optional tunnel url from the body,
    #[derive(RustcDecodable, Debug)]
    struct RegisterBody {
        client: String,
        message: String,
    }

    let mut payload = String::new();
    req.body.read_to_string(&mut payload).unwrap();
    let body: RegisterBody = match json::decode(&payload) {
        Ok(body) => body,
        Err(error) => {
            error!("{:?}", error);
            return from_decoder_error(error);
        }
    };

    let message = body.message;
    let client_id = body.client;

    // And the public IP from the socket.
    let public_ip = format!("{}", req.remote_addr.ip());

    info!("POST /register public_ip={} client={} message={}",
          public_ip,
          client_id,
          message);

    // Save this registration in the database.
    // If we already have the same (local, tunnel, public) match, update it,
    // if not create a new match.
    let db = Db::new(config.redis_host.clone(),
                     config.redis_port,
                     config.redis_pass.clone());

    let record = Record {
        public_ip: public_ip.clone(),
        client: client_id.clone(),
        message: message.clone(),
    };

    if let Err(e) = db.set(record) {
        error!("{}", e);
        return EndpointError::with(status::InternalServerError, 501);
    }

    let mut response = Response::with("{\"status\" : \"registered\"}");
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());

    Ok(response)
}

fn ping(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /ping");
    let public_ip = format!("{}", req.remote_addr.ip());

    let mut serialized = String::from("[");

    let db = Db::new(config.redis_host.clone(),
                     config.redis_port,
                     config.redis_pass.clone());
    match db.get(public_ip.clone()) {
        Ok(rvect) => {
            info!("Registrations {:?}", rvect);
            // Serialize the vector.
            let max = rvect.len();
            let mut index = 0;
            for record in rvect {
                match json::encode(&record) {
                    Ok(ref record) => serialized.push_str(record),
                    Err(_) => return EndpointError::with(status::InternalServerError, 501),
                }

                index += 1;
                if index < max {
                    serialized.push_str(",");
                }
            }
        }
        Err(_) => {}
    };

    serialized.push_str("]");
    let mut response = Response::with(serialized);
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());

    Ok(response)
}

fn reserve(req: &mut Request, config: &Config) -> IronResult<Response> {
    info!("GET /reserve");

    // Extract the name parameter.
    let map = req.get_ref::<Params>().unwrap(); // TODO: don't unwrap.
    match map.find(&["name"]) {
        Some(&Value::String(ref name)) => {
            let full_name = domain_for_name(name, config);
            info!("trying to register {}", full_name);

            let record = config
                .domain_db
                .get_record_by_name(&full_name)
                .recv()
                .unwrap();
            match record {
                Ok(_) => {
                    // We already have a record for this name, return an error.
                    let mut response = Response::with("{\"error\": \"UnavailableName\"}");
                    response.status = Some(Status::Ok);
                    response.headers.set(ContentType::json());
                    Ok(response)
                }
                Err(DomainError::NoRecord) => {
                    // Create a token, create and store a record and finally return the token.
                    let token = format!("{}", Uuid::new_v4());
                    let record = DomainRecord::new(&full_name, &token, None);
                    match config.domain_db.add_record(record).recv().unwrap() {
                        Ok(()) => {
                            // We don't want the full domain name or the dns challenge in the response
                            // so we create a local struct.
                            #[derive(RustcEncodable)]
                            struct NameAndToken {
                                name: String,
                                token: String,
                            }
                            let n_and_t = NameAndToken {
                                name: name.to_owned(),
                                token: token,
                            };
                            match json::encode(&n_and_t) {
                                Ok(serialized) => {
                                    let mut response = Response::with(serialized);
                                    response.status = Some(Status::Ok);
                                    response.headers.set(ContentType::json());

                                    Ok(response)
                                }
                                Err(_) => EndpointError::with(status::InternalServerError, 501)
                            }
                        }
                        Err(_) => EndpointError::with(status::InternalServerError, 501),
                    }
                }
                // Other error, like a db issue.
                Err(_) => EndpointError::with(status::InternalServerError, 501),
            }
        }
        // Missing `name` parameter.
        _ => EndpointError::with(status::BadRequest, 400),
    }
}

pub fn create(config: Config) -> Router {
    let mut router = Router::new();

    let config_ = config.clone();
    router.post("register",
                move |req: &mut Request| -> IronResult<Response> { register(req, &config_) },
                "post_message");

    let config_ = config.clone();
    router.get("ping",
               move |req: &mut Request| -> IronResult<Response> { ping(req, &config_) },
               "ping");

    let config_ = config.clone();
    router.get("reserve",
               move |req: &mut Request| -> IronResult<Response> { reserve(req, &config_) },
               "reserve");

    router
}
<|endoftext|>


<commit_before>//! Running of programs.

use parser::Instruction;
use std;

///
/// A runner of programs.
///
#[derive(Default)]
pub struct Runner {
    /// Program to be run.
    prog: Vec<Instruction>,
    /// A potentially infinite number of data cells.
    data: Vec<u8>,
    /// Instruction pointer (index).
    ip: usize,
    /// Data-cell pointer (index).
    dp: usize,
}

impl Runner {
    ///
    /// Constructs a new runner.
    ///
    pub fn new() -> Self {
        Runner::default()
    }

    ///
    /// Runs the given program.
    ///
    /// # Arguments
    ///
    /// * `prog` - Program to be run.
    /// * `input` - Input for the program.
    /// * `output` - Output for the program.
    ///
    pub fn run(&mut self,
               prog: Vec<Instruction>,
               mut input: &mut std::io::Read,
               mut output: &mut std::io::Write)
               -> Result<(), String> {
        self.prog = prog;
        self.data.clear();
        self.ip = 0;
        self.dp = 0;

        while !self.is_prog_end() {
            try!(self.run_instruction(&mut input, &mut output));
        }

        Ok(())
    }

    fn is_prog_end(&self) -> bool {
        self.ip >= self.prog.len()
    }

    fn run_instruction(&mut self,
                       mut input: &mut std::io::Read,
                       mut output: &mut std::io::Write)
                       -> Result<(), String> {
        match self.prog[self.ip] {
            Instruction::Next => {
                self.dp += 1;
            }
            Instruction::Prev => {
                self.dp -= 1;
            }
            Instruction::Inc => {
                let value = self.load_value();
                self.store_value(value.wrapping_add(1));
            }
            Instruction::Dec => {
                let value = self.load_value();
                self.store_value(value.wrapping_sub(1));
            }
            Instruction::Read => {
                let value = try!(self.read_value(&mut input));
                self.store_value(value);
            }
            Instruction::Write => {
                let value = self.load_value();
                try!(self.write_value(&mut output, value));
            }
            Instruction::LoopStart(loop_end_ip) => {
                if self.is_current_cell_zero() {
                    self.ip = loop_end_ip;
                }
            }
            Instruction::LoopEnd(loop_start_ip) => {
                if !self.is_current_cell_zero() {
                    self.ip = loop_start_ip;
                }
            }
        }
        self.ip += 1;
        Ok(())
    }

    fn load_value(&mut self) -> u8 {
        self.ensure_current_cell_is_accessible();
        self.data[self.dp]
    }

    fn store_value(&mut self, value: u8) {
        self.ensure_current_cell_is_accessible();
        self.data[self.dp] = value;
    }

    fn read_value(&self, mut input: &mut std::io::Read) -> Result<u8, String> {
        let mut buf = [0u8];
        match input.read_exact(&mut buf[..]) {
            Err(err) => Err(
                format!("reading of a value failed (reason: {})", err)
            ),
            Ok(_) => Ok(buf[0]),
        }
    }

    fn write_value(&self, mut output: &mut std::io::Write, value: u8) -> Result<(), String> {
        match output.write(&[value]) {
            Err(err) => Err(
                format!("writing of a value failed (reason: {})", err)
            ),
            Ok(_) => Ok(()),
        }
    }

    fn is_current_cell_zero(&mut self) -> bool {
        self.load_value() == 0
    }

    fn ensure_current_cell_is_accessible(&mut self) {
        let cell_count = self.data.len();
        if self.dp >= cell_count {
            for _ in 0..(self.dp - cell_count + 1) {
                self.data.push(0);
            }
        }
    }
}

///
/// Runs the given program.
///
/// # Arguments
///
/// * `prog` - Program to be run.
/// * `input` - Input for the program.
/// * `output` - Output for the program.
///
pub fn run(prog: Vec<Instruction>,
           mut input: &mut std::io::Read,
           mut output: &mut std::io::Write)
           -> Result<(), String> {
    let mut runner = Runner::new();
    runner.run(prog, &mut input, &mut output)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std;
    use parser::Instruction;

    fn assert_run_writes_correct_output(prog: Vec<Instruction>,
                                        input: &[u8],
                                        expected_output: &[u8]) {
        let mut output = Vec::new();
        {
            let mut input_reader = std::io::BufReader::new(input.as_ref());
            let mut output_writer = std::io::BufWriter::new(&mut output);
            run(prog, &mut input_reader, &mut output_writer).unwrap();
        }

        assert_eq!(output, expected_output);
    }

    #[test]
    fn test_run_does_nothing_when_program_has_no_instructions() {
        assert_run_writes_correct_output(
            vec![],
            &[],
            &[]
        );
    }

    #[test]
    fn test_run_can_read_from_input_and_write_to_output() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Write
            ],
            &[1],
            &[1]
        );
    }

    #[test]
    fn test_run_can_increment_cell() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Inc,
                Instruction::Write,
            ],
            &[1],
            &[2]
        );
    }

    #[test]
    fn test_run_can_decrement_cell() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Dec,
                Instruction::Write,
            ],
            &[1],
            &[0]
        );
    }

    #[test]
    fn test_run_can_move_between_cells() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Next,
                Instruction::Read,
                Instruction::Next,
                Instruction::Prev,
                Instruction::Write,
                Instruction::Prev,
                Instruction::Write,
            ],
            &[1, 2],
            &[2, 1]
        );
    }

    #[test]
    fn test_run_can_loop() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::LoopStart(6),
                Instruction::Dec,
                Instruction::Next,
                Instruction::Inc,
                Instruction::Prev,
                Instruction::LoopEnd(1),
                Instruction::Write,
                Instruction::Next,
                Instruction::Write
            ],
            &[2],
            &[0, 2]
        );
    }
}
<commit_msg>Simplify passing of a buffer to read_exact().<commit_after>//! Running of programs.

use parser::Instruction;
use std;

///
/// A runner of programs.
///
#[derive(Default)]
pub struct Runner {
    /// Program to be run.
    prog: Vec<Instruction>,
    /// A potentially infinite number of data cells.
    data: Vec<u8>,
    /// Instruction pointer (index).
    ip: usize,
    /// Data-cell pointer (index).
    dp: usize,
}

impl Runner {
    ///
    /// Constructs a new runner.
    ///
    pub fn new() -> Self {
        Runner::default()
    }

    ///
    /// Runs the given program.
    ///
    /// # Arguments
    ///
    /// * `prog` - Program to be run.
    /// * `input` - Input for the program.
    /// * `output` - Output for the program.
    ///
    pub fn run(&mut self,
               prog: Vec<Instruction>,
               mut input: &mut std::io::Read,
               mut output: &mut std::io::Write)
               -> Result<(), String> {
        self.prog = prog;
        self.data.clear();
        self.ip = 0;
        self.dp = 0;

        while !self.is_prog_end() {
            try!(self.run_instruction(&mut input, &mut output));
        }

        Ok(())
    }

    fn is_prog_end(&self) -> bool {
        self.ip >= self.prog.len()
    }

    fn run_instruction(&mut self,
                       mut input: &mut std::io::Read,
                       mut output: &mut std::io::Write)
                       -> Result<(), String> {
        match self.prog[self.ip] {
            Instruction::Next => {
                self.dp += 1;
            }
            Instruction::Prev => {
                self.dp -= 1;
            }
            Instruction::Inc => {
                let value = self.load_value();
                self.store_value(value.wrapping_add(1));
            }
            Instruction::Dec => {
                let value = self.load_value();
                self.store_value(value.wrapping_sub(1));
            }
            Instruction::Read => {
                let value = try!(self.read_value(&mut input));
                self.store_value(value);
            }
            Instruction::Write => {
                let value = self.load_value();
                try!(self.write_value(&mut output, value));
            }
            Instruction::LoopStart(loop_end_ip) => {
                if self.is_current_cell_zero() {
                    self.ip = loop_end_ip;
                }
            }
            Instruction::LoopEnd(loop_start_ip) => {
                if !self.is_current_cell_zero() {
                    self.ip = loop_start_ip;
                }
            }
        }
        self.ip += 1;
        Ok(())
    }

    fn load_value(&mut self) -> u8 {
        self.ensure_current_cell_is_accessible();
        self.data[self.dp]
    }

    fn store_value(&mut self, value: u8) {
        self.ensure_current_cell_is_accessible();
        self.data[self.dp] = value;
    }

    fn read_value(&self, mut input: &mut std::io::Read) -> Result<u8, String> {
        let mut buf = [0u8];
        match input.read_exact(&mut buf) {
            Err(err) => Err(
                format!("reading of a value failed (reason: {})", err)
            ),
            Ok(_) => Ok(buf[0]),
        }
    }

    fn write_value(&self, mut output: &mut std::io::Write, value: u8) -> Result<(), String> {
        match output.write(&[value]) {
            Err(err) => Err(
                format!("writing of a value failed (reason: {})", err)
            ),
            Ok(_) => Ok(()),
        }
    }

    fn is_current_cell_zero(&mut self) -> bool {
        self.load_value() == 0
    }

    fn ensure_current_cell_is_accessible(&mut self) {
        let cell_count = self.data.len();
        if self.dp >= cell_count {
            for _ in 0..(self.dp - cell_count + 1) {
                self.data.push(0);
            }
        }
    }
}

///
/// Runs the given program.
///
/// # Arguments
///
/// * `prog` - Program to be run.
/// * `input` - Input for the program.
/// * `output` - Output for the program.
///
pub fn run(prog: Vec<Instruction>,
           mut input: &mut std::io::Read,
           mut output: &mut std::io::Write)
           -> Result<(), String> {
    let mut runner = Runner::new();
    runner.run(prog, &mut input, &mut output)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std;
    use parser::Instruction;

    fn assert_run_writes_correct_output(prog: Vec<Instruction>,
                                        input: &[u8],
                                        expected_output: &[u8]) {
        let mut output = Vec::new();
        {
            let mut input_reader = std::io::BufReader::new(input.as_ref());
            let mut output_writer = std::io::BufWriter::new(&mut output);
            run(prog, &mut input_reader, &mut output_writer).unwrap();
        }

        assert_eq!(output, expected_output);
    }

    #[test]
    fn test_run_does_nothing_when_program_has_no_instructions() {
        assert_run_writes_correct_output(
            vec![],
            &[],
            &[]
        );
    }

    #[test]
    fn test_run_can_read_from_input_and_write_to_output() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Write
            ],
            &[1],
            &[1]
        );
    }

    #[test]
    fn test_run_can_increment_cell() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Inc,
                Instruction::Write,
            ],
            &[1],
            &[2]
        );
    }

    #[test]
    fn test_run_can_decrement_cell() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Dec,
                Instruction::Write,
            ],
            &[1],
            &[0]
        );
    }

    #[test]
    fn test_run_can_move_between_cells() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::Next,
                Instruction::Read,
                Instruction::Next,
                Instruction::Prev,
                Instruction::Write,
                Instruction::Prev,
                Instruction::Write,
            ],
            &[1, 2],
            &[2, 1]
        );
    }

    #[test]
    fn test_run_can_loop() {
        assert_run_writes_correct_output(
            vec![
                Instruction::Read,
                Instruction::LoopStart(6),
                Instruction::Dec,
                Instruction::Next,
                Instruction::Inc,
                Instruction::Prev,
                Instruction::LoopEnd(1),
                Instruction::Write,
                Instruction::Next,
                Instruction::Write
            ],
            &[2],
            &[0, 2]
        );
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::net::UdpSocket;
use std::str;

// Content of the request.
const SEARCH_REQUEST: &'static str =
"M-SEARCH * HTTP/1.1\r
Host:239.255.255.250:1900\r
ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r
Man:\"ssdp:discover\"\r
MX:3\r\n\r\n";

// Error type this module emits.
#[derive(Debug)]
pub enum SearchError {
    IoError(io::Error),
    InvalidResponse,
}

impl From<io::Error> for SearchError {
    fn from(err: io::Error) -> SearchError {
        SearchError::IoError(err)
    }
}

// Try to find the gateway on the local network.
// Bind to the given interface.
pub fn search_gateway_from(ip: Ipv4Addr) -> Result<SocketAddrV4, SearchError> {
    let addr = SocketAddrV4::new(ip, 1900);
    let socket = try!(UdpSocket::bind(addr));

    // send the request on the broadcast address
    try!(socket.send_to(SEARCH_REQUEST.as_bytes(), "239.255.255.250:1900"));
    let mut buf = [0u8; 1024];
    let (read, _) = try!(socket.recv_from(&mut buf));
    let text = str::from_utf8(&buf[..read]).unwrap();
    match parse_result(text) {
        None => Err(SearchError::InvalidResponse),
        Some(socketaddr) => Ok(socketaddr),
    }
}

// Try to find the gateway on the local network.
// Bind to all interfaces.
pub fn search_gateway() -> Result<SocketAddrV4, SearchError> {
    search_gateway_from(Ipv4Addr::new(0, 0, 0, 0))
}

// Parse the result.
fn parse_result(text: &str) -> Option<SocketAddrV4> {
    let re = regex!(r"(?i:Location):\s*http://(\d+\.\d+\.\d+\.\d+):(\d+).*");
    for line in text.lines() {
        match re.captures(line) {
            None => continue,
            Some(cap) => {
                // these shouldn't fail if the regex matched.
                let addr = cap.at(1).unwrap();
                let port = cap.at(2).unwrap();
                return Some(SocketAddrV4::new(
                    addr.parse::<Ipv4Addr>().unwrap(),
                    port.parse::<u16>().unwrap()
                ));
            },
        }
    }
    None
}

#[test]
fn test_parse_result_case_insensitivity() {
    assert!(parse_result("location:http://0.0.0.0:0").is_some());
    assert!(parse_result("LOCATION:http://0.0.0.0:0").is_some());
}
<commit_msg>use non-fixed number for local udp port<commit_after>use std::io;
use std::net::{Ipv4Addr, SocketAddrV4};
use std::net::UdpSocket;
use std::str;

// Content of the request.
const SEARCH_REQUEST: &'static str =
"M-SEARCH * HTTP/1.1\r
Host:239.255.255.250:1900\r
ST:urn:schemas-upnp-org:device:InternetGatewayDevice:1\r
Man:\"ssdp:discover\"\r
MX:3\r\n\r\n";

// Error type this module emits.
#[derive(Debug)]
pub enum SearchError {
    IoError(io::Error),
    InvalidResponse,
}

impl From<io::Error> for SearchError {
    fn from(err: io::Error) -> SearchError {
        SearchError::IoError(err)
    }
}

// Try to find the gateway on the local network.
// Bind to the given interface.
pub fn search_gateway_from(ip: Ipv4Addr) -> Result<SocketAddrV4, SearchError> {
    let addr = SocketAddrV4::new(ip, 0);
    let socket = try!(UdpSocket::bind(addr));

    // send the request on the broadcast address
    try!(socket.send_to(SEARCH_REQUEST.as_bytes(), "239.255.255.250:1900"));
    let mut buf = [0u8; 1024];
    let (read, _) = try!(socket.recv_from(&mut buf));
    let text = str::from_utf8(&buf[..read]).unwrap();
    match parse_result(text) {
        None => Err(SearchError::InvalidResponse),
        Some(socketaddr) => Ok(socketaddr),
    }
}

// Try to find the gateway on the local network.
// Bind to all interfaces.
pub fn search_gateway() -> Result<SocketAddrV4, SearchError> {
    search_gateway_from(Ipv4Addr::new(0, 0, 0, 0))
}

// Parse the result.
fn parse_result(text: &str) -> Option<SocketAddrV4> {
    let re = regex!(r"(?i:Location):\s*http://(\d+\.\d+\.\d+\.\d+):(\d+).*");
    for line in text.lines() {
        match re.captures(line) {
            None => continue,
            Some(cap) => {
                // these shouldn't fail if the regex matched.
                let addr = cap.at(1).unwrap();
                let port = cap.at(2).unwrap();
                return Some(SocketAddrV4::new(
                    addr.parse::<Ipv4Addr>().unwrap(),
                    port.parse::<u16>().unwrap()
                ));
            },
        }
    }
    None
}

#[test]
fn test_parse_result_case_insensitivity() {
    assert!(parse_result("location:http://0.0.0.0:0").is_some());
    assert!(parse_result("LOCATION:http://0.0.0.0:0").is_some());
}
<|endoftext|>