<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use core::*;

struct SymbolTable {
    pub table: HashMap<String, Option<Epiq>>,
}

pub struct Evaluator<'a> {
    ast :&'a RefCell<AbstractSyntaxTree>,
    symbol_table: SymbolTable,
}

enum Result {
    MakeEpiq(Option<Epiq>),
    NewIndex(u32),
}

impl<'a> Evaluator<'a> {
    pub fn new(ast :&'a RefCell<AbstractSyntaxTree>) -> Evaluator {
        Evaluator{ ast: ast, symbol_table: SymbolTable{ table: HashMap::new() } }
    }

    pub fn walk(&mut self) -> Option<&RefCell<AbstractSyntaxTree>> {
        println!("\n");
        let index;
        {
            let borrowed_ast = self.ast.borrow();
            index = borrowed_ast.entrypoint.unwrap();
        }
        let result = self.walk_internal(index, 0);
        // println!("max: {:?} index: {:?}", result, index);
        if result != index {
            // なんらかの変化があったので反映する必要がある
            // ここだと、entrypointを変更する
            let mut ast = self.ast.borrow_mut();
            (*ast).entrypoint = Some(result);
        }

        Some(self.ast)
    }

    fn walk_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        // self.eval_internal(index)
        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}walk ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ひとまずpは無視
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        _ => {

                            // その他のTpiqの場合は、pとq両方をwalkしてみて、
                            // 結果が両方とも変わらなければそのまま返す、
                            // そうでなければ新しくTpiqを作ってそのindexを返す
                            println!("{}walk >以外 pに入ります", " ".repeat(lvl));
                            let new_p = self.walk_internal(p, nest_level+1);
                            println!("{}walk >以外 qに入ります", " ".repeat(lvl));
                            let new_q = self.walk_internal(q, nest_level+1);
                            if new_p == p && new_q == q {
                                // println!("{}pもqも同じなので変化なし", " ".repeat(lvl));
                                Result::MakeEpiq(None)
                            } else {
                                // 新しくTpiqを作成

                                Result::MakeEpiq(Some(Epiq::Tpiq{o: o.to_string(), p: new_p, q: new_q}))
                            }
                        },
                    }
                },
                _ => Result::MakeEpiq(None),
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}walk 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}walk 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}walk 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}eval ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Unit | Epiq::Uit8(_) | Epiq::Name(_) => Result::MakeEpiq(None),
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        // bind
                        "#" => {
                            let p_name = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(p).clone()
                            };
                            if let Epiq::Name(ref n) = p_name {
                                let q_val = {
                                    let borrowed_ast = self.ast.borrow();
                                    borrowed_ast.get(q).clone()
                                };
                                self.symbol_table.table.insert(n.to_string(), Some(q_val));

                                Result::MakeEpiq(Some(Epiq::Unit))
                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // environment
                        "%" => {
                            // ひとまずNoneを返しておく
                            Result::MakeEpiq(None)
                        },

                        // block
                        r"\" => {
                            // TODO: 一つ目の環境の中身はひとまず無視する
                            // qのリストだけを逐次実行して、勝手に最後の値をwalkしてから返却するようにする
                            // ただ、そもそも、blockをevalしても、何も変化はないはず。
                            Result::MakeEpiq(None)
                        },

                        // apply
                        "!" => {
                            // p: lambda q:arguments
                            // 1. bind p.p(環境)の順番に沿って、q(引数リスト)を当てはめていく

                            // TODO: とりあえず引数なしとして処理する

                            // 2. p.q(関数本体)をそのまま返却する
                            let borrowed_ast = self.ast.borrow();
                            let lambda_piq = borrowed_ast.get(p);
                            if let &Epiq::Tpiq{o:_, p:_, q:lambda_body} = lambda_piq {
                                // 本来は一応walkを挟むべきかもしれない
                                let new_lambda_body = self.walk_internal(lambda_body, nest_level+1);
                                /*
                                if new_lambda_body == lambda_body {
                                    // walk_internalの結果でも変化はないし、Noneを返す
                                    Result::MakeEpiq(None)
                                } else {
                                    // walk_internalの結果、変化があったんだけど、
                                    // それってもうepiqとしては作られているので、
                                    // そのままNoneを返せばいい？
                                    // でもそうなると、新しいnew_lambda_bodyが返せない

                                    // Some(borrowed_ast.get(new_lambda_body).clone())
                                    Result::NewIndex(new_lambda_body)
                                }
                                */
                                Result::NewIndex(new_lambda_body)

                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // eval
                        ">" => {
                            println!("eval");
                            // p: 用途未定。新しく何かを限定したりとかかなあ。
                            //    アイディアは思いつくけど、
                            //    そもそもパーサを変えたりとか？
                            //    環境を変更したりとか？
                            //    継続っぽく使うとか？
                            // q: evalされる本体。
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        // resolve
                        "@" => {
                            // p: 用途未定。ひとまず無視
                            // q: シンボルというか名前
                            let p_name = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(q).clone()
                            };
                            if let Epiq::Name(ref n) = p_name {
                                match self.symbol_table.table.get(n) {
                                    Some(&Some(ref res)) => Result::MakeEpiq(Some(res.clone())),
                                    _ => Result::MakeEpiq(None),
                                }
                            } else {
                                Result::MakeEpiq(None)
                            }
                        }

                        _ => Result::MakeEpiq(None),
                    }
                },

                Epiq::Mpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ^> リストのeval
                            // リストの要素それぞれをevalする
                            // pは-1だとして処理する(最後の項目の評価結果が最終的な結果となる)
                            // Result::MakeEpiq(None)
                            let res = self.eval_list(q, nest_level+1);
                            // 戻り値のindexがすでに存在するなら何もしない
                            if res <= self.ast.borrow().max_index.get() {
                                Result::NewIndex(res)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(res).clone()))
                            }

                        },
                        _ => Result::MakeEpiq(None),
                    }
                },
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}eval 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}eval 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}eval 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_list(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        if let Some(res_index) = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}eval_list ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Tpiq{ref o,p,q} => {
                    match o.as_ref() {
                        ":" => {
                            let q_piq = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(q).clone()
                            };

                            if q_piq == Epiq::Unit {
                                // リストの最後なので評価の結果を返す
                                Some(self.eval_internal(p, nest_level+1))
                            } else {
                                // 評価はするが返さない
                                let _p_ret = self.eval_internal(p, nest_level+1);
                                // 次の項目へ
                                Some(self.eval_list(q, nest_level+1))
                            }
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        } {
            res_index
        } else {
            index
        }
    }
}

#[test]
#[ignore]
fn test() {
    let ast = &RefCell::new(AbstractSyntaxTree::new());
    let mut evaluator = Evaluator::new(ast);
    evaluator.walk();
}

/*
fn beta_reduct(&mut self, entry: usize) {
    /*
    // 仮引数に実引数を入れる
    let mut a = vec![1, 3, 5];
    a.remove(1);
    a.insert(1, 2);
    println!("{:?}", a);

    // confirm that target is "application-piq"
    match self.vm.vctr.get(entry) {
        Some(&Epiq::Apiq { p: p1, q: q1 }) => {
            /* 引数をまず、lambdaの中に入れる */

            // ApiqのpはFpiqである必要がある(=ラムダ適用の左側はラムダ式でなければならない)
            match self.vm.vctr.get(p1) {
                Some(&Epiq::Fpiq { p: p2, q: q2 }) => {

                    // FpiqのpはPrmtである必要がある(=ラムダ式のは引数のシンボルが入る)
                    match self.vm.vctr.get(p2) {
                        Some(&Epiq::Prmt(_)) => {
                        },
                        Some(p3) => println!("not anonymous parameter {:?}", p3),
                        None => println!("{:?}", "index error"),
                    }
                },
                Some(p2) => println!("not function epiq {:?}", p2),
                None => println!("{:?}", "index error"),
            }

            println!("v.len(): {:?} entry: {:?}", self.vm.vctr.len(), entry);
        },
        Some(p1) => println!("not application epiq {:?}", p1),
        None => println!("{:?}", "index error"),
    }
    */

    let mut is_ok: (usize, usize) = (0, 0);

    match apiq_f((self, entry))
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e).and_then(fpiq_p)
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e) {
            Some(t) => {
                println!("{:?}", t.1);
                match apiq_q((self, entry)) {
                    Some(t2) => {
                        is_ok = (t.1, t2.1);
                    }
                    _ => {},
                }
            }
            None => {},
    }

    if is_ok != (0, 0) {
        self.vm.vctr.remove(is_ok.0);
        self.vm.vctr.insert(is_ok.0, Epiq::Prmt(is_ok.1));
    }
}
*/
<commit_msg>fix SymbolTable for multiple frame<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use core::*;

struct SymbolTable {
    table: Vec<HashMap<String, Option<Epiq>>>,
    current_index: usize,
}

impl SymbolTable {
    fn define(&mut self, name: &str, value: Epiq) {
        self.table[self.current_index].insert(name.to_string(), Some(value));
    }

