<commit_before>use rand::random;
use std::collections::HashMap;

#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    // references logic in env and emits varkinds;
    // logic must resolve to true
    // ex: if item_logic give_quest
    // Can optionally end execution and begin next node
    If(ExpectKind, Vec<VarKind>, Option<String>),

    Composite(String,ExpectKind,Vec<String>),
    Next(String), // ends execution and begins next node
}

#[derive(Debug,PartialEq)]
pub enum ExpectKind {
    All,
    Any,
    None,

    Ref(String) // references env variable set from logic
}
impl ExpectKind {
    pub fn parse(s: String) -> ExpectKind {
        match &s[..] {
            "all" => ExpectKind::All,
            "any" => ExpectKind::Any,
            "none" => ExpectKind::None,
            _ => ExpectKind::Ref(s),
        }
    }
}

impl SrcKind {
    fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>, data: &D)
                     -> (Vec<VarKind>,Option<String>)
    {
        match self {
            &SrcKind::Next(ref node) => {
                return (vec![],Some(node.clone()))
            },
            &SrcKind::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &LogicKind::Is(ref lookup) => {
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                    },
                    &LogicKind::IsNot(ref lookup) => { //inverse state
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },

                    &LogicKind::GT(ref lookup, ref var) => {
                        let num:f32 = VarKind::get_num::<D>(var,data).unwrap();

                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Num(num_) => {
                                    state.insert(name, num > num_);
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },
                    &LogicKind::LT(ref lookup, ref var) => {
                        let num = VarKind::get_num::<D>(var,data).unwrap();

                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Num(num_) => {
                                    state.insert(name, num > num_);
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    }
                }

                return (vec![],None) // logic does not return anything
            },
            &SrcKind::Composite(ref name, ref x, ref lookups) => {
                let mut comp_value = false;
                match x {
                    &ExpectKind::All => { // all must pass as true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                            }
                            else { comp_value = false; break }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Any => { // first truth passes for set
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::None => { // inverse of any, none must be true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = false;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Ref(_) => panic!("ERROR: Unexpected parsing") // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &SrcKind::If(ref x, ref v, ref node) => {
                let mut if_value = false;
                match x {
                    &ExpectKind::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &ExpectKind::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &ExpectKind::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &ExpectKind::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if val.is_some() && *val.unwrap() { if_value = true; }
                    },
                }

                if if_value { return ((*v).clone(),node.clone()) }
                else { return (vec![],None) }
            }
        }
    }

    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "if" {
            if exp.len() < 3 { panic!("ERROR: Invalid IF Logic {:?}",exp) }

            let x = exp.remove(1);

            let mut node = None;
            if exp.len() > 2 {
                let next = &exp[exp.len() - 2] == "next";
                if next {
                    node = exp.pop();
                    let _ = exp.pop(); // remove next tag
                }
            }

            let v = exp.drain(1..).map(|n| VarKind::parse(n)).collect();
            SrcKind::If(ExpectKind::parse(x),
                        v, node)
        }
        else if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else {
            let keys = exp.remove(0);
            let mut keys: Vec<&str> = keys.split_terminator(':').collect();

            if keys.len() < 2 { // regular logic
                SrcKind::Logic(keys.pop().unwrap().to_owned(),
                               LogicKind::parse(exp))
            }
            else { // composite type
                let kind = ExpectKind::parse(keys.pop().unwrap().to_owned());
                match kind { // only formal expected types allowed
                    ExpectKind::Ref(_) => { panic!("ERROR: Informal ExpectKind found {:?}", kind) },
                    _ => {}
                }
                SrcKind::Composite(keys.pop().unwrap().to_owned(),
                                   kind,
                                   exp)
            }
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(String,VarKind), // weight > 1
    LT(String,VarKind),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    pub fn parse(mut exp: Vec<String>) -> LogicKind {
        let len = exp.len();

        if len == 1 {
            let mut exp = exp.pop().unwrap();
            let inv = exp.remove(0);
            if inv == '!' {
                LogicKind::IsNot(exp)
            }
            else {
                LogicKind::Is(exp)
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = VarKind::parse(var);

            let sym = exp.pop().unwrap();
            let key = exp.pop().unwrap();

            if sym == ">" {
                LogicKind::GT(key,var)
            }
            else if sym == "<" {
                LogicKind::LT(key,var)
            }
            else { panic!("ERROR: Invalid LogicKind Syntax") }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq, Clone)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl ToString for VarKind {
    fn to_string(&self) -> String {
        match self {
            &VarKind::String(ref s) => s.clone(),
            &VarKind::Num(ref n) => n.to_string(),
            &VarKind::Bool(ref b) => b.to_string(),
        }
    }
}

impl VarKind {
    pub fn parse(t: String) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t) }

        val
    }

    pub fn get_num<D:Eval> (&self, data: &D) -> Result<f32,&'static str> {
        let num;
        match self {
            &VarKind::Num(n) => { num = n; },
            &VarKind::String(ref s) => {
                if let Some(n) = data.eval(s) {
                    match n {
                        VarKind::Num(n) => { num = n; },
                        _ => return Err("ERROR: NaN Evaluation")
                    }
                }
                else {  return Err("ERROR: Empty Evaluation") }
            },
            _ =>  return Err("ERROR: NaN Evaluation")
        }

        return Ok(num)
    }
}

pub trait Eval {
    fn eval (&self, data: &str) -> Option<VarKind>;
}

pub struct Parser {
    //state: HashMap<String,usize>, //lookup table
}

impl Parser {
    pub fn eval_block<D:Eval>
        (block: &BlockKind, data: &D)
         -> (Vec<VarKind>,Option<String>)
    {
        let mut r = vec!();
        let mut node = None;

        match block {
            &BlockKind::Src(ref b) => {
                let mut state: HashMap<String,bool> = HashMap::new();
                for src in b.src.iter() {
                    let (mut vars, node_) = src.eval(&mut state, data);
                    for n in vars.drain(..) { r.push(n); }
                    if node.is_some() { node = node_; break; }
                }
            },
            _ => panic!("ERROR: Unimplemented block evaluation type")
        }

        for var in r.iter_mut() {
            match var {
                &mut VarKind::String(ref mut s) => { //format string
                    let mut fs = String::new();
                    let mut started = false;
                    for word in s.split_whitespace() {
                        if started { fs.push(' '); }

                        if word.chars().next().unwrap() == '`' {
                            if let Some(ref val) = data.eval(&word[1..]) {
                                fs.push_str(&val.to_string());
                            }
                        }
                        else {
                            fs.push_str(word);
                        }

                        started = true;
                    }

                    *s = fs;
                },
                _ => {}
            }
        }

        return (r,node)
    }

    pub fn parse_blocks (src: &str) -> Vec<BlockKind> {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;
        let mut in_comment = false;
        let mut in_vec = false;

        for c in src.chars() {
            if c == '[' { in_vec = true; continue }
            else if c == ']' { in_vec = false; }
            else if c == '#' && !in_string { in_comment = true; }
            else if  c == '\n' && in_comment && !in_string {
                in_comment = false;
                continue;
            }

            if c == '\n' && in_vec { continue }

            if (c == ']' ||
                c == '#' ||
                c == '\n')
                && !in_string
            {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "def" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    let mut qsyms = vec!();
                    for n in exps.iter_mut() {
                        if n.chars().next().expect("ERROR: Empty QSYM") == '\'' {
                            let mut qsym = "__".to_owned();
                            let sym = n[1..].trim().to_owned();
                            qsym.push_str(&random::<u16>().to_string());

                            qsyms.push(qsym.clone());
                            qsyms.push(sym);
                            *n = qsym;
                        }
                    }

                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(exps[1].to_owned())));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            //println!("EXPS{:?}",exps); //DEBUG
                            if qsyms.len() > 1 {
                                b.src.push(SrcKind::parse(qsyms));
                            }

                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' && !in_comment {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string && !in_comment {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                if !in_comment {
                    exp.push(c);
                }
            }
        }

        v
    }
}
<commit_msg>fix logic bug<commit_after>use rand::random;
use std::collections::HashMap;

#[derive(Debug,PartialEq)]
pub struct SrcBlock {
    pub name: String,
    pub src: Vec<SrcKind>
}

#[derive(Debug,PartialEq)]
pub struct DefBlock {
    pub name: String,
    pub defs: Vec<(String,VarKind)>
}

#[derive(Debug,PartialEq)]
pub enum BlockKind {
    Src(SrcBlock),
    Def(DefBlock),
}

/// delimited by new line
#[derive(Debug,PartialEq)]
pub enum SrcKind {
    Logic(String, LogicKind), // ex: item_logic has_item

    // references logic in env and emits varkinds;
    // logic must resolve to true
    // ex: if item_logic give_quest
    // Can optionally end execution and begin next node
    If(ExpectKind, Vec<VarKind>, Option<String>),

    Composite(String,ExpectKind,Vec<String>),
    Next(String), // ends execution and begins next node
}

#[derive(Debug,PartialEq)]
pub enum ExpectKind {
    All,
    Any,
    None,

