<commit_before>use env;

#[deriving(Clone, PartialEq)]
pub enum ExprAst {
    Int(IntNode),
    Str(StrNode),
    Bool(BoolNode),
    Pair(PairNode),
    Symbol(SymbolNode),
    Char(CharNode),
    Proc(ProcNode),
    CompProc(CompProcNode),
    Nil
}

pub trait Ast {
    fn print(&self);
}

impl Ast for ExprAst {
    fn print(&self) {
        match *self {
            ExprAst::Int(ref ast) =>  ast.print(),
            ExprAst::Str(ref ast) =>  ast.print(),
            ExprAst::Bool(ref ast) => ast.print(),
            ExprAst::Pair(ref ast) => ast.print(),
            ExprAst::Symbol(ref ast) => ast.print(),
            ExprAst::Char(ref ast) => ast.print(),
            ExprAst::Proc(ref ast) => ast.print(),
            ExprAst::CompProc(ref ast) => ast.print(),
            ExprAst::Nil => println!("Nil")
        }
    }
}

macro_rules! is_ast_type {
    ($func_name:ident, $type_name:ident) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            match *self {
                ExprAst::$type_name(_) => true,
                _ => false
            }
        }})
}

is_ast_type!(is_char, Char);
is_ast_type!(is_int, Int);
is_ast_type!(is_symbol, Symbol);
is_ast_type!(is_string, Str);
is_ast_type!(is_proc, Proc);
is_ast_type!(is_bool, Bool);
is_ast_type!(is_cproc, CompProc);

macro_rules! is_type {
    ($func_name:ident, $type_str:expr) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            return self.is_tagged(ExprAst::Symbol(SymbolNode::new($type_str)))
        }
    })
}

is_type!(is_quote, "quote");
is_type!(is_def, "define");
is_type!(is_and, "and");
is_type!(is_or, "or");
is_type!(is_if, "if");
is_type!(is_assign, "set!");
is_type!(is_lambda, "lambda");
is_type!(is_cond, "cond");
is_type!(is_let, "let");
is_type!(is_begin, "begin");

impl ExprAst {
    pub fn is_true(&self) -> bool {
        return self.as_bool();
    }

    pub fn is_false(&self) -> bool {
        return !self.as_bool();
    }