    fn resolve(&self, name: &str) -> Option<&Option<Epiq>> {
        self.table[self.current_index].get(name)
    }
}

pub struct Evaluator<'a> {
    ast :&'a RefCell<AbstractSyntaxTree>,
    symbol_table: SymbolTable,
}

enum Result {
    MakeEpiq(Option<Epiq>),
    NewIndex(u32),
}

impl<'a> Evaluator<'a> {
    pub fn new(ast :&'a RefCell<AbstractSyntaxTree>) -> Evaluator {
        Evaluator {
            ast: ast,
            symbol_table: SymbolTable {
                table: vec![HashMap::new()],
                current_index: Default::default(),
            }
        }
    }

    pub fn walk(&mut self) -> Option<&RefCell<AbstractSyntaxTree>> {
        println!("\n");
        let index;
        {
            let borrowed_ast = self.ast.borrow();
            index = borrowed_ast.entrypoint.unwrap();
        }
        let result = self.walk_internal(index, 0);
        // println!("max: {:?} index: {:?}", result, index);
        if result != index {
            // なんらかの変化があったので反映する必要がある
            // ここだと、entrypointを変更する
            let mut ast = self.ast.borrow_mut();
            (*ast).entrypoint = Some(result);
        }

        Some(self.ast)
    }

    fn walk_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        // self.eval_internal(index)
        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}walk ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ひとまずpは無視
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        _ => {

                            // その他のTpiqの場合は、pとq両方をwalkしてみて、
                            // 結果が両方とも変わらなければそのまま返す、
                            // そうでなければ新しくTpiqを作ってそのindexを返す
                            println!("{}walk >以外 pに入ります", " ".repeat(lvl));
                            let new_p = self.walk_internal(p, nest_level+1);
                            println!("{}walk >以外 qに入ります", " ".repeat(lvl));
                            let new_q = self.walk_internal(q, nest_level+1);
                            if new_p == p && new_q == q {
                                // println!("{}pもqも同じなので変化なし", " ".repeat(lvl));
                                Result::MakeEpiq(None)
                            } else {
                                // 新しくTpiqを作成

                                Result::MakeEpiq(Some(Epiq::Tpiq{o: o.to_string(), p: new_p, q: new_q}))
                            }
                        },
                    }
                },
                _ => Result::MakeEpiq(None),
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}walk 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}walk 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}walk 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_internal(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        let res = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}eval ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Unit | Epiq::Uit8(_) | Epiq::Name(_) => Result::MakeEpiq(None),
                Epiq::Tpiq{ref o, p, q} => {
                    match o.as_ref() {
                        // bind
                        "#" => {
                            let p_name = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(p).clone()
                            };
                            if let Epiq::Name(ref n) = p_name {
                                let q_val = {
                                    let borrowed_ast = self.ast.borrow();
                                    borrowed_ast.get(q).clone()
                                };
                                self.symbol_table.define(n, q_val);

                                Result::MakeEpiq(Some(Epiq::Unit))
                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // environment
                        "%" => {
                            // ひとまずNoneを返しておく
                            Result::MakeEpiq(None)
                        },

                        // block
                        r"\" => {
                            // TODO: 一つ目の環境の中身はひとまず無視する
                            // qのリストだけを逐次実行して、勝手に最後の値をwalkしてから返却するようにする
                            // ただ、そもそも、blockをevalしても、何も変化はないはず。
                            Result::MakeEpiq(None)
                        },

                        // apply
                        "!" => {
                            // p: lambda q:arguments
                            // 1. bind p.p(環境)の順番に沿って、q(引数リスト)を当てはめていく

                            // 2. p.q(関数本体)をそのまま返却する
                            let borrowed_ast = self.ast.borrow();
                            let lambda_piq = borrowed_ast.get(p);
                            if let &Epiq::Tpiq{o:_, p:_, q:lambda_body} = lambda_piq {
                                // walkを挟んでから返す
                                let new_lambda_body = self.walk_internal(lambda_body, nest_level+1);

                                Result::NewIndex(new_lambda_body)

                            } else {
                                Result::MakeEpiq(None)
                            }
                        },

                        // eval
                        ">" => {
                            println!("eval");
                            // p: 用途未定。新しく何かを限定したりとかかなあ。
                            //    アイディアは思いつくけど、
                            //    そもそもパーサを変えたりとか？
                            //    環境を変更したりとか？
                            //    継続っぽく使うとか？
                            // q: evalされる本体。
                            let new_q = self.eval_internal(q, nest_level+1);
                            if new_q == q {
                                Result::MakeEpiq(None)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(new_q).clone()))
                            }
                        },

                        // resolve
                        "@" => {
                            // p: 用途未定。ひとまず無視
                            // q: シンボルというか名前
                            let p_name = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(q).clone()
                            };
                            if let Epiq::Name(ref n) = p_name {
                                match self.symbol_table.resolve(n) {
                                    Some(&Some(ref res)) => Result::MakeEpiq(Some(res.clone())),
                                    _ => Result::MakeEpiq(None),
                                }
                            } else {
                                Result::MakeEpiq(None)
                            }
                        }

                        _ => Result::MakeEpiq(None),
                    }
                },

                Epiq::Mpiq{ref o, p, q} => {
                    match o.as_ref() {
                        ">" => {
                            // ^> リストのeval
                            // リストの要素それぞれをevalする
                            // pは-1だとして処理する(最後の項目の評価結果が最終的な結果となる)
                            // Result::MakeEpiq(None)
                            let res = self.eval_list(q, nest_level+1);
                            // 戻り値のindexがすでに存在するなら何もしない
                            if res <= self.ast.borrow().max_index.get() {
                                Result::NewIndex(res)
                            } else {
                                let borrowed_ast = self.ast.borrow();
                                Result::MakeEpiq(Some(borrowed_ast.get(res).clone()))
                            }
                        },
                        _ => Result::MakeEpiq(None),
                    }
                },
            }
        };

        match res {
            Result::MakeEpiq(Some(new_epiq)) => {
                // まずpushだけ
                println!("{}eval 生み出す: {:?}", " ".repeat(lvl), new_epiq);
                self.ast.borrow_mut().push(new_epiq);
                self.ast.borrow().max_index.get()
            },
            Result::MakeEpiq(None) => {
                // 変化なし
                let borrowed_ast = self.ast.borrow();
                let piq = borrowed_ast.get(index);
                println!("{}eval 変化なし: {:?}", " ".repeat(lvl), piq);
                index
            },
            Result::NewIndex(i) => {
                let borrowed_ast = self.ast.borrow();
                let piq1 = borrowed_ast.get(index);
                let piq2 = borrowed_ast.get(i);
                println!("{}eval 付け替え: {:?} から {:?}", " ".repeat(lvl), piq1, piq2);
                i
            },
        }
    }

    fn eval_list(&mut self, index: u32, nest_level: u32) -> u32 {
        let lvl = (nest_level * 2) as usize;

        if let Some(res_index) = {
            let piq = {
                let borrowed_ast = self.ast.borrow();
                borrowed_ast.get(index).clone()
            };
            println!("{}eval_list ＿開始＿: {:?}", " ".repeat(lvl), piq);

            match piq {
                Epiq::Tpiq{ref o,p,q} => {
                    match o.as_ref() {
                        ":" => {
                            let q_piq = {
                                let borrowed_ast = self.ast.borrow();
                                borrowed_ast.get(q).clone()
                            };

                            if q_piq == Epiq::Unit {
                                // リストの最後なので評価の結果を返す
                                Some(self.eval_internal(p, nest_level+1))
                            } else {
                                // 評価はするが返さない
                                let _p_ret = self.eval_internal(p, nest_level+1);
                                // 次の項目へ
                                Some(self.eval_list(q, nest_level+1))
                            }
                        },
                        _ => None,
                    }
                },
                _ => None,
            }
        } {
            res_index
        } else {
            index
        }
    }
}

#[test]
#[ignore]
fn test() {
    let ast = &RefCell::new(AbstractSyntaxTree::new());
    let mut evaluator = Evaluator::new(ast);
    evaluator.walk();
}