    Ref(String) // references env variable set from logic
}
impl ExpectKind {
    pub fn parse(s: String) -> ExpectKind {
        match &s[..] {
            "all" => ExpectKind::All,
            "any" => ExpectKind::Any,
            "none" => ExpectKind::None,
            _ => ExpectKind::Ref(s),
        }
    }
}

impl SrcKind {
    fn eval<D:Eval> (&self, state: &mut HashMap<String,bool>, data: &D)
                     -> (Vec<VarKind>,Option<String>)
    {
        match self {
            &SrcKind::Next(ref node) => {
                return (vec![],Some(node.clone()))
            },
            &SrcKind::Logic(ref name, ref logic) => { //logic updates state
                let name = name.clone();
                match logic {
                    &LogicKind::Is(ref lookup) => {
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => { state.insert(name,v); },
                                _ => { state.insert(name,true); }, //if exists?
                            }
                        }
                    },
                    &LogicKind::IsNot(ref lookup) => { //inverse state
                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Bool(v) => {
                                    if !v { state.insert(name,true); }
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },

                    &LogicKind::GT(ref lookup, ref var) => {
                        let num:f32 = VarKind::get_num::<D>(var,data).unwrap();

                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Num(num_) => {
                                    state.insert(name, num_ > num);
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    },
                    &LogicKind::LT(ref lookup, ref var) => {
                        let num = VarKind::get_num::<D>(var,data).unwrap();

                        let r = data.eval(&lookup);
                        if r.is_some() {
                            match r.unwrap() {
                                VarKind::Num(num_) => {
                                    state.insert(name, num_ < num);
                                },
                                _ => { state.insert(name,false); },
                            }
                        }
                    }
                }

                return (vec![],None) // logic does not return anything
            },
            &SrcKind::Composite(ref name, ref x, ref lookups) => {
                let mut comp_value = false;
                match x {
                    &ExpectKind::All => { // all must pass as true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                            }
                            else { comp_value = false; break }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Any => { // first truth passes for set
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = true;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::None => { // inverse of any, none must be true
                        for lookup in lookups.iter() {
                            let val = state.get(lookup);
                            if val.is_some() && *val.unwrap() {
                                comp_value = false;
                                break;
                            }
                        }

                        state.insert(name.clone(),comp_value);
                    },
                    &ExpectKind::Ref(_) => panic!("ERROR: Unexpected parsing") // this should never hit
                }

                return (vec![],None) // composite does not return anything
            },
            &SrcKind::If(ref x, ref v, ref node) => {
                let mut if_value = false;
                match x {
                    &ExpectKind::All => {
                        for n in state.values() {
                            if !n { if_value = false; break }
                            else { if_value = true; }
                        }
                    },
                    &ExpectKind::Any => {
                        for n in state.values() {
                            if *n { if_value = true; break }
                        }
                    },
                    &ExpectKind::None => {
                        for n in state.values() {
                            if !n { if_value = true; }
                            else { if_value = true; break }
                        }
                    },
                    &ExpectKind::Ref(ref lookup) => {
                        let val = state.get(lookup);
                        if val.is_some() && *val.unwrap() { if_value = true; }
                    },
                }

                if if_value { return ((*v).clone(),node.clone()) }
                else { return (vec![],None) }
            }
        }
    }

    pub fn parse(mut exp: Vec<String>) -> SrcKind {
        if exp[0] == "if" {
            if exp.len() < 3 { panic!("ERROR: Invalid IF Logic {:?}",exp) }

            let x = exp.remove(1);

            let mut node = None;
            if exp.len() > 2 {
                let next = &exp[exp.len() - 2] == "next";
                if next {
                    node = exp.pop();
                    let _ = exp.pop(); // remove next tag
                }
            }

            let v = exp.drain(1..).map(|n| VarKind::parse(n)).collect();
            SrcKind::If(ExpectKind::parse(x),
                        v, node)
        }
        else if exp[0] == "next" {
            if exp.len() == 2 {
                SrcKind::Next(exp.pop().unwrap())
            }
            else { panic!("ERROR: Uneven NEXT Logic {:?}",exp) }
        }
        else {
            let keys = exp.remove(0);
            let mut keys: Vec<&str> = keys.split_terminator(':').collect();

            if keys.len() < 2 { // regular logic
                SrcKind::Logic(keys.pop().unwrap().to_owned(),
                               LogicKind::parse(exp))
            }
            else { // composite type
                let kind = ExpectKind::parse(keys.pop().unwrap().to_owned());
                match kind { // only formal expected types allowed
                    ExpectKind::Ref(_) => { panic!("ERROR: Informal ExpectKind found {:?}", kind) },
                    _ => {}
                }
                SrcKind::Composite(keys.pop().unwrap().to_owned(),
                                   kind,
                                   exp)
            }
        }
    }
}

/// delimited by new line
/// should resolve to boolean
#[derive(Debug,PartialEq)]
pub enum LogicKind {
    GT(String,VarKind), // weight > 1
    LT(String,VarKind),

    //boolean checks
    Is(String),
    IsNot(String),
}

impl LogicKind {
    pub fn parse(mut exp: Vec<String>) -> LogicKind {
        let len = exp.len();

        if len == 1 {
            let mut exp = exp.pop().unwrap();
            let inv = exp.remove(0);
            if inv == '!' {
                LogicKind::IsNot(exp)
            }
            else {
                LogicKind::Is(exp)
            }
        }
        else if len == 3 {
            let var = exp.pop().unwrap();
            let var = VarKind::parse(var);

            let sym = exp.pop().unwrap();
            let key = exp.pop().unwrap();

            if sym == ">" {
                LogicKind::GT(key,var)
            }
            else if sym == "<" {
                LogicKind::LT(key,var)
            }
            else { panic!("ERROR: Invalid LogicKind Syntax") }
        }
        else { panic!("ERROR: Unbalanced LogicKind Syntax ({:?})",exp) }
    }
}

#[derive(Debug,PartialEq, Clone)]
pub enum VarKind {
    String(String),
    Num(f32),
    Bool(bool),
}

impl ToString for VarKind {
    fn to_string(&self) -> String {
        match self {
            &VarKind::String(ref s) => s.clone(),
            &VarKind::Num(ref n) => n.to_string(),
            &VarKind::Bool(ref b) => b.to_string(),
        }
    }
}

impl VarKind {
    pub fn parse(t: String) -> VarKind {
        let val;

        if let Ok(v) = t.parse::<f32>() {
            val = VarKind::Num(v);
        }
        else if let Ok(v) = t.parse::<bool>() {
            val = VarKind::Bool(v);
        }
        else { val = VarKind::String(t) }

        val
    }

    pub fn get_num<D:Eval> (&self, data: &D) -> Result<f32,&'static str> {
        let num;
        match self {
            &VarKind::Num(n) => { num = n; },
            &VarKind::String(ref s) => {
                if let Some(n) = data.eval(s) {
                    match n {
                        VarKind::Num(n) => { num = n; },
                        _ => return Err("ERROR: NaN Evaluation")
                    }
                }
                else {  return Err("ERROR: Empty Evaluation") }
            },
            _ =>  return Err("ERROR: NaN Evaluation")
        }

        return Ok(num)
    }
}

pub trait Eval {
    fn eval (&self, data: &str) -> Option<VarKind>;
}

pub struct Parser {
    //state: HashMap<String,usize>, //lookup table
}

impl Parser {
    pub fn eval_block<D:Eval>
        (block: &BlockKind, data: &D)
         -> (Vec<VarKind>,Option<String>)
    {
        let mut r = vec!();
        let mut node = None;

        match block {
            &BlockKind::Src(ref b) => {
                let mut state: HashMap<String,bool> = HashMap::new();
                for src in b.src.iter() {
                    let (mut vars, node_) = src.eval(&mut state, data);
                    for n in vars.drain(..) { r.push(n); }
                    if node.is_some() { node = node_; break; }
                }
            },
            _ => panic!("ERROR: Unimplemented block evaluation type")
        }

        for var in r.iter_mut() {
            match var {
                &mut VarKind::String(ref mut s) => { //format string
                    let mut fs = String::new();
                    let mut started = false;
                    for word in s.split_whitespace() {
                        if started { fs.push(' '); }

                        if word.chars().next().unwrap() == '`' {
                            if let Some(ref val) = data.eval(&word[1..]) {
                                fs.push_str(&val.to_string());
                            }
                        }
                        else {
                            fs.push_str(word);
                        }

                        started = true;
                    }

                    *s = fs;
                },
                _ => {}
            }
        }

        return (r,node)
    }

