<commit_before>use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Instruction {
    NOP,
    MOV { src: Operand, dst: Operand },
    SWP,
    SAV,
    ADD { addend: Operand },
    SUB { subtrahend: Operand} ,
    NEG,
    J { cond: Condition, dst: Label},
    JRO { dst: Operand },
}

pub static BAD_OPCODE_ERR: &'static str = "Bad opcode for # of arguments";
pub static NUM_ARGS_ERR: &'static str = "Wrong number of arguments";
pub static LIT_DST_ERR: &'static str = "Literal not allowed as dst operand";

impl FromStr for Instruction {
    type Err = &'static str;

    fn from_str(insn: &str) -> Result<Instruction, Self::Err> {
        //Nightly: let words: Vec<&str> = insn.split_whitespace().collect();
        let words: Vec<&str> = insn.split(' ').filter(|s| *s != "").collect();

        match words.len() {
            1 => match words[0] {
                "NOP" => Ok(Instruction::NOP),
                "SWP" => Ok(Instruction::SWP),
                "SAV" => Ok(Instruction::SAV),
                "NEG" => Ok(Instruction::NEG),
                _ => Err(BAD_OPCODE_ERR),
            },

            2 => match words[0] {
                "ADD" => Operand::from_str(words[1]).map(|o| Instruction::ADD { addend: o }),
                "SUB" => Operand::from_str(words[1]).map(|o| Instruction::SUB { subtrahend: o }),
                "JMP" => Ok(Instruction::J { cond: Condition::Unconditional, dst: words[1].to_string() }),
                "JEZ" => Ok(Instruction::J { cond: Condition::Ez,            dst: words[1].to_string() }),
                "JNZ" => Ok(Instruction::J { cond: Condition::Nz,            dst: words[1].to_string() }),
                "JGZ" => Ok(Instruction::J { cond: Condition::Gz,            dst: words[1].to_string() }),
                "JLZ" => Ok(Instruction::J { cond: Condition::Lz,            dst: words[1].to_string() }),
                "JRO" => Operand::from_str(words[1]).map(|o| Instruction::JRO { dst: o }),
                _ => Err(BAD_OPCODE_ERR),
            },

            3 => match words[0] {
                "MOV" => Operand::from_str(words[1]).and_then(|s| Operand::from_str(words[2])
                    .and_then(|d| match d {
                        Operand::Lit(_) => Err(LIT_DST_ERR),
                        _ => Ok(Instruction::MOV { src: s, dst: d })
                        })),
                _ => Err(BAD_OPCODE_ERR),
            },

            _ => Err(NUM_ARGS_ERR)
        }
    }
}

#[test]
fn instruction_from_str() {
    fn i(s: &str) -> Instruction {
        Instruction::from_str(s).unwrap()
    }
    assert_eq!(i("NOP"), Instruction::NOP);
    assert_eq!(i("SWP"), Instruction::SWP);
    assert_eq!(i("SAV"), Instruction::SAV);
    assert_eq!(i("NEG"), Instruction::NEG);
    assert_eq!(Instruction::from_str("BOGUS").unwrap_err(), BAD_OPCODE_ERR);

    assert_eq!(i("ADD 10"), Instruction::ADD { addend: Operand::Lit(10) });
    assert_eq!(i("SUB 10"), Instruction::SUB { subtrahend: Operand::Lit(10) });
    assert_eq!(i("JMP LOC"), Instruction::J { cond: Condition::Unconditional,   dst: "LOC".to_string() });
    assert_eq!(i("JEZ LOC"), Instruction::J { cond: Condition::Ez,              dst: "LOC".to_string() });
    assert_eq!(i("JNZ LOC"), Instruction::J { cond: Condition::Nz,              dst: "LOC".to_string() });
    assert_eq!(i("JGZ LOC"), Instruction::J { cond: Condition::Gz,              dst: "LOC".to_string() });
    assert_eq!(i("JLZ LOC"), Instruction::J { cond: Condition::Lz,              dst: "LOC".to_string() });
    assert_eq!(i("JRO 1"), Instruction::JRO { dst: Operand::Lit(1) });
    assert_eq!(Instruction::from_str("JEQ LOC").unwrap_err(), BAD_OPCODE_ERR);

    assert_eq!(i("MOV UP DOWN"),    Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
    assert_eq!(i("MOV  UP  DOWN"),  Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
    assert_eq!(i("MOV UP ACC"),     Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::ACC });
    assert_eq!(i("MOV ACC ACC"),    Instruction::MOV { src: Operand::ACC, dst: Operand::ACC });
    assert_eq!(Instruction::from_str("MV UP ACC").unwrap_err(), BAD_OPCODE_ERR);
    assert_eq!(Instruction::from_str("MOV UP 10").unwrap_err(), LIT_DST_ERR);

    assert_eq!(Instruction::from_str("1 2 3 4").unwrap_err(), NUM_ARGS_ERR);
}

#[derive(Clone, Debug, PartialEq)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
}

impl FromStr for Port {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UP" => Ok(Port::Up),
            "DOWN" => Ok(Port::Down),
            "LEFT" => Ok(Port::Left),
            "RIGHT" => Ok(Port::Right),
            _ => Err("bad port"),
        }
    }
}

#[test]
fn port_from_str() {
    assert_eq!(Port::from_str("UP").unwrap(),   Port::Up);
    assert_eq!(Port::from_str("DOWN").unwrap(), Port::Down);
    assert_eq!(Port::from_str("LEFT").unwrap(), Port::Left);
    assert_eq!(Port::from_str("RIGHT").unwrap(), Port::Right);
    assert_eq!(Port::from_str("OTHER").unwrap_err(), "bad port");
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Lit(i32),
    Port(Port),
    ACC,
}

impl FromStr for Operand {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "ACC" {
            Ok(Operand::ACC)
        } else if let Ok(as_int) = i32::from_str(s) {
            Ok(Operand::Lit(as_int))
        } else if let Ok(as_port) = Port::from_str(s) {
            Ok(Operand::Port(as_port))
        } else {
            Err("Invalid operand")
        }
    }
}

#[test]
fn operand_from_str() {
    assert_eq!(Operand::from_str("ACC").unwrap(), Operand::ACC);
    assert_eq!(Operand::from_str("32").unwrap(), Operand::Lit(32));
    assert_eq!(Operand::from_str("UP").unwrap(), Operand::Port(Port::Up));
    assert_eq!(Operand::from_str("FOO").unwrap_err(), "Invalid operand");
}

#[derive(Debug, PartialEq)]
pub enum Condition {
    Unconditional,
    Ez,
    Nz,
    Gz,
    Lz,
}

pub type Label = String;
<commit_msg>instruction: organize tests<commit_after>use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Instruction {
    NOP,
    MOV { src: Operand, dst: Operand },
    SWP,
    SAV,
    ADD { addend: Operand },
    SUB { subtrahend: Operand} ,
    NEG,
    J { cond: Condition, dst: Label},
    JRO { dst: Operand },
}

pub static BAD_OPCODE_ERR: &'static str = "Bad opcode for # of arguments";
pub static NUM_ARGS_ERR: &'static str = "Wrong number of arguments";
pub static LIT_DST_ERR: &'static str = "Literal not allowed as dst operand";

impl FromStr for Instruction {
    type Err = &'static str;