/*
fn beta_reduct(&mut self, entry: usize) {
    /*
    // 仮引数に実引数を入れる
    let mut a = vec![1, 3, 5];
    a.remove(1);
    a.insert(1, 2);
    println!("{:?}", a);

    // confirm that target is "application-piq"
    match self.vm.vctr.get(entry) {
        Some(&Epiq::Apiq { p: p1, q: q1 }) => {
            /* 引数をまず、lambdaの中に入れる */

            // ApiqのpはFpiqである必要がある(=ラムダ適用の左側はラムダ式でなければならない)
            match self.vm.vctr.get(p1) {
                Some(&Epiq::Fpiq { p: p2, q: q2 }) => {

                    // FpiqのpはPrmtである必要がある(=ラムダ式のは引数のシンボルが入る)
                    match self.vm.vctr.get(p2) {
                        Some(&Epiq::Prmt(_)) => {
                        },
                        Some(p3) => println!("not anonymous parameter {:?}", p3),
                        None => println!("{:?}", "index error"),
                    }
                },
                Some(p2) => println!("not function epiq {:?}", p2),
                None => println!("{:?}", "index error"),
            }

            println!("v.len(): {:?} entry: {:?}", self.vm.vctr.len(), entry);
        },
        Some(p1) => println!("not application epiq {:?}", p1),
        None => println!("{:?}", "index error"),
    }
    */

    let mut is_ok: (usize, usize) = (0, 0);

    match apiq_f((self, entry))
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e).and_then(fpiq_p)
        // .and_then(aexp_e).and_then(pprn)
        .and_then(aexp_e) {
            Some(t) => {
                println!("{:?}", t.1);
                match apiq_q((self, entry)) {
                    Some(t2) => {
                        is_ok = (t.1, t2.1);
                    }
                    _ => {},
                }
            }
            None => {},
    }

    if is_ok != (0, 0) {
        self.vm.vctr.remove(is_ok.0);
        self.vm.vctr.insert(is_ok.0, Epiq::Prmt(is_ok.1));
    }
}
*/
<|endoftext|>


<commit_before>use lexer::{Symbol, Token, Tokens};
use function::{Function, Functions, functions};
use error::EvaluatorError;

pub struct Evaluator {
    functions: Functions,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator { functions: Functions::new() }
    }

    pub fn evaluate(&self, tokens: Tokens) -> Result<Vec<String>, EvaluatorError> {
        let mut result: Vec<String> = Vec::with_capacity(3);
        let mut stack: Vec<i32> = Vec::with_capacity(3);

        for (position, ref token) in tokens {
            match *token {
                Token::Decimal(ref dec) => {
                    stack.push(dec.parse().unwrap());
                }
                Token::Operator(ref op) => {
                    let function = self.functions.get(&op).unwrap();
                    if stack.len() >= function.arity {
                        let stack_len = stack.len();
                        let args: Vec<i32> = stack.split_off(stack_len - function.arity);
                        let interm_result = try!((function.handle)(args, position));
                        stack.push(interm_result.0);
                        result.push(interm_result.1);
                        result.push(interm_result.0.to_string());
                    } else {
                        return Err(EvaluatorError::MissingArgument(position));
                    }
                }
                _ => continue,

            }
        }
        if stack.len() == 1 {
            result.push(stack.pop().unwrap().to_string());
        } else {
            return Err(EvaluatorError::TooManyArguments);
        }
        Ok(result)
    }
}

impl Default for Evaluator {
    fn default() -> Evaluator {
        let mut evaluator = Evaluator::new();

        evaluator.functions.insert(Symbol::NOT, Function::new(1, Box::new(functions::not)));
        evaluator.functions.insert(Symbol::XOR, Function::new(2, Box::new(functions::xor)));
        evaluator.functions.insert(Symbol::OR, Function::new(2, Box::new(functions::or)));
        evaluator.functions.insert(Symbol::AND, Function::new(2, Box::new(functions::and)));
        evaluator.functions.insert(Symbol::LSHIFT,
                                   Function::new(2, Box::new(functions::lshift)));
        evaluator.functions.insert(Symbol::RSHIFT,
                                   Function::new(2, Box::new(functions::rshift)));

        evaluator
    }
}
<commit_msg>Return early if no tokens need to be evaluated<commit_after>use lexer::{Symbol, Token, Tokens};
use function::{Function, Functions, functions};
use error::EvaluatorError;

pub struct Evaluator {
    functions: Functions,
}

impl Evaluator {
    pub fn new() -> Evaluator {
        Evaluator { functions: Functions::new() }
    }

    pub fn evaluate(&self, tokens: Tokens) -> Result<Vec<String>, EvaluatorError> {
        let mut result: Vec<String> = Vec::with_capacity(3);
        let mut stack: Vec<i32> = Vec::with_capacity(3);

        if tokens.is_empty() {
            return Ok(result);
        }

        for (position, ref token) in tokens {
            match *token {
                Token::Decimal(ref dec) => {
                    stack.push(dec.parse().unwrap());
                }
                Token::Operator(ref op) => {
                    let function = self.functions.get(&op).unwrap();
                    if stack.len() >= function.arity {
                        let stack_len = stack.len();
                        let args: Vec<i32> = stack.split_off(stack_len - function.arity);
                        let interm_result = try!((function.handle)(args, position));
                        stack.push(interm_result.0);
                        result.push(interm_result.1);
                        result.push(interm_result.0.to_string());
                    } else {
                        return Err(EvaluatorError::MissingArgument(position));
                    }
                }
                _ => continue,

            }
        }
        if stack.len() == 1 {
            result.push(stack.pop().unwrap().to_string());
        } else {
            return Err(EvaluatorError::TooManyArguments);
        }
        Ok(result)
    }
}