    pub fn parse_blocks (src: &str) -> Vec<BlockKind> {
        let mut v = vec!();
        let mut exp = String::new();
        let mut exps: Vec<String> = vec!();
        let mut block: Option<BlockKind> = None;

        let mut in_string = false;
        let mut in_comment = false;
        let mut in_vec = false;

        for c in src.chars() {
            if c == '[' { in_vec = true; continue }
            else if c == ']' { in_vec = false; }
            else if c == '#' && !in_string { in_comment = true; }
            else if  c == '\n' && in_comment && !in_string {
                in_comment = false;
                continue;
            }

            if c == '\n' && in_vec { continue }

            if (c == ']' ||
                c == '#' ||
                c == '\n')
                && !in_string
            {
                for n in exp.split_whitespace() {
                    exps.push(n.trim().to_owned());
                }
                exp = String::new();

                if exps.len() < 1 { continue }

                // determine block type
                if block.is_none() {
                    let name = exps.pop().unwrap();

                    if name == "def" {
                        let b = DefBlock {
                            name: exps.pop().unwrap(),
                            defs: vec!()
                        };

                        block = Some(BlockKind::Def(b));
                    }
                    else {
                        let b = SrcBlock {
                            name: name,
                            src: vec!()
                        };

                        block = Some(BlockKind::Src(b));
                    }
                }
                else { // build block type
                    let mut qsyms = vec!();
                    for n in exps.iter_mut() {
                        if n.chars().next().expect("ERROR: Empty QSYM") == '\'' {
                            let mut qsym = "__".to_owned();
                            let sym = n[1..].trim().to_owned();
                            qsym.push_str(&random::<u16>().to_string());

                            qsyms.push(qsym.clone());
                            qsyms.push(sym);
                            *n = qsym;
                        }
                    }

                    match block {
                        Some(BlockKind::Def(ref mut b)) => {
                            b.defs.push((exps[0].to_owned(),
                                         VarKind::parse(exps[1].to_owned())));
                        },
                        Some(BlockKind::Src(ref mut b)) => {
                            //println!("EXPS{:?}",exps); //DEBUG
                            if qsyms.len() > 1 {
                                b.src.push(SrcKind::parse(qsyms));
                            }

                            b.src.push(SrcKind::parse(exps));
                        },
                        _ => {}
                    }

                    exps = vec!();
                }
            }
            else if c == '"' && !in_comment {
                in_string = !in_string;
                if in_string {
                    for n in exp.split_whitespace() {
                        exps.push(n.trim().to_owned());
                    }
                    exp = String::new();
                }
                else if !in_string {
                    exps.push(exp);
                    exp = String::new();
                }
            }
            else if c == ';' && !in_string && !in_comment {
                //fail otherwise, block should be built!
                v.push(block.unwrap());
                block = None;
            }
            else {
                if !in_comment {
                    exp.push(c);
                }
            }
        }

        v
    }
}
<|endoftext|>


<commit_before>use super::avx;
use super::bit;
use super::index_builder;
use super::parser;
use super::query::Query;
use super::stat::Stat;
use super::utf8::{BACKSLASH, COLON, DOT, LEFT_BRACE, QUOTE, RIGHT_BRACE};
use std::cmp;
use fnv::{FnvHashMap, FnvHashSet};
use x86intrin::m256i;

const ROOT_QUERY_STR_OFFSET: usize = 2;

/// JSON parser which picks up values directly without performing tokenization
pub struct Pikkr<'a> {
    backslash: m256i,
    quote: m256i,
    colon: m256i,
    left_brace: m256i,
    right_brace: m256i,

    query_strs: &'a Vec<&'a[u8]>,
    query_strs_len: usize,
    queries: FnvHashMap<&'a[u8], Query<'a>>,
    query_num: usize,
    level: usize,

    train_num: usize,
    trained_num: usize,
    trained: bool,

    stats: FnvHashMap<&'a[u8], Stat<'a>>,
}

impl<'a> Pikkr<'a> {
    /// Creates a JSON parser and returns it.
    #[inline]
    pub fn new(query_strs: &'a Vec<&'a[u8]>, train_num: usize) -> Pikkr<'a> {
        let mut p = Pikkr {
            backslash: avx::mm256i(BACKSLASH as i8),
            quote: avx::mm256i(QUOTE as i8),
            colon: avx::mm256i(COLON as i8),
            left_brace: avx::mm256i(LEFT_BRACE as i8),
            right_brace: avx::mm256i(RIGHT_BRACE as i8),

            query_strs: query_strs,
            query_strs_len: query_strs.len(),
            queries: FnvHashMap::default(),
            query_num: 0,
            level: 0,

            train_num: train_num,
            trained_num: 0,
            trained: false,

            stats: FnvHashMap::default(),
        };

        let mut level = 0;
        for query_str in query_strs {
            let query_num = set_queries(&mut p.queries, query_str, ROOT_QUERY_STR_OFFSET);
            p.query_num += query_num;
            level = cmp::max(level, query_num);
        }
        p.level = level;

        p
    }

    /// Parses a JSON record and returns the result.
    #[inline]
    pub fn parse<'b>(&mut self, rec: &'b[u8]) -> Vec<Option<&'b[u8]>> {
        let rec_len = rec.len();

        let rec_m256i_len = (rec_len + 31) / 32;
        let mut rec_m256i = Vec::with_capacity(rec_m256i_len);
        avx::u8_to_m256i(rec, &mut rec_m256i);

        let b_len = (rec_m256i_len + 1) / 2;
        let mut b_backslash = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_backslash, self.backslash);
        let mut b_quote = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_quote, self.quote);
        let mut b_colon = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_colon, self.colon);
        let mut b_left = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_left, self.left_brace);
        let mut b_right = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_right, self.right_brace);

        index_builder::build_structural_quote_bitmap(&b_backslash, &mut b_quote);

        index_builder::build_string_mask_bitmap(&mut b_quote);
        let b_string_mask = b_quote;

        bit::and(&b_string_mask, &mut b_colon);
        bit::and(&b_string_mask, &mut b_left);
        bit::and(&b_string_mask, &mut b_right);

        let mut index = Vec::with_capacity(self.level);
        index_builder::build_leveled_colon_bitmap(&b_colon, &b_left, &b_right, self.level, &mut index);

        clear_query_results(&mut self.queries);

        if self.trained {
            if !parser::speculative_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, &self.stats) {
                parser::basic_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, self.query_num, 0);
            }
        } else {
            parser::basic_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, self.query_num, 0);
            set_stats(&self.queries, &mut self.stats);
            self.trained_num += 1;
            if self.trained_num >= self.train_num {
                self.trained = true;
            }
        }

        let mut results = Vec::with_capacity(self.query_strs_len);
        for query_str in self.query_strs {
            set_result(rec, &self.queries, query_str, &mut results, ROOT_QUERY_STR_OFFSET);
        }

        results
    }
}

#[inline]
fn set_queries<'a>(queries: &mut FnvHashMap<&'a[u8], Query<'a>>, s: &'a[u8], i: usize) -> usize {
    for j in i..s.len() {
        if s[j] == DOT {
            let t = s.get(i..j).unwrap();
            let query = queries.entry(t).or_insert(Query {
                result: None,
                children: None,
            });
            let mut children = query.children.get_or_insert(FnvHashMap::default());
            return set_queries(&mut children, s, j+1) + 1;
        }
    }
    let t = s.get(i..s.len()).unwrap();
    if !queries.contains_key(t) {
        queries.insert(t, Query {
            result: None,
            children: None,
        });
        return 1;
    }
    0
}

#[inline]
fn clear_query_results(queries: &mut FnvHashMap<&[u8], Query>) {
    for (_, q) in queries.iter_mut() {
        q.result = None;
        if let Some(ref mut children) = q.children {
            clear_query_results(children);
        }
    }
}

#[inline]
fn set_stats<'a>(queries: &FnvHashMap<&'a[u8], Query<'a>>, stats: &mut FnvHashMap<&'a[u8], Stat<'a>>) {
    for (s, q) in queries.iter() {
        if let Some(result) = q.result {
            let st = stats.entry(s).or_insert(Stat {
                locs: FnvHashSet::default(),
                children: None,
            });
            st.locs.insert(result.2);
            if let Some(ref children) = q.children {
                let st_children = st.children.get_or_insert(FnvHashMap::default());
                set_stats(&children, st_children);
            }
        }
    }
}