    fn from_str(insn: &str) -> Result<Instruction, Self::Err> {
        //Nightly: let words: Vec<&str> = insn.split_whitespace().collect();
        let words: Vec<&str> = insn.split(' ').filter(|s| *s != "").collect();

        match words.len() {
            1 => match words[0] {
                "NOP" => Ok(Instruction::NOP),
                "SWP" => Ok(Instruction::SWP),
                "SAV" => Ok(Instruction::SAV),
                "NEG" => Ok(Instruction::NEG),
                _ => Err(BAD_OPCODE_ERR),
            },

            2 => match words[0] {
                "ADD" => Operand::from_str(words[1]).map(|o| Instruction::ADD { addend: o }),
                "SUB" => Operand::from_str(words[1]).map(|o| Instruction::SUB { subtrahend: o }),
                "JMP" => Ok(Instruction::J { cond: Condition::Unconditional, dst: words[1].to_string() }),
                "JEZ" => Ok(Instruction::J { cond: Condition::Ez,            dst: words[1].to_string() }),
                "JNZ" => Ok(Instruction::J { cond: Condition::Nz,            dst: words[1].to_string() }),
                "JGZ" => Ok(Instruction::J { cond: Condition::Gz,            dst: words[1].to_string() }),
                "JLZ" => Ok(Instruction::J { cond: Condition::Lz,            dst: words[1].to_string() }),
                "JRO" => Operand::from_str(words[1]).map(|o| Instruction::JRO { dst: o }),
                _ => Err(BAD_OPCODE_ERR),
            },

            3 => match words[0] {
                "MOV" => Operand::from_str(words[1]).and_then(|s| Operand::from_str(words[2])
                    .and_then(|d| match d {
                        Operand::Lit(_) => Err(LIT_DST_ERR),
                        _ => Ok(Instruction::MOV { src: s, dst: d })
                        })),
                _ => Err(BAD_OPCODE_ERR),
            },

            _ => Err(NUM_ARGS_ERR)
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Port {
    Up,
    Down,
    Left,
    Right,
}

impl FromStr for Port {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "UP" => Ok(Port::Up),
            "DOWN" => Ok(Port::Down),
            "LEFT" => Ok(Port::Left),
            "RIGHT" => Ok(Port::Right),
            _ => Err("bad port"),
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Operand {
    Lit(i32),
    Port(Port),
    ACC,
}

impl FromStr for Operand {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        if s == "ACC" {
            Ok(Operand::ACC)
        } else if let Ok(as_int) = i32::from_str(s) {
            Ok(Operand::Lit(as_int))
        } else if let Ok(as_port) = Port::from_str(s) {
            Ok(Operand::Port(as_port))
        } else {
            Err("Invalid operand")
        }
    }
}

#[derive(Debug, PartialEq)]
pub enum Condition {
    Unconditional,
    Ez,
    Nz,
    Gz,
    Lz,
}

pub type Label = String;

#[cfg(test)]
mod tests {
    use super::{Condition, Instruction, Operand, Port};
    use super::{BAD_OPCODE_ERR,NUM_ARGS_ERR, LIT_DST_ERR};
    use std::str::FromStr;

    #[test]
    fn port_from_str() {
        assert_eq!(Port::from_str("UP").unwrap(),   Port::Up);
        assert_eq!(Port::from_str("DOWN").unwrap(), Port::Down);
        assert_eq!(Port::from_str("LEFT").unwrap(), Port::Left);
        assert_eq!(Port::from_str("RIGHT").unwrap(), Port::Right);
        assert_eq!(Port::from_str("OTHER").unwrap_err(), "bad port");
    }

    #[test]
    fn operand_from_str() {
        assert_eq!(Operand::from_str("ACC").unwrap(), Operand::ACC);
        assert_eq!(Operand::from_str("32").unwrap(), Operand::Lit(32));
        assert_eq!(Operand::from_str("UP").unwrap(), Operand::Port(Port::Up));
        assert_eq!(Operand::from_str("FOO").unwrap_err(), "Invalid operand");
    }

    #[test]
    fn instruction_from_str() {
        fn i(s: &str) -> Instruction {
            Instruction::from_str(s).unwrap()
        }
        assert_eq!(i("NOP"), Instruction::NOP);
        assert_eq!(i("SWP"), Instruction::SWP);
        assert_eq!(i("SAV"), Instruction::SAV);
        assert_eq!(i("NEG"), Instruction::NEG);
        assert_eq!(Instruction::from_str("BOGUS").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("ADD 10"), Instruction::ADD { addend: Operand::Lit(10) });
        assert_eq!(i("SUB 10"), Instruction::SUB { subtrahend: Operand::Lit(10) });
        assert_eq!(i("JMP LOC"), Instruction::J { cond: Condition::Unconditional,   dst: "LOC".to_string() });
        assert_eq!(i("JEZ LOC"), Instruction::J { cond: Condition::Ez,              dst: "LOC".to_string() });
        assert_eq!(i("JNZ LOC"), Instruction::J { cond: Condition::Nz,              dst: "LOC".to_string() });
        assert_eq!(i("JGZ LOC"), Instruction::J { cond: Condition::Gz,              dst: "LOC".to_string() });
        assert_eq!(i("JLZ LOC"), Instruction::J { cond: Condition::Lz,              dst: "LOC".to_string() });
        assert_eq!(i("JRO 1"), Instruction::JRO { dst: Operand::Lit(1) });
        assert_eq!(Instruction::from_str("JEQ LOC").unwrap_err(), BAD_OPCODE_ERR);

        assert_eq!(i("MOV UP DOWN"),    Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV  UP  DOWN"),  Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::Port(Port::Down) });
        assert_eq!(i("MOV UP ACC"),     Instruction::MOV { src: Operand::Port(Port::Up), dst: Operand::ACC });
        assert_eq!(i("MOV ACC ACC"),    Instruction::MOV { src: Operand::ACC, dst: Operand::ACC });
        assert_eq!(Instruction::from_str("MV UP ACC").unwrap_err(), BAD_OPCODE_ERR);
        assert_eq!(Instruction::from_str("MOV UP 10").unwrap_err(), LIT_DST_ERR);

        assert_eq!(Instruction::from_str("1 2 3 4").unwrap_err(), NUM_ARGS_ERR);
    }
}
<|endoftext|>


<commit_before>//! Extracts JSON data by interpreting a JMESPath AST

extern crate rustc_serialize;

use self::rustc_serialize::json::Json;
use std::collections::BTreeMap;

use ast::Ast;
use utils;

pub fn interpret(data: &Json, node: &Ast) -> Result<Json, String> {
    match node {
        &Ast::CurrentNode => Ok(data.clone()),
        &Ast::Literal(ref json) => Ok(json.clone()),
        &Ast::Subexpr(ref lhs, ref rhs) => {
            let result = try!(interpret(data, lhs));
            interpret(&result, rhs)
        },
        &Ast::Identifier(ref f) => {
            match data.find(f) {
                Some(j) => Ok(j.clone()),
                _ => Ok(Json::Null)
            }
        },
        &Ast::Index(ref i) => {
            match data.as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let result = if *i >= 0 {
                        a.get(*i as usize)
                    } else {
                        utils::negative_offset(a, i)
                    };
                    match result {
                        Some(result) => Ok(result.clone()),
                        None => Ok(Json::Null)
                    }
                }
            }
        },
        &Ast::Or(ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            if utils::is_truthy(&left) {
                Ok(left)
            } else {
                interpret(data, rhs)
            }
        },
        // Returns the resut of RHS if cond yields truthy value.
        &Ast::Condition(ref cond, ref cond_rhs) => {
            let cond_result = try!(interpret(data, cond));
            if utils::is_truthy(&cond_result) {
                interpret(data, cond_rhs)
            } else {
                Ok(Json::Null)
            }
        },
        &Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            let right = try!(interpret(data, rhs));
            Ok(utils::comparison(cmp, &left, &right))
        },
        // Converts an object into a JSON array of its values.
        &Ast::ObjectValues(ref predicate) => {
            let result = try!(interpret(data, predicate));
            Ok(utils::object_to_array(&result))
        },
        // Passes the results of lhs into rhs if lhs yields an array and
        // each node of lhs that passes through rhs yields a non-null value.
        &Ast::Projection(ref lhs, ref rhs) => {
            match try!(interpret(data, lhs)).as_array() {
                None => Ok(Json::Null),
                Some(left) => {
                    let mut collected = vec!();
                    for element in left {
                        let current = try!(interpret(element, rhs));
                        if !current.is_null() {
                            collected.push(current);
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::Flatten(ref node) => {
            match try!(interpret(data, node)).as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let mut collected = vec!();
                    for element in a {
                        match element {
                            &Json::Array(ref a) => collected.extend(a.iter().cloned()),
                            _ => collected.push(element.clone())
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::MultiList(ref nodes) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = vec!();
            for node in nodes {
                collected.push(try!(interpret(data, node)));
            }
            Ok(Json::Array(collected))
        },
        &Ast::MultiHash(ref kvp_list) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = BTreeMap::new();
            for kvp in kvp_list {
                let key = try!(interpret(data, &kvp.key));
                let value = try!(interpret(data, &kvp.value));
                collected.insert(key.as_string().unwrap().to_string(), value);
            }
            Ok(Json::Object(collected))
        },
        ref node @ _ => panic!(format!("not implemented yet: {:?}", node))
    }
}

#[cfg(test)]
mod tests {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator};

    #[test] fn interprets_identifier() {
        let ast = Ast::Identifier("foo".to_string());
        let data = Json::from_str("{\"foo\":\"baz\"}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_current_node() {
        let ast = Ast::CurrentNode;
        let data = Json::Boolean(true);
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_literal() {
        let ast = Ast::Literal(Json::Boolean(true));
        let data = Json::from_str("{}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_subexpr() {
        let ast = Ast::Subexpr(Box::new(Ast::Identifier("foo".to_string())),
                               Box::new(Ast::Identifier("bar".to_string())));
        let data = Json::from_str("{\"foo\":{\"bar\":\"baz\"}}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index_when_not_array_as_null() {
        let ast = Ast::Index(1);
        let data = Json::String("foo".to_string());
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or_expr() {
        let ast = Ast::Or(Box::new(Ast::Identifier("bar".to_string())),
                          Box::new(Ast::Identifier("foo".to_string())));
        let data = Json::from_str("{\"foo\":true}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(true))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::String("foo".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr_negative() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(false))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_comparison() {
        // Left, right, result, comparator.
        let cases = vec!(vec!["true", "true", "true", "=="],
                         vec!["true", "false", "false", "=="],
                         vec!["true", "null", "false", "=="],
                         vec!["null", "null", "true", "=="],
                         vec!["10", "20", "false", ">"],
                         vec!["10", "20", "true", "<"]);
        for test_case in cases {
            let cmp = match test_case[3] {
                "==" => Comparator::Eq,
                ">" => Comparator::Gt,
                _ => Comparator::Lt,
            };
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Literal(Json::from_str(test_case[0]).unwrap())),
                Box::new(Ast::Literal(Json::from_str(test_case[1]).unwrap())));
            let result = Json::from_str(test_case[2]).unwrap();
            assert_eq!(result, interpret(&Json::Null, &ast).unwrap());
        }
    }
}
<commit_msg>Adding comparison tests<commit_after>//! Extracts JSON data by interpreting a JMESPath AST

extern crate rustc_serialize;

use self::rustc_serialize::json::Json;
use std::collections::BTreeMap;

use ast::Ast;
use utils;

pub fn interpret(data: &Json, node: &Ast) -> Result<Json, String> {
    match node {
        &Ast::CurrentNode => Ok(data.clone()),
        &Ast::Literal(ref json) => Ok(json.clone()),
        &Ast::Subexpr(ref lhs, ref rhs) => {
            let result = try!(interpret(data, lhs));
            interpret(&result, rhs)
        },
        &Ast::Identifier(ref f) => {
            match data.find(f) {
                Some(j) => Ok(j.clone()),
                _ => Ok(Json::Null)
            }
        },
        &Ast::Index(ref i) => {
            match data.as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let result = if *i >= 0 {
                        a.get(*i as usize)
                    } else {
                        utils::negative_offset(a, i)
                    };
                    match result {
                        Some(result) => Ok(result.clone()),
                        None => Ok(Json::Null)
                    }
                }
            }
        },
        &Ast::Or(ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            if utils::is_truthy(&left) {
                Ok(left)
            } else {
                interpret(data, rhs)
            }
        },
        // Returns the resut of RHS if cond yields truthy value.
        &Ast::Condition(ref cond, ref cond_rhs) => {
            let cond_result = try!(interpret(data, cond));
            if utils::is_truthy(&cond_result) {
                interpret(data, cond_rhs)
            } else {
                Ok(Json::Null)
            }
        },
        &Ast::Comparison(ref cmp, ref lhs, ref rhs) => {
            let left = try!(interpret(data, lhs));
            let right = try!(interpret(data, rhs));
            Ok(utils::comparison(cmp, &left, &right))
        },
        // Converts an object into a JSON array of its values.
        &Ast::ObjectValues(ref predicate) => {
            let result = try!(interpret(data, predicate));
            Ok(utils::object_to_array(&result))
        },
        // Passes the results of lhs into rhs if lhs yields an array and
        // each node of lhs that passes through rhs yields a non-null value.
        &Ast::Projection(ref lhs, ref rhs) => {
            match try!(interpret(data, lhs)).as_array() {
                None => Ok(Json::Null),
                Some(left) => {
                    let mut collected = vec!();
                    for element in left {
                        let current = try!(interpret(element, rhs));
                        if !current.is_null() {
                            collected.push(current);
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::Flatten(ref node) => {
            match try!(interpret(data, node)).as_array() {
                None => Ok(Json::Null),
                Some(a) => {
                    let mut collected = vec!();
                    for element in a {
                        match element {
                            &Json::Array(ref a) => collected.extend(a.iter().cloned()),
                            _ => collected.push(element.clone())
                        }
                    }
                    Ok(Json::Array(collected))
                }
            }
        },
        &Ast::MultiList(ref nodes) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = vec!();
            for node in nodes {
                collected.push(try!(interpret(data, node)));
            }
            Ok(Json::Array(collected))
        },
        &Ast::MultiHash(ref kvp_list) => {
            if data.is_null() {
                return Ok(Json::Null);
            }
            let mut collected = BTreeMap::new();
            for kvp in kvp_list {
                let key = try!(interpret(data, &kvp.key));
                let value = try!(interpret(data, &kvp.value));
                collected.insert(key.as_string().unwrap().to_string(), value);
            }
            Ok(Json::Object(collected))
        },
        ref node @ _ => panic!(format!("not implemented yet: {:?}", node))
    }
}

#[cfg(test)]
mod tests {
    extern crate rustc_serialize;
    use self::rustc_serialize::json::Json;
    use super::*;
    use ast::{Ast, Comparator};

    #[test] fn interprets_identifier() {
        let ast = Ast::Identifier("foo".to_string());
        let data = Json::from_str("{\"foo\":\"baz\"}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_current_node() {
        let ast = Ast::CurrentNode;
        let data = Json::Boolean(true);
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_literal() {
        let ast = Ast::Literal(Json::Boolean(true));
        let data = Json::from_str("{}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_subexpr() {
        let ast = Ast::Subexpr(Box::new(Ast::Identifier("foo".to_string())),
                               Box::new(Ast::Identifier("bar".to_string())));
        let data = Json::from_str("{\"foo\":{\"bar\":\"baz\"}}").unwrap();
        assert_eq!(Json::String("baz".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index() {
        let data = Json::Array(vec!(Json::Boolean(false), Json::Boolean(true)));
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(-1)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(-2)).unwrap());
        assert_eq!(Json::Boolean(false), interpret(&data, &Ast::Index(0)).unwrap());
        assert_eq!(Json::Boolean(true), interpret(&data, &Ast::Index(1)).unwrap());
    }

    #[test] fn interprets_index_when_not_array_as_null() {
        let ast = Ast::Index(1);
        let data = Json::String("foo".to_string());
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_or_expr() {
        let ast = Ast::Or(Box::new(Ast::Identifier("bar".to_string())),
                          Box::new(Ast::Identifier("foo".to_string())));
        let data = Json::from_str("{\"foo\":true}").unwrap();
        assert_eq!(Json::Boolean(true), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(true))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::String("foo".to_string()), interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_cond_expr_negative() {
        let ast = Ast::Condition(
            Box::new(Ast::Literal(Json::Boolean(false))),
            Box::new(Ast::Literal(Json::String("foo".to_string()))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_comparison() {
        // Left, right, result, comparator.
        let cases = vec!(vec!["true", "true", "true", "=="],
                         vec!["true", "false", "false", "=="],
                         vec!["true", "null", "false", "=="],
                         vec!["null", "null", "true", "=="],
                         vec!["10", "20", "false", ">"],
                         vec!["10", "20", "true", "<"]);
        for test_case in cases {
            let cmp = match test_case[3] {
                "==" => Comparator::Eq,
                ">" => Comparator::Gt,
                _ => Comparator::Lt,
            };
            let ast = Ast::Comparison(
                cmp,
                Box::new(Ast::Literal(Json::from_str(test_case[0]).unwrap())),
                Box::new(Ast::Literal(Json::from_str(test_case[1]).unwrap())));
            let result = Json::from_str(test_case[2]).unwrap();
            assert_eq!(result, interpret(&Json::Null, &ast).unwrap());
        }
    }

    #[test] fn interprets_object_values_negative() {
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(Json::Boolean(false))));
        let data = Json::Null;
        assert_eq!(Json::Null, interpret(&data, &ast).unwrap());
    }

    #[test] fn interprets_object_values_affirmative() {
        let json_value = Json::from_str("{\"foo\": \"bar\"}").unwrap();
        let ast = Ast::ObjectValues(Box::new(Ast::Literal(json_value)));
        let data = Json::Null;
        assert_eq!(Json::from_str("[\"bar\"]").unwrap(),
                   interpret(&data, &ast).unwrap());
    }
}
<|endoftext|>


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

plague! {
    for [ 1, 2 ]
    test fn foo(a: i32) {
        println!("{}", a);
    }
}

plague! {
    for [1 -> 2, 2 -> 4]
    test fn foo_ret(a: i32) -> i32 {
        2*a
    }
}

plague! {
    for [
        (1, 1),
        (2, 2),
    ]
    test fn fooes(a: i32, b: i32) {
        assert_eq!(a, b);
    }
}

plague! {
    for [ 1, 2 ]
    test! fn bar(a: i32) {
        panic!("{}", a);
    }
}

plague! {
    for [
        (1, 2),
        (2, 3),
    ]
    test! fn bars(a: i32, b: i32) {
        assert_eq!(a, b);
    }
}

fn baz(a: i32, b: i32) {
    assert_eq!(a, b-1);
}

plague! {
    for [(1, 2), (2, 3)] test baz
}

plague! {
    for [(1, 2), (2, 3)] test tests::qux
}

mod tests {
    pub fn qux(a: i32, b: i32) {
        assert_eq!(a, b-1);
    }
}

plague! {
    for [(&mut vec!["foo"], 1, "bar")] test Vec::insert
}
<commit_msg>More tests<commit_after>#![feature(plugin)]
#![plugin(plague)]

plague! {
    for [ 1, 2 ]
    test fn foo(a: i32) {
        println!("{}", a);
    }
}

plague! {
    for [1 -> 2, 2 -> 4]
    test fn foo_ret(a: i32) -> i32 {
        2*a
    }
}

plague! {
    for [
        (1, 1),
        (2, 2),
    ]
    test fn fooes(a: i32, b: i32) {
        assert_eq!(a, b);
    }
}

plague! {
    for [
        (1, 1) -> 2,
        (2, 3) -> 5,
    ]
    test fn fooes_ret(a: i32, b: i32) -> i32 {
        a + b
    }
}

plague! {
    for [ 1, 2 ]
    test! fn bar(a: i32) {
        panic!("{}", a);
    }
}

plague! {
    for [
        (1, 2),
        (2, 3),
    ]
    test! fn bars(a: i32, b: i32) {
        assert_eq!(a, b);
    }
}

fn baz(a: i32, b: i32) {
    assert_eq!(a, b-1);
}

plague! {
    for [(1, 2), (2, 3)] test baz
}

plague! {
    for [(1, 2), (2, 3)] test tests::qux
}

mod tests {
    pub fn qux(a: i32, b: i32) {
        assert_eq!(a, b-1);
    }
}

plague! {
    for [(&mut vec!["foo"], 1, "bar")] test Vec::insert
}

plague! {
    for [
        ("",) -> 0,
        ("foo",) -> 3,
        ("foo\u{0}bar",) -> 7,
    ]
    test str::len
}
<|endoftext|>


<commit_before>extern crate lichen;

use lichen::parse::{Parser,Block,SrcBlock,Map};
use lichen::{Logic,Expect};
use lichen::var::Var;
use lichen::source::{Src,Next};
use lichen::eval::{Eval,Evaluator};

use std::collections::HashMap;

struct Data;
impl Eval for Data {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        match lookup {
            "some_item" => {
                Some(false.into())
            },
            "other_item" => {
                Some(true.into())
            },
            "some_weight" => {
                Some(4.0 .into())
            },
            "other_weight" => {
                Some(5.0 .into())
            },
            "name" => {
                Some("Io".into())
            }
            _ => None
        }
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {}

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        None
    }
}

#[test]
fn parse_block() {
    let src = "root\n
    unequipped !some_item\n
    has_weight some_weight < 5.0\n
    some_comp:any [\nunequipped \nhas_weight\n]\n
\n
    if unequipped \"you're looking for something?\"\n
\n
    if all \"welcome, \nlook around\"\n
    next:now end\n
;";

    let block = Parser::parse_blocks(src);

    let block_ = [Block::Src(
        SrcBlock {
            await_idx: 0,
            visited: false,
            name: "root".to_owned(),
            src: vec![Src::Logic("unequipped".to_owned(),
                                 Logic::IsNot("some_item".to_owned())),

                      Src::Logic("has_weight".to_owned(),
                                 Logic::LT(Var::Sym("some_weight".to_owned()), 5.0 .into())),
                      Src::Composite("some_comp".to_owned(),
                                     Expect::Any,
                                     vec!["unequipped".to_owned(),"has_weight".to_owned()]),
                      Src::If(Expect::Ref("unequipped".to_owned()),
                              vec!["you're looking for something?".into()],
                              None),
                      Src::If(Expect::All,
                              vec!["welcome, \nlook around".into()],
                              None),
                      Src::Next(Next::Now("end".to_owned()))]
        })];

    assert_eq!(block[0],block_[0]);
}

#[test]
fn parse_qsym_block() {
    let src = "root\n
    if !some_item \"you're looking for something?\"\n
;";
    let block = Parser::parse_blocks(src);
    match &block[0] {
        &Block::Src(ref b) => {
            let r;
            match b.src[0] {
                Src::Logic(ref qsym,_) => { r = qsym; },
                _ => panic!("unknown source found")
            }

            match b.src[1] {
                Src::If(ref x,_,_) => {
                    match x {
                        &Expect::Ref(ref r_) => {
                            assert_eq!(r,r_);
                        },
                        _ => panic!("unknown expect found")
                    }
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn parse_qsym_comp_block() {
    let src =  "root\n
    has_weight some_weight < 5.0\n
    some_comp:any [has_weight !some_item ]\n
    ;";

    let block = Parser::parse_blocks(src);

    match &block[0] {
        &Block::Src(ref b) => {
            let r;
            match b.src[1] {
                Src::Logic(ref qsym,_) => { r = qsym; },
                _ => panic!("unknown source found")
            }

            match b.src[2] {
                Src::Composite(_,_,ref x) => {
                    assert_eq!(r,&x[1]);
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn validate_qsym_block() {
    let src =  "root\n
    if other_item next:await store\n
    ;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_,nn) = ev.next().unwrap();

    assert_eq!(nn, Some(Next::Await("store".into())));
}

#[test]
fn validate_reflection_block() {
    let src =  "root\n
    has other_item
    hasnt some_item
    hasnt-too !hasnt
    comp:all has hasnt-too
    if comp next:await store\n
    ;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_,nn) = ev.next().unwrap();

    assert_eq!(nn, Some(Next::Await("store".into())));
}

#[test]
fn parse_if_vec_block() {
    let src = "root\n
    if !some_item [\n
        \"you're looking for something?\"\n
        \"welcome, \nlook around\"\n
        next:now store]\n
;";

    let block = Parser::parse_blocks(src);

    match &block[0] {
        &Block::Src(ref b) => {
            match b.src[1] {
                Src::If(_,_, ref next) => {
                    assert_eq!(next,&Some(Next::Now("store".to_owned())));
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn parse_eval_str_block() {
    let src = "root\n
        has_weight some_weight < 5.0\n
        some_comp:all [has_weight !some_item ]\n
    if some_comp \"looks like you are `some_weight kgs heavy, `name\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_node) = ev.run("root");

    assert_eq!(vars, ["looks like you are 4 kgs heavy, Io".into()]);
}

#[test]
fn parse_compare_env_block() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight next:now store\n
;";
    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_vars,node) = ev.run("root");

    assert_eq!(node, Some(Next::Now("store".to_string())));
}

#[test]
fn parse_return_varkind() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight some_weight \"hi `name\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.run("root");

    assert_eq!(vars[0], 4.0 .into());
    assert_eq!(vars[1], "hi Io" .into());
}

#[test]
fn parse_follow_nodes() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight next:now store\n
;\n
\n
store\n
    if !some_item \"welcome, \nlook around\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    ev.next(); // runs root
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], "welcome, \nlook around".into());
}

#[test]
fn parse_select_nodes() {
    let src = "root\n
    next:select {\"Head to Store?\" store,\n
                \"Leave the town?\" exit-town}\n
\n
    if !some_item [\"Some choices\"
        next:select {\"Head to Store?\" store,\n
                    \"Leave the town?\" exit-town}]\n
\n
    next:select {\"Head to town?\" store bakery tanner,\n
                5 hike,
                \"Leave the town?\" exit-town}\n
\n
    emit \"A dustball blows by\"\n
;";
    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_vars,select1) = ev.next().unwrap();
    let (_vars,select2) = ev.next().unwrap();

    assert_eq!(select1,select2);

    let mut map: Map = HashMap::new();
    map.insert("Head to Store?".to_owned(), vec![Var::Sym("store".to_owned())]);
    map.insert("Leave the town?".to_owned(), vec![Var::Sym("exit-town".to_owned())]);

    assert_eq!(select1, Some(Next::Select(map)));

    let (_,select) = ev.next().unwrap();
    match select.expect("Unable to parse map") {
        Next::Select(map) => {
            println!("Map: {:?}",map);
            assert!(map.contains_key("5"));
            assert_eq!(map.get("5"), Some(&vec![Var::Sym("hike".to_owned())]));
        },
        _ => { panic!("Invalid Next type found") }
    }
}

// Test for mutable state
#[derive(Debug)]
struct Player {
    coins: f32,
    name: String
}
impl Eval for Player {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        if lookup == "coins" { Some(self.coins.into()) }
        else if lookup == "name" { Some(self.name.clone().into()) }
        else { None }
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {
        if lookup == "coins" {
            match var {
                Var::Num(n) => {
                    self.coins = n;
                },
                _ => {}
            }
        }
        else if lookup == "name" {
            match var {
                Var::String(s) => {
                    self.name = s;
                },
                _ => {}
            }
        }
    }

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        match fun {
            "inc" => {
                if let Ok(v) = Var::get_num(&var, self) {
                    let mut r = v;
                    for n in vars.iter() {
                        if let Ok(v) = Var::get_num(&n, self) {
                            r += v;
                        }
                    }

                    return Some(Var::Num(r))
                }
            },
            _ => { }
        }

        None
    }
}

#[test]
/// this test shows that all statements are processed in one Eval iteration
fn state_mut() {
    let src = "root\n
    @coins + 1\n
    emit \"step\"\n
    @coins 5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {
        let mut ev = Evaluator::new(&mut env, &mut data);
        let (_vars,_) = ev.next().unwrap();
    }

    assert_eq!(data.coins, 5.0);
}

#[test]
fn parse_cust_fn() {
    let src = "root\n
    @coins (inc) 1 2 3\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {
        let mut ev = Evaluator::new(&mut env, &mut data);
        let (_,_) = ev.next().unwrap();
    }

    assert_eq!(data.coins, 6.0);
}

#[test]
fn parse_def_block() {
    let src = "root\n
    emit global.name global.size\n
;\n
\n
def global\n
    name \"my-game\"\n
    size 1.5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], Var::String("my-game".to_owned()));
    assert_eq!(vars[1], Var::Num(1.5 .to_owned()));
}

#[test]
fn validate_def_block() {
    let src = "root\n
    @global.size + 0.5\n
    @global.name \"other-game\"\n
    @name global.name\n
    @coins - global.size\n
    emit [global.name global.size\n
         name coins]\n
;\n
\n
def global\n
    name \"my-game\"\n
    size 1.5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], Var::String("other-game".to_owned()));
    assert_eq!(vars[1], Var::Num(2.0 .to_owned()));

    assert_eq!(vars[2], Var::String("Pan".to_owned()));
    assert_eq!(vars[3], Var::Num(-2.0 .to_owned()));
}

#[test]
fn parse_with_block() {
    let src = "root\n
    needs_coins coins < 1
    has_name name
    with {needs_coins @coins + 2, \n
         has_name @name \"new-name\"}\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {let mut ev = Evaluator::new(&mut env, &mut data);
     let (_,_) = ev.next().unwrap();}

    assert_eq!(data.coins, 2.0);
    assert_eq!(data.name, "new-name".to_owned());
}
<commit_msg>tweak<commit_after>extern crate lichen;

use lichen::parse::{Parser,Block,SrcBlock,Map};
use lichen::{Logic,Expect};
use lichen::var::Var;
use lichen::source::{Src,Next};
use lichen::eval::{Eval,Evaluator};

use std::collections::HashMap;

struct Data;
impl Eval for Data {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        match lookup {
            "some_item" => {
                Some(false.into())
            },
            "other_item" => {
                Some(true.into())
            },
            "some_weight" => {
                Some(4.0 .into())
            },
            "other_weight" => {
                Some(5.0 .into())
            },
            "name" => {
                Some("Io".into())
            }
            _ => None
        }
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {}

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        None
    }
}

#[test]
fn parse_block() {
    let src = "root\n
    unequipped !some_item\n
    has_weight some_weight < 5.0\n
    some_comp:any [\nunequipped \nhas_weight\n]\n
\n
    if unequipped \"you're looking for something?\"\n
\n
    if all \"welcome, \nlook around\"\n
    next:now end\n
;";

    let block = Parser::parse_blocks(src);

    let block_ = [Block::Src(
        SrcBlock {
            await_idx: 0,
            visited: false,
            name: "root".to_owned(),
            src: vec![Src::Logic("unequipped".to_owned(),
                                 Logic::IsNot("some_item".to_owned())),

                      Src::Logic("has_weight".to_owned(),
                                 Logic::LT(Var::Sym("some_weight".to_owned()), 5.0 .into())),
                      Src::Composite("some_comp".to_owned(),
                                     Expect::Any,
                                     vec!["unequipped".to_owned(),"has_weight".to_owned()]),
                      Src::If(Expect::Ref("unequipped".to_owned()),
                              vec!["you're looking for something?".into()],
                              None),
                      Src::If(Expect::All,
                              vec!["welcome, \nlook around".into()],
                              None),
                      Src::Next(Next::Now("end".to_owned()))]
        })];

    assert_eq!(block[0],block_[0]);
}

#[test]
fn parse_qsym_block() {
    let src = "root\n
    if !some_item \"you're looking for something?\"\n
;";
    let block = Parser::parse_blocks(src);
    match &block[0] {
        &Block::Src(ref b) => {
            let r;
            match b.src[0] {
                Src::Logic(ref qsym,_) => { r = qsym; },
                _ => panic!("unknown source found")
            }

            match b.src[1] {
                Src::If(ref x,_,_) => {
                    match x {
                        &Expect::Ref(ref r_) => {
                            assert_eq!(r,r_);
                        },
                        _ => panic!("unknown expect found")
                    }
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn parse_qsym_comp_block() {
    let src =  "root\n
    has_weight some_weight < 5.0\n
    some_comp:any [has_weight !some_item ]\n
    ;";

    let block = Parser::parse_blocks(src);

    match &block[0] {
        &Block::Src(ref b) => {
            let r;
            match b.src[1] {
                Src::Logic(ref qsym,_) => { r = qsym; },
                _ => panic!("unknown source found")
            }

            match b.src[2] {
                Src::Composite(_,_,ref x) => {
                    assert_eq!(r,&x[1]);
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn validate_qsym_block() {
    let src =  "root\n
    if other_item next:await store\n
    ;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_,nn) = ev.next().unwrap();

    assert_eq!(nn, Some(Next::Await("store".into())));
}

#[test]
fn validate_reflection_block() {
    let src =  "root\n
    has other_item
    hasnt some_item
    hasnt-too !hasnt
    comp:all has hasnt-too
    if comp next:await store\n
    ;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_,nn) = ev.next().unwrap();

    assert_eq!(nn, Some(Next::Await("store".into())));
}

#[test]
fn parse_if_vec_block() {
    let src = "root\n
    if !some_item [\n
        \"you're looking for something?\"\n
        \"welcome, \nlook around\"\n
        next:now store]\n
;";

    let block = Parser::parse_blocks(src);

    match &block[0] {
        &Block::Src(ref b) => {
            match b.src[1] {
                Src::If(_,_, ref next) => {
                    assert_eq!(next,&Some(Next::Now("store".to_owned())));
                },
                _ => panic!("unknown source found")
            }
        },
        _ => panic!("unknown block found")
    }
}

#[test]
fn parse_eval_str_block() {
    let src = "root\n
        has_weight some_weight < 5.0\n
        some_comp:all [has_weight !some_item ]\n
    if some_comp \"looks like you are `some_weight kgs heavy, `name\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_node) = ev.run("root");

    assert_eq!(vars, ["looks like you are 4 kgs heavy, Io".into()]);
}

#[test]
fn parse_compare_env_block() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight next:now store\n
;";
    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_vars,node) = ev.run("root");

    assert_eq!(node, Some(Next::Now("store".to_string())));
}

#[test]
fn parse_return_varkind() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight some_weight \"hi `name\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.run("root");

    assert_eq!(vars[0], 4.0 .into());
    assert_eq!(vars[1], "hi Io" .into());
}

#[test]
fn parse_follow_nodes() {
    let src = "root\n
    weight some_weight < other_weight\n
    if weight next:now store\n
;\n
\n
store\n
    if !some_item \"welcome, \nlook around\"\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    ev.next(); // runs root
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], "welcome, \nlook around".into());
}

#[test]
fn parse_select_nodes() {
    let src = "root\n
    next:select {\"Head to Store?\" store,\n
                \"Leave the town?\" exit-town}\n
\n
    if !some_item [\"Some choices\"
        next:select {\"Head to Store?\" store,\n
                    \"Leave the town?\" exit-town}]\n
\n
    next:select {\"Head to town?\" store bakery tanner,\n
                5 hike,
                \"Leave the town?\" exit-town}\n
\n
    emit \"A dustball blows by\"\n
;";
    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (_vars,select1) = ev.next().unwrap();
    let (_vars,select2) = ev.next().unwrap();

    assert_eq!(select1,select2);

    let mut map: Map = HashMap::new();
    map.insert("Head to Store?".to_owned(), vec![Var::Sym("store".to_owned())]);
    map.insert("Leave the town?".to_owned(), vec![Var::Sym("exit-town".to_owned())]);

    assert_eq!(select1, Some(Next::Select(map)));

    let (_,select) = ev.next().unwrap();
    match select.expect("Unable to parse map") {
        Next::Select(map) => {
            println!("Map: {:?}",map);
            assert!(map.contains_key("5"));
            assert_eq!(map.get("5"), Some(&vec![Var::Sym("hike".to_owned())]));
        },
        _ => { panic!("Invalid Next type found") }
    }
}

// Test for mutable state
#[derive(Debug)]
struct Player {
    coins: f32,
    name: String
}
impl Eval for Player {
    #[allow(unused_variables)]
    fn get (&self, path: Option<Vec<&str>>, lookup: &str) -> Option<Var> {
        if lookup == "coins" { Some(self.coins.into()) }
        else if lookup == "name" { Some(self.name.clone().into()) }
        else { None }
    }

    #[allow(unused_variables)]
    fn set (&mut self, path: Option<Vec<&str>>, lookup: &str, var: Var) {
        if lookup == "coins" {
            match var {
                Var::Num(n) => {
                    self.coins = n;
                },
                _ => {}
            }
        }
        else if lookup == "name" {
            match var {
                Var::String(s) => {
                    self.name = s;
                },
                _ => {}
            }
        }
    }

    #[allow(unused_variables)]
    fn call (&mut self, var: Var, fun: &str, vars: &Vec<Var>) -> Option<Var> {
        match fun {
            "inc" => {
                if let Ok(v) = Var::get_num(&var, self) {
                    let mut r = v;
                    for n in vars.iter() {
                        if let Ok(v) = Var::get_num(&n, self) {
                            r += v;
                        }
                    }

                    return Some(Var::Num(r))
                }
            },
            _ => { }
        }

        None
    }
}

#[test]
/// this test shows that all statements are processed in one Eval iteration
fn state_mut() {
    let src = "root\n
    @coins + 1\n
    emit \"step\"\n
    @coins 5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {
        let mut ev = Evaluator::new(&mut env, &mut data);
        let (_vars,_) = ev.next().unwrap();
    }

    assert_eq!(data.coins, 5.0);
}

#[test]
fn parse_cust_fn() {
    let src = "root\n
    @coins (inc) 1 2 3\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {
        let mut ev = Evaluator::new(&mut env, &mut data);
        let (_,_) = ev.next().unwrap();
    }

    assert_eq!(data.coins, 6.0);
}

#[test]
fn parse_def_block() {
    let src = "root\n
    emit global.name global.size\n
;\n
\n
def global\n
    name \"my-game\"\n
    size 1.5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Data;

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], Var::String("my-game".to_owned()));
    assert_eq!(vars[1], Var::Num(1.5 .to_owned()));
}

#[test]
fn validate_def_block() {
    let src = "root\n
    @global.size + 0.5\n
    @global.name \"other-game\"\n
    @name global.name\n
    @coins - global.size\n
    emit [global.name global.size\n
         name coins]\n
;\n
\n
def global\n
    name \"my-game\"\n
    size 1.5\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    let mut ev = Evaluator::new(&mut env, &mut data);
    let (vars,_) = ev.next().unwrap();

    assert_eq!(vars[0], Var::String("other-game".to_owned()));
    assert_eq!(vars[1], Var::Num(2.0 .to_owned()));

    assert_eq!(vars[2], Var::String("Pan".to_owned()));
    assert_eq!(vars[3], Var::Num(-2.0 .to_owned()));
}

#[test]
fn parse_with_block() {
    let src = "root\n
    needs_coins coins < 1\n
    has_name name\n
    with {needs_coins @coins + 2, \n
         has_name @name \"new-name\"}\n
;";

    let mut env = Parser::parse_blocks(src).into_env();
    let mut data = Player { coins: 0.0, name: "Pan".to_owned() };

    {let mut ev = Evaluator::new(&mut env, &mut data);
     let (_,_) = ev.next().unwrap();}

    assert_eq!(data.coins, 2.0);
    assert_eq!(data.name, "new-name".to_owned());
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/100_doors

use std::iter::range_inclusive;

#[cfg(not(test))]
fn main() {
    let drs = doors();
    for (i, x) in drs.iter().enumerate() {
        println!("Door {} is {}", i+1, x);
    }
}

fn doors() -> Vec<DoorState> {
    range_inclusive(1.0f32, 100.0).map(|f| {
        let x = f.sqrt();
        if x == x.round() {Open} else {Closed}
    }).collect()
}

#[deriving(Show, PartialEq, Eq)]
enum DoorState {
    Open,
    Closed
}

#[test]
fn solution() {
    let drs = doors();

    // test that the doors with index corresponding to
    // a perfect square are now open
    for i in range_inclusive(1u,10u) {
        assert_eq!(drs[i*i - 1], Open);
    }
}
<commit_msg>100 doors: Demonstrate returning an iterator to control allocation<commit_after>// Implements http://rosettacode.org/wiki/100_doors
use std::iter::{Map, RangeInclusive, range_inclusive};

type DoorIter<'a> = Map<'a, f32, DoorState, RangeInclusive<f32>>;

#[deriving(Show, PartialEq)]
enum DoorState {
    Open,
    Closed
}

// This is an example of returning an iterator, this allows the caller to
// choose if they want to allocate or just process as a stream.
fn calculate_doors<'a>() -> DoorIter<'a> {
    range_inclusive(1.0f32, 100.0).map(|f| {
        let x = f.sqrt();
        if x == x.round() {Open} else {Closed}
    })
}

#[cfg(not(test))]
fn main() {
    let doors = calculate_doors();
    for (i, x) in doors.enumerate() {
        println!("Door {} is {}", i + 1, x);
    }
}

#[test]
fn solution() {
    let doors = calculate_doors().collect::<Vec<DoorState>>();

    // test that the doors with index corresponding to
    // a perfect square are now open
    for i in range_inclusive(1u,10u) {
        assert_eq!(doors[i*i - 1], Open);
    }
}
<|endoftext|>


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

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident, $ignored_bits:expr) => {
        mod $mod_name {
            use rand::{Rand, Rng, Open01, Closed01};

            static SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    // using any more than `mantissa_bits` bits will
                    // cause (e.g.) 0xffff_ffff to correspond to 1
                    // exactly, so we need to drop some (8 for f32, 11
                    // for f64) to guarantee the open end.
                    (rng.$method_name() >> $ignored_bits) as $ty / SCALE
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add a small amount (specifically 2 bits below
                    // the precision of f64/f32 at 1.0), so that small
                    // numbers are larger than 0, but large numbers
                    // aren't pushed to/above 1.
                    Open01(((rng.$method_name() >> $ignored_bits) as $ty + 0.25) / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // divide by the maximum value of the numerator to
                    // get a non-zero probability of getting exactly
                    // 1.0.
                    Closed01((rng.$method_name() >> $ignored_bits) as $ty / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 53, next_u64, 11 }
float_impls! { f32_rand_impls, f32, 24, next_u32, 8 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}

#[cfg(test)]
mod tests {
    use rand::{Rng, task_rng, Open01, Closed01};
    use iter::range;
    use option::{None, Some};

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            (**self) as u32
        }
        fn next_u64(&mut self) -> u64 {
            **self
        }
    }

    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0)
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0)
    }

    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = task_rng();
        for _ in range(0, 1_000) {
            // strict inequalities
            let f = *rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let f = *rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    fn rand_closed() {
        let mut rng = task_rng();
        for _ in range(0, 1_000) {
            // strict inequalities
            let f = *rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let f = *rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<commit_msg>std: silence warnings when compiling test.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The implementations of `Rand` for the built-in types.

use char;
use int;
use option::{Option, Some, None};
use rand::{Rand,Rng};
use uint;

impl Rand for int {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> int {
        if int::bits == 32 {
            rng.gen::<i32>() as int
        } else {
            rng.gen::<i64>() as int
        }
    }
}

impl Rand for i8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i8 {
        rng.next_u32() as i8
    }
}

impl Rand for i16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i16 {
        rng.next_u32() as i16
    }
}

impl Rand for i32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i32 {
        rng.next_u32() as i32
    }
}

impl Rand for i64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> i64 {
        rng.next_u64() as i64
    }
}

impl Rand for uint {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> uint {
        if uint::bits == 32 {
            rng.gen::<u32>() as uint
        } else {
            rng.gen::<u64>() as uint
        }
    }
}

impl Rand for u8 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u8 {
        rng.next_u32() as u8
    }
}

impl Rand for u16 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u16 {
        rng.next_u32() as u16
    }
}

impl Rand for u32 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u32 {
        rng.next_u32()
    }
}

impl Rand for u64 {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> u64 {
        rng.next_u64()
    }
}

macro_rules! float_impls {
    ($mod_name:ident, $ty:ty, $mantissa_bits:expr, $method_name:ident, $ignored_bits:expr) => {
        mod $mod_name {
            use rand::{Rand, Rng, Open01, Closed01};

            static SCALE: $ty = (1u64 << $mantissa_bits) as $ty;

            impl Rand for $ty {
                /// Generate a floating point number in the half-open
                /// interval `[0,1)`.
                ///
                /// See `Closed01` for the closed interval `[0,1]`,
                /// and `Open01` for the open interval `(0,1)`.
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> $ty {
                    // using any more than `mantissa_bits` bits will
                    // cause (e.g.) 0xffff_ffff to correspond to 1
                    // exactly, so we need to drop some (8 for f32, 11
                    // for f64) to guarantee the open end.
                    (rng.$method_name() >> $ignored_bits) as $ty / SCALE
                }
            }
            impl Rand for Open01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Open01<$ty> {
                    // add a small amount (specifically 2 bits below
                    // the precision of f64/f32 at 1.0), so that small
                    // numbers are larger than 0, but large numbers
                    // aren't pushed to/above 1.
                    Open01(((rng.$method_name() >> $ignored_bits) as $ty + 0.25) / SCALE)
                }
            }
            impl Rand for Closed01<$ty> {
                #[inline]
                fn rand<R: Rng>(rng: &mut R) -> Closed01<$ty> {
                    // divide by the maximum value of the numerator to
                    // get a non-zero probability of getting exactly
                    // 1.0.
                    Closed01((rng.$method_name() >> $ignored_bits) as $ty / (SCALE - 1.0))
                }
            }
        }
    }
}
float_impls! { f64_rand_impls, f64, 53, next_u64, 11 }
float_impls! { f32_rand_impls, f32, 24, next_u32, 8 }

impl Rand for char {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> char {
        // a char is 21 bits
        static CHAR_MASK: u32 = 0x001f_ffff;
        loop {
            // Rejection sampling. About 0.2% of numbers with at most
            // 21-bits are invalid codepoints (surrogates), so this
            // will succeed first go almost every time.
            match char::from_u32(rng.next_u32() & CHAR_MASK) {
                Some(c) => return c,
                None => {}
            }
        }
    }
}

impl Rand for bool {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> bool {
        rng.gen::<u8>() & 1 == 1
    }
}

macro_rules! tuple_impl {
    // use variables to indicate the arity of the tuple
    ($($tyvar:ident),* ) => {
        // the trailing commas are for the 1 tuple
        impl<
            $( $tyvar : Rand ),*
            > Rand for ( $( $tyvar ),* , ) {

            #[inline]
            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
                (
                    // use the $tyvar's to get the appropriate number of
                    // repeats (they're not actually needed)
                    $(
                        _rng.gen::<$tyvar>()
                    ),*
                    ,
                )
            }
        }
    }
}

impl Rand for () {
    #[inline]
    fn rand<R: Rng>(_: &mut R) -> () { () }
}
tuple_impl!{A}
tuple_impl!{A, B}
tuple_impl!{A, B, C}
tuple_impl!{A, B, C, D}
tuple_impl!{A, B, C, D, E}
tuple_impl!{A, B, C, D, E, F}
tuple_impl!{A, B, C, D, E, F, G}
tuple_impl!{A, B, C, D, E, F, G, H}
tuple_impl!{A, B, C, D, E, F, G, H, I}
tuple_impl!{A, B, C, D, E, F, G, H, I, J}

impl<T:Rand> Rand for Option<T> {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
        if rng.gen() {
            Some(rng.gen())
        } else {
            None
        }
    }
}

impl<T: Rand> Rand for ~T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
}

impl<T: Rand + 'static> Rand for @T {
    #[inline]
    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
}

#[cfg(test)]
mod tests {
    use rand::{Rng, task_rng, Open01, Closed01};
    use iter::range;
    use option::{None, Some};

    struct ConstantRng(u64);
    impl Rng for ConstantRng {
        fn next_u32(&mut self) -> u32 {
            (**self) as u32
        }
        fn next_u64(&mut self) -> u64 {
            **self
        }
    }

    #[test]
    fn floating_point_edge_cases() {
        // the test for exact equality is correct here.
        assert!(ConstantRng(0xffff_ffff).gen::<f32>() != 1.0)
        assert!(ConstantRng(0xffff_ffff_ffff_ffff).gen::<f64>() != 1.0)
    }

    #[test]
    fn rand_open() {
        // this is unlikely to catch an incorrect implementation that
        // generates exactly 0 or 1, but it keeps it sane.
        let mut rng = task_rng();
        for _ in range(0, 1_000) {
            // strict inequalities
            let f = *rng.gen::<Open01<f64>>();
            assert!(0.0 < f && f < 1.0);

            let f = *rng.gen::<Open01<f32>>();
            assert!(0.0 < f && f < 1.0);
        }
    }

    #[test]
    fn rand_closed() {
        let mut rng = task_rng();
        for _ in range(0, 1_000) {
            // strict inequalities
            let f = *rng.gen::<Closed01<f64>>();
            assert!(0.0 <= f && f <= 1.0);

            let f = *rng.gen::<Closed01<f32>>();
            assert!(0.0 <= f && f <= 1.0);
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Metrics

use std::sync::Arc;

mod counter;
mod gauge;
mod meter;

pub use self::counter::{Counter, CounterSnapshot, StdCounter};
pub use self::gauge::{Gauge, GaugeSnapshot, StdGauge};
pub use self::meter::{Meter, MeterSnapshot, StdMeter};

/// a Metric
use histogram::Histogram;

#[allow(missing_docs)]
pub enum Metric {
    Counter(Arc<Counter>),
    Gauge(Arc<Gauge>),
    Meter(Arc<Meter>),
    Histogram(Histogram),
}

#[allow(unsafe_code)]
unsafe impl Send for Metric {}
#[allow(unsafe_code)]
unsafe impl Sync for Metric {}
<commit_msg>Remove unsafe impl Send+Sync on Metric.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Metrics

use std::sync::Arc;

mod counter;
mod gauge;
mod meter;

pub use self::counter::{Counter, CounterSnapshot, StdCounter};
pub use self::gauge::{Gauge, GaugeSnapshot, StdGauge};
pub use self::meter::{Meter, MeterSnapshot, StdMeter};

/// a Metric
use histogram::Histogram;

#[allow(missing_docs)]
pub enum Metric {
    Counter(Arc<Counter>),
    Gauge(Arc<Gauge>),
    Meter(Arc<Meter>),
    Histogram(Histogram),
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.2

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "0.0.0.0";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    /* IMPORTANT NOTE: 	Weilin's new code for this adding file requests ('do spawn' part) is buggy.
			So don't change the code right below !
    */

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    // FIFO
    do spawn {
        loop {
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // FILO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let mut tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));

                    match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                        Ok(file_data) => {
                            println(fmt!("begin serving file [%?]", tf.filepath));
                            // A web server should always reply a HTTP header for any legal HTTP request.
                            tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                            tf.stream.write(file_data);
                            println(fmt!("finish file [%?]", tf.filepath));
                        }
                        Err(err) => {
                            println(err);
                        }
                    }
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name()
			{	Some(pn) => { println( fmt!("\nPeer address: %s", pn.to_str() ));},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("\ncount: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // may do scheduling here

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<commit_msg>added code to determine whether the request is from a Charlottesville client<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.2

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "0.0.0.0";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

// determine if the request is from a Charlottesville client

fn is_Wahoo_Client(peer_addr: ~str) ->bool
{
	let WahooIPs: ~[~str] = ~[~"128.143.", ~"137.54."]; // probably add some more ip addresses on the way

	let mut index = 0;

	let mut isWahoo = false;

	while index < WahooIPs.len()
	{
		if peer_addr.starts_with(WahooIPs[index])
		{
			isWahoo = true;
			break;
		}
		index += 1;
	}
	//println( fmt!("is wahoo? : %?\n", isWahoo) );

	return isWahoo;
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let mut isWahoo: bool = false;

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    /* IMPORTANT NOTE: 	Weilin's new code for this adding file requests ('do spawn' part) is buggy.
			So don't change the code right below !
    */

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    // FIFO
    do spawn {
        loop {
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // FILO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let mut tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));

                    match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                        Ok(file_data) => {
                            println(fmt!("begin serving file [%?]", tf.filepath));
                            // A web server should always reply a HTTP header for any legal HTTP request.
                            tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                            tf.stream.write(file_data);
                            println(fmt!("finish file [%?]", tf.filepath));
                        }
                        Err(err) => {
                            println(err);
                        }
                    }
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@
	let mut peer_addr: ~str = ~"";

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name()
			{	Some(pn) => {
						peer_addr = pn.to_str();
						println( fmt!("\nPeer address: %s", peer_addr ));
					    },
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	isWahoo = is_Wahoo_Client(peer_addr);

	println( fmt!("is wahoo? : %?\n", isWahoo) );

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // may do scheduling here

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<|endoftext|>


<commit_before>mod pkg;
pub mod update;
pub mod find;
pub mod version;
<commit_msg>Change to public<commit_after>pub mod pkg;
pub mod update;
pub mod find;
pub mod version;
<|endoftext|>


<commit_before>// This is an X-Macro.
#[macro_export]
macro_rules! list_of_all_specifier_classes {
    ($your_macro:ident) => {
        $your_macro!($crate::ws_client_peer::WsClientClass);
        #[cfg(all(unix, feature = "ssl"))]
        $your_macro!($crate::ws_client_peer::WsClientSecureClass);
        $your_macro!($crate::ws_server_peer::WsTcpServerClass);
        $your_macro!($crate::ws_server_peer::WsInetdServerClass);
        $your_macro!($crate::ws_server_peer::WsUnixServerClass);
        $your_macro!($crate::ws_server_peer::WsAbstractUnixServerClass);
        $your_macro!($crate::ws_server_peer::WsServerClass);

        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::StdioClass);
        $your_macro!($crate::stdio_peer::InetdClass);
        #[cfg(not(all(unix, feature = "unix_stdio")))]
        $your_macro!($crate::stdio_threaded_peer::ThreadedStdioSubstituteClass);
        #[cfg(not(all(unix, feature = "unix_stdio")))]
        $your_macro!($crate::stdio_threaded_peer::InetdClass);

        $your_macro!($crate::net_peer::TcpConnectClass);
        $your_macro!($crate::net_peer::TcpListenClass);

        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::ShCClass);
        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::CmdClass);
        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::ExecClass);

        $your_macro!($crate::file_peer::ReadFileClass);
        $your_macro!($crate::file_peer::WriteFileClass);
        $your_macro!($crate::file_peer::AppendFileClass);

        $your_macro!($crate::primitive_reuse_peer::ReuserClass);
        $your_macro!($crate::broadcast_reuse_peer::BroadcastReuserClass);
        $your_macro!($crate::reconnect_peer::AutoReconnectClass);

        $your_macro!($crate::ws_client_peer::WsConnectClass);

        $your_macro!($crate::net_peer::UdpConnectClass);
        $your_macro!($crate::net_peer::UdpListenClass);

        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::OpenAsyncClass);
        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::OpenFdAsyncClass);

        $your_macro!($crate::stdio_threaded_peer::ThreadedStdioClass);

        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixConnectClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixListenClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixDgramClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractConnectClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractListenClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractDgramClass);

        $your_macro!($crate::line_peer::Message2LineClass);
        $your_macro!($crate::line_peer::Line2MessageClass);
        $your_macro!($crate::mirror_peer::MirrorClass);
        $your_macro!($crate::mirror_peer::LiteralReplyClass);
        $your_macro!($crate::trivial_peer::CloggedClass);
        $your_macro!($crate::trivial_peer::LiteralClass);
        $your_macro!($crate::trivial_peer::AssertClass);
        $your_macro!($crate::trivial_peer::Assert2Class);

        #[cfg(feature = "seqpacket")]
        $your_macro!($crate::unix_peer::SeqpacketConnectClass);
        #[cfg(feature = "seqpacket")]
        $your_macro!($crate::unix_peer::SeqpacketListenClass);

        /*
                                $your_macro!($crate:: :: );
                                $your_macro!($crate:: :: );
                                $your_macro!($crate:: :: );
                                */
    };
}
<commit_msg>Fix building<commit_after>// This is an X-Macro.
#[macro_export]
macro_rules! list_of_all_specifier_classes {
    ($your_macro:ident) => {
        $your_macro!($crate::ws_client_peer::WsClientClass);
        #[cfg(all(unix, feature = "ssl"))]
        $your_macro!($crate::ws_client_peer::WsClientSecureClass);
        $your_macro!($crate::ws_server_peer::WsTcpServerClass);
        $your_macro!($crate::ws_server_peer::WsInetdServerClass);
        $your_macro!($crate::ws_server_peer::WsUnixServerClass);
        $your_macro!($crate::ws_server_peer::WsAbstractUnixServerClass);
        $your_macro!($crate::ws_server_peer::WsServerClass);

        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::StdioClass);
        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::InetdClass);
        #[cfg(not(all(unix, feature = "unix_stdio")))]
        $your_macro!($crate::stdio_threaded_peer::ThreadedStdioSubstituteClass);
        #[cfg(not(all(unix, feature = "unix_stdio")))]
        $your_macro!($crate::stdio_threaded_peer::InetdClass);

        $your_macro!($crate::net_peer::TcpConnectClass);
        $your_macro!($crate::net_peer::TcpListenClass);

        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::ShCClass);
        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::CmdClass);
        #[cfg(feature = "tokio-process")]
        $your_macro!($crate::process_peer::ExecClass);

        $your_macro!($crate::file_peer::ReadFileClass);
        $your_macro!($crate::file_peer::WriteFileClass);
        $your_macro!($crate::file_peer::AppendFileClass);

        $your_macro!($crate::primitive_reuse_peer::ReuserClass);
        $your_macro!($crate::broadcast_reuse_peer::BroadcastReuserClass);
        $your_macro!($crate::reconnect_peer::AutoReconnectClass);

        $your_macro!($crate::ws_client_peer::WsConnectClass);

        $your_macro!($crate::net_peer::UdpConnectClass);
        $your_macro!($crate::net_peer::UdpListenClass);

        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::OpenAsyncClass);
        #[cfg(all(unix, feature = "unix_stdio"))]
        $your_macro!($crate::stdio_peer::OpenFdAsyncClass);

        $your_macro!($crate::stdio_threaded_peer::ThreadedStdioClass);

        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixConnectClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixListenClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::UnixDgramClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractConnectClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractListenClass);
        #[cfg(unix)]
        $your_macro!($crate::unix_peer::AbstractDgramClass);

        $your_macro!($crate::line_peer::Message2LineClass);
        $your_macro!($crate::line_peer::Line2MessageClass);
        $your_macro!($crate::mirror_peer::MirrorClass);
        $your_macro!($crate::mirror_peer::LiteralReplyClass);
        $your_macro!($crate::trivial_peer::CloggedClass);
        $your_macro!($crate::trivial_peer::LiteralClass);
        $your_macro!($crate::trivial_peer::AssertClass);
        $your_macro!($crate::trivial_peer::Assert2Class);

        #[cfg(feature = "seqpacket")]
        $your_macro!($crate::unix_peer::SeqpacketConnectClass);
        #[cfg(feature = "seqpacket")]
        $your_macro!($crate::unix_peer::SeqpacketListenClass);

        /*
                                $your_macro!($crate:: :: );
                                $your_macro!($crate:: :: );
                                $your_macro!($crate:: :: );
                                */
    };
}
<|endoftext|>