impl Default for Evaluator {
    fn default() -> Evaluator {
        let mut evaluator = Evaluator::new();

        evaluator.functions.insert(Symbol::NOT, Function::new(1, Box::new(functions::not)));
        evaluator.functions.insert(Symbol::XOR, Function::new(2, Box::new(functions::xor)));
        evaluator.functions.insert(Symbol::OR, Function::new(2, Box::new(functions::or)));
        evaluator.functions.insert(Symbol::AND, Function::new(2, Box::new(functions::and)));
        evaluator.functions.insert(Symbol::LSHIFT,
                                   Function::new(2, Box::new(functions::lshift)));
        evaluator.functions.insert(Symbol::RSHIFT,
                                   Function::new(2, Box::new(functions::rshift)));

        evaluator
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fs;
use std::io;
use std::io::{Read,Write,SeekFrom,Seek};
use std::mem;
use std::str;
use std::path::Path;

use fat::RootEntry;
use fat::BIOSParam;

// Always the same
const SECTORS_PER_ROOT: usize = 14;
const BYTES_PER_ROOT_ENTRY: usize = 32;

#[test]
fn test_root_entry_size() {
    assert_eq!(mem::size_of::<RootEntry>(), BYTES_PER_ROOT_ENTRY);
}

#[derive(Debug)]
pub struct Image {
    boot_sector: Vec<u8>,
    fat_1: Vec<u8>,
    fat_2: Vec<u8>,
    root_dir: Vec<u8>,
    data_area: Vec<u8>,
    bpb_data: BIOSParam,
}

#[allow(dead_code)]
impl Image {
    /// Create a new blank FAT Image from a defined BPB
    fn new(bpb: BIOSParam, length: usize) -> Image {
        let boot_sector_size = bpb.bytes_per_sector as usize
            * bpb.reserved_sectors as usize;
        let bytes_per_fat = (bpb.sectors_per_fat
            * bpb.bytes_per_sector as u32) as usize;
        let bytes_per_root = SECTORS_PER_ROOT * bpb.bytes_per_sector as usize;
        let data_offset = boot_sector_size as usize
            + (bytes_per_fat * 2) as usize + bytes_per_root as usize;
        let bytes_per_data_area = length - data_offset;
        Image {
            boot_sector: vec![0; boot_sector_size],
            fat_1: vec![0; bytes_per_fat],
            fat_2: vec![0; bytes_per_fat],
            root_dir: vec![0; bytes_per_root],
            data_area: vec![0; bytes_per_data_area],
            bpb_data: bpb,
        }
    }

    /// Create a new FAT Image from the specified file.
    pub fn from_file<P: AsRef<Path>>(image_fn: P)
        -> Result<Image, Box<error::Error>>
    {
        let metadata = fs::metadata(image_fn.as_ref())?;
        let bpb = BIOSParam::from_file(image_fn.as_ref(), 0)?;

        let mut file = fs::File::open(image_fn.as_ref())?;
        let mut image = Image::new(bpb, metadata.len() as usize);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Create a new FAT Image from the specified file and offset.
    pub fn from_file_offset<P: AsRef<Path>>(image_fn: P, start: usize, length: usize)
        -> Result<Image, Box<error::Error>>
    {
        let metadata = fs::metadata(image_fn.as_ref())?;
        let bpb = BIOSParam::from_file(image_fn.as_ref(), start)?;

        if metadata.is_file() && (start + length > (metadata.len() as usize)) {
            return Err(From::from(format!("start + offset outside image bounds")));
        }

        let mut file = fs::File::open(image_fn.as_ref())?;
        file.seek(SeekFrom::Start(start as u64))?;

        let mut image = Image::new(bpb, length);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Save the FAT filesystem image to the specified file.
    pub fn save(&self, image_fn: String)
        -> Result<(), io::Error>
    {
        let mut file = fs::File::create(image_fn)?;

        try!(file.write_all(&self.boot_sector));
        try!(file.write_all(&self.fat_1));
        try!(file.write_all(&self.fat_2));
        try!(file.write_all(&self.root_dir));
        try!(file.write_all(&self.data_area));

        Ok(())
    }

    /// Extract the BIOS Parameter Block (BPB) from the FAT filesystem.
    pub fn bios_parameter(&self) -> BIOSParam {
        self.bpb_data.clone()
    }

    /// FAT sector size in bytes.
    pub fn sector_size(&self) -> usize {
        self.bpb_data.bytes_per_sector as usize
    }

    /// FAT volume label
    pub fn volume_label(&self) -> Result<String, Box<error::Error>> {
        let entries = self.root_entries();
        for entry in entries {
            if !entry.is_volume_label() {
                continue;
            }
            let label = format!("{}{}",
                str::from_utf8(&entry.filename)?,
                str::from_utf8(&entry.extension)?);
            return Ok(label);
        }
        return Ok("has no label".to_string());
    }

    // TODO: Make iterator once "impl Trait" is stable.
    /// Return all FAT root entries (including unused)
    pub fn root_entries_all(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .collect::<Vec<RootEntry>>()
    }

    // TODO: Make iterator once "impl Trait" is stable.
    /// Return used FAT root entries
    pub fn root_entries(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .filter(|entry| { entry.filename[0] != 0xe5 })
            .take_while(|entry| { entry.filename[0] != 0 })
            .collect::<Vec<RootEntry>>()
    }

    /// Get the RootEntry for the specified file within the Image.
    pub fn get_file_entry(&self, filename: String)
        -> Result<RootEntry, Box<error::Error>>
    {
        let entries = self.root_entries();
        for entry in entries {
            let entry_name: String;
            match entry.filename() {
                Ok(name) => entry_name = name,
                Err(_) => continue,
            }

            if entry_name.to_lowercase() == filename.to_lowercase() {
                return Ok(entry);
            }
        }

        Err(From::from(format!("file {} not found", filename)))
    }

    /// Create a new RootEntry within the Image with the specified filename.
    pub fn create_file_entry(&self, filename: String)
        -> Result<(RootEntry, u16), Box<error::Error>>
    {
        for (index, e) in self.root_entries_all().iter().enumerate() {
            if !e.is_free() { continue; }

            let mut entry = RootEntry::new();
            try!(entry.set_filename(filename));
            return Ok((entry.clone(), index as u16));
        }

        Err(From::from("no free entries"))
    }

    pub fn save_file_entry(&mut self, entry: RootEntry, index: u16)
        -> Result<(), Box<error::Error>>
    {
        let entry_bytes: [u8; BYTES_PER_ROOT_ENTRY];
        unsafe { entry_bytes = mem::transmute(entry); }

        self.root_dir[
            index as usize * BYTES_PER_ROOT_ENTRY ..
            (index as usize + 1) * BYTES_PER_ROOT_ENTRY
        ].clone_from_slice(&entry_bytes[..]);
        Ok(())
    }

    pub fn fat_entries<'a>(&'a self)
        -> Box<Iterator<Item=(usize, u16)> + 'a>
    {
        Box::new(
            self.fat_1
            .windows(2)
            .enumerate()
            .filter_map(|(i, w)|
                if i % 3 == 2 {
                    None
                } else {
                    let val = if i % 3 == 0 {
                        ((w[1] as u16 & 0xf) << 8) | w[0] as u16
                    } else {
                        (w[1] as u16 & 0xf0) | ((w[1] as u16) << 4)
                    };
                    Some((i, val))
                }
            )
        )
    }

    pub fn get_fat_entry(&self, cluster_num: u16) -> u16 {
        let offset: usize = cluster_num as usize * 3 / 2;
        let byte_1: u16 = self.fat_1[offset] as u16;
        let byte_2: u16 = self.fat_1[offset + 1] as u16;

        if cluster_num % 2 == 0 { byte_1 | ((byte_2 & 0x0f) << 8) }
        else                    { (byte_1 >> 4) | (byte_2 << 4) }
    }

    pub fn get_free_fat_entry(&self) -> Option<usize> {
        self.fat_entries()
            .filter(|&(_, e)| e == 0)
            .map(|(i, _)| i + 2)
            .nth(0)
    }

    pub fn write_data_sector(&mut self, sector: usize, data: &[u8])
        -> Result<(), Box<error::Error>>
    {
        let sector = sector - 2;
        let bytes = sector * self.bpb_data.bytes_per_sector as usize;
        if bytes >= self.data_area.len() {
            return Err(From::from(format!("sector {} too high to write to", sector)))
        }

        let mut target_slice = &mut self.data_area[
            self.bpb_data.bytes_per_sector as usize * sector ..
            self.bpb_data.bytes_per_sector as usize * (sector + 1)
        ];

        target_slice.copy_from_slice(data);
        Ok(())
    }
}
<commit_msg>fat/image: Dynamic write based on input data<commit_after>use std::error;
use std::fs;
use std::io;
use std::io::{Read,Write,SeekFrom,Seek};
use std::mem;
use std::str;
use std::path::Path;

use fat::RootEntry;
use fat::BIOSParam;

// Always the same
const SECTORS_PER_ROOT: usize = 14;
const BYTES_PER_ROOT_ENTRY: usize = 32;

#[test]
fn test_root_entry_size() {
    assert_eq!(mem::size_of::<RootEntry>(), BYTES_PER_ROOT_ENTRY);
}

#[derive(Debug)]
pub struct Image {
    boot_sector: Vec<u8>,
    fat_1: Vec<u8>,
    fat_2: Vec<u8>,
    root_dir: Vec<u8>,
    data_area: Vec<u8>,
    bpb_data: BIOSParam,
}

#[allow(dead_code)]
impl Image {
    /// Create a new blank FAT Image from a defined BPB
    fn new(bpb: BIOSParam, length: usize) -> Image {
        let boot_sector_size = bpb.bytes_per_sector as usize
            * bpb.reserved_sectors as usize;
        let bytes_per_fat = (bpb.sectors_per_fat
            * bpb.bytes_per_sector as u32) as usize;
        let bytes_per_root = SECTORS_PER_ROOT * bpb.bytes_per_sector as usize;
        let data_offset = boot_sector_size as usize
            + (bytes_per_fat * 2) as usize + bytes_per_root as usize;
        let bytes_per_data_area = length - data_offset;
        Image {
            boot_sector: vec![0; boot_sector_size],
            fat_1: vec![0; bytes_per_fat],
            fat_2: vec![0; bytes_per_fat],
            root_dir: vec![0; bytes_per_root],
            data_area: vec![0; bytes_per_data_area],
            bpb_data: bpb,
        }
    }

    /// Create a new FAT Image from the specified file.
    pub fn from_file<P: AsRef<Path>>(image_fn: P)
        -> Result<Image, Box<error::Error>>
    {
        let metadata = fs::metadata(image_fn.as_ref())?;
        let bpb = BIOSParam::from_file(image_fn.as_ref(), 0)?;

        let mut file = fs::File::open(image_fn.as_ref())?;
        let mut image = Image::new(bpb, metadata.len() as usize);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Create a new FAT Image from the specified file and offset.
    pub fn from_file_offset<P: AsRef<Path>>(image_fn: P, start: usize, length: usize)
        -> Result<Image, Box<error::Error>>
    {
        let metadata = fs::metadata(image_fn.as_ref())?;
        let bpb = BIOSParam::from_file(image_fn.as_ref(), start)?;

        if metadata.is_file() && (start + length > (metadata.len() as usize)) {
            return Err(From::from(format!("start + offset outside image bounds")));
        }

        let mut file = fs::File::open(image_fn.as_ref())?;
        file.seek(SeekFrom::Start(start as u64))?;

        let mut image = Image::new(bpb, length);

        try!(file.read_exact(&mut image.boot_sector));
        try!(file.read_exact(&mut image.fat_1));
        try!(file.read_exact(&mut image.fat_2));
        try!(file.read_exact(&mut image.root_dir));
        try!(file.read_exact(&mut image.data_area));

        Ok(image)
    }

    /// Save the FAT filesystem image to the specified file.
    pub fn save(&self, image_fn: String)
        -> Result<(), io::Error>
    {
        let mut file = fs::File::create(image_fn)?;

        try!(file.write_all(&self.boot_sector));
        try!(file.write_all(&self.fat_1));
        try!(file.write_all(&self.fat_2));
        try!(file.write_all(&self.root_dir));
        try!(file.write_all(&self.data_area));

        Ok(())
    }

    /// Extract the BIOS Parameter Block (BPB) from the FAT filesystem.
    pub fn bios_parameter(&self) -> BIOSParam {
        self.bpb_data.clone()
    }

    /// FAT sector size in bytes.
    pub fn sector_size(&self) -> usize {
        self.bpb_data.bytes_per_sector as usize
    }

    /// FAT volume label
    pub fn volume_label(&self) -> Result<String, Box<error::Error>> {
        let entries = self.root_entries();
        for entry in entries {
            if !entry.is_volume_label() {
                continue;
            }
            let label = format!("{}{}",
                str::from_utf8(&entry.filename)?,
                str::from_utf8(&entry.extension)?);
            return Ok(label);
        }
        return Ok("has no label".to_string());
    }

    // TODO: Make iterator once "impl Trait" is stable.
    /// Return all FAT root entries (including unused)
    pub fn root_entries_all(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .collect::<Vec<RootEntry>>()
    }

    // TODO: Make iterator once "impl Trait" is stable.
    /// Return used FAT root entries
    pub fn root_entries(&self) -> Vec<RootEntry> {
        self.root_dir
            .chunks(BYTES_PER_ROOT_ENTRY)
            .map(|chunk| {
                let mut entry_bytes = [0; BYTES_PER_ROOT_ENTRY];
                entry_bytes.clone_from_slice(chunk);

                let entry: RootEntry;
                unsafe { entry = mem::transmute(entry_bytes); }
                entry
            })
            .filter(|entry| { entry.filename[0] != 0xe5 })
            .take_while(|entry| { entry.filename[0] != 0 })
            .collect::<Vec<RootEntry>>()
    }

    /// Get the RootEntry for the specified file within the Image.
    pub fn get_file_entry(&self, filename: String)
        -> Result<RootEntry, Box<error::Error>>
    {
        let entries = self.root_entries();
        for entry in entries {
            let entry_name: String;
            match entry.filename() {
                Ok(name) => entry_name = name,
                Err(_) => continue,
            }

            if entry_name.to_lowercase() == filename.to_lowercase() {
                return Ok(entry);
            }
        }

        Err(From::from(format!("file {} not found", filename)))
    }

    /// Create a new RootEntry within the Image with the specified filename.
    pub fn create_file_entry(&self, filename: String)
        -> Result<(RootEntry, u16), Box<error::Error>>
    {
        for (index, e) in self.root_entries_all().iter().enumerate() {
            if !e.is_free() { continue; }

            let mut entry = RootEntry::new();
            try!(entry.set_filename(filename));
            return Ok((entry.clone(), index as u16));
        }

        Err(From::from("no free entries"))
    }

    pub fn save_file_entry(&mut self, entry: RootEntry, index: u16)
        -> Result<(), Box<error::Error>>
    {
        let entry_bytes: [u8; BYTES_PER_ROOT_ENTRY];
        unsafe { entry_bytes = mem::transmute(entry); }

        self.root_dir[
            index as usize * BYTES_PER_ROOT_ENTRY ..
            (index as usize + 1) * BYTES_PER_ROOT_ENTRY
        ].clone_from_slice(&entry_bytes[..]);
        Ok(())
    }

    pub fn fat_entries<'a>(&'a self)
        -> Box<Iterator<Item=(usize, u16)> + 'a>
    {
        Box::new(
            self.fat_1
            .windows(2)
            .enumerate()
            .filter_map(|(i, w)|
                if i % 3 == 2 {
                    None
                } else {
                    let val = if i % 3 == 0 {
                        ((w[1] as u16 & 0xf) << 8) | w[0] as u16
                    } else {
                        (w[1] as u16 & 0xf0) | ((w[1] as u16) << 4)
                    };
                    Some((i, val))
                }
            )
        )
    }

    pub fn get_fat_entry(&self, cluster_num: u16) -> u16 {
        let offset: usize = cluster_num as usize * 3 / 2;
        let byte_1: u16 = self.fat_1[offset] as u16;
        let byte_2: u16 = self.fat_1[offset + 1] as u16;

        if cluster_num % 2 == 0 { byte_1 | ((byte_2 & 0x0f) << 8) }
        else                    { (byte_1 >> 4) | (byte_2 << 4) }
    }

    pub fn get_free_fat_entry(&self) -> Option<usize> {
        self.fat_entries()
            .filter(|&(_, e)| e == 0)
            .map(|(i, _)| i + 2)
            .nth(0)
    }

    pub fn write_data_sector(&mut self, sector: usize, data: &[u8])
        -> Result<(), Box<error::Error>>
    {
        let sector = sector - 2;
        let bytes_per_sector = self.bpb_data.bytes_per_sector as usize;
        let start_byte = bytes_per_sector * sector;

        if start_byte >= self.data_area.len() {
            return Err(From::from(format!("sector {} too high to write to", sector)))
        }

        let mut target_slice = &mut self.data_area[start_byte..start_byte + data.len()];
        target_slice.copy_from_slice(data);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::os::raw::c_char;
use std::fmt;
use std::ffi::{CStr, CString};
use std::fmt::Display;
use std::str::Utf8Error;

use ffi::functions::*;
use ffi::utils::*;

/// Possible error codes. You can print the
/// corresponding error message easily, because
/// this enum implements `Display`.
///
/// # Example
///
/// ```
/// use rsoundio::ffi::SioError;
/// println!("{}", SioError::SystemResources)
/// ```
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum SioError {
    None = 0,
    /// Out of memory.
    NoMem = 1,
    /// The backend does not appear to be active or running.
    InitAudioBackend = 2,
    /// A system resource other than memory (Dummy) was not available.
    SystemResources = 3,
    /// Attempted to open a device and failed.
    OpeningDevice = 4,
    NoSuchDevice = 5,
    /// The programmer did not comply with the API.
    Invalid = 6,
    /// libsoundio was compiled without support for that backend.
    ///
    /// Currently there is no JACK support in Arch Linux until
    /// `jack2{,-dbus}1.9.10-4` is available. See [this](https://bugs.archlinux.org/task/47839)
    /// bug report for details.
    BackendUnavailable = 7,
    /// An open stream had an error that can only be recovered from by
    /// destroying the stream and creating it again.
    Streaming = 8,
    /// Attempted to use a device with parameters it cannot support.
    IncompatibleDevice = 9,
    /// When JACK returns `JackNoSuchClient`
    NoSuchClient = 10,
    /// Attempted to use parameters that the backend cannot support.
    IncompatibleBackend = 11,
    /// Backend server shutdown or became inactive.
    BackendDisconnected = 12,
    Interrupted = 13,
    /// Buffer underrun occurred.
    Underflow = 14,
    /// Unable to convert to or from UTF-8 to the native string format.
    EncodingString = 15,
}
impl Display for SioError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_strerror(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}

/// Specifies where a channel is physically located.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u32)]
pub enum SioChannelId {
    Invalid = 0,
    /// First of the more commonly supported ids.
    FrontLeft = 1,
    FrontRight = 2,
    FrontCenter = 3,
    Lfe = 4,
    BackLeft = 5,
    BackRight = 6,
    FrontLeftCenter = 7,
    FrontRightCenter = 8,
    BackCenter = 9,
    SideLeft = 10,
    SideRight = 11,
    TopCenter = 12,
    TopFrontLeft = 13,
    TopFrontCenter = 14,
    TopFrontRight = 15,
    TopBackLeft = 16,
    TopBackCenter = 17,
    /// Last of the more commonly supported ids.
    TopBackRight = 18,
    /// First of the less commonly supported ids.
    BackLeftCenter = 19,
    BackRightCenter = 20,
    FrontLeftWide = 21,
    FrontRightWide = 22,
    FrontLeftHigh = 23,
    FrontCenterHigh = 24,
    FrontRightHigh = 25,
    TopFrontLeftCenter = 26,
    TopFrontRightCenter = 27,
    TopSideLeft = 28,
    TopSideRight = 29,
    LeftLfe = 30,
    RightLfe = 31,
    Lfe2 = 32,
    BottomCenter = 33,
    BottomLeftCenter = 34,
    BottomRightCenter = 35,
    /// Mid/side recording
    MsMid = 36,
    MsSide = 37,
    /// first order ambisonic channels
    AmbisonicW = 38,
    AmbisonicX = 39,
    AmbisonicY = 40,
    AmbisonicZ = 41,
    /// X-Y Recording
    XyX = 42,
    XyY = 43,
    /// First of the "other" channel ids
    HeadphonesLeft = 44,
    HeadphonesRight = 45,
    ClickTrack = 46,
    ForeignLanguage = 47,
    HearingImpaired = 48,
    Narration = 49,
    Haptic = 50,
    /// Last of the "other" channel ids
    DialogCentricMix = 51,
    Aux = 52,
    Aux0 = 53,
    Aux1 = 54,
    Aux2 = 55,
    Aux3 = 56,
    Aux4 = 57,
    Aux5 = 58,
    Aux6 = 59,
    Aux7 = 60,
    Aux8 = 61,
    Aux9 = 62,
    Aux10 = 63,
    Aux11 = 64,
    Aux12 = 65,
    Aux13 = 66,
    Aux14 = 67,
    Aux15 = 68,
}
impl Display for SioChannelId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_get_channel_name(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}
impl From<String> for SioChannelId {
    fn from(id: String) -> Self {
        let str_len = id.len() as i32;
        let cstr = CString::new(id).unwrap();
        unsafe { soundio_parse_channel_id(cstr.as_ptr(), str_len) }
    }
}

/// Built-in channel layouts for convenience.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioChannelLayoutId {
    Mono = 0,
    Stereo = 1,
    TwoPointOne = 2,
    ThreePointZero = 3,
    ThreePointZeroBack = 4,
    ThreePointOne = 5,
    FourPointZero = 6,
    Quad = 7,
    QuadSide = 8,
    FourPointOne = 9,
    FivePointZeroBack = 10,
    FivePointZeroSide = 11,
    FivePointOne = 12,
    FivePointOneBack = 13,
    SixPointZeroSide = 14,
    SixPointZeroFront = 15,
    Hexagonal = 16,
    SixPointOne = 17,
    SixPointOneBack = 18,
    SixPointOneFront = 19,
    SevenPointZero = 20,
    SevenPointZeroFront = 21,
    SevenPointOne = 22,
    SevenPointOneWide = 23,
    SevenPointOneWideBack = 24,
    Octagonal = 25,
}

#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum SioBackend {
    None = 0,
    Jack = 1,
    PulseAudio = 2,
    Alsa = 3,
    CoreAudio = 4,
    Wasapi = 5,
    Dummy = 6,
}
impl Display for SioBackend {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_backend_name(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}

#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioDeviceAim {
    /// capture/recording
    Input = 0,
    /// playback
    Output = 1,
}

/// Supported sound formats, each for little- and big-endian.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioFormat {
    Invalid = 0,
    /// Signed 8 bit
    S8 = 1,
    /// Unsigned 8 bit
    U8 = 2,
    /// Signed 16 bit little-endian
    S16LE = 3,
    /// Signed 16 bit big-endian
    S16BE = 4,
    /// Unsigned 16 bit little-endian
    U16LE = 5,
    /// Unsigned 16 bit big-endian
    U16BE = 6,
    /// The 24 bit types are not supported in rsoundio at the moment.
    /// Because there is no native number type that is 24 bits wide,
    /// (at least not in Rusts `std`) I had to use something like
    /// C unions in Rust to support them.
    /// This would probably be unsafe and working with
    /// 3 byte number types is also not too much fun.
    ///
    /// Signed 24 bit little-endian
    S24LE = 7,
    /// Signed 24 bit big-endian
    S24BE = 8,
    /// Unsigned 24 bit little-endian
    U24LE = 9,
    /// Unsigned 24 bit big-endian
    U24BE = 10,
    /// Signed 32 bit little-endian
    S32LE = 11,
    /// Signed 32 bit big-endian
    S32BE = 12,
    /// Unsigned 32 bit little-endian
    U32LE = 13,
    /// Unsigend 32 bit big-endian
    U32BE = 14,
    /// 32 bit float little-endian in [-1.0, 1.0]
    Float32LE = 15,
    /// 32 bit float big-endian in [-1.0, 1.0]
    Float32BE = 16,
    /// 64 bit float little-endian in [-1.0, 1.0]
    Float64LE = 17,
    /// 64 bit float big-endian in [-1.0, 1.0]
    Float64BE = 18,
}
impl Display for SioFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_format_string(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}
impl SioFormat {
    /// Returns the number of bytes a sample takes in this format.
    pub fn bytes_per_sample(self) -> i32 {
        unsafe { soundio_get_bytes_per_sample(self) as i32 }
    }
}

// #[allow(dead_code,non_camel_case_types)]
// enum SoundIoRingBuffer { }
<commit_msg>Be a bit more concise<commit_after>use std::os::raw::c_char;
use std::fmt;
use std::ffi::{CStr, CString};
use std::fmt::Display;
use std::str::Utf8Error;

use ffi::functions::*;
use ffi::utils::*;

/// Possible error codes.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum SioError {
    None = 0,
    /// Out of memory.
    NoMem = 1,
    /// The backend does not appear to be active or running.
    InitAudioBackend = 2,
    /// A system resource other than memory (Dummy) was not available.
    SystemResources = 3,
    /// Attempted to open a device and failed.
    OpeningDevice = 4,
    NoSuchDevice = 5,
    /// The programmer did not comply with the API.
    Invalid = 6,
    /// libsoundio was compiled without support for that backend.
    ///
    /// Currently there is no JACK support in Arch Linux until
    /// `jack2{,-dbus}1.9.10-4` is available. See [this](https://bugs.archlinux.org/task/47839)
    /// bug report for details.
    BackendUnavailable = 7,
    /// An open stream had an error that can only be recovered from by
    /// destroying the stream and creating it again.
    Streaming = 8,
    /// Attempted to use a device with parameters it cannot support.
    IncompatibleDevice = 9,
    /// When JACK returns `JackNoSuchClient`
    NoSuchClient = 10,
    /// Attempted to use parameters that the backend cannot support.
    IncompatibleBackend = 11,
    /// Backend server shutdown or became inactive.
    BackendDisconnected = 12,
    Interrupted = 13,
    /// Buffer underrun occurred.
    Underflow = 14,
    /// Unable to convert to or from UTF-8 to the native string format.
    EncodingString = 15,
}
impl Display for SioError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_strerror(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}

/// Specifies where a channel is physically located.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u32)]
pub enum SioChannelId {
    Invalid = 0,
    /// First of the more commonly supported ids.
    FrontLeft = 1,
    FrontRight = 2,
    FrontCenter = 3,
    Lfe = 4,
    BackLeft = 5,
    BackRight = 6,
    FrontLeftCenter = 7,
    FrontRightCenter = 8,
    BackCenter = 9,
    SideLeft = 10,
    SideRight = 11,
    TopCenter = 12,
    TopFrontLeft = 13,
    TopFrontCenter = 14,
    TopFrontRight = 15,
    TopBackLeft = 16,
    TopBackCenter = 17,
    /// Last of the more commonly supported ids.
    TopBackRight = 18,
    /// First of the less commonly supported ids.
    BackLeftCenter = 19,
    BackRightCenter = 20,
    FrontLeftWide = 21,
    FrontRightWide = 22,
    FrontLeftHigh = 23,
    FrontCenterHigh = 24,
    FrontRightHigh = 25,
    TopFrontLeftCenter = 26,
    TopFrontRightCenter = 27,
    TopSideLeft = 28,
    TopSideRight = 29,
    LeftLfe = 30,
    RightLfe = 31,
    Lfe2 = 32,
    BottomCenter = 33,
    BottomLeftCenter = 34,
    BottomRightCenter = 35,
    /// Mid/side recording
    MsMid = 36,
    MsSide = 37,
    /// first order ambisonic channels
    AmbisonicW = 38,
    AmbisonicX = 39,
    AmbisonicY = 40,
    AmbisonicZ = 41,
    /// X-Y Recording
    XyX = 42,
    XyY = 43,
    /// First of the "other" channel ids
    HeadphonesLeft = 44,
    HeadphonesRight = 45,
    ClickTrack = 46,
    ForeignLanguage = 47,
    HearingImpaired = 48,
    Narration = 49,
    Haptic = 50,
    /// Last of the "other" channel ids
    DialogCentricMix = 51,
    Aux = 52,
    Aux0 = 53,
    Aux1 = 54,
    Aux2 = 55,
    Aux3 = 56,
    Aux4 = 57,
    Aux5 = 58,
    Aux6 = 59,
    Aux7 = 60,
    Aux8 = 61,
    Aux9 = 62,
    Aux10 = 63,
    Aux11 = 64,
    Aux12 = 65,
    Aux13 = 66,
    Aux14 = 67,
    Aux15 = 68,
}
impl Display for SioChannelId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_get_channel_name(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}
impl From<String> for SioChannelId {
    fn from(id: String) -> Self {
        let str_len = id.len() as i32;
        let cstr = CString::new(id).unwrap();
        unsafe { soundio_parse_channel_id(cstr.as_ptr(), str_len) }
    }
}

/// Built-in channel layouts for convenience.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioChannelLayoutId {
    Mono = 0,
    Stereo = 1,
    TwoPointOne = 2,
    ThreePointZero = 3,
    ThreePointZeroBack = 4,
    ThreePointOne = 5,
    FourPointZero = 6,
    Quad = 7,
    QuadSide = 8,
    FourPointOne = 9,
    FivePointZeroBack = 10,
    FivePointZeroSide = 11,
    FivePointOne = 12,
    FivePointOneBack = 13,
    SixPointZeroSide = 14,
    SixPointZeroFront = 15,
    Hexagonal = 16,
    SixPointOne = 17,
    SixPointOneBack = 18,
    SixPointOneFront = 19,
    SevenPointZero = 20,
    SevenPointZeroFront = 21,
    SevenPointOne = 22,
    SevenPointOneWide = 23,
    SevenPointOneWideBack = 24,
    Octagonal = 25,
}