#[inline]
fn set_result<'a>(rec: &'a[u8], queries: &FnvHashMap<&[u8], Query>, s: &[u8], d: &mut Vec<Option<&'a[u8]>>, i: usize) {
    for j in i..s.len() {
        if s[j] == DOT {
            let t = s.get(i..j).unwrap();
            match queries.get(t) {
                Some(query) => {
                    match query.children {
                        Some(ref children) => set_result(rec, children, s, d, j+1),
                        _ => d.push(None)
                    }
                },
                _ => d.push(None)
            }
            return;
        }
    }
    let t = s.get(i..s.len()).unwrap();
    d.push(match queries.get(t) {
        Some(query) => {
            match query.result {
                Some(result) => {
                    Some(rec.get(result.0..result.1).unwrap())
                },
                _ => None,
            }
        },
        _ => None,
    });
}

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

    #[test]
    fn test_pikkr_basic_parse() {
        let queries = vec![
            "$.f1".as_bytes(),
            "$.f2".as_bytes(),
            "$.f2.f1".as_bytes(),
            "$.f2.f2.f1".as_bytes(),
            "$.f2.f3".as_bytes(),
            "$.f3".as_bytes(),
            "$.f4".as_bytes(),
        ];
        let mut p = Pikkr::new(&queries, 1000000000);
        struct TestCase<'a> {
            rec: &'a str,
            want: Vec<Option<&'a[u8]>>,
        }
        let test_cases = vec![
            TestCase {
                rec: r#"{}"#,
                want: vec![None, None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a"}"#,
                want: vec![None, None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b"}"#,
                want: vec![Some(r#""b""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    None,
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                    None,
                ]
            },
            TestCase {
                rec: r#"{"f1": "Português do Brasil,Català,Deutsch,Español,Français,Bahasa,Italiano,עִבְרִית,日本語,한국어,Română,中文（简体）,中文（繁體）,Українська,Ўзбекча,Türkçe"}"#,
                want: vec![Some(r#""Português do Brasil,Català,Deutsch,Español,Français,Bahasa,Italiano,עִבְרִית,日本語,한국어,Română,中文（简体）,中文（繁體）,Українська,Ўзбекча,Türkçe""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f1": "\"f1\": \\"}"#,
                want: vec![Some(r#""\"f1\": \\""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"
                    	{
                     	"f1" 	 : 	 "b"
                    }
                "#,
                want: vec![Some(r#""b""#.as_bytes()), None, None, None, None, None, None],
            }
        ];
        for t in test_cases {
            let got = p.parse(t.rec.as_bytes());
            assert_eq!(t.want, got);
        }
    }

    #[test]
    fn test_pikkr_speculative_parse() {
        let queries = vec![
            "$.f1".as_bytes(),
            "$.f2".as_bytes(),
            "$.f2.f1".as_bytes(),
            "$.f2.f2.f1".as_bytes(),
            "$.f3".as_bytes(),
        ];
        let mut p = Pikkr::new(&queries, 1);
        struct TestCase<'a> {
            rec: &'a str,
            want: Vec<Option<&'a[u8]>>,
        }
        let test_cases = vec![
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f1": "b", "f0": "a", "f3": [1, 2, 3], "f2": {"f2": {"f2": "d", "f1": "c"}, "f1": 1}}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f2": {"f2": "d", "f1": "c"}, "f1": 1}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    None,
                ]
            },
            TestCase {
                rec: r#"{}"#,
                want: vec![None, None, None, None, None],
            }
        ];
        for t in test_cases {
            let got = p.parse(t.rec.as_bytes());
            assert_eq!(t.want, got);
        }
    }
}
<commit_msg>test: add the test case for #10<commit_after>use super::avx;
use super::bit;
use super::index_builder;
use super::parser;
use super::query::Query;
use super::stat::Stat;
use super::utf8::{BACKSLASH, COLON, DOT, LEFT_BRACE, QUOTE, RIGHT_BRACE};
use std::cmp;
use fnv::{FnvHashMap, FnvHashSet};
use x86intrin::m256i;

const ROOT_QUERY_STR_OFFSET: usize = 2;

/// JSON parser which picks up values directly without performing tokenization
pub struct Pikkr<'a> {
    backslash: m256i,
    quote: m256i,
    colon: m256i,
    left_brace: m256i,
    right_brace: m256i,

    query_strs: &'a Vec<&'a[u8]>,
    query_strs_len: usize,
    queries: FnvHashMap<&'a[u8], Query<'a>>,
    query_num: usize,
    level: usize,

    train_num: usize,
    trained_num: usize,
    trained: bool,

    stats: FnvHashMap<&'a[u8], Stat<'a>>,
}

impl<'a> Pikkr<'a> {
    /// Creates a JSON parser and returns it.
    #[inline]
    pub fn new(query_strs: &'a Vec<&'a[u8]>, train_num: usize) -> Pikkr<'a> {
        let mut p = Pikkr {
            backslash: avx::mm256i(BACKSLASH as i8),
            quote: avx::mm256i(QUOTE as i8),
            colon: avx::mm256i(COLON as i8),
            left_brace: avx::mm256i(LEFT_BRACE as i8),
            right_brace: avx::mm256i(RIGHT_BRACE as i8),

            query_strs: query_strs,
            query_strs_len: query_strs.len(),
            queries: FnvHashMap::default(),
            query_num: 0,
            level: 0,

            train_num: train_num,
            trained_num: 0,
            trained: false,

            stats: FnvHashMap::default(),
        };

        let mut level = 0;
        for query_str in query_strs {
            let query_num = set_queries(&mut p.queries, query_str, ROOT_QUERY_STR_OFFSET);
            p.query_num += query_num;
            level = cmp::max(level, query_num);
        }
        p.level = level;

        p
    }

    /// Parses a JSON record and returns the result.
    #[inline]
    pub fn parse<'b>(&mut self, rec: &'b[u8]) -> Vec<Option<&'b[u8]>> {
        let rec_len = rec.len();

        let rec_m256i_len = (rec_len + 31) / 32;
        let mut rec_m256i = Vec::with_capacity(rec_m256i_len);
        avx::u8_to_m256i(rec, &mut rec_m256i);

        let b_len = (rec_m256i_len + 1) / 2;
        let mut b_backslash = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_backslash, self.backslash);
        let mut b_quote = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_quote, self.quote);
        let mut b_colon = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_colon, self.colon);
        let mut b_left = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_left, self.left_brace);
        let mut b_right = Vec::with_capacity(b_len);
        index_builder::build_structural_character_bitmap(&rec_m256i, &mut b_right, self.right_brace);

        index_builder::build_structural_quote_bitmap(&b_backslash, &mut b_quote);

        index_builder::build_string_mask_bitmap(&mut b_quote);
        let b_string_mask = b_quote;

        bit::and(&b_string_mask, &mut b_colon);
        bit::and(&b_string_mask, &mut b_left);
        bit::and(&b_string_mask, &mut b_right);

        let mut index = Vec::with_capacity(self.level);
        index_builder::build_leveled_colon_bitmap(&b_colon, &b_left, &b_right, self.level, &mut index);

        clear_query_results(&mut self.queries);

        if self.trained {
            if !parser::speculative_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, &self.stats) {
                parser::basic_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, self.query_num, 0);
            }
        } else {
            parser::basic_parse(rec, &index, &mut self.queries, 0, rec_len-1, 0, self.query_num, 0);
            set_stats(&self.queries, &mut self.stats);
            self.trained_num += 1;
            if self.trained_num >= self.train_num {
                self.trained = true;
            }
        }

        let mut results = Vec::with_capacity(self.query_strs_len);
        for query_str in self.query_strs {
            set_result(rec, &self.queries, query_str, &mut results, ROOT_QUERY_STR_OFFSET);
        }

        results
    }
}

#[inline]
fn set_queries<'a>(queries: &mut FnvHashMap<&'a[u8], Query<'a>>, s: &'a[u8], i: usize) -> usize {
    for j in i..s.len() {
        if s[j] == DOT {
            let t = s.get(i..j).unwrap();
            let query = queries.entry(t).or_insert(Query {
                result: None,
                children: None,
            });
            let mut children = query.children.get_or_insert(FnvHashMap::default());
            return set_queries(&mut children, s, j+1) + 1;
        }
    }
    let t = s.get(i..s.len()).unwrap();
    if !queries.contains_key(t) {
        queries.insert(t, Query {
            result: None,
            children: None,
        });
        return 1;
    }
    0
}

#[inline]
fn clear_query_results(queries: &mut FnvHashMap<&[u8], Query>) {
    for (_, q) in queries.iter_mut() {
        q.result = None;
        if let Some(ref mut children) = q.children {
            clear_query_results(children);
        }
    }
}

#[inline]
fn set_stats<'a>(queries: &FnvHashMap<&'a[u8], Query<'a>>, stats: &mut FnvHashMap<&'a[u8], Stat<'a>>) {
    for (s, q) in queries.iter() {
        if let Some(result) = q.result {
            let st = stats.entry(s).or_insert(Stat {
                locs: FnvHashSet::default(),
                children: None,
            });
            st.locs.insert(result.2);
            if let Some(ref children) = q.children {
                let st_children = st.children.get_or_insert(FnvHashMap::default());
                set_stats(&children, st_children);
            }
        }
    }
}