    pub fn is_pair(&self) -> bool {
        match *self {
            ExprAst::Pair(_) => true,
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn as_bool(&self) -> bool {
        match *self {
            ExprAst::Bool(ref ast) => ast.value,
            _ => panic!("error type: expect BoolNode")
        }
    }

    pub fn as_int(&self) -> int {
        match *self {
            ExprAst::Int(ref ast) => ast.value,
            _ => panic!("error type: expect IntNode")
        }
    }

    pub fn as_str(&self) -> String {
        match *self {
            ExprAst::Str(ref ast) => ast.value.clone(),
            ExprAst::Symbol(ref ast) => ast.value.clone(),
            _ => panic!("error type: expect StrNode")
        }
    }

    pub fn as_char(&self) -> char {
        match *self {
            ExprAst::Char(ref ast) => ast.value,
            _ => panic!("error type: expect CharNode")
        }
    }

    pub fn as_proc(&self) -> ProcFunc {
        match *self {
            ExprAst::Proc(ref ast) => ast.func.clone(),
            _ => panic!("error type: expct ProcNode")
        }
    }

    pub fn car(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn cdr(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn c(&self, s: &str) -> ExprAst {
        assert!(self.is_pair());
        let mut r = self.clone();
        for c in s.to_string().chars() {
            if c == 'a' { r = r.car(); }
            else { r = r.cdr(); }
        }
        return r;
    }

    pub fn is_last(&self) -> bool {
        assert!(self.is_pair());
        return self.cdr().is_empty();
    }

    pub fn is_self(&self) -> bool {
        match *self {
            ExprAst::Bool(_) => true,
            ExprAst::Int(_) => true,
            ExprAst::Char(_) => true,
            ExprAst::Str(_) => true,
            _ => false
        }
    }

    pub fn def_var(&self) -> ExprAst {
        assert!(self.is_def());
        if self.cdr().car().is_symbol() {
            self.c("da")
        } else {
            self.c("daa")
        }
    }

    pub fn def_val(&self) -> ExprAst {
        assert!(self.is_def());
        if self.c("da").is_symbol() {
            self.c("dda")
        } else {
            //proc
            return self.c("dad").make_lambda(self.c("dd"));
        }
    }

    pub fn make_lambda(&self, body: ExprAst) -> ExprAst {
        let lambda = ExprAst::Symbol(SymbolNode::new("lambda"));
        return ExprAst::Pair(PairNode::new(lambda,
                                           ExprAst::Pair(PairNode::new(
                                               (*self).clone(), body))));
    }

    pub fn params(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    pub fn body(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    fn is_tagged(&self, tag: ExprAst) -> bool {
        if self.is_pair() {
            let car = self.car();
            return car.is_symbol() && car == tag;
        }
        return false;
    }
}

#[deriving(Clone, PartialEq, Eq)]
pub struct IntNode {
    value: int
}

impl IntNode {
    pub fn new(val: int) -> IntNode {
        IntNode{ value: val}
    }

    fn print(&self) {
        println!("IntNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct StrNode {
    value: String
}

impl StrNode {
    pub fn new(val: &str) -> StrNode {
        StrNode{ value: val.to_string()}
    }

    fn print(&self) {
        println!("StrNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct BoolNode {
    value: bool
}

impl BoolNode {
    pub fn new(val: bool) -> BoolNode {
        BoolNode{ value: val}
    }

    fn print(&self) {
        println!("BoolNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct PairNode{
    pair: Vec<ExprAst>,
}

impl PairNode {
    pub fn new(car: ExprAst, cdr: ExprAst) -> PairNode {
        PairNode {
            pair: vec![car, cdr]
        }
    }

    fn print(&self) {
        println!("PairNode (");
        self.pair[0].print();
        self.pair[1].print();
        println!(")");
    }
}

#[deriving(Clone, PartialEq)]
pub struct SymbolNode {
    value: String
}

impl SymbolNode {
    pub fn new(val: &str) -> SymbolNode {
        SymbolNode { value: val.to_string() }
    }

    fn print(&self) {
        println!("SymbolNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct CharNode {
    value: char
}

impl CharNode {
    pub fn new(val: char) -> CharNode {
        CharNode { value: val}
    }

    fn print(&self) {
        println!("CharNode: {}", self.value);
    }
}

#[deriving(Clone)]
pub struct ProcFunc(fn(ExprAst) -> ExprAst);
impl PartialEq for ProcFunc {
    fn eq(&self, o: &ProcFunc) -> bool {
        let _o: *const() = unsafe { ::std::mem::transmute(o)};
        let _s: *const() = unsafe { ::std::mem::transmute(self)};
        _s == _o
    }
    fn ne(&self, o: &ProcFunc) -> bool {
        !self.eq(o)
    }
}

impl ProcFunc {
    pub fn func(&self) -> (fn(ExprAst) -> ExprAst) {
        match *self {
            ProcFunc(fun) => fun
        }
    }
}

#[deriving(Clone, PartialEq)]
pub struct ProcNode {
    value: String,
    func: ProcFunc
}

impl ProcNode {
    pub fn new(obj: fn(ExprAst)-> ExprAst) -> ProcNode {
        ProcNode { value: "proc".to_string(), func: ProcFunc(obj) }
    }

    fn print(&self) {
        println!("ProcNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct CompProcNode {
    pub pair:   Vec<ExprAst>,
    pub env:    Option<Box<env::Env>>
}

impl CompProcNode {
    pub fn new(params: ExprAst, body: ExprAst, env: Box<env::Env>) -> CompProcNode {
        CompProcNode { pair: vec![params, body],  env: Some(env) }
    }

    fn print(&self) {
        println!("CompProcNode: ");
    }
}

#[test]
fn test_ast_int() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_int() == 3);
}

#[test]
#[should_fail]
fn test_ast_int_fail() {
    let str_node = ExprAst::Str(StrNode::new("hello"));
    assert!(str_node.as_int() == 3);
}

#[test]
fn test_ast_bool() {
    let bool_node = ExprAst::Bool(BoolNode::new(false));
    assert!(bool_node.as_bool() == false);
}

#[test]
#[should_fail]
fn test_ast_bool_fail() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_bool() == false);
}

#[test]
fn test_ast_char() {
    let char_node = ExprAst::Char(CharNode::new('a'));
    assert!(char_node.as_char() == 'a');
}

#[test]
#[should_fail]
fn test_ast_char_fail() {
    let int_node = ExprAst::Int(IntNode::new(1));
    assert!(int_node.as_char() == 'a');
    assert!(int_node.is_self());
}

#[test]
fn test_ast_str() {
    let str_node = ExprAst::Str(StrNode::new("hello"));
    assert!(str_node.as_str() == "hello");
    assert!(str_node.is_self());
}

#[test]
#[should_fail]
fn test_ast_str_fail() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_str() == "3");
    assert!(int_node.is_self());
}

#[test]
fn test_ast_pair() {
    let int_node = ExprAst::Int(IntNode::new(3));
    int_node.print();
    let str_node = ExprAst::Str(StrNode::new("hello"));
    str_node.print();
    let pair_node = ExprAst::Pair(PairNode::new(int_node, str_node));
    let car_node = pair_node.car();
    let cdr_node = pair_node.cdr();
    assert!(car_node.as_int() == 3);
    assert!(cdr_node.as_str() == "hello");
    assert!(!pair_node.is_self());
}

#[test]
fn test_ast_symbol() {
    let sym_node = ExprAst::Symbol(SymbolNode::new("sym"));
    assert!(sym_node.is_symbol());
    assert!(!sym_node.is_self());
}

#[test]
#[should_fail]
fn test_ast_pair_fail() {
    let int_node = ExprAst::Int(IntNode::new(3));
    let car_node = int_node.car();
    assert!(car_node.as_int() == 3);
}

#[test]
fn test_ast_empty() {
    let empty_node = ExprAst::Nil;
    assert!(empty_node.is_empty());
    assert!(!empty_node.is_self());
}

#[test]
#[should_fail]
fn test_ast_empty_fail() {
    let empty_node = ExprAst::Int(IntNode::new(3));
    assert!(empty_node.is_empty());
    assert!(empty_node.is_quote());
}

#[test]
fn test_ast_is_set() {
    macro_rules! test_case {
        ($str_name:expr) => {
            {let node = ExprAst::Pair(PairNode::new(
                ExprAst::Symbol(SymbolNode::new($str_name)),
                ExprAst::Int(IntNode::new(3))));
            node}
        }
    }
    assert!(test_case!("let").is_let());
    assert!(test_case!("if").is_if());
    assert!(test_case!("lambda").is_lambda());
    assert!(test_case!("cond").is_cond());
    assert!(test_case!("set!").is_assign());
    assert!(test_case!("begin").is_begin());
}

#[test]
fn test_symbol_eq() {
    let aa = ExprAst::Symbol(SymbolNode::new("else"));
    let bb = ExprAst::Symbol(SymbolNode::new("else"));
    assert!(aa == bb);
}

#[test]
fn test_proc() {
    fn _proc(obj: ExprAst) -> ExprAst {
        obj.print();
        return ExprAst::Symbol(SymbolNode::new("ok"));
    }

    let proc_node = ExprAst::Proc(ProcNode::new(_proc));
    assert!(proc_node.is_proc());
    assert!(!proc_node.is_cproc());
}
<commit_msg>clean test cases for ast<commit_after>use env;

#[deriving(Clone, PartialEq)]
pub enum ExprAst {
    Int(IntNode),
    Str(StrNode),
    Bool(BoolNode),
    Pair(PairNode),
    Symbol(SymbolNode),
    Char(CharNode),
    Proc(ProcNode),
    CompProc(CompProcNode),
    Nil
}

pub trait Ast {
    fn print(&self);
}

impl Ast for ExprAst {
    fn print(&self) {
        match *self {
            ExprAst::Int(ref ast) =>  ast.print(),
            ExprAst::Str(ref ast) =>  ast.print(),
            ExprAst::Bool(ref ast) => ast.print(),
            ExprAst::Pair(ref ast) => ast.print(),
            ExprAst::Symbol(ref ast) => ast.print(),
            ExprAst::Char(ref ast) => ast.print(),
            ExprAst::Proc(ref ast) => ast.print(),
            ExprAst::CompProc(ref ast) => ast.print(),
            ExprAst::Nil => println!("Nil")
        }
    }
}

macro_rules! is_ast_type {
    ($func_name:ident, $type_name:ident) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            match *self {
                ExprAst::$type_name(_) => true,
                _ => false
            }
        }})
}

is_ast_type!(is_char, Char);
is_ast_type!(is_int, Int);
is_ast_type!(is_symbol, Symbol);
is_ast_type!(is_string, Str);
is_ast_type!(is_proc, Proc);
is_ast_type!(is_bool, Bool);
is_ast_type!(is_cproc, CompProc);

macro_rules! is_type {
    ($func_name:ident, $type_str:expr) => (impl ExprAst {
        pub fn $func_name(&self) -> bool {
            return self.is_tagged(ExprAst::Symbol(SymbolNode::new($type_str)))
        }
    })
}

is_type!(is_quote, "quote");
is_type!(is_def, "define");
is_type!(is_and, "and");
is_type!(is_or, "or");
is_type!(is_if, "if");
is_type!(is_assign, "set!");
is_type!(is_lambda, "lambda");
is_type!(is_cond, "cond");
is_type!(is_let, "let");
is_type!(is_begin, "begin");

impl ExprAst {
    pub fn is_true(&self) -> bool {
        return self.as_bool();
    }

    pub fn is_false(&self) -> bool {
        return !self.as_bool();
    }

    pub fn is_pair(&self) -> bool {
        match *self {
            ExprAst::Pair(_) => true,
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn is_empty(&self) -> bool {
        match *self {
            ExprAst::Nil => true,
            _ => false
        }
    }

    pub fn as_bool(&self) -> bool {
        match *self {
            ExprAst::Bool(ref ast) => ast.value,
            _ => panic!("error type: expect BoolNode")
        }
    }

    pub fn as_int(&self) -> int {
        match *self {
            ExprAst::Int(ref ast) => ast.value,
            _ => panic!("error type: expect IntNode")
        }
    }

    pub fn as_str(&self) -> String {
        match *self {
            ExprAst::Str(ref ast) => ast.value.clone(),
            ExprAst::Symbol(ref ast) => ast.value.clone(),
            _ => panic!("error type: expect StrNode")
        }
    }

    pub fn as_char(&self) -> char {
        match *self {
            ExprAst::Char(ref ast) => ast.value,
            _ => panic!("error type: expect CharNode")
        }
    }

    pub fn as_proc(&self) -> ProcFunc {
        match *self {
            ExprAst::Proc(ref ast) => ast.func.clone(),
            _ => panic!("error type: expct ProcNode")
        }
    }

    pub fn car(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn cdr(&self) -> ExprAst {
        match *self {
            ExprAst::Pair(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect PairNode")
        }
    }

    pub fn c(&self, s: &str) -> ExprAst {
        assert!(self.is_pair());
        let mut r = self.clone();
        for c in s.to_string().chars() {
            if c == 'a' { r = r.car(); }
            else { r = r.cdr(); }
        }
        return r;
    }

    pub fn is_last(&self) -> bool {
        assert!(self.is_pair());
        return self.cdr().is_empty();
    }

    pub fn is_self(&self) -> bool {
        match *self {
            ExprAst::Bool(_) => true,
            ExprAst::Int(_) => true,
            ExprAst::Char(_) => true,
            ExprAst::Str(_) => true,
            _ => false
        }
    }

    pub fn def_var(&self) -> ExprAst {
        assert!(self.is_def());
        if self.cdr().car().is_symbol() {
            self.c("da")
        } else {
            self.c("daa")
        }
    }

    pub fn def_val(&self) -> ExprAst {
        assert!(self.is_def());
        if self.c("da").is_symbol() {
            self.c("dda")
        } else {
            //proc
            return self.c("dad").make_lambda(self.c("dd"));
        }
    }

    pub fn make_lambda(&self, body: ExprAst) -> ExprAst {
        let lambda = ExprAst::Symbol(SymbolNode::new("lambda"));
        return ExprAst::Pair(PairNode::new(lambda,
                                           ExprAst::Pair(PairNode::new(
                                               (*self).clone(), body))));
    }

    pub fn params(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[0].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    pub fn body(&self) -> ExprAst {
        match *self {
            ExprAst::CompProc(ref ast) => ast.pair[1].clone(),
            _ => panic!("error type: expect CompProc")
        }
    }

    fn is_tagged(&self, tag: ExprAst) -> bool {
        if self.is_pair() {
            let car = self.car();
            return car.is_symbol() && car == tag;
        }
        return false;
    }
}

#[deriving(Clone, PartialEq, Eq)]
pub struct IntNode {
    value: int
}

impl IntNode {
    pub fn new(val: int) -> IntNode {
        IntNode{ value: val}
    }

    fn print(&self) {
        println!("IntNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct StrNode {
    value: String
}

impl StrNode {
    pub fn new(val: &str) -> StrNode {
        StrNode{ value: val.to_string()}
    }

    fn print(&self) {
        println!("StrNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct BoolNode {
    value: bool
}

impl BoolNode {
    pub fn new(val: bool) -> BoolNode {
        BoolNode{ value: val}
    }

    fn print(&self) {
        println!("BoolNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct PairNode{
    pair: Vec<ExprAst>,
}

impl PairNode {
    pub fn new(car: ExprAst, cdr: ExprAst) -> PairNode {
        PairNode {
            pair: vec![car, cdr]
        }
    }

    fn print(&self) {
        println!("PairNode (");
        self.pair[0].print();
        self.pair[1].print();
        println!(")");
    }
}

#[deriving(Clone, PartialEq)]
pub struct SymbolNode {
    value: String
}

impl SymbolNode {
    pub fn new(val: &str) -> SymbolNode {
        SymbolNode { value: val.to_string() }
    }

    fn print(&self) {
        println!("SymbolNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct CharNode {
    value: char
}

impl CharNode {
    pub fn new(val: char) -> CharNode {
        CharNode { value: val}
    }

    fn print(&self) {
        println!("CharNode: {}", self.value);
    }
}

#[deriving(Clone)]
pub struct ProcFunc(fn(ExprAst) -> ExprAst);
impl PartialEq for ProcFunc {
    fn eq(&self, o: &ProcFunc) -> bool {
        let _o: *const() = unsafe { ::std::mem::transmute(o)};
        let _s: *const() = unsafe { ::std::mem::transmute(self)};
        _s == _o
    }
    fn ne(&self, o: &ProcFunc) -> bool {
        !self.eq(o)
    }
}

impl ProcFunc {
    pub fn func(&self) -> (fn(ExprAst) -> ExprAst) {
        match *self {
            ProcFunc(fun) => fun
        }
    }
}

#[deriving(Clone, PartialEq)]
pub struct ProcNode {
    value: String,
    func: ProcFunc
}

impl ProcNode {
    pub fn new(obj: fn(ExprAst)-> ExprAst) -> ProcNode {
        ProcNode { value: "proc".to_string(), func: ProcFunc(obj) }
    }

    fn print(&self) {
        println!("ProcNode: {}", self.value);
    }
}

#[deriving(Clone, PartialEq)]
pub struct CompProcNode {
    pub pair:   Vec<ExprAst>,
    pub env:    Option<Box<env::Env>>
}

impl CompProcNode {
    pub fn new(params: ExprAst, body: ExprAst, env: Box<env::Env>) -> CompProcNode {
        CompProcNode { pair: vec![params, body],  env: Some(env) }
    }

    fn print(&self) {
        println!("CompProcNode: ");
    }
}

#[test]
fn test_ast() {
    let int_node = ExprAst::Int(IntNode::new(3));
    assert!(int_node.as_int() == 3);

    let char_node = ExprAst::Char(CharNode::new('a'));
    assert!(char_node.as_char() == 'a');

    let bool_node = ExprAst::Bool(BoolNode::new(false));
    assert!(bool_node.as_bool() == false);

    let str_node = ExprAst::Str(StrNode::new("hello"));
    assert!(str_node.as_str() == "hello");
    assert!(str_node.is_self());

    let int_node = ExprAst::Int(IntNode::new(3));
    int_node.print();
    let str_node = ExprAst::Str(StrNode::new("hello"));
    str_node.print();
    let pair_node = ExprAst::Pair(PairNode::new(int_node, str_node));
    let car_node = pair_node.car();
    let cdr_node = pair_node.cdr();
    assert!(car_node.as_int() == 3);
    assert!(cdr_node.as_str() == "hello");
    assert!(!pair_node.is_self());

    let sym_node = ExprAst::Symbol(SymbolNode::new("sym"));
    assert!(sym_node.is_symbol());
    assert!(!sym_node.is_self());

    let empty_node = ExprAst::Nil;
    assert!(empty_node.is_empty());
    assert!(!empty_node.is_self());
}

#[test]
fn test_ast_is_set() {
    macro_rules! test_case {
        ($str_name:expr) => {
            {let node = ExprAst::Pair(PairNode::new(
                ExprAst::Symbol(SymbolNode::new($str_name)),
                ExprAst::Int(IntNode::new(3))));
            node}
        }
    }
    assert!(test_case!("let").is_let());
    assert!(test_case!("if").is_if());
    assert!(test_case!("lambda").is_lambda());
    assert!(test_case!("cond").is_cond());
    assert!(test_case!("set!").is_assign());
    assert!(test_case!("begin").is_begin());
    assert!(!test_case!("begin").is_assign());
}

#[test]
fn test_symbol_eq() {
    let aa = ExprAst::Symbol(SymbolNode::new("else"));
    let bb = ExprAst::Symbol(SymbolNode::new("else"));
    assert!(aa == bb);
}

#[test]
fn test_proc() {
    fn _proc(obj: ExprAst) -> ExprAst {
        obj.print();
        return ExprAst::Symbol(SymbolNode::new("ok"));
    }

    let proc_node = ExprAst::Proc(ProcNode::new(_proc));
    assert!(proc_node.is_proc());
    assert!(!proc_node.is_cproc());
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate dent;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

fn print_summary(s: &Summary) {
    println!("N\tMin\tMax\tMedian\tMean\tStdDev\tStdErr");
    println!(
        "{}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}",
        s.size(),
        s.min(),
        s.max(),
        s.median(),
        s.mean(),
        s.standard_deviation(),
        s.standard_error(),
    );
}

fn print_t_test(t_test: &TTest) {
    println!("T\tDF\tAlpha\tCrit\tRejectNull");
    println!(
        "{:0.3}\t{}\t{:0.3}\t{:0.3}\t{}",
        t_test.t,
        t_test.df,
        t_test.alpha,
        t_test.crit,
        t_test.reject,
    );
}

fn read_file(path: &str) -> Summary {
    let p = Path::new(path);
    let f = File::open(p).unwrap();
    let r = BufReader::new(f);

    let data: Vec<f64> = r
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    Summary::new(&data).unwrap()
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(draw_plot: bool, width: usize, ascii: bool) {
    let stdin = io::stdin();

    let data: Vec<f64> = stdin
        .lock()
        .lines()
        .map(|l| l.unwrap().parse().unwrap())
        .collect();

    let s = Summary::new(&data).unwrap();

    if draw_plot {
        println!("{}\n", plot::summary_plot(&s, width, ascii));
    }

    print_summary(&s);
}

fn t_test_files(
    file1: &str,
    file2: &str,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let s1 = read_file(file1);
    let s2 = read_file(file2);

    let t_test = welch_t_test(&s1, &s2, alpha);

    if draw_plot {
        println!("{}\n", plot::comparison_plot(&s1, &s2, width, ascii, true));
    }

    print_summary(&s1);
    println!();
    print_summary(&s2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("file1")
             .index(1)
             .value_name("FILE1")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 1st file of sample data"))
        .arg(Arg::with_name("file2")
             .index(2)
             .value_name("FILE2")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 2nd file of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    if use_stdin {
        summarize_stdin(draw_plot, width, ascii);
    } else {
        let alpha = parse_alpha(matches.value_of("alpha").unwrap());
        let file1 = matches.value_of("file1").unwrap();
        let file2 = matches.value_of("file2").unwrap();

        t_test_files(file1, file2, alpha, draw_plot, width, ascii);
    }
}
<commit_msg>Allow blank lines in input files and streams<commit_after>extern crate clap;
extern crate dent;
extern crate term_size;

use clap::{App, Arg};
use dent::plot;
use dent::summary::Summary;
use dent::t_test::{SigLevel, TTest, welch_t_test};

use std::fs::File;
use std::path::Path;
use std::io::{self, BufRead, BufReader};

fn print_summary(s: &Summary) {
    println!("N\tMin\tMax\tMedian\tMean\tStdDev\tStdErr");
    println!(
        "{}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}\t{:0.2}",
        s.size(),
        s.min(),
        s.max(),
        s.median(),
        s.mean(),
        s.standard_deviation(),
        s.standard_error(),
    );
}

fn print_t_test(t_test: &TTest) {
    println!("T\tDF\tAlpha\tCrit\tRejectNull");
    println!(
        "{:0.3}\t{}\t{:0.3}\t{:0.3}\t{}",
        t_test.t,
        t_test.df,
        t_test.alpha,
        t_test.crit,
        t_test.reject,
    );
}

fn read_file(path: &str) -> Summary {
    let p = Path::new(path);
    let f = File::open(p).unwrap();
    let reader = BufReader::new(f);

    let mut data: Vec<f64> = vec![];

    for l in reader.lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        if let Ok(d) = s.parse() {
            data.push(d);
        }
    }

    Summary::new(&data).unwrap()
}

fn parse_alpha(arg: &str) -> SigLevel {
    match arg {
        ".001" => SigLevel::Alpha001,
        ".005" => SigLevel::Alpha005,
        ".01"  => SigLevel::Alpha010,
        ".025" => SigLevel::Alpha025,
        ".05"  => SigLevel::Alpha050,
        ".1"   => SigLevel::Alpha100,
        _ => panic!(),
    }
}

fn summarize_stdin(draw_plot: bool, width: usize, ascii: bool) {
    let stdin = io::stdin();

    let mut data: Vec<f64> = vec![];

    for l in stdin.lock().lines() {
        let s = l.unwrap().trim().to_string();

        if s.is_empty() {
            continue;
        }

        if let Ok(d) = s.parse() {
            data.push(d);
        }
    }

    let s = Summary::new(&data).unwrap();

    if draw_plot {
        println!("{}\n", plot::summary_plot(&s, width, ascii));
    }

    print_summary(&s);
}

fn t_test_files(
    file1: &str,
    file2: &str,
    alpha: SigLevel,
    draw_plot: bool,
    width: usize,
    ascii: bool,
) {
    let s1 = read_file(file1);
    let s2 = read_file(file2);

    let t_test = welch_t_test(&s1, &s2, alpha);

    if draw_plot {
        println!("{}\n", plot::comparison_plot(&s1, &s2, width, ascii, true));
    }

    print_summary(&s1);
    println!();
    print_summary(&s2);
    println!();
    print_t_test(&t_test);
}

fn main() {
    let matches = App::new("dent")
        .version("0.3.0")
        .author("Joe Ranweiler <joe@lemma.co>")
        .about("A tiny tool for t-tests &c.")
        .arg(Arg::with_name("stdin")
             .short("s")
             .long("stdin")
             .help("Read and summarize data from stdin"))
        .arg(Arg::with_name("file1")
             .index(1)
             .value_name("FILE1")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 1st file of sample data"))
        .arg(Arg::with_name("file2")
             .index(2)
             .value_name("FILE2")
             .takes_value(true)
             .required_unless("stdin")
             .help("Path to 2nd file of sample data"))
        .arg(Arg::with_name("alpha")
             .short("a")
             .long("alpha")
             .value_name("ALPHA")
             .help("Significance level α")
             .takes_value(true)
             .default_value(".05"))
        .arg(Arg::with_name("plot")
             .short("p")
             .long("plot")
             .help("Print standard boxplots"))
        .arg(Arg::with_name("ascii")
             .long("ascii")
             .help("Use only ASCII characters in boxplots"))
        .arg(Arg::with_name("width")
             .short("w")
             .long("width")
             .value_name("WIDTH")
             .takes_value(true)
             .help("Width of boxplot"))
        .get_matches();

    let ascii = matches.is_present("ascii");
    let draw_plot = matches.is_present("plot");
    let use_stdin = matches.is_present("stdin");

    let width = matches
        .value_of("width")
        .and_then(|w| w.parse::<usize>().ok())
        .or(term_size::dimensions().map(|(w, _)| w))
        .unwrap_or(80);

    if use_stdin {
        summarize_stdin(draw_plot, width, ascii);
    } else {
        let alpha = parse_alpha(matches.value_of("alpha").unwrap());
        let file1 = matches.value_of("file1").unwrap();
        let file2 = matches.value_of("file2").unwrap();

        t_test_files(file1, file2, alpha, draw_plot, width, ascii);
    }
}
<|endoftext|>


<commit_before>
//! A 3D camera.

pub type Vector3 = [f64, ..3];

pub struct Camera {
    pub position: Vector3,
    pub target: Vector3,
    pub right: Vector3,
    pub up: Vector3,
}

pub struct CameraSettings {
    pub fov_rad: f64,
    pub near_clip: f64,
    pub far_clip: f64,
    pub aspect_ratio: f64,
}

<commit_msg>Generating orthogonal matrix<commit_after>
//! A 3D camera.

pub type Vector3 = [f64, ..3];
pub type Matrix4x3 = [[f64, ..3], ..4];

pub struct Camera {
    pub position: Vector3,
    pub target: Vector3,
    pub right: Vector3,
    pub up: Vector3,
}

pub struct CameraSettings {
    pub fov_rad: f64,
    pub near_clip: f64,
    pub far_clip: f64,
    pub aspect_ratio: f64,
}

impl Camera {
    /// Computes the direction forward.
    ///
    /// Returns the normalized difference between target and position.
    pub fn forward(&self) -> Vector3 {
        let diff = [
                self.target[0] - self.position[0],
                self.target[1] - self.position[1],
                self.target[2] - self.position[2],
            ];
        let len = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
        [
            diff[0] / len,
            diff[1] / len,
            diff[2] / len,
        ]
    }

    /// Computes an orthogonal matrix for the camera.
    ///
    /// This matrix can be used to transform coordinates to the screen.
    pub fn orthogonal(&self) -> Matrix4x3 {
        [
            self.right,
            self.up,
            self.forward(),
            self.position
        ]
    }
}

<|endoftext|>


<commit_before>extern crate clap;
use clap::{App, ArgMatches};

pub struct ModuleConfig {
    pub load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            load: false,
        }
    }
}

pub struct CliConfig<'a> {
    pub module_configs  : Vec<ModuleConfig>,
    pub cli_matches     : ArgMatches<'a, 'a>,
}

impl<'a> CliConfig<'a> {
    pub fn new(app : clap::App<'a, 'a, 'a, 'a, 'a, 'a>) -> CliConfig<'a> {
        CliConfig {
            module_configs: vec![],
            cli_matches: app.get_matches(),
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbose") || self.is_debugging()
    }

    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debug")
    }

    pub fn get_rtp(&self) -> Option<String> {
        self.cli_matches.value_of("rtp").and_then(|s| Some(String::from(s)))
    }
}

<commit_msg>Implement Debug for CliConfig<commit_after>extern crate clap;
use clap::{App, ArgMatches};

use std::fmt::Debug;
use std::fmt::Formatter;
use std::fmt::Error;

pub struct ModuleConfig {
    pub load : bool,
}

impl ModuleConfig {
    pub fn new() -> ModuleConfig {
        ModuleConfig {
            load: false,
        }
    }
}

pub struct CliConfig<'a> {
    pub module_configs  : Vec<ModuleConfig>,
    pub cli_matches     : ArgMatches<'a, 'a>,
}

impl<'a> CliConfig<'a> {
    pub fn new(app : clap::App<'a, 'a, 'a, 'a, 'a, 'a>) -> CliConfig<'a> {
        CliConfig {
            module_configs: vec![],
            cli_matches: app.get_matches(),
        }
    }

    pub fn is_verbose(&self) -> bool {
        self.cli_matches.is_present("verbose") || self.is_debugging()
    }

    pub fn is_debugging(&self) -> bool {
        self.cli_matches.is_present("debug")
    }

    pub fn get_rtp(&self) -> Option<String> {
        self.cli_matches.value_of("rtp").and_then(|s| Some(String::from(s)))
    }
}

impl<'a> Debug for CliConfig<'a> {

    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "CliConfig (verbose: {}, debugging: {}, rtp: {})",
            self.is_verbose(),
            self.is_debugging(),
            self.get_rtp().or(Some(String::from("NONE"))).unwrap())
    }

}
<|endoftext|>


<commit_before>use clap::{Arg, App, SubCommand};
use super::{APP_VERSION, APP_NAME};

pub fn build_cli() -> App<'static, 'static> {
    App::new(APP_NAME)
        .version(APP_VERSION)
        .author("James K. <james.kominick@gmail.com>")
        .about("Postgres/SQLite migration manager")
        .subcommand(SubCommand::with_name("self")
                    .about("Self referential things")
                    .subcommand(SubCommand::with_name("update")
                        .about("Update to the latest binary release, replacing this binary")
                        .arg(Arg::with_name("no_confirm")
                             .help("Skip download/update confirmation")
                             .long("no-confirm")
                             .short("y")
                             .required(false)
                             .takes_value(false))
                        .arg(Arg::with_name("quiet")
                             .help("Suppress unnecessary download output (progress bar)")
                             .long("quiet")
                             .short("q")
                             .required(false)
                             .takes_value(false)))
                    .subcommand(SubCommand::with_name("bash-completions")
                        .about("Generate bash completions & output to stdout or a file if specified")
                        .subcommand(SubCommand::with_name("install")
                            .about("Installs generated bash completions")
                            .arg(Arg::with_name("path")
                                .help("Path to install bash completions at")
                                .long("path")
                                .default_value("/etc/bash_completion.d/migrant")
                                .takes_value(true)))))
        .subcommand(SubCommand::with_name("init")
            .about("Initialize project config")
            .arg(Arg::with_name("type")
                 .long("type")
                 .short("t")
                 .takes_value(true)
                 .help("Specify the database type (sqlite|postgres)"))
            .arg(Arg::with_name("location")
                 .long("location")
                 .short("l")
                 .takes_value(true)
                 .help("Directory to initialize in"))
            .arg(Arg::with_name("no-confirm")
                 .long("no-confirm")
                 .takes_value(false)
                 .help("Disable interactive prompts")))
        .subcommand(SubCommand::with_name("setup")
            .about("Setup migration table"))
        .subcommand(SubCommand::with_name("connect-string")
            .about("Print out the connection string for postgres, or file-path for sqlite"))
        .subcommand(SubCommand::with_name("list")
            .about("List status of applied and available migrations"))
        .subcommand(SubCommand::with_name("apply")
            .about("Moves up or down (applies up/down.sql) one migration. Default direction is up unless specified with `-d/--down`.")
            .arg(Arg::with_name("down")
                .long("down")
                .short("d")
                .help("Applies `down.sql` migrations"))
            .arg(Arg::with_name("all")
                .long("all")
                .short("a")
                .help("Applies all available migrations"))
            .arg(Arg::with_name("force")
                .long("force")
                .help("Applies the migration and treats it as if it were successful"))
            .arg(Arg::with_name("fake")
                .long("fake")
                .help("Updates the `.migrant.toml` file as if the specified migration was applied")))
        .subcommand(SubCommand::with_name("redo")
            .about("Shortcut for running the latest `down` and `up` migration. Can be augmented with `all` and `force`")
            .arg(Arg::with_name("all")
                .long("all")
                .short("a")
                .help("Applies all available migrations"))
            .arg(Arg::with_name("force")
                .long("force")
                .help("Applies the migration and treats it as if it were successful")))
        .subcommand(SubCommand::with_name("new")
            .about("Create new migration up/down files")
            .arg(Arg::with_name("tag")
                 .required(true)
                 .help("tag to use for new migration")))
        .subcommand(SubCommand::with_name("shell")
            .about("Open a repl connection"))
        .subcommand(SubCommand::with_name("edit")
            .about("Edit a migration file by tag name")
            .arg(Arg::with_name("tag")
                 .help("Tag name"))
            .arg(Arg::with_name("down")
                 .long("down")
                 .short("d")
                 .help("Edit the down.sql file")))
        .subcommand(SubCommand::with_name("which-config")
            .about("Display the path to the configuration file being used"))
}

<commit_msg>make tag required<commit_after>use clap::{Arg, App, SubCommand};
use super::{APP_VERSION, APP_NAME};

pub fn build_cli() -> App<'static, 'static> {
    App::new(APP_NAME)
        .version(APP_VERSION)
        .author("James K. <james.kominick@gmail.com>")
        .about("Postgres/SQLite migration manager")
        .subcommand(SubCommand::with_name("self")
                    .about("Self referential things")
                    .subcommand(SubCommand::with_name("update")
                        .about("Update to the latest binary release, replacing this binary")
                        .arg(Arg::with_name("no_confirm")
                             .help("Skip download/update confirmation")
                             .long("no-confirm")
                             .short("y")
                             .required(false)
                             .takes_value(false))
                        .arg(Arg::with_name("quiet")
                             .help("Suppress unnecessary download output (progress bar)")
                             .long("quiet")
                             .short("q")
                             .required(false)
                             .takes_value(false)))
                    .subcommand(SubCommand::with_name("bash-completions")
                        .about("Generate bash completions & output to stdout or a file if specified")
                        .subcommand(SubCommand::with_name("install")
                            .about("Installs generated bash completions")
                            .arg(Arg::with_name("path")
                                .help("Path to install bash completions at")
                                .long("path")
                                .default_value("/etc/bash_completion.d/migrant")
                                .takes_value(true)))))
        .subcommand(SubCommand::with_name("init")
            .about("Initialize project config")
            .arg(Arg::with_name("type")
                 .long("type")
                 .short("t")
                 .takes_value(true)
                 .help("Specify the database type (sqlite|postgres)"))
            .arg(Arg::with_name("location")
                 .long("location")
                 .short("l")
                 .takes_value(true)
                 .help("Directory to initialize in"))
            .arg(Arg::with_name("no-confirm")
                 .long("no-confirm")
                 .takes_value(false)
                 .help("Disable interactive prompts")))
        .subcommand(SubCommand::with_name("setup")
            .about("Setup migration table"))
        .subcommand(SubCommand::with_name("connect-string")
            .about("Print out the connection string for postgres, or file-path for sqlite"))
        .subcommand(SubCommand::with_name("list")
            .about("List status of applied and available migrations"))
        .subcommand(SubCommand::with_name("apply")
            .about("Moves up or down (applies up/down.sql) one migration. Default direction is up unless specified with `-d/--down`.")
            .arg(Arg::with_name("down")
                .long("down")
                .short("d")
                .help("Applies `down.sql` migrations"))
            .arg(Arg::with_name("all")
                .long("all")
                .short("a")
                .help("Applies all available migrations"))
            .arg(Arg::with_name("force")
                .long("force")
                .help("Applies the migration and treats it as if it were successful"))
            .arg(Arg::with_name("fake")
                .long("fake")
                .help("Updates the `.migrant.toml` file as if the specified migration was applied")))
        .subcommand(SubCommand::with_name("redo")
            .about("Shortcut for running the latest `down` and `up` migration. Can be augmented with `all` and `force`")
            .arg(Arg::with_name("all")
                .long("all")
                .short("a")
                .help("Applies all available migrations"))
            .arg(Arg::with_name("force")
                .long("force")
                .help("Applies the migration and treats it as if it were successful")))
        .subcommand(SubCommand::with_name("new")
            .about("Create new migration up/down files")
            .arg(Arg::with_name("tag")
                 .required(true)
                 .help("tag to use for new migration")))
        .subcommand(SubCommand::with_name("shell")
            .about("Open a repl connection"))
        .subcommand(SubCommand::with_name("edit")
            .about("Edit a migration file by tag name")
            .arg(Arg::with_name("tag")
                 .required(true)
                 .help("Tag name"))
            .arg(Arg::with_name("down")
                 .long("down")
                 .short("d")
                 .help("Edit the down.sql file")))
        .subcommand(SubCommand::with_name("which-config")
            .about("Display the path to the configuration file being used"))
}

<|endoftext|>


<commit_before>extern crate std;
extern crate num;
extern crate uuid;

use std::str::SendStr;
use std::io::net::ip::IpAddr;
use self::uuid::Uuid;

pub enum OpcodeRequest {
    //requests
    OpcodeStartup = 0x01,
    OpcodeCredentials = 0x04,
    OpcodeOptions = 0x05,
    OpcodeQuery = 0x07,
    OpcodePrepare = 0x09,
    OpcodeExecute = 0x0A,
    OpcodeRegister = 0x0B,
}

#[deriving(Show)]
pub enum OpcodeResponse {
    //responces
    OpcodeError = 0x00,
    OpcodeReady = 0x02,
    OpcodeAuthenticate = 0x03,
    OpcodeSupported = 0x06,
    OpcodeResult = 0x08,
    OpcodeEvent = 0x0C,

    OpcodeUnknown
}

#[deriving(Show, FromPrimitive)]
pub enum KindResult {
    KindVoid = 0x0001,
    KindRows = 0x0002,
    KindSetKeyspace = 0x0003,
    KindPrepared = 0x0004,
    KindSchemaChange = 0x0005
}

pub fn opcode_response(val: u8) -> OpcodeResponse {
    match val {
        /* requests
        0x01 => OpcodeStartup,
        0x04 => OpcodeCredentials,
        0x05 => OpcodeOptions,
        0x07 => OpcodeQuery,
        0x09 => OpcodePrepare,
        0x0B => OpcodeRegister,
        */

        0x00 => OpcodeError,
        0x02 => OpcodeReady,
        0x03 => OpcodeAuthenticate,
        0x06 => OpcodeSupported,
        0x08 => OpcodeResult,
        // 0x0A => OpcodeExecute,
        0x0C => OpcodeEvent,

        _ => OpcodeUnknown
    }
}

pub mod Consistency {
    pub enum Consistency {
        Any = 0x0000,
        One = 0x0001,
        Two = 0x0002,
        Three = 0x0003,
        Quorum = 0x0004,
        All = 0x0005,
        LocalQuorum = 0x0006,
        EachQuorum = 0x0007,
        Unknown,
    }
}

#[deriving(Show)]
pub enum CqlValueType {
    ColumnCustom = 0x0000,
    ColumnASCII = 0x0001,
    ColumnBigInt = 0x0002,
    ColumnBlob = 0x0003,
    ColumnBoolean = 0x0004,
    ColumnCounter = 0x0005,
    ColumnDecimal = 0x0006,
    ColumnDouble = 0x0007,
    ColumnFloat = 0x0008,
    ColumnInt = 0x0009,
    ColumnText = 0x000A,
    ColumnTimestamp = 0x000B,
    ColumnUuid = 0x000C,
    ColumnVarChar = 0x000D,
    ColumnVarint = 0x000E,
    ColumnTimeUuid = 0x000F,
    ColumnInet = 0x0010,
    ColumnList = 0x0020,
    ColumnMap = 0x0021,
    ColumnSet = 0x0022,
    ColumnUnknown,
}

pub fn cql_column_type(val: u16) -> CqlValueType {
    match val {
        0x0000 => ColumnCustom,
        0x0001 => ColumnASCII,
        0x0002 => ColumnBigInt,
        0x0003 => ColumnBlob,
        0x0004 => ColumnBoolean,
        0x0005 => ColumnCounter,
        0x0006 => ColumnDecimal,
        0x0007 => ColumnDouble,
        0x0008 => ColumnFloat,
        0x0009 => ColumnInt,
        0x000A => ColumnText,
        0x000B => ColumnTimestamp,
        0x000C => ColumnUuid,
        0x000D => ColumnVarChar,
        0x000E => ColumnVarint,
        0x000F => ColumnTimeUuid,
        0x0010 => ColumnInet,
        0x0020 => ColumnList,
        0x0021 => ColumnMap,
        0x0022 => ColumnSet,
        _ => ColumnUnknown
    }
}

#[deriving(Show)]
pub enum RCErrorType {
    ReadError,
    WriteError,
    SerializeError,
    ConnectionError,
    NoDataError,
    GenericError
}

#[deriving(Show)]
pub struct RCError {
    pub kind: RCErrorType,
    pub desc: SendStr,
}

impl RCError {
    pub fn new<T: IntoMaybeOwned<'static>>(msg: T, kind: RCErrorType) -> RCError {
        RCError {
            kind: kind,
            desc: msg.into_maybe_owned()
        }
    }
}

pub type RCResult<T> = Result<T, RCError>;

pub struct CqlStringMap {
    pub pairs: Vec<CqlPair>,
}

pub struct CqlPair {
    pub key: &'static str,
    pub value: &'static str,
}

pub enum CqlBytesSize {
   Cqli32,
   Cqli16
}

#[deriving(Show)]
pub struct CqlColMetadata {
    pub keyspace: SendStr,
    pub table: SendStr,
    pub col_name: SendStr,
    pub col_type: CqlValueType,
    pub col_type_aux1: CqlValueType,
    pub col_type_aux2: CqlValueType
}

#[deriving(Show)]
pub struct CqlMetadata {
    pub flags: u32,
    pub column_count: u32,
    pub keyspace: SendStr,
    pub table: SendStr,
    pub row_metadata: Vec<CqlColMetadata>,
}

#[deriving(Show)]
pub struct Pair<T, V> {
    pub key: T,
    pub value: V
}

pub type CQLList = Vec<CqlValue>;
pub type CQLMap = Vec<Pair<CqlValue, CqlValue>>;
pub type CQLSet = Vec<CqlValue>;

#[deriving(Show)]
pub enum CqlValue {
    CqlASCII(Option<SendStr>),
    CqlBigInt(Option<i64>),
    CqlBlob(Option<Vec<u8>>),
    CqlBoolean(Option<bool>),
    CqlCounter(Option<i64>),
    CqlDecimal(Option<num::BigInt>),
    CqlDouble(Option<f64>),
    CqlFloat(Option<f32>),
    CqlInet(Option<IpAddr>),
    CqlInt(Option<i32>),
    CqlList(Option<CQLList>),
    CqlMap(Option<CQLMap>),
    CqlSet(Option<CQLSet>),
    CqlText(Option<SendStr>),
    CqlTimestamp(Option<u64>),
    CqlUuid(Option<Uuid>),
    CqlTimeUuid(Option<Uuid>),
    CqlVarchar(Option<SendStr>),
    CqlVarint(Option<num::BigInt>),
    CqlUnknown,
}

#[deriving(Show)]
pub struct CqlRow {
    pub cols: Vec<CqlValue>,
}

/*
impl CqlRow {
    fn get_column(&self, col_name: &str) -> Option<CqlValue> {
        let mut i = 0;
        let len = self.metadata.row_metadata.len();
        while i < len {
            if self.metadata.row_metadata.get(i).col_name.as_slice() == col_name {
                return Some(*self.cols.get(i));
            }
            i += 1;
        }
        None
    }
}
*/

#[deriving(Show)]
pub struct CqlRows {
    pub metadata: Box<CqlMetadata>,
    pub rows: Vec<CqlRow>,
}

pub struct CqlRequest<'a> {
    pub version: u8,
    pub flags: u8,
    pub stream: i8,
    pub opcode: OpcodeRequest,
    pub body: CqlRequestBody<'a>,
}

pub enum CqlRequestBody<'a> {
    RequestStartup(CqlStringMap),
    RequestCred(&'a Vec<SendStr>),
    RequestQuery(&'a str, Consistency::Consistency, u8),
    RequestPrepare(&'a str),
    RequestExec(&'a CqlPreparedStat, &'a [CqlValue], Consistency::Consistency, u8),
    RequestOptions,
}

#[deriving(Show)]
pub struct CqlResponse {
    pub version: u8,
    pub flags: u8,
    pub stream: i8,
    pub opcode: OpcodeResponse,
    pub body: CqlResponseBody,
}

#[deriving(Show)]
pub enum CqlResponseBody {
    ResponseError(u32, SendStr),
    ResponseReady,
    ResponseAuth(SendStr),

    ResultVoid,
    ResultRows(Box<CqlRows>),
    ResultKeyspace(SendStr),
    ResultPrepared(Box<CqlPreparedStat>),
    ResultSchemaChange(SendStr, SendStr, SendStr),
    ResultUnknown,

    ResponseEmpty,
}

#[deriving(Show)]
pub struct CqlPreparedStat {
    pub id: Vec<u8>,
    pub meta: Box<CqlMetadata>,
    pub meta_result: Option<Box<CqlMetadata>>
}

<commit_msg>Now RequestPrepare takes a SendStr as query id<commit_after>extern crate std;
extern crate num;
extern crate uuid;

use std::str::SendStr;
use std::io::net::ip::IpAddr;
use self::uuid::Uuid;

pub enum OpcodeRequest {
    //requests
    OpcodeStartup = 0x01,
    OpcodeCredentials = 0x04,
    OpcodeOptions = 0x05,
    OpcodeQuery = 0x07,
    OpcodePrepare = 0x09,
    OpcodeExecute = 0x0A,
    OpcodeRegister = 0x0B,
}

#[deriving(Show)]
pub enum OpcodeResponse {
    //responces
    OpcodeError = 0x00,
    OpcodeReady = 0x02,
    OpcodeAuthenticate = 0x03,
    OpcodeSupported = 0x06,
    OpcodeResult = 0x08,
    OpcodeEvent = 0x0C,

    OpcodeUnknown
}

#[deriving(Show, FromPrimitive)]
pub enum KindResult {
    KindVoid = 0x0001,
    KindRows = 0x0002,
    KindSetKeyspace = 0x0003,
    KindPrepared = 0x0004,
    KindSchemaChange = 0x0005
}

pub fn opcode_response(val: u8) -> OpcodeResponse {
    match val {
        /* requests
        0x01 => OpcodeStartup,
        0x04 => OpcodeCredentials,
        0x05 => OpcodeOptions,
        0x07 => OpcodeQuery,
        0x09 => OpcodePrepare,
        0x0B => OpcodeRegister,
        */

        0x00 => OpcodeError,
        0x02 => OpcodeReady,
        0x03 => OpcodeAuthenticate,
        0x06 => OpcodeSupported,
        0x08 => OpcodeResult,
        // 0x0A => OpcodeExecute,
        0x0C => OpcodeEvent,

        _ => OpcodeUnknown
    }
}

pub mod Consistency {
    pub enum Consistency {
        Any = 0x0000,
        One = 0x0001,
        Two = 0x0002,
        Three = 0x0003,
        Quorum = 0x0004,
        All = 0x0005,
        LocalQuorum = 0x0006,
        EachQuorum = 0x0007,
        Unknown,
    }
}

#[deriving(Show)]
pub enum CqlValueType {
    ColumnCustom = 0x0000,
    ColumnASCII = 0x0001,
    ColumnBigInt = 0x0002,
    ColumnBlob = 0x0003,
    ColumnBoolean = 0x0004,
    ColumnCounter = 0x0005,
    ColumnDecimal = 0x0006,
    ColumnDouble = 0x0007,
    ColumnFloat = 0x0008,
    ColumnInt = 0x0009,
    ColumnText = 0x000A,
    ColumnTimestamp = 0x000B,
    ColumnUuid = 0x000C,
    ColumnVarChar = 0x000D,
    ColumnVarint = 0x000E,
    ColumnTimeUuid = 0x000F,
    ColumnInet = 0x0010,
    ColumnList = 0x0020,
    ColumnMap = 0x0021,
    ColumnSet = 0x0022,
    ColumnUnknown,
}

pub fn cql_column_type(val: u16) -> CqlValueType {
    match val {
        0x0000 => ColumnCustom,
        0x0001 => ColumnASCII,
        0x0002 => ColumnBigInt,
        0x0003 => ColumnBlob,
        0x0004 => ColumnBoolean,
        0x0005 => ColumnCounter,
        0x0006 => ColumnDecimal,
        0x0007 => ColumnDouble,
        0x0008 => ColumnFloat,
        0x0009 => ColumnInt,
        0x000A => ColumnText,
        0x000B => ColumnTimestamp,
        0x000C => ColumnUuid,
        0x000D => ColumnVarChar,
        0x000E => ColumnVarint,
        0x000F => ColumnTimeUuid,
        0x0010 => ColumnInet,
        0x0020 => ColumnList,
        0x0021 => ColumnMap,
        0x0022 => ColumnSet,
        _ => ColumnUnknown
    }
}

#[deriving(Show)]
pub enum RCErrorType {
    ReadError,
    WriteError,
    SerializeError,
    ConnectionError,
    NoDataError,
    GenericError
}

#[deriving(Show)]
pub struct RCError {
    pub kind: RCErrorType,
    pub desc: SendStr,
}

impl RCError {
    pub fn new<T: IntoMaybeOwned<'static>>(msg: T, kind: RCErrorType) -> RCError {
        RCError {
            kind: kind,
            desc: msg.into_maybe_owned()
        }
    }
}

pub type RCResult<T> = Result<T, RCError>;

pub struct CqlStringMap {
    pub pairs: Vec<CqlPair>,
}

pub struct CqlPair {
    pub key: &'static str,
    pub value: &'static str,
}

pub enum CqlBytesSize {
   Cqli32,
   Cqli16
}

#[deriving(Show)]
pub struct CqlColMetadata {
    pub keyspace: SendStr,
    pub table: SendStr,
    pub col_name: SendStr,
    pub col_type: CqlValueType,
    pub col_type_aux1: CqlValueType,
    pub col_type_aux2: CqlValueType
}

#[deriving(Show)]
pub struct CqlMetadata {
    pub flags: u32,
    pub column_count: u32,
    pub keyspace: SendStr,
    pub table: SendStr,
    pub row_metadata: Vec<CqlColMetadata>,
}

#[deriving(Show)]
pub struct Pair<T, V> {
    pub key: T,
    pub value: V
}

pub type CQLList = Vec<CqlValue>;
pub type CQLMap = Vec<Pair<CqlValue, CqlValue>>;
pub type CQLSet = Vec<CqlValue>;

#[deriving(Show)]
pub enum CqlValue {
    CqlASCII(Option<SendStr>),
    CqlBigInt(Option<i64>),
    CqlBlob(Option<Vec<u8>>),
    CqlBoolean(Option<bool>),
    CqlCounter(Option<i64>),
    CqlDecimal(Option<num::BigInt>),
    CqlDouble(Option<f64>),
    CqlFloat(Option<f32>),
    CqlInet(Option<IpAddr>),
    CqlInt(Option<i32>),
    CqlList(Option<CQLList>),
    CqlMap(Option<CQLMap>),
    CqlSet(Option<CQLSet>),
    CqlText(Option<SendStr>),
    CqlTimestamp(Option<u64>),
    CqlUuid(Option<Uuid>),
    CqlTimeUuid(Option<Uuid>),
    CqlVarchar(Option<SendStr>),
    CqlVarint(Option<num::BigInt>),
    CqlUnknown,
}

#[deriving(Show)]
pub struct CqlRow {
    pub cols: Vec<CqlValue>,
}

/*
impl CqlRow {
    fn get_column(&self, col_name: &str) -> Option<CqlValue> {
        let mut i = 0;
        let len = self.metadata.row_metadata.len();
        while i < len {
            if self.metadata.row_metadata.get(i).col_name.as_slice() == col_name {
                return Some(*self.cols.get(i));
            }
            i += 1;
        }
        None
    }
}
*/

#[deriving(Show)]
pub struct CqlRows {
    pub metadata: Box<CqlMetadata>,
    pub rows: Vec<CqlRow>,
}

pub struct CqlRequest<'a> {
    pub version: u8,
    pub flags: u8,
    pub stream: i8,
    pub opcode: OpcodeRequest,
    pub body: CqlRequestBody<'a>,
}

pub enum CqlRequestBody<'a> {
    RequestStartup(CqlStringMap),
    RequestCred(&'a Vec<SendStr>),
    RequestQuery(&'a str, Consistency::Consistency, u8),
    RequestPrepare(&'a str),
    RequestExec(SendStr, &'a [CqlValue], Consistency::Consistency, u8),
    RequestOptions,
}

#[deriving(Show)]
pub struct CqlResponse {
    pub version: u8,
    pub flags: u8,
    pub stream: i8,
    pub opcode: OpcodeResponse,
    pub body: CqlResponseBody,
}

#[deriving(Show)]
pub enum CqlResponseBody {
    ResponseError(u32, SendStr),
    ResponseReady,
    ResponseAuth(SendStr),

    ResultVoid,
    ResultRows(Box<CqlRows>),
    ResultKeyspace(SendStr),
    ResultPrepared(Box<CqlPreparedStat>),
    ResultSchemaChange(SendStr, SendStr, SendStr),
    ResultUnknown,

    ResponseEmpty,
}

#[deriving(Show)]
pub struct CqlPreparedStat {
    pub id: Vec<u8>,
    pub meta: Box<CqlMetadata>,
    pub meta_result: Option<Box<CqlMetadata>>
}

<|endoftext|>


<commit_before>use libc::{c_int, c_char, uint32_t};

pub static MAX_CPUID_LEVEL: uint = 32u;
pub static MAX_EXT_CPUID_LEVEL: uint = 32u;
pub static MAX_INTELFN4_LEVEL: uint = 4u;
pub static MAX_INTELFN11_LEVEL: uint = 4u;

#[repr(C)]
pub struct cpu_raw_data_t {
    pub basic_cpuid: [[uint32_t, ..MAX_CPUID_LEVEL], ..4u],
    pub ext_cpuid: [[uint32_t, ..MAX_EXT_CPUID_LEVEL], ..4u],
    pub intel_fn4: [[uint32_t, ..MAX_INTELFN4_LEVEL], ..4u],
    pub intel_fn11: [[uint32_t, ..MAX_INTELFN11_LEVEL], ..4u],
}

// TODO: definition for struct cpu_id_t

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
    pub fn cpuid_get_raw_data(raw: *mut cpu_raw_data_t) -> c_int;
    // TODO: add cpu_identify
}
<commit_msg>Added rest of cpuid constants.<commit_after>use libc::{c_int, c_char, uint32_t};

pub static MAX_CPUID_LEVEL: uint = 32u;
pub static MAX_EXT_CPUID_LEVEL: uint = 32u;
pub static MAX_INTELFN4_LEVEL: uint = 4u;
pub static MAX_INTELFN11_LEVEL: uint = 4u;
pub static VENDOR_STR_MAX: uint = 16u;
pub static BRAND_STR_MAX: uint = 64u;
pub static CPU_FLAGS_MAX: uint = 128u;
pub static CPU_HINTS_MAX: uint = 16u;

#[repr(C)]
pub struct cpu_raw_data_t {
    pub basic_cpuid: [[uint32_t, ..MAX_CPUID_LEVEL], ..4u],
    pub ext_cpuid: [[uint32_t, ..MAX_EXT_CPUID_LEVEL], ..4u],
    pub intel_fn4: [[uint32_t, ..MAX_INTELFN4_LEVEL], ..4u],
    pub intel_fn11: [[uint32_t, ..MAX_INTELFN11_LEVEL], ..4u],
}

// TODO: definition for struct cpu_id_t

#[link(name = "cpuid")]
extern {
    pub fn cpuid_present() -> c_int;
    pub fn cpuid_lib_version() -> *const c_char;
    pub fn cpuid_error() -> *const c_char;
    pub fn cpuid_get_raw_data(raw: *mut cpu_raw_data_t) -> c_int;
    // TODO: add cpu_identify
}
<|endoftext|>


<commit_before>#![deny(missing_docs,trivial_casts,trivial_numeric_casts,
        missing_debug_implementations, missing_copy_implementations,
        unsafe_code,unstable_features,unused_import_braces,unused_qualifications)
]

// Copyright 2015-2016 Daniel P. Clark & array_tool Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! # Array Tool
//!
//! is a collection of powerful methods for working with collections.
//! Some of the most common methods you would use on Arrays made available
//! on Vectors. Polymorphic implementations for handling most of your use cases.
//!
//! In your rust files where you plan to use it put this at the top
//!
//! ```
//! extern crate array_tool;
//! ```
//!
//! And if you plan to use all of the Vector helper methods available:
//!
//! ```
//! use array_tool::vec::*;
//! ```

/// Array Tool provides many useful methods for vectors
pub mod vec {

  /// Several different methods for getting, or evaluating, uniqueness.
  pub trait Uniq {
    /// `uniq` returns a vector of unique values within itself as compared to
    /// the other vector which is provided as a input parameter.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] );
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![3,4,6]
    /// ```
    fn uniq(&self, other: Self) -> Self;

    /// `unique` removes duplicates from within the vector and returns Self.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,2,3,4,5,6].unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,4,5,6]
    /// ```
    fn unique(&self) -> Self;
    /// `is_unique` returns boolean value on whether all values within
    /// Self are unique.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,4,3,4,5,6].is_unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// false
    /// ```
    fn is_unique(&self) -> bool;
  }

  impl<T: Clone + PartialEq> Uniq for Vec<T> {
    fn uniq(&self, other: Vec<T>) -> Vec<T> {
      let mut out = self.unique();
      for x in other.unique() {
        for y in (0..out.len()).rev() {
          if x == out[y] {
            out.remove(y);
          }
        }
      }
      out
    }
    fn unique(&self) -> Vec<T> {
      let mut a = self.clone();
      for x in (0..a.len()).rev() {
        for y in (x+1..a.len()).rev() {
          if a[x] == a[y] {
            a.remove(y);
          }
        }
      }
      a
    }
    fn is_unique(&self) -> bool {
      let mut a = true;
      for x in 0..self.len() {
        for y in x+1..self.len() {
          if self[x] == self[y] {
            a = false;
            break;
          }
        }
      }
      a
    }
  }

  /// Removes, or Adds, the first element of self.
  pub trait Shift<T> {
    /// Removes and returns the first item from the vector
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![0,1,2,3];
    /// assert_eq!(x.shift(), 0);
    /// assert_eq!(x, vec![1,2,3]);
    /// ```
    fn shift(&mut self) -> T;
    /// Insert item at the beginning of the vector.  No return value.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![1,2,3];
    /// x.unshift(0);
    /// assert_eq!(x, vec![0,1,2,3]);
    /// ```
    fn unshift(&mut self, other: T);
  }
  impl<T: PartialEq> Shift<T> for Vec<T> {
    fn shift(&mut self) -> T {
      self.remove(0)
    }
    fn unshift(&mut self, other: T) {
      &self.insert(0, other);
    }
  }

  /// Set Intersection — Returns a new array containing elements common to the two arrays,
  /// excluding any duplicates. The order is preserved from the original array.
  pub trait Intersect {
    /// # Example
    /// ```
    /// use array_tool::vec::Intersect;
    ///
    /// vec![1,1,3,5].intersect(vec![1,2,3]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,3]
    /// ```
    fn intersect(&self, Self) -> Self;
  }
  impl<T: PartialEq + Clone> Intersect for Vec<T> {
    fn intersect(&self, other: Vec<T>) -> Vec<T> {
      let mut out = vec![];
      let a = self.unique();
      let length = other.len();
      for x in a {
        for y in 0..length {
          if x == other[y] {
            out.push(x);
            break;
          }
        }
      }
      out
    }
  }

  /// Join vector of ToString capable things to a String with given delimiter.
  pub trait Join {
    /// # Example
    /// ```
    /// use array_tool::vec::Join;
    ///
    /// vec![1,2,3].join(",");
    /// ```
    ///
    /// # Output
    /// ```text
    /// "1,2,3"
    /// ```
    fn join(&self, joiner: &'static str) -> String;
  }
  impl<T: ToString> Join for Vec<T> {
    fn join(&self, joiner: &'static str) -> String {
      let mut out = String::from("");
      for x in 0..self.len() {
        out.push_str(&self[x].to_string());
        if x < self.len()-1 {
          out.push_str(&joiner)
        }
      }
      out
    }
  }

  /// Expand and duplicate the vectors content `times` the integer given
  pub trait Times {
    /// # Example
    /// ```
    /// use array_tool::vec::Times;
    ///
    /// vec![1,2,3].times(3);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,1,2,3,1,2,3]
    /// ```
    fn times(&self, qty: i32) -> Self;
  }
  impl<T: Clone> Times for Vec<T> {
    /// Expand and duplicate the vectors content `times` the integer given
    fn times(&self, qty: i32) -> Vec<T> {
      let mut out = vec![self[0].clone();self.len()*(qty as usize)];
      let mut cycle = self.iter().cycle();
      for x in 0..self.len()*(qty as usize) {
        out[x] = cycle.next().unwrap().clone();
      }
      out
    }
  }

  /// Create a `union` between two vectors.
  /// Returns a new vector by joining with other, excluding any duplicates and preserving
  /// the order from the original vector.
  pub trait Union {
    /// # Example
    /// ```
    /// use array_tool::vec::Union;
    ///
    /// vec!["a","b","c"].union(vec!["c","d","a"]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![ "a", "b", "c", "d" ]
    /// ```
    fn union(&self, other: Self) -> Self;
  }
  impl<T: PartialEq + Clone> Union for Vec<T> {
    fn union(&self, other: Vec<T>) -> Vec<T> {
      let mut stack = self.clone();
      for x in other { // don't use append method as it's destructive
        stack.push(x)
      }
      stack.unique()
    }
  }
}

/// Get `uniques` from two vectors
///
/// # Example
/// ```
/// use array_tool::uniques;
///
/// uniques(vec![1,2,3,4,5], vec![2,5,6,7,8]);
/// ```
///
/// # Output
/// ```text
/// vec![vec![1,3,4], vec![6,7,8]]
/// ```
pub fn uniques<T: PartialEq + Clone>(a: Vec<T>, b: Vec<T>) -> Vec<Vec<T>> {
  use self::vec::Uniq;
  vec![a.uniq(b.clone()), b.uniq(a)]
}

<commit_msg>grammar [ci skip]<commit_after>#![deny(missing_docs,trivial_casts,trivial_numeric_casts,
        missing_debug_implementations, missing_copy_implementations,
        unsafe_code,unstable_features,unused_import_braces,unused_qualifications)
]

// Copyright 2015-2016 Daniel P. Clark & array_tool Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! # Array Tool
//!
//! is a collection of powerful methods for working with collections.
//! Some of the most common methods you would use on Arrays made available
//! on Vectors. Polymorphic implementations for handling most of your use cases.
//!
//! In your rust files where you plan to use it put this at the top
//!
//! ```
//! extern crate array_tool;
//! ```
//!
//! And if you plan to use all of the Vector helper methods available:
//!
//! ```
//! use array_tool::vec::*;
//! ```

/// Array Tool provides many useful methods for vectors
pub mod vec {

  /// Several different methods for getting, or evaluating, uniqueness.
  pub trait Uniq {
    /// `uniq` returns a vector of unique values within itself as compared to
    /// the other vector which is provided as an input parameter.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,3,4,5,6].uniq( vec![1,2,5,7,9] );
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![3,4,6]
    /// ```
    fn uniq(&self, other: Self) -> Self;

    /// `unique` removes duplicates from within the vector and returns Self.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,2,3,4,5,6].unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,4,5,6]
    /// ```
    fn unique(&self) -> Self;
    /// `is_unique` returns boolean value on whether all values within
    /// Self are unique.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Uniq;
    ///
    /// vec![1,2,1,3,4,3,4,5,6].is_unique();
    /// ```
    ///
    /// # Output
    /// ```text
    /// false
    /// ```
    fn is_unique(&self) -> bool;
  }

  impl<T: Clone + PartialEq> Uniq for Vec<T> {
    fn uniq(&self, other: Vec<T>) -> Vec<T> {
      let mut out = self.unique();
      for x in other.unique() {
        for y in (0..out.len()).rev() {
          if x == out[y] {
            out.remove(y);
          }
        }
      }
      out
    }
    fn unique(&self) -> Vec<T> {
      let mut a = self.clone();
      for x in (0..a.len()).rev() {
        for y in (x+1..a.len()).rev() {
          if a[x] == a[y] {
            a.remove(y);
          }
        }
      }
      a
    }
    fn is_unique(&self) -> bool {
      let mut a = true;
      for x in 0..self.len() {
        for y in x+1..self.len() {
          if self[x] == self[y] {
            a = false;
            break;
          }
        }
      }
      a
    }
  }

  /// Removes, or Adds, the first element of self.
  pub trait Shift<T> {
    /// Removes and returns the first item from the vector
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![0,1,2,3];
    /// assert_eq!(x.shift(), 0);
    /// assert_eq!(x, vec![1,2,3]);
    /// ```
    fn shift(&mut self) -> T;
    /// Insert item at the beginning of the vector.  No return value.
    ///
    /// # Example
    /// ```
    /// use array_tool::vec::Shift;
    ///
    /// let mut x = vec![1,2,3];
    /// x.unshift(0);
    /// assert_eq!(x, vec![0,1,2,3]);
    /// ```
    fn unshift(&mut self, other: T);
  }
  impl<T: PartialEq> Shift<T> for Vec<T> {
    fn shift(&mut self) -> T {
      self.remove(0)
    }
    fn unshift(&mut self, other: T) {
      &self.insert(0, other);
    }
  }

  /// Set Intersection — Returns a new array containing elements common to the two arrays,
  /// excluding any duplicates. The order is preserved from the original array.
  pub trait Intersect {
    /// # Example
    /// ```
    /// use array_tool::vec::Intersect;
    ///
    /// vec![1,1,3,5].intersect(vec![1,2,3]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,3]
    /// ```
    fn intersect(&self, Self) -> Self;
  }
  impl<T: PartialEq + Clone> Intersect for Vec<T> {
    fn intersect(&self, other: Vec<T>) -> Vec<T> {
      let mut out = vec![];
      let a = self.unique();
      let length = other.len();
      for x in a {
        for y in 0..length {
          if x == other[y] {
            out.push(x);
            break;
          }
        }
      }
      out
    }
  }

  /// Join vector of ToString capable things to a String with given delimiter.
  pub trait Join {
    /// # Example
    /// ```
    /// use array_tool::vec::Join;
    ///
    /// vec![1,2,3].join(",");
    /// ```
    ///
    /// # Output
    /// ```text
    /// "1,2,3"
    /// ```
    fn join(&self, joiner: &'static str) -> String;
  }
  impl<T: ToString> Join for Vec<T> {
    fn join(&self, joiner: &'static str) -> String {
      let mut out = String::from("");
      for x in 0..self.len() {
        out.push_str(&self[x].to_string());
        if x < self.len()-1 {
          out.push_str(&joiner)
        }
      }
      out
    }
  }

  /// Expand and duplicate the vectors content `times` the integer given
  pub trait Times {
    /// # Example
    /// ```
    /// use array_tool::vec::Times;
    ///
    /// vec![1,2,3].times(3);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![1,2,3,1,2,3,1,2,3]
    /// ```
    fn times(&self, qty: i32) -> Self;
  }
  impl<T: Clone> Times for Vec<T> {
    /// Expand and duplicate the vectors content `times` the integer given
    fn times(&self, qty: i32) -> Vec<T> {
      let mut out = vec![self[0].clone();self.len()*(qty as usize)];
      let mut cycle = self.iter().cycle();
      for x in 0..self.len()*(qty as usize) {
        out[x] = cycle.next().unwrap().clone();
      }
      out
    }
  }

  /// Create a `union` between two vectors.
  /// Returns a new vector by joining with other, excluding any duplicates and preserving
  /// the order from the original vector.
  pub trait Union {
    /// # Example
    /// ```
    /// use array_tool::vec::Union;
    ///
    /// vec!["a","b","c"].union(vec!["c","d","a"]);
    /// ```
    ///
    /// # Output
    /// ```text
    /// vec![ "a", "b", "c", "d" ]
    /// ```
    fn union(&self, other: Self) -> Self;
  }
  impl<T: PartialEq + Clone> Union for Vec<T> {
    fn union(&self, other: Vec<T>) -> Vec<T> {
      let mut stack = self.clone();
      for x in other { // don't use append method as it's destructive
        stack.push(x)
      }
      stack.unique()
    }
  }
}

/// Get `uniques` from two vectors
///
/// # Example
/// ```
/// use array_tool::uniques;
///
/// uniques(vec![1,2,3,4,5], vec![2,5,6,7,8]);
/// ```
///
/// # Output
/// ```text
/// vec![vec![1,3,4], vec![6,7,8]]
/// ```
pub fn uniques<T: PartialEq + Clone>(a: Vec<T>, b: Vec<T>) -> Vec<Vec<T>> {
  use self::vec::Uniq;
  vec![a.uniq(b.clone()), b.uniq(a)]
}

<|endoftext|>


<commit_before>use std::fmt::{self, Debug, Formatter};

/// A data-structure for storing a sequence of 4-bit values.
///
/// Values are stored in a `Vec<u8>`, with two values per byte.
///
/// Values at even indices are stored in the most-significant half of their byte,
/// while values at odd indices are stored in the least-significant half.
///
/// Imagine a vector of MSB bytes, and you'll be right.
///
/// n = [_ _ | _ _ | _ _]
///
/// # Invariants
/// * If the length is odd, then the second half of the last byte must be 0.
pub struct NibbleVec {
    length: usize,
    data: Vec<u8>
}

impl NibbleVec {
    /// Create an empty nibble vector.
    pub fn new() -> NibbleVec {
        NibbleVec {
            length: 0,
            data: Vec::new()
        }
    }

    /// Create a nibble vector from a vector of bytes.
    ///
    /// Each byte is split into two 4-bit entries (MSB, LSB).
    pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec {
        let length = 2 * vec.len();
        NibbleVec {
            length: length,
            data: vec
        }
    }

    /// Get the number of elements stored in the vector.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Fetch a single entry from the vector.
    ///
    /// Guaranteed to be a value in the interval [0, 15].
    ///
    /// **Panics** if `idx >= self.len()`.
    pub fn get(&self, idx: usize) -> u8 {
        if idx >= self.length {
            panic!("attempted access beyond vector end. len is {}, index is {}", self.length, idx);
        }
        let vec_idx = idx / 2;
        match idx % 2 {
            // If the index is even, take the first (most significant) half of the stored byte.
            0 => self.data[vec_idx] >> 4,
            // If the index is odd, take the second (least significant) half.
            _ => self.data[vec_idx] & 0x0F
        }
    }

    /// Add a single nibble to the vector.
    ///
    /// Only the 4 least-significant bits of the value are used.
    pub fn push(&mut self, val: u8) {
        if self.length % 2 == 0 {
            self.data.push(val << 4);
        } else {
            let vec_len = self.data.len();

            // Zero the second half of the last byte just to be safe.
            self.data[vec_len - 1] &= 0xF0;

            // Write the new value.
            self.data[vec_len - 1] |= val & 0x0F;
        }
        self.length += 1;
    }

    /// Split the vector into two parts.
    ///
    /// All elements at or following the given index are returned in a new `NibbleVec`,
    /// with exactly `idx` elements remaining in this vector.
    ///
    /// **Panics** if `idx > self.len()`.
    pub fn split(&mut self, idx: usize) -> NibbleVec {
        if idx > self.length {
            panic!("attempted to split past vector end. len is {}, index is {}", self.length, idx);
        } else if idx == self.length {
            NibbleVec::new()
        } else if idx % 2 == 0 {
            self.split_even(idx)
        } else {
            self.split_odd(idx)
        }
    }

    /// Split function for odd *indices*.
    #[inline(always)]
    fn split_odd(&mut self, idx: usize) -> NibbleVec {
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Perform an overlap copy, copying the last nibble of the original vector only if
        // the length of the new tail is *odd*.
        let tail_length = self.length - idx;
        let take_last = tail_length % 2 == 1;
        self.overlap_copy(idx / 2, self.data.len(), &mut tail.data, &mut tail.length, take_last);

        // Remove the copied bytes, being careful to skip the idx byte.
        for _ in range(idx / 2 + 1, self.data.len()) {
            self.data.pop();
        }

        // Zero the second half of the index byte so as to maintain the last-nibble invariant.
        self.data[idx / 2] &= 0xF0;

        // Update the length of the first NibbleVec.
        self.length = idx;

        tail
    }

    /// Split function for even *indices*.
    #[inline(always)]
    fn split_even(&mut self, idx: usize) -> NibbleVec {
        // Avoid allocating a temporary vector by copying all the bytes in order, then popping them.
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Copy the bytes.
        for i in range(idx / 2, self.data.len()) {
            tail.data.push(self.data[i]);
        }

        // Pop the same bytes.
        for _ in range(0, tail_vec_size) {
            self.data.pop();
        }

        // Update lengths.
        tail.length = self.length - idx;
        self.length = idx;

        tail
    }

    /// Copy data between the second half of self.data[start] and
    /// self.data[end - 1]. The second half of the last entry is included
    /// if include_last is true.
    #[inline(always)]
    fn overlap_copy(&self, start: usize, end: usize, vec: &mut Vec<u8>, length: &mut usize, include_last: bool) {
        // Copy up to the first half of the last byte.
        for i in range(start, end - 1) {
            // The first half is the second half of the old entry.
            let first_half = self.data[i] & 0x0f;

            // The second half is the first half of the next entry.
            let second_half = self.data[i + 1] >> 4;

            vec.push((first_half << 4) | second_half);
            *length += 2;
        }

        if include_last {
            let last = self.data[end - 1] & 0x0f;
            vec.push(last << 4);
            *length += 1;
        }
    }

    /// Append another nibble vector.
    pub fn join(&mut self, other: &NibbleVec) {
        // If the length is even, we can append directly.
        if self.length % 2 == 0 {
            self.length += other.length;
            self.data.push_all(other.data.as_slice());
            return;
        }

        // If the other vector is empty, bail out.
        if other.len() == 0 {
            return;
        }

        // If the length is odd, we have to perform an overlap copy.
        // Copy the first half of the first element, to make the vector an even length.
        self.push(other.get(0));

        // Copy the rest of the vector using an overlap copy.
        let take_last = other.len() % 2 == 0;
        other.overlap_copy(0, other.data.len(), &mut self.data, &mut self.length, take_last);
    }
}

impl PartialEq<[u8]> for NibbleVec {
    fn eq(&self, other: &[u8]) -> bool {
        if other.len() != self.len() {
            return false;
        }

        for (i, x) in other.iter().enumerate() {
            if self.get(i) != *x {
                return false;
            }
        }
        true
    }
}

impl Clone for NibbleVec {
    fn clone(&self) -> NibbleVec {
        NibbleVec {
            length: self.length,
            data: self.data.clone()
        }
    }
}

impl Debug for NibbleVec {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "NibbleVec ["));

        if self.len() > 0 {
            try!(write!(fmt, "{}", self.get(0)));
        }

        for i in range(1, self.len()) {
            try!(write!(fmt, ", {}", self.get(i)));
        }
        write!(fmt, "]")
    }
}

#[cfg(test)]
mod test {
    use NibbleVec;

    fn v8_7_6_5() -> NibbleVec {
        NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
    }

    fn v11_10_9() -> NibbleVec {
        let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
        result.push(9);
        result
    }

    #[test]
    fn get() {
        let nv = NibbleVec::from_byte_vec(vec![3 << 4 | 7]);
        assert_eq!(nv.get(0), 3u8);
        assert_eq!(nv.get(1), 7u8);
    }

    #[test]
    fn push() {
        let mut nv = NibbleVec::new();
        let data = vec![0, 1, 3, 5, 7, 9, 11, 15];
        for val in data.iter() {
            nv.push(*val);
        }

        for (i, val) in data.iter().enumerate() {
            assert_eq!(nv.get(i), *val);
        }
    }

    fn split_test(  nibble_vec: &NibbleVec,
                    idx: usize,
                    first: Vec<u8>,
                    second: Vec<u8>) {
        let mut init = nibble_vec.clone();
        let tail = init.split(idx);
        assert!(init == first[]);
        assert!(tail == second[]);
    }

    #[test]
    fn split_even_length() {
        let even_length = v8_7_6_5();
        split_test(&even_length, 0, vec![], vec![8, 7, 6, 5]);
        split_test(&even_length, 1, vec![8], vec![7, 6, 5]);
        split_test(&even_length, 2, vec![8, 7], vec![6, 5]);
        split_test(&even_length, 4, vec![8, 7, 6, 5], vec![]);
    }

    #[test]
    fn split_odd_length() {
        let odd_length = v11_10_9();
        split_test(&odd_length, 0, vec![], vec![11, 10, 9]);
        split_test(&odd_length, 1, vec![11], vec![10, 9]);
        split_test(&odd_length, 2, vec![11, 10], vec![9]);
        split_test(&odd_length, 3, vec![11, 10, 9], vec![]);
    }

    /// Join vec2 onto vec1 and ensure that the results matches the one expected.
    fn join_test(vec1: &NibbleVec, vec2: &NibbleVec, result: Vec<u8>) {
        let mut joined = vec1.clone();
        joined.join(vec2);
        assert!(joined == result[]);
    }

    #[test]
    fn join_even_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v1, &v2, vec![8, 7, 6, 5, 11, 10, 9]);
        join_test(&v1, &v1, vec![8, 7, 6, 5, 8, 7, 6, 5]);
        join_test(&v1, &NibbleVec::new(), vec![8, 7, 6, 5]);
        join_test(&NibbleVec::new(), &v1, vec![8, 7, 6, 5]);
    }

    #[test]
    fn join_odd_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v2, &v1, vec![11, 10, 9, 8, 7, 6, 5]);
        join_test(&v2, &v2, vec![11, 10, 9, 11, 10, 9]);
        join_test(&v2, &NibbleVec::new(), vec![11, 10, 9]);
    }

    /// Ensure that the last nibble is zeroed before reuse.
    #[test]
    fn memory_reuse() {
        let mut vec = NibbleVec::new();
        vec.push(10);
        vec.push(1);

        // Pushing.
        vec.split(1);
        vec.push(2);
        assert_eq!(vec.get(1), 2);

        // Joining.
        vec.split(1);
        vec.join(&NibbleVec::from_byte_vec(vec![1 << 4 | 3, 5 << 4]));
        assert_eq!(vec.get(1), 1);
    }
}
<commit_msg>Update for Rust master.<commit_after>use std::fmt::{self, Debug, Formatter};

/// A data-structure for storing a sequence of 4-bit values.
///
/// Values are stored in a `Vec<u8>`, with two values per byte.
///
/// Values at even indices are stored in the most-significant half of their byte,
/// while values at odd indices are stored in the least-significant half.
///
/// Imagine a vector of MSB bytes, and you'll be right.
///
/// n = [_ _ | _ _ | _ _]
///
/// # Invariants
/// * If the length is odd, then the second half of the last byte must be 0.
pub struct NibbleVec {
    length: usize,
    data: Vec<u8>
}

impl NibbleVec {
    /// Create an empty nibble vector.
    pub fn new() -> NibbleVec {
        NibbleVec {
            length: 0,
            data: Vec::new()
        }
    }

    /// Create a nibble vector from a vector of bytes.
    ///
    /// Each byte is split into two 4-bit entries (MSB, LSB).
    pub fn from_byte_vec(vec: Vec<u8>) -> NibbleVec {
        let length = 2 * vec.len();
        NibbleVec {
            length: length,
            data: vec
        }
    }

    /// Get the number of elements stored in the vector.
    pub fn len(&self) -> usize {
        self.length
    }

    /// Fetch a single entry from the vector.
    ///
    /// Guaranteed to be a value in the interval [0, 15].
    ///
    /// **Panics** if `idx >= self.len()`.
    pub fn get(&self, idx: usize) -> u8 {
        if idx >= self.length {
            panic!("attempted access beyond vector end. len is {}, index is {}", self.length, idx);
        }
        let vec_idx = idx / 2;
        match idx % 2 {
            // If the index is even, take the first (most significant) half of the stored byte.
            0 => self.data[vec_idx] >> 4,
            // If the index is odd, take the second (least significant) half.
            _ => self.data[vec_idx] & 0x0F
        }
    }

    /// Add a single nibble to the vector.
    ///
    /// Only the 4 least-significant bits of the value are used.
    pub fn push(&mut self, val: u8) {
        if self.length % 2 == 0 {
            self.data.push(val << 4);
        } else {
            let vec_len = self.data.len();

            // Zero the second half of the last byte just to be safe.
            self.data[vec_len - 1] &= 0xF0;

            // Write the new value.
            self.data[vec_len - 1] |= val & 0x0F;
        }
        self.length += 1;
    }

    /// Split the vector into two parts.
    ///
    /// All elements at or following the given index are returned in a new `NibbleVec`,
    /// with exactly `idx` elements remaining in this vector.
    ///
    /// **Panics** if `idx > self.len()`.
    pub fn split(&mut self, idx: usize) -> NibbleVec {
        if idx > self.length {
            panic!("attempted to split past vector end. len is {}, index is {}", self.length, idx);
        } else if idx == self.length {
            NibbleVec::new()
        } else if idx % 2 == 0 {
            self.split_even(idx)
        } else {
            self.split_odd(idx)
        }
    }

    /// Split function for odd *indices*.
    #[inline(always)]
    fn split_odd(&mut self, idx: usize) -> NibbleVec {
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Perform an overlap copy, copying the last nibble of the original vector only if
        // the length of the new tail is *odd*.
        let tail_length = self.length - idx;
        let take_last = tail_length % 2 == 1;
        self.overlap_copy(idx / 2, self.data.len(), &mut tail.data, &mut tail.length, take_last);

        // Remove the copied bytes, being careful to skip the idx byte.
        for _ in range(idx / 2 + 1, self.data.len()) {
            self.data.pop();
        }

        // Zero the second half of the index byte so as to maintain the last-nibble invariant.
        self.data[idx / 2] &= 0xF0;

        // Update the length of the first NibbleVec.
        self.length = idx;

        tail
    }

    /// Split function for even *indices*.
    #[inline(always)]
    fn split_even(&mut self, idx: usize) -> NibbleVec {
        // Avoid allocating a temporary vector by copying all the bytes in order, then popping them.
        let tail_vec_size = (self.length - idx) / 2;
        let mut tail = NibbleVec::from_byte_vec(Vec::with_capacity(tail_vec_size));

        // Copy the bytes.
        for i in range(idx / 2, self.data.len()) {
            tail.data.push(self.data[i]);
        }

        // Pop the same bytes.
        for _ in range(0, tail_vec_size) {
            self.data.pop();
        }

        // Update lengths.
        tail.length = self.length - idx;
        self.length = idx;

        tail
    }

    /// Copy data between the second half of self.data[start] and
    /// self.data[end - 1]. The second half of the last entry is included
    /// if include_last is true.
    #[inline(always)]
    fn overlap_copy(&self, start: usize, end: usize, vec: &mut Vec<u8>, length: &mut usize, include_last: bool) {
        // Copy up to the first half of the last byte.
        for i in range(start, end - 1) {
            // The first half is the second half of the old entry.
            let first_half = self.data[i] & 0x0f;

            // The second half is the first half of the next entry.
            let second_half = self.data[i + 1] >> 4;

            vec.push((first_half << 4) | second_half);
            *length += 2;
        }

        if include_last {
            let last = self.data[end - 1] & 0x0f;
            vec.push(last << 4);
            *length += 1;
        }
    }

    /// Append another nibble vector.
    pub fn join(&mut self, other: &NibbleVec) {
        // If the length is even, we can append directly.
        if self.length % 2 == 0 {
            self.length += other.length;
            self.data.push_all(other.data.as_slice());
            return;
        }

        // If the other vector is empty, bail out.
        if other.len() == 0 {
            return;
        }

        // If the length is odd, we have to perform an overlap copy.
        // Copy the first half of the first element, to make the vector an even length.
        self.push(other.get(0));

        // Copy the rest of the vector using an overlap copy.
        let take_last = other.len() % 2 == 0;
        other.overlap_copy(0, other.data.len(), &mut self.data, &mut self.length, take_last);
    }
}

impl PartialEq<[u8]> for NibbleVec {
    fn eq(&self, other: &[u8]) -> bool {
        if other.len() != self.len() {
            return false;
        }

        for (i, x) in other.iter().enumerate() {
            if self.get(i) != *x {
                return false;
            }
        }
        true
    }
}

impl Clone for NibbleVec {
    fn clone(&self) -> NibbleVec {
        NibbleVec {
            length: self.length,
            data: self.data.clone()
        }
    }
}

impl Debug for NibbleVec {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "NibbleVec ["));

        if self.len() > 0 {
            try!(write!(fmt, "{}", self.get(0)));
        }

        for i in range(1, self.len()) {
            try!(write!(fmt, ", {}", self.get(i)));
        }
        write!(fmt, "]")
    }
}

#[cfg(test)]
mod test {
    use NibbleVec;

    fn v8_7_6_5() -> NibbleVec {
        NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
    }

    fn v11_10_9() -> NibbleVec {
        let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
        result.push(9);
        result
    }

    #[test]
    fn get() {
        let nv = NibbleVec::from_byte_vec(vec![3 << 4 | 7]);
        assert_eq!(nv.get(0), 3u8);
        assert_eq!(nv.get(1), 7u8);
    }

    #[test]
    fn push() {
        let mut nv = NibbleVec::new();
        let data = vec![0, 1, 3, 5, 7, 9, 11, 15];
        for val in data.iter() {
            nv.push(*val);
        }

        for (i, val) in data.iter().enumerate() {
            assert_eq!(nv.get(i), *val);
        }
    }

    fn split_test(  nibble_vec: &NibbleVec,
                    idx: usize,
                    first: Vec<u8>,
                    second: Vec<u8>) {
        let mut init = nibble_vec.clone();
        let tail = init.split(idx);
        assert!(init == first[..]);
        assert!(tail == second[..]);
    }

    #[test]
    fn split_even_length() {
        let even_length = v8_7_6_5();
        split_test(&even_length, 0, vec![], vec![8, 7, 6, 5]);
        split_test(&even_length, 1, vec![8], vec![7, 6, 5]);
        split_test(&even_length, 2, vec![8, 7], vec![6, 5]);
        split_test(&even_length, 4, vec![8, 7, 6, 5], vec![]);
    }

    #[test]
    fn split_odd_length() {
        let odd_length = v11_10_9();
        split_test(&odd_length, 0, vec![], vec![11, 10, 9]);
        split_test(&odd_length, 1, vec![11], vec![10, 9]);
        split_test(&odd_length, 2, vec![11, 10], vec![9]);
        split_test(&odd_length, 3, vec![11, 10, 9], vec![]);
    }

    /// Join vec2 onto vec1 and ensure that the results matches the one expected.
    fn join_test(vec1: &NibbleVec, vec2: &NibbleVec, result: Vec<u8>) {
        let mut joined = vec1.clone();
        joined.join(vec2);
        assert!(joined == result[..]);
    }

    #[test]
    fn join_even_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v1, &v2, vec![8, 7, 6, 5, 11, 10, 9]);
        join_test(&v1, &v1, vec![8, 7, 6, 5, 8, 7, 6, 5]);
        join_test(&v1, &NibbleVec::new(), vec![8, 7, 6, 5]);
        join_test(&NibbleVec::new(), &v1, vec![8, 7, 6, 5]);
    }

    #[test]
    fn join_odd_length() {
        let v1 = v8_7_6_5();
        let v2 = v11_10_9();
        join_test(&v2, &v1, vec![11, 10, 9, 8, 7, 6, 5]);
        join_test(&v2, &v2, vec![11, 10, 9, 11, 10, 9]);
        join_test(&v2, &NibbleVec::new(), vec![11, 10, 9]);
    }

    /// Ensure that the last nibble is zeroed before reuse.
    #[test]
    fn memory_reuse() {
        let mut vec = NibbleVec::new();
        vec.push(10);
        vec.push(1);

        // Pushing.
        vec.split(1);
        vec.push(2);
        assert_eq!(vec.get(1), 2);

        // Joining.
        vec.split(1);
        vec.join(&NibbleVec::from_byte_vec(vec![1 << 4 | 3, 5 << 4]));
        assert_eq!(vec.get(1), 1);
    }
}
<|endoftext|>