#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)]
pub enum SioBackend {
    None = 0,
    Jack = 1,
    PulseAudio = 2,
    Alsa = 3,
    CoreAudio = 4,
    Wasapi = 5,
    Dummy = 6,
}
impl Display for SioBackend {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_backend_name(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}

#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioDeviceAim {
    /// capture/recording
    Input = 0,
    /// playback
    Output = 1,
}

/// Supported sound formats, each for little- and big-endian.
#[allow(dead_code,non_camel_case_types)]
#[derive(Clone, Copy)]
#[repr(u32)]
pub enum SioFormat {
    Invalid = 0,
    /// Signed 8 bit
    S8 = 1,
    /// Unsigned 8 bit
    U8 = 2,
    /// Signed 16 bit little-endian
    S16LE = 3,
    /// Signed 16 bit big-endian
    S16BE = 4,
    /// Unsigned 16 bit little-endian
    U16LE = 5,
    /// Unsigned 16 bit big-endian
    U16BE = 6,
    /// The 24 bit types are not supported in rsoundio at the moment.
    /// Because there is no native number type that is 24 bits wide,
    /// (at least not in Rusts `std`) I had to use something like
    /// C unions in Rust to support them.
    /// This would probably be unsafe and working with
    /// 3 byte number types is also not too much fun.
    ///
    /// Signed 24 bit little-endian
    S24LE = 7,
    /// Signed 24 bit big-endian
    S24BE = 8,
    /// Unsigned 24 bit little-endian
    U24LE = 9,
    /// Unsigned 24 bit big-endian
    U24BE = 10,
    /// Signed 32 bit little-endian
    S32LE = 11,
    /// Signed 32 bit big-endian
    S32BE = 12,
    /// Unsigned 32 bit little-endian
    U32LE = 13,
    /// Unsigend 32 bit big-endian
    U32BE = 14,
    /// 32 bit float little-endian in [-1.0, 1.0]
    Float32LE = 15,
    /// 32 bit float big-endian in [-1.0, 1.0]
    Float32BE = 16,
    /// 64 bit float little-endian in [-1.0, 1.0]
    Float64LE = 17,
    /// 64 bit float big-endian in [-1.0, 1.0]
    Float64BE = 18,
}
impl Display for SioFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str_ptr = unsafe { soundio_format_string(*self) };
        write!(f, "{}", ptr_to_string(str_ptr).unwrap())
    }
}
impl SioFormat {
    /// Returns the number of bytes a sample takes in this format.
    pub fn bytes_per_sample(self) -> i32 {
        unsafe { soundio_get_bytes_per_sample(self) as i32 }
    }
}