#[inline]
fn set_result<'a>(rec: &'a[u8], queries: &FnvHashMap<&[u8], Query>, s: &[u8], d: &mut Vec<Option<&'a[u8]>>, i: usize) {
    for j in i..s.len() {
        if s[j] == DOT {
            let t = s.get(i..j).unwrap();
            match queries.get(t) {
                Some(query) => {
                    match query.children {
                        Some(ref children) => set_result(rec, children, s, d, j+1),
                        _ => d.push(None)
                    }
                },
                _ => d.push(None)
            }
            return;
        }
    }
    let t = s.get(i..s.len()).unwrap();
    d.push(match queries.get(t) {
        Some(query) => {
            match query.result {
                Some(result) => {
                    Some(rec.get(result.0..result.1).unwrap())
                },
                _ => None,
            }
        },
        _ => None,
    });
}

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

    #[test]
    fn test_pikkr_basic_parse() {
        let queries = vec![
            "$.f1".as_bytes(),
            "$.f2".as_bytes(),
            "$.f2.f1".as_bytes(),
            "$.f2.f2.f1".as_bytes(),
            "$.f2.f3".as_bytes(),
            "$.f3".as_bytes(),
            "$.f4".as_bytes(),
        ];
        let mut p = Pikkr::new(&queries, 1000000000);
        struct TestCase<'a> {
            rec: &'a str,
            want: Vec<Option<&'a[u8]>>,
        }
        let test_cases = vec![
            TestCase {
                rec: r#"{}"#,
                want: vec![None, None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a"}"#,
                want: vec![None, None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b"}"#,
                want: vec![Some(r#""b""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    None,
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                    None,
                ]
            },
            TestCase {
                rec: r#"{"f1": "Português do Brasil,Català,Deutsch,Español,Français,Bahasa,Italiano,עִבְרִית,日本語,한국어,Română,中文（简体）,中文（繁體）,Українська,Ўзбекча,Türkçe"}"#,
                want: vec![Some(r#""Português do Brasil,Català,Deutsch,Español,Français,Bahasa,Italiano,עִבְרִית,日本語,한국어,Română,中文（简体）,中文（繁體）,Українська,Ўзбекча,Türkçe""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"{"f1": "\"f1\": \\"}"#,
                want: vec![Some(r#""\"f1\": \\""#.as_bytes()), None, None, None, None, None, None],
            },
            TestCase {
                rec: r#"
                    	{
                     	"f1" 	 : 	 "b"
                    }
                "#,
                want: vec![Some(r#""b""#.as_bytes()), None, None, None, None, None, None],
            },
            // for issue #10
            TestCase {
                rec: r#""#,
                want: vec![None, None, None, None, None],
            },

        ];
        for t in test_cases {
            let got = p.parse(t.rec.as_bytes());
            assert_eq!(t.want, got);
        }
    }

    #[test]
    fn test_pikkr_speculative_parse() {
        let queries = vec![
            "$.f1".as_bytes(),
            "$.f2".as_bytes(),
            "$.f2.f1".as_bytes(),
            "$.f2.f2.f1".as_bytes(),
            "$.f3".as_bytes(),
        ];
        let mut p = Pikkr::new(&queries, 1);
        struct TestCase<'a> {
            rec: &'a str,
            want: Vec<Option<&'a[u8]>>,
        }
        let test_cases = vec![
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}, "f3": [1, 2, 3]}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f1": "b", "f0": "a", "f3": [1, 2, 3], "f2": {"f2": {"f2": "d", "f1": "c"}, "f1": 1}}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f2": {"f2": "d", "f1": "c"}, "f1": 1}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    Some(r#"[1, 2, 3]"#.as_bytes()),
                ]
            },
            TestCase {
                rec: r#"{"f0": "a", "f1": "b", "f2": {"f1": 1, "f2": {"f1": "c", "f2": "d"}}}"#,
                want: vec![
                    Some(r#""b""#.as_bytes()),
                    Some(r#"{"f1": 1, "f2": {"f1": "c", "f2": "d"}}"#.as_bytes()),
                    Some(r#"1"#.as_bytes()),
                    Some(r#""c""#.as_bytes()),
                    None,
                ]
            },
            TestCase {
                rec: r#"{}"#,
                want: vec![None, None, None, None, None],
            },
            // for issue #10
            TestCase {
                rec: r#""#,
                want: vec![None, None, None, None, None],
            },
        ];
        for t in test_cases {
            let got = p.parse(t.rec.as_bytes());
            assert_eq!(t.want, got);
        }
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use primitives::{ConsumedResult, Error, Info, ParseError, Parser, RangeStream};
use primitives::FastResult::*;

pub struct Range<I>(I::Range) where I: RangeStream;

impl<I> Parser for Range<I>
    where I: RangeStream,
          I::Range: PartialEq + ::primitives::Range
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, mut input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        use primitives::Range;
        let position = input.position();
        match input.uncons_range(self.0.len()) {
            Ok(other) => {
                if other == self.0 {
                    ConsumedOk((other, input))
                } else {
                    EmptyErr(ParseError::empty(position))
                }
            }
            Err(err) => EmptyErr(ParseError::new(position, err)),
        }
    }
    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
        // TODO Add unexpected message?
        errors.add_error(Error::Expected(Info::Range(self.0.clone())));
    }
}

/// ```
/// # extern crate combine;
/// # use combine::range::range;
/// # use combine::*;
/// # fn main() {
/// let mut parser = range("hello");
/// let result = parser.parse("hello world");
/// assert_eq!(result, Ok(("hello", " world")));
/// let result = parser.parse("hel world");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn range<I>(i: I::Range) -> Range<I>
    where I: RangeStream,
          I::Range: PartialEq + ::primitives::Range
{
    Range(i)
}

pub struct Take<I>(usize, PhantomData<fn(I) -> I>);
impl<I> Parser for Take<I>
    where I: RangeStream,
          I::Range: ::primitives::Range
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, mut input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        let position = input.position();
        match input.uncons_range(self.0) {
            Ok(x) => ConsumedOk((x, input)),
            Err(err) => EmptyErr(ParseError::new(position, err)),
        }
    }
}

/// ```
/// # extern crate combine;
/// # use combine::range::take;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take(1);
/// let result = parser.parse("1");
/// assert_eq!(result, Ok(("1", "")));
/// let mut parser = take(4);
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123a", "bc")));
/// let result = parser.parse("abc");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn take<I>(n: usize) -> Take<I>
    where I: RangeStream,
          I::Range: ::primitives::Range
{
    Take(n, PhantomData)
}

pub struct TakeWhile<I, F>(F, PhantomData<fn(I) -> I>);
impl<I, F> Parser for TakeWhile<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        ::primitives::uncons_while(input, &mut self.0)
    }
}

/// ```
/// # extern crate combine;
/// # use combine::range::take_while;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take_while(|c: char| c.is_digit(10));
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123", "abc")));
/// let result = parser.parse("abc");
/// assert_eq!(result, Ok(("", "abc")));
/// # }
/// ```
#[inline(always)]
pub fn take_while<I, F>(f: F) -> TakeWhile<I, F>
    where I: RangeStream,
          F: FnMut(I::Item) -> bool
{
    TakeWhile(f, PhantomData)
}

pub struct TakeWhile1<I, F>(F, PhantomData<fn(I) -> I>);
impl<I, F> Parser for TakeWhile1<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        match ::primitives::uncons_while(input, &mut self.0) {
            ConsumedOk((v, input)) => ConsumedOk((v, input)),
            EmptyOk((_, input)) => {
                let position = input.position();
                EmptyErr(ParseError::empty(position))
            }
            EmptyErr(err) => EmptyErr(err),
            ConsumedErr(err) => ConsumedErr(err),
        }
    }
}

/// ```
/// # extern crate combine;
/// # use combine::range::take_while1;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take_while1(|c: char| c.is_digit(10));
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123", "abc")));
/// let result = parser.parse("abc");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn take_while1<I, F>(f: F) -> TakeWhile1<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    TakeWhile1(f, PhantomData)
}

#[cfg(test)]
mod tests {
    use super::*;
    use primitives::Parser;

    #[test]
    fn take_while_test() {
        let result = take_while(|c: char| c.is_digit(10)).parse("123abc");
        assert_eq!(result, Ok(("123", "abc")));
        let result = take_while(|c: char| c.is_digit(10)).parse("abc");
        assert_eq!(result, Ok(("", "abc")));
    }

    #[test]
    fn take_while1_test() {
        let result = take_while1(|c: char| c.is_digit(10)).parse("123abc");
        assert_eq!(result, Ok(("123", "abc")));
        let result = take_while1(|c: char| c.is_digit(10)).parse("abc");
        assert!(result.is_err());
    }

    #[test]
    fn range_string_no_char_boundary_error() {
        let mut parser = range("hello");
        let result = parser.parse("hell\u{00EE} world");
        assert!(result.is_err());
    }
}
<commit_msg>docs: Document the zero copy parsers<commit_after>use std::marker::PhantomData;

use primitives::{ConsumedResult, Error, Info, ParseError, Parser, RangeStream};
use primitives::FastResult::*;

pub struct Range<I>(I::Range) where I: RangeStream;

impl<I> Parser for Range<I>
    where I: RangeStream,
          I::Range: PartialEq + ::primitives::Range
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, mut input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        use primitives::Range;
        let position = input.position();
        match input.uncons_range(self.0.len()) {
            Ok(other) => {
                if other == self.0 {
                    ConsumedOk((other, input))
                } else {
                    EmptyErr(ParseError::empty(position))
                }
            }
            Err(err) => EmptyErr(ParseError::new(position, err)),
        }
    }
    fn add_error(&mut self, errors: &mut ParseError<Self::Input>) {
        // TODO Add unexpected message?
        errors.add_error(Error::Expected(Info::Range(self.0.clone())));
    }
}