// #[allow(dead_code,non_camel_case_types)]
// enum SoundIoRingBuffer { }
<|endoftext|>


<commit_before>//! Frame parsers and data handlers
//!
//! Parse various frame types and return a fully-constructed object. See individual functions for
//! their descriptions.

use structs::{Frame, Callsign, InformationField};
use constants;
use util;

pub fn parse_frame(raw_frame: &[u8]) -> Frame {
    for win in raw_frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            return parse_frame_ax25(raw_frame);
        }
    }
    parse_frame_text(raw_frame)
}

pub fn parse_frame_text(raw_frame: &[u8]) -> Frame {
    // src>dest[,path]:info
    let src_dest:  usize = raw_frame.iter().position(|x| *x == b'>').unwrap();
    let path_info: usize = raw_frame.iter().position(|x| *x == b':').unwrap();

    let source: Callsign = parse_callsign_text(&raw_frame[..src_dest]);
    let mut dest: Callsign = Callsign::new();
    let info: InformationField = parse_info_field(&raw_frame[(path_info + 1)..]);

    // Full path slice
    let mut _path: Vec<Callsign> = Vec::new();
    let _paths: &[u8] = &raw_frame[src_dest + 1..path_info];
    for (ind, path) in _paths.split(|x| *x == b',').enumerate() {
        if ind == 0 {
            dest = parse_callsign_text(path);
        } else {
            _path.push(parse_callsign_text(path));
        }
    }
    Frame {
        source: source,
        destination: dest,
        path: _path,
        info: info
    }
}

pub fn parse_frame_ax25(raw_frame: &[u8]) -> Frame {
    let mut _frame: &[u8] = raw_frame;
    let mut kiss_call: bool = false;

    if _frame.starts_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[ind..];
        kiss_call = true;
    }
    if _frame.ends_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().rev().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[..(_frame.len() - ind)];
        kiss_call = true;
    }

    let mut info_pos: usize = 0;
    for win in _frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            break;
        }
        info_pos += 1;
    }
    let (frame_addressing, _) = _frame.split_at(info_pos);
    let (_, mut info_field)   = _frame.split_at(info_pos + 2);
    if info_field.ends_with(&[0xff, 0x07]) {
        info_field = &info_field[..(info_field.len() - 2)];
    }
    let dest: Callsign = parse_callsign_ax25(&frame_addressing, kiss_call);
    let src: Callsign = parse_callsign_ax25(&frame_addressing[7..], kiss_call);

    let mut path: Vec<Callsign> = Vec::new();
    for chunk in frame_addressing[14..].chunks(7) {
        path.push(parse_callsign_ax25(chunk, false));
    }

    Frame {
        source: src,
        destination: dest,
        path: path,
        info: parse_info_field(info_field),
    }
}

pub fn parse_callsign(raw_callsign: &[u8]) -> Callsign {
    parse_callsign_text(raw_callsign)
}

pub fn parse_callsign_text(raw_callsign: &[u8]) -> Callsign {
    let mut _callsign: String = String::from_utf8(raw_callsign.to_vec()).unwrap();
    let mut ssid: u8 = 0;
    let mut digi: bool = false;

    if _callsign.contains('*') {
        _callsign.trim_matches('*');
        digi = true;
    }
    let pos: Option<usize> = _callsign.find('-');
    match pos {
        Some(x) => {
            _callsign = {
                let (call, id): (&str, &str) = _callsign.split_at(x);
                ssid = id[1..].parse::<u8>().unwrap();
                call.to_string()
            };
        },
        None => {}
    }
    Callsign {
        callsign: _callsign,
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_callsign_ax25(raw_callsign: &[u8], kiss_call: bool) -> Callsign {
    Callsign::new()
}

pub fn parse_info_field(raw_data: &[u8]) -> InformationField {
    let first_byte: &u8 = raw_data.first().unwrap();
    let data_type: String = constants::DATA_TYPE_MAP.get(first_byte).unwrap().to_string();
    InformationField {
        data: raw_data.to_vec(),
        data_type: data_type,
        safe: true
    }
}

pub fn default_data_handler(data: &[u8], data_type: &str) -> String {
    String::new()
}
<commit_msg>parse_callsign_ax25<commit_after>//! Frame parsers and data handlers
//!
//! Parse various frame types and return a fully-constructed object. See individual functions for
//! their descriptions.

use structs::{Frame, Callsign, InformationField};
use constants;
use util;

pub fn parse_frame(raw_frame: &[u8]) -> Frame {
    for win in raw_frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            return parse_frame_ax25(raw_frame);
        }
    }
    parse_frame_text(raw_frame)
}

pub fn parse_frame_text(raw_frame: &[u8]) -> Frame {
    // src>dest[,path]:info
    let src_dest:  usize = raw_frame.iter().position(|x| *x == b'>').unwrap();
    let path_info: usize = raw_frame.iter().position(|x| *x == b':').unwrap();

    let source: Callsign = parse_callsign_text(&raw_frame[..src_dest]);
    let mut dest: Callsign = Callsign::new();
    let info: InformationField = parse_info_field(&raw_frame[(path_info + 1)..]);

    // Full path slice
    let mut _path: Vec<Callsign> = Vec::new();
    let _paths: &[u8] = &raw_frame[src_dest + 1..path_info];
    for (ind, path) in _paths.split(|x| *x == b',').enumerate() {
        if ind == 0 {
            dest = parse_callsign_text(path);
        } else {
            _path.push(parse_callsign_text(path));
        }
    }
    Frame {
        source: source,
        destination: dest,
        path: _path,
        info: info
    }
}

pub fn parse_frame_ax25(raw_frame: &[u8]) -> Frame {
    let mut _frame: &[u8] = raw_frame;
    let mut kiss_call: bool = false;

    if _frame.starts_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[ind..];
        kiss_call = true;
    }
    if _frame.ends_with(&[constants::KISS_DATA_FRAME]) {
        let mut ind: usize = 0;
        for (id, byt) in _frame.iter().rev().enumerate() {
            if byt == &constants::KISS_DATA_FRAME {
                continue;
            } else {
                ind = id;
                break;
            }
        }
        _frame = &_frame[..(_frame.len() - ind)];
        kiss_call = true;
    }

    let mut info_pos: usize = 0;
    for win in _frame.windows(2) {
        if win == constants::ADDR_INFO_DELIM {
            break;
        }
        info_pos += 1;
    }
    let (frame_addressing, _) = _frame.split_at(info_pos);
    let (_, mut info_field)   = _frame.split_at(info_pos + 2);
    if info_field.ends_with(&[0xff, 0x07]) {
        info_field = &info_field[..(info_field.len() - 2)];
    }
    let dest: Callsign = parse_callsign_ax25(&frame_addressing, kiss_call);
    let src: Callsign = parse_callsign_ax25(&frame_addressing[7..], kiss_call);

    let mut path: Vec<Callsign> = Vec::new();
    for chunk in frame_addressing[14..].chunks(7) {
        path.push(parse_callsign_ax25(chunk, false));
    }

    Frame {
        source: src,
        destination: dest,
        path: path,
        info: parse_info_field(info_field),
    }
}