/// Zero-copy parser which reads a range of length `i.len()` and succeds if `i` is equal to that
/// range
///
/// ```
/// # extern crate combine;
/// # use combine::range::range;
/// # use combine::*;
/// # fn main() {
/// let mut parser = range("hello");
/// let result = parser.parse("hello world");
/// assert_eq!(result, Ok(("hello", " world")));
/// let result = parser.parse("hel world");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn range<I>(i: I::Range) -> Range<I>
    where I: RangeStream,
          I::Range: PartialEq + ::primitives::Range
{
    Range(i)
}

pub struct Take<I>(usize, PhantomData<fn(I) -> I>);
impl<I> Parser for Take<I>
    where I: RangeStream,
          I::Range: ::primitives::Range
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, mut input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        let position = input.position();
        match input.uncons_range(self.0) {
            Ok(x) => ConsumedOk((x, input)),
            Err(err) => EmptyErr(ParseError::new(position, err)),
        }
    }
}

/// Zero-copy parser which reads a range of length `n`
///
/// ```
/// # extern crate combine;
/// # use combine::range::take;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take(1);
/// let result = parser.parse("1");
/// assert_eq!(result, Ok(("1", "")));
/// let mut parser = take(4);
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123a", "bc")));
/// let result = parser.parse("abc");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn take<I>(n: usize) -> Take<I>
    where I: RangeStream,
          I::Range: ::primitives::Range
{
    Take(n, PhantomData)
}

pub struct TakeWhile<I, F>(F, PhantomData<fn(I) -> I>);
impl<I, F> Parser for TakeWhile<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        ::primitives::uncons_while(input, &mut self.0)
    }
}

/// Zero-copy parser which reads a range of 0 or more tokens which satisfy `f`
///
/// ```
/// # extern crate combine;
/// # use combine::range::take_while;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take_while(|c: char| c.is_digit(10));
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123", "abc")));
/// let result = parser.parse("abc");
/// assert_eq!(result, Ok(("", "abc")));
/// # }
/// ```
#[inline(always)]
pub fn take_while<I, F>(f: F) -> TakeWhile<I, F>
    where I: RangeStream,
          F: FnMut(I::Item) -> bool
{
    TakeWhile(f, PhantomData)
}

pub struct TakeWhile1<I, F>(F, PhantomData<fn(I) -> I>);
impl<I, F> Parser for TakeWhile1<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    type Input = I;
    type Output = I::Range;

    #[inline]
    fn parse_lazy(&mut self, input: Self::Input) -> ConsumedResult<Self::Output, Self::Input> {
        match ::primitives::uncons_while(input, &mut self.0) {
            ConsumedOk((v, input)) => ConsumedOk((v, input)),
            EmptyOk((_, input)) => {
                let position = input.position();
                EmptyErr(ParseError::empty(position))
            }
            EmptyErr(err) => EmptyErr(err),
            ConsumedErr(err) => ConsumedErr(err),
        }
    }
}

/// Zero-copy parser which reads a range of 1 or more tokens which satisfy `f`
///
/// ```
/// # extern crate combine;
/// # use combine::range::take_while1;
/// # use combine::*;
/// # fn main() {
/// let mut parser = take_while1(|c: char| c.is_digit(10));
/// let result = parser.parse("123abc");
/// assert_eq!(result, Ok(("123", "abc")));
/// let result = parser.parse("abc");
/// assert!(result.is_err());
/// # }
/// ```
#[inline(always)]
pub fn take_while1<I, F>(f: F) -> TakeWhile1<I, F>
    where I: RangeStream,
          I::Range: ::primitives::Range,
          F: FnMut(I::Item) -> bool
{
    TakeWhile1(f, PhantomData)
}

#[cfg(test)]
mod tests {
    use super::*;
    use primitives::Parser;

    #[test]
    fn take_while_test() {
        let result = take_while(|c: char| c.is_digit(10)).parse("123abc");
        assert_eq!(result, Ok(("123", "abc")));
        let result = take_while(|c: char| c.is_digit(10)).parse("abc");
        assert_eq!(result, Ok(("", "abc")));
    }

    #[test]
    fn take_while1_test() {
        let result = take_while1(|c: char| c.is_digit(10)).parse("123abc");
        assert_eq!(result, Ok(("123", "abc")));
        let result = take_while1(|c: char| c.is_digit(10)).parse("abc");
        assert!(result.is_err());
    }

    #[test]
    fn range_string_no_char_boundary_error() {
        let mut parser = range("hello");
        let result = parser.parse("hell\u{00EE} world");
        assert!(result.is_err());
    }
}
<|endoftext|>


<commit_before>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = usize;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

s! {
    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
        __align: [u32; 0],
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_in {
        pub sin_family: sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [u8; 8],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }
}

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
}
<commit_msg>Auto merge of #488 - redox-os:redox, r=alexcrichton<commit_after>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = usize;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type in_addr_t = u32;
pub type in_port_t = u16;

pub type socklen_t = u32;
pub type sa_family_t = u16;

s! {
    pub struct in_addr {
        pub s_addr: in_addr_t,
    }

    pub struct in6_addr {
        pub s6_addr: [u8; 16],
        __align: [u32; 0],
    }

    pub struct sockaddr {
        pub sa_family: sa_family_t,
        pub sa_data: [::c_char; 14],
    }

    pub struct sockaddr_in {
        pub sin_family: sa_family_t,
        pub sin_port: ::in_port_t,
        pub sin_addr: ::in_addr,
        pub sin_zero: [u8; 8],
    }

    pub struct sockaddr_in6 {
        pub sin6_family: sa_family_t,
        pub sin6_port: in_port_t,
        pub sin6_flowinfo: u32,
        pub sin6_addr: ::in6_addr,
        pub sin6_scope_id: u32,
    }
}

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
}

#[link(name = "c", kind = "static")]
#[link(name = "m", kind = "static")]
extern {}
<|endoftext|>


<commit_before>//!
//! A reply is passed to filesystem operation implementations and must
//! be used to send back the result of an operation.
//! The reply can optionally be sent to another task to asynchronously
//! work on an operation and provide the result later. Also it allows
//! replying with a block of data without cloning the data.
//! A reply *must always* be used (by calling either ok() or error()
//! exactly once).
//!

use std::mem;
use std::libc::{c_int, EIO};
use channel::ChannelSender;
use fuse::fuse_out_header;
use sendable::Sendable;

/// Create a new reply for the given request
pub fn reply<T: Sendable> (ch: ChannelSender, unique: u64) -> Reply<T> {
	Reply::new(ch, unique)
}

/// Reply data structure
pub struct Reply<T> {
	/// Channel sender for sending the reply
	priv ch: ChannelSender,
	/// Unique id of the request to reply to
	priv unique: u64,
	/// Flag whether the reply was sent
	priv replied: bool,
}

impl<T: Sendable> Reply<T> {
	/// Create a new reply for the given request
	fn new (ch: ChannelSender, unique: u64) -> Reply<T> {
		Reply { ch: ch, unique: unique, replied: false }
	}

	/// Reply to a request with the given error code and data
	fn send (&mut self, err: c_int, bytes: &[&[u8]]) {
		if self.replied {
			warn!("Ignoring duplicate reply for operation {:u}", self.unique);
			return;
		}
		let len = bytes.iter().fold(0, |l, b| { l +  b.len()});
		let outheader = fuse_out_header {
			len: mem::size_of::<fuse_out_header>() as u32 + len as u32,
			error: err,
			unique: self.unique,
		};
		outheader.as_bytegroups(|headbytes| {
			let _ = self.ch.send(headbytes + bytes);
			self.replied = true;
		});
	}

	/// Reply to a request with the given data
	pub fn ok (mut self, data: &T) {
		data.as_bytegroups(|bytes| {
			self.send(0, bytes);
		});
	}

	/// Reply to a request with the given error code
	pub fn error (mut self, err: c_int) {
		self.send(-err, []);
	}
}

#[unsafe_destructor]
impl<T: Sendable> Drop for Reply<T> {
	fn drop (&mut self) {
		if !self.replied {
			warn!("Reply not sent for operation {:u}, replying with I/O error", self.unique);
			self.send(-EIO, []);
		}
	}
}
<commit_msg>Replace duplicate reply warning with a simple assertion since `ok` and `reply` can only be called once now<commit_after>//!
//! A reply is passed to filesystem operation implementations and must
//! be used to send back the result of an operation.
//! The reply can optionally be sent to another task to asynchronously
//! work on an operation and provide the result later. Also it allows
//! replying with a block of data without cloning the data.
//! A reply *must always* be used (by calling either ok() or error()
//! exactly once).
//!

use std::mem;
use std::libc::{c_int, EIO};
use channel::ChannelSender;
use fuse::fuse_out_header;
use sendable::Sendable;

/// Create a new reply for the given request
pub fn reply<T: Sendable> (ch: ChannelSender, unique: u64) -> Reply<T> {
	Reply::new(ch, unique)
}