pub fn parse_callsign(raw_callsign: &[u8]) -> Callsign {
    parse_callsign_text(raw_callsign)
}

pub fn parse_callsign_text(raw_callsign: &[u8]) -> Callsign {
    let mut _callsign: String = String::from_utf8(raw_callsign.to_vec()).unwrap();
    let mut ssid: u8 = 0;
    let mut digi: bool = false;

    if _callsign.contains('*') {
        _callsign.trim_matches('*');
        digi = true;
    }
    let pos: Option<usize> = _callsign.find('-');
    match pos {
        Some(x) => {
            _callsign = {
                let (call, id): (&str, &str) = _callsign.split_at(x);
                ssid = id[1..].parse::<u8>().unwrap();
                call.to_string()
            };
        },
        None => {}
    }
    Callsign {
        callsign: _callsign,
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_callsign_ax25(raw_callsign: &[u8], kiss_call: bool) -> Callsign {
    // based on ax.25 v2.0 protocol, NOT v2.2
    let mut _callsign: Vec<u8> = Vec::new();
    let mut digi: bool = false;

    for chunk in raw_callsign[..6].iter() {
        let mut _chunk = chunk & 0xFF;
        // shift 1 bit
        _chunk = _chunk >> 1;
        if (_chunk as char).is_alphanumeric() {
            _callsign.push(_chunk);
        }
    }

    // seventh byte is ssid or digi
    let seven_chunk: u8 = raw_callsign[6] & 0xFF;
    let ssid = (seven_chunk >> 1) & 0x0F;

    // fixme - see python module
    if kiss_call {
        if (seven_chunk >> 1 & 0x80) == 1 {
            digi = true;
        }
    } else {
        if (seven_chunk & 0x80) == 1 {
            digi = true;
        }
    }
    Callsign {
        callsign: String::from_utf8(_callsign).unwrap(),
        ssid: ssid,
        digi: digi
    }
}

pub fn parse_info_field(raw_data: &[u8]) -> InformationField {
    let first_byte: &u8 = raw_data.first().unwrap();
    let data_type: String = constants::DATA_TYPE_MAP.get(first_byte).unwrap().to_string();
    InformationField {
        data: raw_data.to_vec(),
        data_type: data_type,
        safe: true
    }
}

pub fn default_data_handler(data: &[u8], data_type: &str) -> String {
    String::new()
}
<|endoftext|>


<commit_before>use std::io::Write;
use euclid::{Point2D, Rect};
use rand;
use calx_grid::Dir6;
use scancode::Scancode;
use world::{on_screen, Command, Location, TerrainQuery, World};
use display;

pub struct View {
    pub world: World,
    pub console: display::Console,
    pub console_is_large: bool,
}

impl View {
    pub fn new(world: World) -> View {
        View {
            world: world,
            console: display::Console::new(),
            console_is_large: false,
        }
    }

    fn game_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => Ok(self.console_is_large = !self.console_is_large),
            Q => self.world.step(Dir6::Northwest),
            W => self.world.step(Dir6::North),
            E => self.world.step(Dir6::Northeast),
            A => self.world.step(Dir6::Southwest),
            S => self.world.step(Dir6::South),
            D => self.world.step(Dir6::Southeast),
            _ => Ok(()),
        }
    }

    fn console_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => Ok(self.console_is_large = !self.console_is_large),
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn dump(&mut self) {
        dump_map(&self.world);
    }

    /// Generate a new random cave map.
    fn cave(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::caves(&mut self.world,
                      &mut rand::thread_rng(),
                      Location::new(0, 0, 0),
                      300);
    }

    /// Generate a new random maze map.
    fn maze(&mut self, sparseness: usize) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::maze(&mut self.world, &mut rand::thread_rng(), sparseness);
    }

    /// Generate a new random rooms and corridors
    fn rooms(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::rooms(&mut self.world, &mut rand::thread_rng());
    }

    command_parser!{
        fn cave(&mut self);
        fn maze(&mut self, sparseness: usize);
        fn rooms(&mut self);

        fn dump(&mut self);
    }

    fn parse_command(&mut self, command: &str) {
        writeln!(&mut self.console,
                 "TODO: Do something clever with '{}' here.",
                 command);
    }

    pub fn draw(&mut self, context: &mut display::Context, screen_area: &Rect<f32>) {
        let camera_loc = Location::new(0, 0, 0);
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;

        view.draw(&self.world, context);

        if self.console_is_large {
            let mut console_area = *screen_area;
            console_area.size.height /= 2.0;
            self.console.draw_large(context, &console_area);
        } else {
            self.console.draw_small(context, screen_area);
        }

        if let Some(scancode) = context.backend.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            if self.console_is_large {
                self.console_input(scancode)
            } else {
                self.game_input(scancode)
            };
        }
    }
}

/// Print the world map as ASCII.
fn dump_map(world: &World) {
    for y in -21..21 {
        for x in -39..41 {
            if (x + y) % 2 != 0 { print!(" "); continue; }
            let pos = Point2D::new((x + y) / 2, y);
            if on_screen(pos) {
                let t = world.terrain(Location::new(0, 0, 0) + pos);
                if t.is_open() {
                    print!(".");
                } else if t.is_door() {
                    print!("+");
                } else if t.is_wall() {
                    print!("#");
                } else {
                    print!("*");
                }
            } else {
                print!(" ");
            }
        }
        println!("");
    }
}
<commit_msg>Cleanup obsolete placeholder<commit_after>use std::io::Write;
use euclid::{Point2D, Rect};
use rand;
use calx_grid::Dir6;
use scancode::Scancode;
use world::{on_screen, Command, Location, TerrainQuery, World};
use display;

pub struct View {
    pub world: World,
    pub console: display::Console,
    pub console_is_large: bool,
}

impl View {
    pub fn new(world: World) -> View {
        View {
            world: world,
            console: display::Console::new(),
            console_is_large: false,
        }
    }

    fn game_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => Ok(self.console_is_large = !self.console_is_large),
            Q => self.world.step(Dir6::Northwest),
            W => self.world.step(Dir6::North),
            E => self.world.step(Dir6::Northeast),
            A => self.world.step(Dir6::Southwest),
            S => self.world.step(Dir6::South),
            D => self.world.step(Dir6::Southeast),
            _ => Ok(()),
        }
    }

    fn console_input(&mut self, scancode: Scancode) -> Result<(), ()> {
        use scancode::Scancode::*;
        match scancode {
            Tab => Ok(self.console_is_large = !self.console_is_large),
            Enter | PadEnter => {
                let input = self.console.get_input();
                let _ = writeln!(&mut self.console, "{}", input);
                if let Err(e) = self.parse(&input) {
                    let _ = writeln!(&mut self.console, "{}", e);
                }
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn dump(&mut self) {
        dump_map(&self.world);
    }

    /// Generate a new random cave map.
    fn cave(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::caves(&mut self.world,
                      &mut rand::thread_rng(),
                      Location::new(0, 0, 0),
                      300);
    }

    /// Generate a new random maze map.
    fn maze(&mut self, sparseness: usize) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::maze(&mut self.world, &mut rand::thread_rng(), sparseness);
    }

    /// Generate a new random rooms and corridors
    fn rooms(&mut self) {
        use world::mapgen;
        self.world = World::new(1);
        mapgen::rooms(&mut self.world, &mut rand::thread_rng());
    }

    command_parser!{
        fn cave(&mut self);
        fn maze(&mut self, sparseness: usize);
        fn rooms(&mut self);

        fn dump(&mut self);
    }

    pub fn draw(&mut self, context: &mut display::Context, screen_area: &Rect<f32>) {
        let camera_loc = Location::new(0, 0, 0);
        let mut view = display::WorldView::new(camera_loc, *screen_area);
        view.show_cursor = true;

        view.draw(&self.world, context);

        if self.console_is_large {
            let mut console_area = *screen_area;
            console_area.size.height /= 2.0;
            self.console.draw_large(context, &console_area);
        } else {
            self.console.draw_small(context, screen_area);
        }

        if let Some(scancode) = context.backend.poll_key().and_then(|k| Scancode::new(k.scancode)) {
            if self.console_is_large {
                self.console_input(scancode)
            } else {
                self.game_input(scancode)
            };
        }
    }
}

/// Print the world map as ASCII.
fn dump_map(world: &World) {
    for y in -21..21 {
        for x in -39..41 {
            if (x + y) % 2 != 0 { print!(" "); continue; }
            let pos = Point2D::new((x + y) / 2, y);
            if on_screen(pos) {
                let t = world.terrain(Location::new(0, 0, 0) + pos);
                if t.is_open() {
                    print!(".");
                } else if t.is_door() {
                    print!("+");
                } else if t.is_wall() {
                    print!("#");
                } else {
                    print!("*");
                }
            } else {
                print!(" ");
            }
        }
        println!("");
    }
}
<|endoftext|>