/// Reply data structure
pub struct Reply<T> {
	/// Channel sender for sending the reply
	priv ch: ChannelSender,
	/// Unique id of the request to reply to
	priv unique: u64,
	/// Flag whether the reply was sent
	priv replied: bool,
}

impl<T: Sendable> Reply<T> {
	/// Create a new reply for the given request
	fn new (ch: ChannelSender, unique: u64) -> Reply<T> {
		Reply { ch: ch, unique: unique, replied: false }
	}

	/// Reply to a request with the given error code and data. Must be called
	/// only once (the `ok` and `error` methods ensure this by consuming `self`)
	fn send (&mut self, err: c_int, bytes: &[&[u8]]) {
		assert!(!self.replied);
		let len = bytes.iter().fold(0, |l, b| { l +  b.len()});
		let outheader = fuse_out_header {
			len: mem::size_of::<fuse_out_header>() as u32 + len as u32,
			error: err,
			unique: self.unique,
		};
		outheader.as_bytegroups(|headbytes| {
			let _ = self.ch.send(headbytes + bytes);
			self.replied = true;
		});
	}

	/// Reply to a request with the given data
	pub fn ok (mut self, data: &T) {
		data.as_bytegroups(|bytes| {
			self.send(0, bytes);
		});
	}

	/// Reply to a request with the given error code
	pub fn error (mut self, err: c_int) {
		self.send(-err, []);
	}
}

#[unsafe_destructor]
impl<T: Sendable> Drop for Reply<T> {
	fn drop (&mut self) {
		if !self.replied {
			warn!("Reply not sent for operation {:u}, replying with I/O error", self.unique);
			self.send(-EIO, []);
		}
	}
}
<|endoftext|>


<commit_before>use physics_client::PhysicsClientHandle;

use mint::{Vector3, Vector4};

pub enum ShapeType {
    Sphere { radius: f64 },
    Cylinder,
    Box,
    Capsule { height: f64, radius: f64 },
    Plane { normal: Vector3<f64>, constant: f64 },
    TriMesh {
        vertices: Vec<Vector3<f64>>,
        scale: Vector3<f64>,
    },
    Compound(Vec<(ShapeType, Vector3<f64>, Vector4<f64>)>),
}

#[derive(Clone)]
pub struct Shape {
    pub(crate) client_handle: PhysicsClientHandle,
    pub(crate) unique_id: i32,
}

impl ShapeType {
    pub(crate) fn create_shape(&self, command: ::sys::b3SharedMemoryCommandHandle) -> Option<i32> {
        match self {
            &ShapeType::Plane { normal, constant } => {
                let mut normal: [f64; 3] = normal.into();
                let shape_id = unsafe {
                    ::sys::b3CreateCollisionShapeAddPlane(
                        command,
                        &mut normal[0] as *mut f64,
                        constant,
                    )
                };
                Some(shape_id)
            }
            &ShapeType::Capsule { radius, height } => unsafe {
                let shape_id = ::sys::b3CreateCollisionShapeAddCapsule(command, radius, height);
                Some(shape_id)
            },
            &ShapeType::Sphere { radius } => unsafe {
                let shape_id = ::sys::b3CreateCollisionShapeAddSphere(command, radius);
                Some(shape_id)
            },
            &ShapeType::TriMesh {
                ref vertices,
                scale,
            } => unsafe {
                let mut scale: [f64; 3] = scale.into();

                let shape_id = ::sys::b3CreateCollisionShapeAddTriMesh(
                    command,
                    vertices.len() as i32,
                    ::std::mem::transmute(vertices.as_ptr()),
                    (&mut scale).as_mut_ptr(),
                );
                Some(shape_id)
            },

            &ShapeType::Compound(ref shapes) => {
                for &(ref shape, position, orientation) in shapes {
                    let shape_unique_id = shape
                        .create_shape(command)
                        .expect("Only one level of compound shapes supprted!");
                    let mut position: [f64; 3] = position.into();
                    let mut orientation: [f64; 4] = orientation.into();

                    unsafe {
                        ::sys::b3CreateCollisionShapeSetChildTransform(
                            command,
                            shape_unique_id,
                            &mut position[0] as *mut _,
                            &mut orientation[0] as *mut _,
                        );
                    }
                }
                None
            }
            _ => unimplemented!(),
        }
    }
}

<commit_msg>add support for Box shapes<commit_after>use physics_client::PhysicsClientHandle;

use mint::{Vector3, Vector4};

pub enum ShapeType {
    Sphere { radius: f64 },
    Cylinder,
    Box { half_extents: Vector3<f64> },
    Capsule { height: f64, radius: f64 },
    Plane { normal: Vector3<f64>, constant: f64 },
    TriMesh {
        vertices: Vec<Vector3<f64>>,
        scale: Vector3<f64>,
    },
    Compound(Vec<(ShapeType, Vector3<f64>, Vector4<f64>)>),
}

#[derive(Clone)]
pub struct Shape {
    pub(crate) client_handle: PhysicsClientHandle,
    pub(crate) unique_id: i32,
}

impl ShapeType {
    pub(crate) fn create_shape(&self, command: ::sys::b3SharedMemoryCommandHandle) -> Option<i32> {
        match self {
            &ShapeType::Plane { normal, constant } => {
                let mut normal: [f64; 3] = normal.into();
                let shape_id = unsafe {
                    ::sys::b3CreateCollisionShapeAddPlane(
                        command,
                        &mut normal[0] as *mut f64,
                        constant,
                    )
                };
                Some(shape_id)
            }
            &ShapeType::Box { half_extents } => unsafe {
                let mut half_extents: [f64; 3] = half_extents.into();
                let shape_id =
                    ::sys::b3CreateCollisionShapeAddBox(command, &mut half_extents[0] as *mut f64);
                Some(shape_id)
            },
            &ShapeType::Capsule { radius, height } => unsafe {
                let shape_id = ::sys::b3CreateCollisionShapeAddCapsule(command, radius, height);
                Some(shape_id)
            },
            &ShapeType::Sphere { radius } => unsafe {
                let shape_id = ::sys::b3CreateCollisionShapeAddSphere(command, radius);
                Some(shape_id)
            },
            &ShapeType::TriMesh {
                ref vertices,
                scale,
            } => unsafe {
                let mut scale: [f64; 3] = scale.into();

                let shape_id = ::sys::b3CreateCollisionShapeAddTriMesh(
                    command,
                    vertices.len() as i32,
                    ::std::mem::transmute(vertices.as_ptr()),
                    (&mut scale).as_mut_ptr(),
                );
                Some(shape_id)
            },

            &ShapeType::Compound(ref shapes) => {
                for &(ref shape, position, orientation) in shapes {
                    let shape_unique_id = shape
                        .create_shape(command)
                        .expect("Only one level of compound shapes supprted!");
                    let mut position: [f64; 3] = position.into();
                    let mut orientation: [f64; 4] = orientation.into();

                    unsafe {
                        ::sys::b3CreateCollisionShapeSetChildTransform(
                            command,
                            shape_unique_id,
                            &mut position[0] as *mut _,
                            &mut orientation[0] as *mut _,
                        );
                    }
                }
                None
            }
            _ => unimplemented!(),
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
extern crate arcball;
extern crate cgmath;

use glium::Surface;
use glium::index::PrimitiveType;
use glium::glutin::{self, ControlFlow, ElementState, Event, MouseButton, MouseScrollDelta,
                    VirtualKeyCode, WindowEvent};
use cgmath::{Point3, Vector3, Vector2, Matrix4};
use arcball::ArcballCamera;

#[derive(Copy, Clone)]
struct Vertex {
    pos: [f32; 3],
    color: [f32; 3],
}
implement_vertex!(Vertex, pos, color);

fn main() {

    let window = glutin::WindowBuilder::new()
        .with_title("Arcball Camera Cube Example");
    let context = glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_depth_buffer(24);
    let mut events_loop = glutin::EventsLoop::new();

    let display =
        glium::Display::new(window, context, &events_loop).expect("failed to create display");

    // Hard-coded cube triangle strip
    let vertex_buffer = glium::VertexBuffer::new(&display,
        &[Vertex { pos: [1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 0.0, 0.0] },

            Vertex { pos: [-1.0, 1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [0.0, 1.0, 0.0] },

            Vertex { pos: [-1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, 1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },

            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },

            Vertex { pos: [1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] },
            Vertex { pos: [-1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] }
        ]
    ).unwrap();
    let index_buffer = glium::index::NoIndices(PrimitiveType::TriangleStrip);

    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 proj_view;

                in vec3 pos;
                in vec3 color;

                out vec3 vcolor;

                void main(void) {
                    gl_Position = proj_view * vec4(pos, 1.0);
                    vcolor = color;
                }
            ",
            fragment: "
                #version 140

                in vec3 vcolor;
                out vec4 color;

                void main(void) {
                    color = vec4(vcolor, 1.0);
                }
            "
        },
    ).unwrap();

    let display_dims = display.get_framebuffer_dimensions();
    let mut persp_proj = cgmath::perspective(cgmath::Deg(65.0), display_dims.0 as f32 / display_dims.1 as f32,
                                             1.0, 200.0);
    let mut arcball_camera = {
        let look_at = Matrix4::<f32>::look_at(Point3::new(0.0, 0.0, 6.0),
                                              Point3::new(0.0, 0.0, 0.0),
                                              Vector3::new(0.0, 1.0, 0.0));
        ArcballCamera::new(&look_at, 0.05, 4.0, [display_dims.0 as f32, display_dims.1 as f32])
    };

    // Track if left/right mouse is down
    let mut mouse_pressed = [false, false];
    let mut prev_mouse: Option<(f32, f32)> = None;

    events_loop.run_forever(|e| {
        match e {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::CloseRequested => return ControlFlow::Break,
                WindowEvent::KeyboardInput { input, .. } => {
                    let code = input.virtual_keycode;
                    let pressed = input.state == ElementState::Pressed;
                    match code {
                        Some(VirtualKeyCode::Escape) if pressed => return ControlFlow::Break,
                        _ => {}
                    }
                }

                WindowEvent::CursorMoved { position, .. } => {
                    let x = position.x as f32;
                    let y = position.y as f32;

                    if prev_mouse.is_none() {
                        prev_mouse = Some((x, y));
                    } else {
                        let prev = prev_mouse.unwrap();
                        if mouse_pressed[0] {
                            arcball_camera.rotate(
                                Vector2::new(prev.0, prev.1),
                                Vector2::new(x, y),
                            );
                        } else if mouse_pressed[1] {
                            let mouse_delta =
                                Vector2::new((x - prev.0), -(y - prev.1));
                            arcball_camera.pan(mouse_delta, 0.16);
                        }
                        prev_mouse = Some((x, y));
                    }
                }
                WindowEvent::MouseInput { state, button, .. } => {
                    if button == MouseButton::Left {
                        mouse_pressed[0] = state == ElementState::Pressed;
                    } else if button == MouseButton::Right {
                        mouse_pressed[1] = state == ElementState::Pressed;
                    }
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let y = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(p) => p.y as f32,
                    };
                    arcball_camera.zoom(y, 0.16);
                }
                WindowEvent::Resized(size) => {
                    let w = size.width as f32;
                    let h = size.height as f32;
                    persp_proj =
                        cgmath::perspective(cgmath::Deg(65.0), w / h, 1.0, 1000.0);
                    arcball_camera.update_screen(w, h);
                }
                _ => {
                    return ControlFlow::Continue;
                }
            },
            _ => {
                return ControlFlow::Continue;
            }
        }

        let proj_view: [[f32; 4]; 4] = (persp_proj * arcball_camera.get_mat4()).into();
        let uniforms = uniform! {
            proj_view: proj_view,
        };
        let draw_params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        let mut target = display.draw();
        target.clear_color(0.1, 0.1, 0.1, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &draw_params).unwrap();
        target.finish().unwrap();

        return ControlFlow::Continue;
    });
}

<commit_msg>Add note on cube example<commit_after>#[macro_use]
extern crate glium;
extern crate arcball;
extern crate cgmath;

use glium::Surface;
use glium::index::PrimitiveType;
use glium::glutin::{self, ControlFlow, ElementState, Event, MouseButton, MouseScrollDelta,
                    VirtualKeyCode, WindowEvent};
use cgmath::{Point3, Vector3, Vector2, Matrix4};
use arcball::ArcballCamera;

#[derive(Copy, Clone)]
struct Vertex {
    pos: [f32; 3],
    color: [f32; 3],
}
implement_vertex!(Vertex, pos, color);

fn main() {

    let window = glutin::WindowBuilder::new()
        .with_title("Arcball Camera Cube Example");
    let context = glutin::ContextBuilder::new()
        .with_vsync(true)
        .with_depth_buffer(24);
    let mut events_loop = glutin::EventsLoop::new();

    let display =
        glium::Display::new(window, context, &events_loop).expect("failed to create display");

    // Hard-coded cube triangle strip
    let vertex_buffer = glium::VertexBuffer::new(&display,
        &[Vertex { pos: [1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [1.0, 0.0, 0.0] },
            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 0.0, 0.0] },

            Vertex { pos: [-1.0, 1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [0.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, 1.0, -1.0], color: [0.0, 1.0, 0.0] },

            Vertex { pos: [-1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, 1.0, -1.0], color: [0.0, 0.0, 1.0] },
            Vertex { pos: [1.0, -1.0, -1.0], color: [0.0, 0.0, 1.0] },

            Vertex { pos: [1.0, 1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },
            Vertex { pos: [-1.0, -1.0, 1.0], color: [1.0, 1.0, 0.0] },

            Vertex { pos: [1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] },
            Vertex { pos: [-1.0, -1.0, -1.0], color: [1.0, 0.0, 1.0] }
        ]
    ).unwrap();
    let index_buffer = glium::index::NoIndices(PrimitiveType::TriangleStrip);

    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 proj_view;

                in vec3 pos;
                in vec3 color;

                out vec3 vcolor;

                void main(void) {
                    gl_Position = proj_view * vec4(pos, 1.0);
                    vcolor = color;
                }
            ",
            fragment: "
                #version 140

                in vec3 vcolor;
                out vec4 color;

                void main(void) {
                    color = vec4(vcolor, 1.0);
                }
            "
        },
    ).unwrap();

    let display_dims = display.get_framebuffer_dimensions();
    let mut persp_proj = cgmath::perspective(cgmath::Deg(65.0), display_dims.0 as f32 / display_dims.1 as f32,
                                             1.0, 200.0);
    let mut arcball_camera = {
        let look_at = Matrix4::<f32>::look_at(Point3::new(0.0, 0.0, 6.0),
                                              Point3::new(0.0, 0.0, 0.0),
                                              Vector3::new(0.0, 1.0, 0.0));
        ArcballCamera::new(&look_at, 0.05, 4.0, [display_dims.0 as f32, display_dims.1 as f32])
    };

    // Track if left/right mouse is down
    let mut mouse_pressed = [false, false];
    let mut prev_mouse: Option<(f32, f32)> = None;

    // TODO: Seems like there's some odd delay or buffering in the event
    // loop that gives this weird latency feel to the interaction and rendering.
    // Should fix this
    events_loop.run_forever(|e| {
        match e {
            Event::WindowEvent { event, .. } => match event {
                WindowEvent::CloseRequested => return ControlFlow::Break,
                WindowEvent::KeyboardInput { input, .. } => {
                    let code = input.virtual_keycode;
                    let pressed = input.state == ElementState::Pressed;
                    match code {
                        Some(VirtualKeyCode::Escape) if pressed => return ControlFlow::Break,
                        _ => {}
                    }
                }

                WindowEvent::CursorMoved { position, .. } => {
                    let x = position.x as f32;
                    let y = position.y as f32;

                    if prev_mouse.is_none() {
                        prev_mouse = Some((x, y));
                    } else {
                        let prev = prev_mouse.unwrap();
                        if mouse_pressed[0] {
                            arcball_camera.rotate(
                                Vector2::new(prev.0, prev.1),
                                Vector2::new(x, y),
                            );
                        } else if mouse_pressed[1] {
                            let mouse_delta =
                                Vector2::new(x - prev.0, -(y - prev.1));
                            arcball_camera.pan(mouse_delta, 0.16);
                        }
                        prev_mouse = Some((x, y));
                    }
                }
                WindowEvent::MouseInput { state, button, .. } => {
                    if button == MouseButton::Left {
                        mouse_pressed[0] = state == ElementState::Pressed;
                    } else if button == MouseButton::Right {
                        mouse_pressed[1] = state == ElementState::Pressed;
                    }
                }
                WindowEvent::MouseWheel { delta, .. } => {
                    let y = match delta {
                        MouseScrollDelta::LineDelta(_, y) => y,
                        MouseScrollDelta::PixelDelta(p) => p.y as f32,
                    };
                    arcball_camera.zoom(y, 0.16);
                }
                WindowEvent::Resized(size) => {
                    let w = size.width as f32;
                    let h = size.height as f32;
                    persp_proj =
                        cgmath::perspective(cgmath::Deg(65.0), w / h, 1.0, 1000.0);
                    arcball_camera.update_screen(w, h);
                }
                _ => {
                    return ControlFlow::Continue;
                }
            },
            _ => {
                return ControlFlow::Continue;
            }
        }

        let proj_view: [[f32; 4]; 4] = (persp_proj * arcball_camera.get_mat4()).into();
        let uniforms = uniform! {
            proj_view: proj_view,
        };
        let draw_params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::draw_parameters::DepthTest::IfLess,
                write: true,
                ..Default::default()
            },
            ..Default::default()
        };

        let mut target = display.draw();
        target.clear_color(0.1, 0.1, 0.1, 0.0);
        target.clear_depth(1.0);
        target.draw(&vertex_buffer, &index_buffer, &program, &uniforms, &draw_params).unwrap();
        target.finish().unwrap();

        return ControlFlow::Continue;
    });
}

<|endoftext|>