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

use common::{Result, Id, Op2, Const};
use explicit;
use implicit;
use env;
use hindley_milner;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Imm {
    Bool(bool),
    Int(i64),
    Var(Id),
    //    Fun(Id, Box<Expr>),
    //    Fix(Id, Box<Expr>),
    //    Star,
    //    V,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Op {
    Op2(Op2, Box<Imm>, Box<Imm>),
    //    MkArray(Box<Imm>, Box<Imm>),
    //    GetArray(Box<Imm>, Box<Imm>),
    //    SetArray(Box<Imm>, Box<Imm>, Box<Imm>),
    Imm(Imm),
}
//    WellFormed(Imm), // Var-only

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
    If(Box<Imm>, Box<Expr>, Box<Expr>),
    //    App(Box<Imm>, Box<Imm>),
    Let(Id, Box<Expr>, Box<Expr>),
    Op(Op),
}

#[derive(PartialEq, Eq, Clone, Debug)]
struct ConvEnv {
    //env: HashMap<Id, explicit::Type>,
    next_id: i32,
}

impl ConvEnv {
    fn new() -> ConvEnv {
        ConvEnv {
            //env: HashMap::new(),
            next_id: 0,
        }
    }

    fn tmp(&self) -> (ConvEnv, Id) {
        let id = self.next_id;
        let c = ConvEnv{
            //env: self.env.clone(),
            next_id: self.next_id+1,
        };

        (c, format!("!tmp!{}", id))
    }
}

fn constant(c: &Const) -> Imm {
    match *c {
        Const::Bool(b) => Imm::Bool(b),
        Const::Int(i) => Imm::Int(i),
    }
}

fn identity(cenv: ConvEnv, i: Imm) -> (ConvEnv, Expr) {
    (cenv, Expr::Op(Op::Imm(i)))
}

// 1:1 translation -- can't fail
fn expr(cenv: ConvEnv, e: &explicit::Expr, k: &Fn(ConvEnv, Imm) -> (ConvEnv, Expr)) -> (ConvEnv, Expr) {

    use self::Imm as I;
    use typed::Expr as E;
    use self::Op::*;
    use self::Expr::*;

    match *e {
        E::Const(ref c) => k(cenv, constant(c)),
        E::Op2(op, ref l, ref r) => {
            expr(cenv, l, &|cenv: ConvEnv, ll: I| -> (ConvEnv, Expr) {
                expr(cenv, r, &|cenv: ConvEnv, rr: I| -> (ConvEnv, Expr) {

                    let (cenv, op_tmp) = cenv.tmp();
                    let op_val = Op(Op2(op, box ll.clone(), box rr));
                    // value to pass to the continuation
                    let op_ref = I::Var(op_tmp.clone());

                    // our inner expression is whatever the
                    // continuation says it is.
                    let (cenv, mut result) = k(cenv, op_ref);

                    result = Let(op_tmp, box op_val, box result);

                    (cenv, result)
                })
            })
        }
        E::Let(ref id, ref e1, ref e2) => {
            expr(cenv, e1, &|cenv: ConvEnv, e1l: I| -> (ConvEnv, Expr) {
                expr(cenv, e2, &|cenv: ConvEnv, e2l: I| -> (ConvEnv, Expr) {
                    let (cenv, inner) = k(cenv, e2l);
                    (cenv, Let(id.clone(), box Op(Imm(e1l.clone())), box inner))
                })
            })
        }
        E::Var(ref x) => {
            k(cenv, I::Var(x.clone()))
        }
        E::If(ref e1, ref e2, ref e3) => {
            expr(cenv, e1, &|cenv: ConvEnv, cond_ref: I| -> (ConvEnv, Expr) {

                let (cenv, l_true) = expr(cenv, e2, &identity);
                let (cenv, l_false) = expr(cenv, e3, &identity);

                // value to pass to the continuation
                let val = If(box cond_ref, box l_true, box l_false);
                let (cenv, val_tmp) = cenv.tmp();

                // our inner expression is whatever the
                // continuation says it is.
                let (cenv, mut result) = k(cenv, I::Var(val_tmp.clone()));

                result = Let(val_tmp, box val, box result);

                (cenv, result)
            })
        }
        _ => {
            panic!("TODO: implement expr for {:?}", e);
        }
    }
    // E::Fun(ref id, ref t1, ref e) => {
    //     let mut renamed = renamed.clone();
    //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

    //     renamed.insert(id.clone(), αid.clone());
    //     env.insert(αid.clone(), t1.clone());

    //     let (n, e, t2) = convert(n, env, &renamed, e);

    //     (n, I::Fun(αid, box e), Type::TFun(box t1.clone(), box t2))
    // }
    // E::Fix(ref id, ref t1, ref e) => {
    //     let mut renamed = renamed.clone();
    //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

    //     renamed.insert(id.clone(), αid.clone());
    //     env.insert(αid.clone(), t1.clone());

    //     let (n, e, t2) = convert(n, env, &renamed, e);

    //     (n, I::Fix(αid, box e), t2)
    // }
    // E::App(ref e1, ref e2) => {
    //     let (n, e1, t1) = convert(n, env, renamed, e1);
    //     let (n, e2, _) = convert(n, env, renamed, e2);
    //     let t = match t1 {
    //         Type::TFun(_, t2) => *t2,
    //         _ => panic!("expected TFun, not {:?}", t1),
    //     };
    //     (n, I::App(box e1, box e2), t)
    // }
    // E::MkArray(ref sz, ref val) => {
    //     let (n, sz, _) = convert(n, env, renamed, sz);
    //     let (n, val, _) = convert(n, env, renamed, val);
    //     (n, I::MkArray(box sz, box val), Type::TIntArray)
    // }
    // E::GetArray(ref id, ref idx) => {
    //     let (n, id, _) = convert(n, env, renamed, id);
    //     let (n, idx, _) = convert(n, env, renamed, idx);
    //     (n, I::GetArray(box id, box idx), Type::TInt)
    // }
    // E::SetArray(ref id, ref idx, ref v) => {
    //     let (n, id, _) = convert(n, env, renamed, id);
    //     let (n, idx, _) = convert(n, env, renamed, idx);
    //     let (n, v, _) = convert(n, env, renamed, v);
    //     (n, I::SetArray(box id, box idx, box v), Type::TIntArray)
    // }
}

pub fn anf(implicit_expr: &implicit::Expr) -> Result<(Expr, HashMap<Id, explicit::Type>)> {

    let explicit_expr = hindley_milner::infer(implicit_expr)?;
    // alpha-renaming
    let (alpha_expr, env) = env::extract(&explicit_expr);

    // println!("α-implicit: {:?}\n", α_expr);
    // println!("Γ         : {:?}\n", env);

    let cenv = ConvEnv::new();
    let (_, expr) = expr(cenv, &alpha_expr, &identity);

    Ok((expr, env))
    // step 1 -- arithmatic + let bindings
    // step 2 -- conds + boolean vals
    // step 3 -- arrays
    // step 4 -- closures

    // (define (Value? M)
    //   (match M
    //     [`(quote ,_)         #t]
    //     [(? number?)         #t]
    //     [(? boolean?)        #t]
    //     [(? string?)         #t]
    //     [(? char?)           #t]
    //     [(? symbol?)         #t]
    //     [(or '+ '- '* '/ '=) #t]
    //     [else                #f]))

    // (define (normalize-term M) (normalize M (λ (x) x)))

    // (define (normalize M k)
    //   (match M
    //     [`(λ ,params ,body)
    //       (k `(λ ,params ,(normalize-term body)))]

    //     [`(let ([,x ,M1]) ,M2)
    //       (normalize M1 (λ (N1)
    //        `(let ([,x ,N1])
    //          ,(normalize M2 k))))]

    //     [`(if ,M1 ,M2 ,M3)
    //       (normalize-name M1 (λ (t)
    //        (k `(if ,t ,(normalize-term M2)
    //                   ,(normalize-term M3)))))]

    //     [`(,Fn . ,M*)
    //       (normalize-name Fn (λ (t)
    //        (normalize-name* M* (λ (t*)
    //         (k `(,t . ,t*))))))]

    //     [(? Value?)             (k M)]))

    // (define (normalize-name M k)
    //   (normalize M (λ (N)
    //     (if (Value? N) (k N)
    //         (let ([t (gensym)])
    //          `(let ([,t ,N]) ,(k t)))))))

    // (define (normalize-name* M* k)
    //   (if (null? M*)
    //       (k '())
    //       (normalize-name (car M*) (λ (t)
    //        (normalize-name* (cdr M*) (λ (t*)
    //         (k `(,t . ,t*))))))))

}

macro_rules! test_anf(
    ($s:expr, $ae:expr) => { {
        use implicit_parse;
        use tok::Tokenizer;
        use std;
        let s = $s;
        let tokenizer = Tokenizer::new(&s);
        let iexpr = match implicit_parse::parse_Program(&s, tokenizer) {
            Ok(iexpr) => iexpr,
            Err(e) => {
                die!("parse_Program({}): {:?}", $s, e);
            }
        };
        let anf_expr = match anf(&iexpr) {
            Ok((anf_expr, _)) => anf_expr,
            Err(e) => {
                die!("anf: {:?}", e);
            }
        };
        if anf_expr != $ae {
            die!("mismatch {:?} != {:?}", anf_expr, $ae);
        }
    } }
);

#[test]
fn anf_transforms() {
    use common::Op2 as O;
    use self::Imm as I;
    use self::Op::*;
    use self::Expr::*;

    test_anf!(
        "-22",
        Op(Imm(I::Int(-22))));

    test_anf!(
        "2+3",
        Let(String::from("!tmp!0"), box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Op(Imm(I::Var(String::from("!tmp!0"))))));

    test_anf!(
        "2+(3 - 2)",
        Let(String::from("!tmp!0"), box Op(Op2(O::Sub, box I::Int(3), box I::Int(2))),
            box Let(String::from("!tmp!1"), box Op(Op2(O::Add, box I::Int(2), box I::Var(String::from("!tmp!0")))),
                    box Op(Imm(I::Var(String::from("!tmp!1")))))));

    test_anf!(
        "2 + 3 - 2",
        Let(String::from("!tmp!0"), box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Let(String::from("!tmp!1"), box Op(Op2(O::Sub, box I::Var(String::from("!tmp!0")), box I::Int(2))),
                    box Op(Imm(I::Var(String::from("!tmp!1")))))));

    test_anf!(
        "let x = 1 in x",
        Let(String::from("x!a1"), box Op(Imm(I::Int(1))),
            box Op(Imm(I::Var(String::from("x!a1"))))));

    test_anf!(
        "let x = (if true then 1 else 2) in x",
        Let(String::from("!tmp!0"), box If(box I::Bool(true), box Op(Imm(I::Int(1))), box Op(Imm(I::Int(2)))),
            box Let(String::from("x!a1"), box Op(Imm(I::Var(String::from("!tmp!0")))),
                    box Op(Imm(I::Var(String::from("x!a1")))))));
}
<commit_msg>lambdal: fix let, add mkarray, getarray, setarray<commit_after>use std::collections::HashMap;

use common::{Result, Id, Op2, Const};
use explicit;
use implicit;
use env;
use hindley_milner;

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Imm {
    Bool(bool),
    Int(i64),
    Var(Id),
    //    Fun(Id, Box<Expr>),
    //    Fix(Id, Box<Expr>),
    //    Star,
    //    V,
}

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Op {
    Op2(Op2, Box<Imm>, Box<Imm>),
    MkArray(Box<Imm>, Box<Imm>),
    GetArray(Box<Imm>, Box<Imm>),
    SetArray(Box<Imm>, Box<Imm>, Box<Imm>),
    Imm(Imm),
}
//    WellFormed(Imm), // Var-only

#[derive(PartialEq, Eq, Clone, Debug)]
pub enum Expr {
    If(Box<Imm>, Box<Expr>, Box<Expr>),
    //    App(Box<Imm>, Box<Imm>),
    Let(Id, Box<Expr>, Box<Expr>),
    Op(Op),
}

#[derive(PartialEq, Eq, Clone, Debug)]
struct ConvEnv {
    //env: HashMap<Id, explicit::Type>,
    next_id: i32,
}

impl ConvEnv {
    fn new() -> ConvEnv {
        ConvEnv {
            //env: HashMap::new(),
            next_id: 0,
        }
    }

    fn tmp(&self) -> (ConvEnv, Id) {
        let id = self.next_id;
        let c = ConvEnv{
            //env: self.env.clone(),
            next_id: self.next_id+1,
        };

        (c, format!("!tmp!{}", id))
    }
}

fn constant(c: &Const) -> Imm {
    match *c {
        Const::Bool(b) => Imm::Bool(b),
        Const::Int(i) => Imm::Int(i),
    }
}

fn identity(cenv: ConvEnv, i: Imm) -> (ConvEnv, Expr) {
    (cenv, Expr::Op(Op::Imm(i)))
}

// 1:1 translation -- can't fail
fn expr(cenv: ConvEnv, e: &explicit::Expr, k: &Fn(ConvEnv, Imm) -> (ConvEnv, Expr)) -> (ConvEnv, Expr) {

    use self::Imm as I;
    use typed::Expr as E;
    use self::Op::*;
    use self::Expr::*;

    match *e {
        E::Const(ref c) => k(cenv, constant(c)),
        E::Op2(op, ref l, ref r) => {
            expr(cenv, l, &|cenv: ConvEnv, ll: I| -> (ConvEnv, Expr) {
                expr(cenv, r, &|cenv: ConvEnv, rr: I| -> (ConvEnv, Expr) {

                    let (cenv, op_tmp) = cenv.tmp();
                    let op_val = Op(Op2(op, box ll.clone(), box rr));
                    // value to pass to the continuation
                    let op_ref = I::Var(op_tmp.clone());

                    // our inner expression is whatever the
                    // continuation says it is.
                    let (cenv, result) = k(cenv, op_ref);

                    (cenv, Let(op_tmp, box op_val, box result))
                })
            })
        }
        E::Let(ref id, ref e1, ref e2) => {
            expr(cenv, e1, &|cenv: ConvEnv, e1l: I| -> (ConvEnv, Expr) {
                let (cenv, inner) = expr(cenv, e2, k);
                (cenv, Let(id.clone(), box Op(Imm(e1l.clone())), box inner))
            })
        }
        E::Var(ref x) => {
            k(cenv, I::Var(x.clone()))
        }
        E::If(ref e1, ref e2, ref e3) => {
            expr(cenv, e1, &|cenv: ConvEnv, cond_ref: I| -> (ConvEnv, Expr) {

                let (cenv, l_true) = expr(cenv, e2, &identity);
                let (cenv, l_false) = expr(cenv, e3, &identity);

                // value to pass to the continuation
                let val = If(box cond_ref, box l_true, box l_false);
                let (cenv, val_tmp) = cenv.tmp();

                // our inner expression is whatever the
                // continuation says it is.
                let (cenv, mut result) = k(cenv, I::Var(val_tmp.clone()));

                result = Let(val_tmp, box val, box result);

                (cenv, result)
            })
        }
        E::MkArray(ref sz, ref val) => {
            println!("O mkarray");
            expr(cenv, sz, &|cenv: ConvEnv, isz: I| -> (ConvEnv, Expr) {
                expr(cenv, val, &|cenv: ConvEnv, ival: I| -> (ConvEnv, Expr) {
                    println!("I mkarray");
                    let val = Op(MkArray(box isz.clone(), box ival));
                    let (cenv, val_ref) = cenv.tmp();
                    let (cenv, result) = k(cenv, I::Var(val_ref.clone()));
                    (cenv, Let(val_ref, box val, box result))
                })
            })
        }
        E::GetArray(ref id, ref idx) => {
            println!("O getarray");
            expr(cenv, id, &|cenv: ConvEnv, iid: I| -> (ConvEnv, Expr) {
                expr(cenv, idx, &|cenv: ConvEnv, iidx: I| -> (ConvEnv, Expr) {
                    println!("I getarray");
                    let val = Op(GetArray(box iid.clone(), box iidx));
                    let (cenv, val_ref) = cenv.tmp();
                    let (cenv, result) = k(cenv, I::Var(val_ref.clone()));
                    (cenv, Let(val_ref, box val, box result))
                })
            })
        }
        E::SetArray(ref id, ref idx, ref v) => {
            expr(cenv, id, &|cenv: ConvEnv, iid: I| -> (ConvEnv, Expr) {
                expr(cenv, idx, &|cenv: ConvEnv, iidx: I| -> (ConvEnv, Expr) {
                    expr(cenv, v, &|cenv: ConvEnv, iv: I| -> (ConvEnv, Expr) {
                        let val = Op(SetArray(box iid.clone(), box iidx.clone(), box iv));
                        let (cenv, val_ref) = cenv.tmp();
                        let (cenv, result) = k(cenv, I::Var(val_ref.clone()));
                        (cenv, Let(val_ref, box val, box result))
                    })
                })
            })
        }
        _ => {
            panic!("TODO: implement expr for {:?}", e);
        }
    }
    // E::Fun(ref id, ref t1, ref e) => {
    //     let mut renamed = renamed.clone();
    //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

    //     renamed.insert(id.clone(), αid.clone());
    //     env.insert(αid.clone(), t1.clone());

    //     let (n, e, t2) = convert(n, env, &renamed, e);

    //     (n, I::Fun(αid, box e), Type::TFun(box t1.clone(), box t2))
    // }
    // E::Fix(ref id, ref t1, ref e) => {
    //     let mut renamed = renamed.clone();
    //     let (n, αid) = (n+1, format!("{}!a{}", id, n));

    //     renamed.insert(id.clone(), αid.clone());
    //     env.insert(αid.clone(), t1.clone());

    //     let (n, e, t2) = convert(n, env, &renamed, e);

    //     (n, I::Fix(αid, box e), t2)
    // }
    // E::App(ref e1, ref e2) => {
    //     let (n, e1, t1) = convert(n, env, renamed, e1);
    //     let (n, e2, _) = convert(n, env, renamed, e2);
    //     let t = match t1 {
    //         Type::TFun(_, t2) => *t2,
    //         _ => panic!("expected TFun, not {:?}", t1),
    //     };
    //     (n, I::App(box e1, box e2), t)
    // }
}

pub fn anf(implicit_expr: &implicit::Expr) -> Result<(Expr, HashMap<Id, explicit::Type>)> {

    let explicit_expr = hindley_milner::infer(implicit_expr)?;
    // alpha-renaming
    let (alpha_expr, env) = env::extract(&explicit_expr);

    let cenv = ConvEnv::new();
    let (_, expr) = expr(cenv, &alpha_expr, &identity);

    Ok((expr, env))
}

macro_rules! test_anf(
    ($s:expr, $ae:expr) => { {
        use implicit_parse;
        use tok::Tokenizer;
        use std;
        let s = $s;
        let tokenizer = Tokenizer::new(&s);
        let iexpr = match implicit_parse::parse_Program(&s, tokenizer) {
            Ok(iexpr) => iexpr,
            Err(e) => {
                die!("parse_Program({}): {:?}", $s, e);
            }
        };
        let anf_expr = match anf(&iexpr) {
            Ok((anf_expr, _)) => anf_expr,
            Err(e) => {
                die!("anf: {:?}", e);
            }
        };
        if anf_expr != $ae {
            die!("mismatch {:?} != {:?}", anf_expr, $ae);
        }
    } }
);

#[test]
fn anf_transforms() {
    use common::Op2 as O;
    use self::Imm as I;
    use self::Op::*;
    use self::Expr::*;

    test_anf!(
        "-22",
        Op(Imm(I::Int(-22))));

    test_anf!(
        "2+3",
        Let(String::from("!tmp!0"), box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Op(Imm(I::Var(String::from("!tmp!0"))))));

    test_anf!(
        "2+(3 - 2)",
        Let(String::from("!tmp!0"), box Op(Op2(O::Sub, box I::Int(3), box I::Int(2))),
            box Let(String::from("!tmp!1"), box Op(Op2(O::Add, box I::Int(2), box I::Var(String::from("!tmp!0")))),
                    box Op(Imm(I::Var(String::from("!tmp!1")))))));

    test_anf!(
        "2 + 3 - 2",
        Let(String::from("!tmp!0"), box Op(Op2(O::Add, box I::Int(2), box I::Int(3))),
            box Let(String::from("!tmp!1"), box Op(Op2(O::Sub, box I::Var(String::from("!tmp!0")), box I::Int(2))),
                    box Op(Imm(I::Var(String::from("!tmp!1")))))));

    test_anf!(
        "let x = 1 in x",
        Let(String::from("x!a1"), box Op(Imm(I::Int(1))),
            box Op(Imm(I::Var(String::from("x!a1"))))));

    test_anf!(
        "let x = (if true then 1 else 2) in x",
        Let(String::from("!tmp!0"), box If(box I::Bool(true), box Op(Imm(I::Int(1))), box Op(Imm(I::Int(2)))),
            box Let(String::from("x!a1"), box Op(Imm(I::Var(String::from("!tmp!0")))),
                    box Op(Imm(I::Var(String::from("x!a1")))))));

    test_anf!(
        "let a = array(3, 5) in a[0]",
        Let(String::from("!tmp!0"), box Op(MkArray(box I::Int(3), box I::Int(5))),
            box Let(String::from("a!a1"), box Op(Imm(I::Var(String::from("!tmp!0")))),
                    box Let(String::from("!tmp!1"), box Op(GetArray(box I::Var(String::from("a!a1")), box I::Int(0))),
                            box Op(Imm(I::Var(String::from("!tmp!1"))))))));
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::thread;
use std::sync::mpsc;

pub enum Message {
    Pause,
    Resume,
    Step,
    Inspect,
}

pub fn spawn() -> (mpsc::Sender<Message>, mpsc::Receiver<String>) {
    let (tx_message, rx_message) = mpsc::channel();
    let (tx_data, rx_data) = mpsc::channel();

    thread::spawn(move || {
        let mut computer = Machine::new();
        let mut paused = false;

        loop {
            let message = rx_message.try_recv();
            if message.is_ok() {
                match message.unwrap() {
                    Message::Pause => {
                        paused = true;
                    },

                    Message::Resume => {
                        paused = false;
                    },

                    Message::Step => {
                        paused = true;
                        computer.step();
                    },

                    Message::Inspect => {
                        let data = format!("PAUSED {}\nPC {}", paused, computer.loc());
                        tx_data.send(data).unwrap();
                    }
                }
            }

            thread::yield_now();

            if !paused {
                computer.step();
            }

        }
    });

    return (tx_message, rx_data);
}

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            // Default to a valid program in memory.
            // This one is an infinite loop.
            memory: vec![1, 2, 0, 0],
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn step(&mut self) {
        let counter = self.counter;
        let opcode = self.memory_at(counter);
        let a = self.memory_at(counter + 1);
        let b = self.memory_at(counter + 2);
        let c = self.memory_at(counter + 3);
        self.exec(opcode, a, b, c);
    }

    fn memory_at(&mut self, index: u32) -> u32 {
        let index = index as usize;

        if index >= self.memory.len() {
            self.memory.resize(index + 1, 0);
        }

        return self.memory[index];
    }

    fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.memory[a as usize];
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.memory[b as usize] {
                  self.counter = self.memory[a as usize];
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.memory[b as usize];
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.memory[b as usize];
                self.memory[b as usize] = self.memory[a as usize];
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] * M[C]
            9 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // M[A] <- M[B] / M[C]
            10 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b / c;
                self.counter += 4;
            },

            // M[A] <- M[B] % M[C]
            11 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b % c;
                self.counter += 4;
            },

            // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
            12 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b < c {
                  self.memory[a as usize] = 1;
                } else {
                  self.memory[a as usize] = 0;
                }
                self.counter += 4;
            },

            // MA[A] <- NOT(M[B] AND M[C])
            13 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b > 0 && c > 0 {
                  self.memory[a as usize] = 0;
                } else {
                  self.memory[a as usize] = 1;
                }
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

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

    #[test]
    fn it_defaults_to_an_infinite_loop() {
        let mut m = Machine::new();

        // Read initial memory and program counter.
        let memory = m.dump().to_vec();
        let counter = m.loc();

        // Step the program twice. If nothing changes, we're in a loop.
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
    }

    #[test]
    fn it_runs_opcode_1() {
        // PC <- M[A]
        let mut m = Machine { memory: vec![1, 4, 0, 0, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_then_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        // M[A] <- PC
        let mut m = Machine { memory: vec![3, 4, 0, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![3, 4, 0, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        // M[A] <- M[B]
        let mut m = Machine { memory: vec![4, 4, 5, 0, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![4, 4, 5, 0, 7, 7], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        // M[A] <- M[M[B]]
        let mut m = Machine { memory: vec![5, 4, 5, 0, 6, 7, 0, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![5, 4, 5, 0, 8, 7, 0, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        // M[M[B]] <- M[A]
        let mut m = Machine { memory: vec![6, 4, 5, 0, 8, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![6, 4, 5, 0, 8, 6, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        // M[A] <- M[B] + M[C]
        let mut m = Machine { memory: vec![7, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![7, 4, 5, 6, 13, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        // M[A] <- M[B] - M[C]
        let mut m = Machine { memory: vec![8, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![8, 4, 5, 6, 9, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        // M[A] <- M[B] * M[C]
        let mut m = Machine { memory: vec![9, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![9, 4, 5, 6, 22, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_10() {
        // M[A] <- M[B] / M[C]
        let mut m = Machine { memory: vec![10, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![10, 4, 5, 6, 5, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_11() {
        // M[A] <- M[B] % M[C]
        let mut m = Machine { memory: vec![11, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![11, 4, 5, 6, 1, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_then_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 8, 9], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 1, 8, 9], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_else_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 9, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 0, 9, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 1, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 0, 1, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_provides_safe_memory_access_when_stepping() {
        let mut m = Machine { memory: vec![0], counter: 3 };

        m.step();
        assert_eq!(&vec![0, 0, 0, 0, 0, 0, 0], m.dump());
    }
}
<commit_msg>Rename memory_at() to read().<commit_after>use std::vec::Vec;
use std::thread;
use std::sync::mpsc;

pub enum Message {
    Pause,
    Resume,
    Step,
    Inspect,
}

pub fn spawn() -> (mpsc::Sender<Message>, mpsc::Receiver<String>) {
    let (tx_message, rx_message) = mpsc::channel();
    let (tx_data, rx_data) = mpsc::channel();

    thread::spawn(move || {
        let mut computer = Machine::new();
        let mut paused = false;

        loop {
            let message = rx_message.try_recv();
            if message.is_ok() {
                match message.unwrap() {
                    Message::Pause => {
                        paused = true;
                    },

                    Message::Resume => {
                        paused = false;
                    },

                    Message::Step => {
                        paused = true;
                        computer.step();
                    },

                    Message::Inspect => {
                        let data = format!("PAUSED {}\nPC {}", paused, computer.loc());
                        tx_data.send(data).unwrap();
                    }
                }
            }

            thread::yield_now();

            if !paused {
                computer.step();
            }

        }
    });

    return (tx_message, rx_data);
}

pub struct Machine {
    memory: Vec<u32>,
    counter: u32,
}

impl Machine {
    pub fn new() -> Machine {
        Machine {
            // Default to a valid program in memory.
            // This one is an infinite loop.
            memory: vec![1, 2, 0, 0],
            counter: 0,
        }
    }

    pub fn loc(&self) -> u32 {
        self.counter
    }

    pub fn dump(&self) -> &Vec<u32> {
        &self.memory
    }

    pub fn step(&mut self) {
        let counter = self.counter;
        let opcode = self.read(counter);
        let a = self.read(counter + 1);
        let b = self.read(counter + 2);
        let c = self.read(counter + 3);
        self.exec(opcode, a, b, c);
    }

    fn read(&mut self, index: u32) -> u32 {
        let index = index as usize;

        if index >= self.memory.len() {
            self.memory.resize(index + 1, 0);
        }

        return self.memory[index];
    }

    fn exec(&mut self, opcode: u32, a: u32, b: u32, c: u32) {
        match opcode {
            // PC <- M[A]
            1 => {
                self.counter = self.memory[a as usize];
            },

            // If M[B] = 0, then PC <- M[A]
            2 => {
                if 0 == self.memory[b as usize] {
                  self.counter = self.memory[a as usize];
                }
            },

            // M[A] <- PC
            3 => {
                self.memory[a as usize] = self.counter;
                self.counter += 4;
            },

            // M[A] <- M[B]
            4 => {
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[A] <- M[M[B]]
            5 => {
                let b = self.memory[b as usize];
                self.memory[a as usize] = self.memory[b as usize];
                self.counter += 4;
            },

            // M[M[B]] <- M[A]
            6 => {
                let b = self.memory[b as usize];
                self.memory[b as usize] = self.memory[a as usize];
                self.counter += 4;
            },

            // M[A] <- M[B] + M[C]
            7 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b + c;
                self.counter += 4;
            },

            // M[A] <- M[B] - M[C]
            8 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b - c;
                self.counter += 4;
            },

            // M[A] <- M[B] * M[C]
            9 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b * c;
                self.counter += 4;
            },

            // M[A] <- M[B] / M[C]
            10 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b / c;
                self.counter += 4;
            },

            // M[A] <- M[B] % M[C]
            11 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                self.memory[a as usize] = b % c;
                self.counter += 4;
            },

            // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
            12 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b < c {
                  self.memory[a as usize] = 1;
                } else {
                  self.memory[a as usize] = 0;
                }
                self.counter += 4;
            },

            // MA[A] <- NOT(M[B] AND M[C])
            13 => {
                let b = self.memory[b as usize];
                let c = self.memory[c as usize];
                if b > 0 && c > 0 {
                  self.memory[a as usize] = 0;
                } else {
                  self.memory[a as usize] = 1;
                }
                self.counter += 4;
            },

            // Unknown opcode
            _ => {
            },
        }
    }
}

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

    #[test]
    fn it_defaults_to_an_infinite_loop() {
        let mut m = Machine::new();

        // Read initial memory and program counter.
        let memory = m.dump().to_vec();
        let counter = m.loc();

        // Step the program twice. If nothing changes, we're in a loop.
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
        m.step();
        assert_eq!(counter, m.loc());
        assert_eq!(&memory, m.dump());
    }

    #[test]
    fn it_runs_opcode_1() {
        // PC <- M[A]
        let mut m = Machine { memory: vec![1, 4, 0, 0, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_then_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(2, m.loc());
    }

    #[test]
    fn it_runs_opcode_2_else_branch() {
        // If M[B] = 0, then PC <- M[A]
        let mut m = Machine { memory: vec![2, 4, 5, 0, 2, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(0, m.loc());
    }

    #[test]
    fn it_runs_opcode_3() {
        // M[A] <- PC
        let mut m = Machine { memory: vec![3, 4, 0, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![3, 4, 0, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_4() {
        // M[A] <- M[B]
        let mut m = Machine { memory: vec![4, 4, 5, 0, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![4, 4, 5, 0, 7, 7], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_5() {
        // M[A] <- M[M[B]]
        let mut m = Machine { memory: vec![5, 4, 5, 0, 6, 7, 0, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![5, 4, 5, 0, 8, 7, 0, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_6() {
        // M[M[B]] <- M[A]
        let mut m = Machine { memory: vec![6, 4, 5, 0, 8, 6, 7], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![6, 4, 5, 0, 8, 6, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_7() {
        // M[A] <- M[B] + M[C]
        let mut m = Machine { memory: vec![7, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![7, 4, 5, 6, 13, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_8() {
        // M[A] <- M[B] - M[C]
        let mut m = Machine { memory: vec![8, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![8, 4, 5, 6, 9, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_9() {
        // M[A] <- M[B] * M[C]
        let mut m = Machine { memory: vec![9, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![9, 4, 5, 6, 22, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_10() {
        // M[A] <- M[B] / M[C]
        let mut m = Machine { memory: vec![10, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![10, 4, 5, 6, 5, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_11() {
        // M[A] <- M[B] % M[C]
        let mut m = Machine { memory: vec![11, 4, 5, 6, 0, 11, 2], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![11, 4, 5, 6, 1, 11, 2], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_then_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 8, 9], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 1, 8, 9], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_12_else_branch() {
        // If M[B] < M[C], then M[A] <- 1, else M[A] <- 0
        let mut m = Machine { memory: vec![12, 4, 5, 6, 2, 9, 8], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![12, 4, 5, 6, 0, 9, 8], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_false_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 0, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 0, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_false_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 0], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 1, 1, 0], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_runs_opcode_13_true_true_branch() {
        // M[A] <- NOT(M[B] AND M[C])
        let mut m = Machine { memory: vec![13, 4, 5, 6, 2, 1, 1], .. Machine::new() };

        assert_eq!(0, m.loc());
        m.step();
        assert_eq!(&vec![13, 4, 5, 6, 0, 1, 1], m.dump());
        assert_eq!(4, m.loc());
    }

    #[test]
    fn it_provides_safe_memory_access_when_stepping() {
        let mut m = Machine { memory: vec![0], counter: 3 };

        m.step();
        assert_eq!(&vec![0, 0, 0, 0, 0, 0, 0], m.dump());
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use dbus_nm::DBusNetworkManager;

use connection::{Connection, get_connections, get_active_connections};
use device::{Device, get_devices, get_device_by_interface};
use service::{start_service, stop_service, get_service_state, ServiceState, Error};

pub struct NetworkManager {
    dbus_manager: Rc<RefCell<DBusNetworkManager>>,
}

impl NetworkManager {
    pub fn new() -> Self {
        NetworkManager { dbus_manager: Rc::new(RefCell::new(DBusNetworkManager::new())) }
    }

    /// Starts the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::start_service(10).unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn start_service(timeout: u64) -> Result<ServiceState, Error> {
        start_service(timeout)
    }

    /// Stops the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::stop_service(10).unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn stop_service(timeout: u64) -> Result<ServiceState, Error> {
        stop_service(timeout)
    }

    /// Gets the state of the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::get_service_state().unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn get_service_state() -> Result<ServiceState, Error> {
        get_service_state()
    }

    pub fn set_method_timeout(&mut self, timeout: u64) {
        self.dbus_manager.borrow_mut().set_method_timeout(timeout);
    }

    /// Get a list of Network Manager connections sorted by path.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let manager = NetworkManager::new();
    /// let connections = manager.get_connections().unwrap();
    /// println!("{:?}", connections);
    /// ```
    pub fn get_connections(&self) -> Result<Vec<Connection>, String> {
        get_connections(&self.dbus_manager)
    }

    pub fn get_active_connections(&self) -> Result<Vec<Connection>, String> {
        get_active_connections(&self.dbus_manager)
    }

    /// Get a list of Network Manager devices.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let manager = NetworkManager::new();
    /// let devices = manager.get_devices().unwrap();
    /// println!("{:?}", devices);
    /// ```
    pub fn get_devices(&self) -> Result<Vec<Device>, String> {
        get_devices(&self.dbus_manager)
    }

    pub fn get_device_by_interface(&self, interface: &str) -> Result<Device, String> {
        get_device_by_interface(&self.dbus_manager, interface)
    }

    pub fn get_state(&self) -> Result<NetworkManagerState, String> {
        self.dbus_manager.borrow().get_state()
    }

    pub fn get_connectivity(&self) -> Result<Connectivity, String> {
        self.dbus_manager.borrow().check_connectivity()
    }

    pub fn is_networking_enabled(&self) -> Result<bool, String> {
        self.dbus_manager.borrow().is_networking_enabled()
    }

    pub fn is_wireless_enabled(&self) -> Result<bool, String> {
        self.dbus_manager.borrow().is_wireless_enabled()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum NetworkManagerState {
    Unknown,
    Asleep,
    Disconnected,
    Disconnecting,
    Connecting,
    ConnectedLocal,
    ConnectedSite,
    ConnectedGlobal,
}

impl From<i64> for NetworkManagerState {
    fn from(state: i64) -> Self {
        match state {
            0  => NetworkManagerState::Unknown,
            10 => NetworkManagerState::Asleep,
            20 => NetworkManagerState::Disconnected,
            30 => NetworkManagerState::Disconnecting,
            40 => NetworkManagerState::Connecting,
            50 => NetworkManagerState::ConnectedLocal,
            60 => NetworkManagerState::ConnectedSite,
            70 => NetworkManagerState::ConnectedGlobal,
            _  => NetworkManagerState::Unknown,

        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Connectivity {
    Unknown,
    None,
    Portal,
    Limited,
    Full,
}

impl From<i64> for Connectivity {
    fn from(state: i64) -> Self {
        match state {
            0 => Connectivity::Unknown,
            1 => Connectivity::None,
            2 => Connectivity::Portal,
            3 => Connectivity::Limited,
            4 => Connectivity::Full,
            _ => Connectivity::Unknown,

        }
    }
}

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

    #[test]
    fn test_get_connections() {
        let manager = NetworkManager::new();
        let connections = manager.get_connections().unwrap();
        assert!(connections.len() > 0);
    }

    #[test]
    fn test_get_devices() {
        let manager = NetworkManager::new();
        let devices = manager.get_devices().unwrap();
        assert!(devices.len() > 0);
    }

    #[test]
    fn test_start_stop_service() {
        let s = NetworkManager::get_service_state().unwrap();

        assert!(s == ServiceState::Active || s == ServiceState::Inactive);

        match s {
            ServiceState::Active => {
                NetworkManager::stop_service(10).unwrap();
                assert_eq!(ServiceState::Inactive,
                           NetworkManager::get_service_state().unwrap());

                NetworkManager::start_service(10).unwrap();
                assert_eq!(ServiceState::Active,
                           NetworkManager::get_service_state().unwrap());
            }
            ServiceState::Inactive => {
                NetworkManager::start_service(10).unwrap();
                assert_eq!(ServiceState::Active,
                           NetworkManager::get_service_state().unwrap());

                NetworkManager::stop_service(10).unwrap();
                assert_eq!(ServiceState::Inactive,
                           NetworkManager::get_service_state().unwrap());
            }
            _ => (),
        }
    }
}
<commit_msg>Formatting<commit_after>use std::rc::Rc;
use std::cell::RefCell;

use dbus_nm::DBusNetworkManager;

use connection::{Connection, get_connections, get_active_connections};
use device::{Device, get_devices, get_device_by_interface};
use service::{start_service, stop_service, get_service_state, ServiceState, Error};

pub struct NetworkManager {
    dbus_manager: Rc<RefCell<DBusNetworkManager>>,
}

impl NetworkManager {
    pub fn new() -> Self {
        NetworkManager { dbus_manager: Rc::new(RefCell::new(DBusNetworkManager::new())) }
    }

    /// Starts the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::start_service(10).unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn start_service(timeout: u64) -> Result<ServiceState, Error> {
        start_service(timeout)
    }

    /// Stops the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::stop_service(10).unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn stop_service(timeout: u64) -> Result<ServiceState, Error> {
        stop_service(timeout)
    }

    /// Gets the state of the Network Manager service.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let state = NetworkManager::get_service_state().unwrap();
    /// println!("{:?}", state);
    /// ```
    pub fn get_service_state() -> Result<ServiceState, Error> {
        get_service_state()
    }

    pub fn set_method_timeout(&mut self, timeout: u64) {
        self.dbus_manager.borrow_mut().set_method_timeout(timeout);
    }

    /// Get a list of Network Manager connections sorted by path.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let manager = NetworkManager::new();
    /// let connections = manager.get_connections().unwrap();
    /// println!("{:?}", connections);
    /// ```
    pub fn get_connections(&self) -> Result<Vec<Connection>, String> {
        get_connections(&self.dbus_manager)
    }

    pub fn get_active_connections(&self) -> Result<Vec<Connection>, String> {
        get_active_connections(&self.dbus_manager)
    }

    /// Get a list of Network Manager devices.
    ///
    /// # Examples
    ///
    /// ```
    /// use network_manager::NetworkManager;
    /// let manager = NetworkManager::new();
    /// let devices = manager.get_devices().unwrap();
    /// println!("{:?}", devices);
    /// ```
    pub fn get_devices(&self) -> Result<Vec<Device>, String> {
        get_devices(&self.dbus_manager)
    }

    pub fn get_device_by_interface(&self, interface: &str) -> Result<Device, String> {
        get_device_by_interface(&self.dbus_manager, interface)
    }

    pub fn get_state(&self) -> Result<NetworkManagerState, String> {
        self.dbus_manager.borrow().get_state()
    }

    pub fn get_connectivity(&self) -> Result<Connectivity, String> {
        self.dbus_manager.borrow().check_connectivity()
    }

    pub fn is_networking_enabled(&self) -> Result<bool, String> {
        self.dbus_manager.borrow().is_networking_enabled()
    }

    pub fn is_wireless_enabled(&self) -> Result<bool, String> {
        self.dbus_manager.borrow().is_wireless_enabled()
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum NetworkManagerState {
    Unknown,
    Asleep,
    Disconnected,
    Disconnecting,
    Connecting,
    ConnectedLocal,
    ConnectedSite,
    ConnectedGlobal,
}

impl From<i64> for NetworkManagerState {
    fn from(state: i64) -> Self {
        match state {
            0 => NetworkManagerState::Unknown,
            10 => NetworkManagerState::Asleep,
            20 => NetworkManagerState::Disconnected,
            30 => NetworkManagerState::Disconnecting,
            40 => NetworkManagerState::Connecting,
            50 => NetworkManagerState::ConnectedLocal,
            60 => NetworkManagerState::ConnectedSite,
            70 => NetworkManagerState::ConnectedGlobal,
            _ => NetworkManagerState::Unknown,

        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Connectivity {
    Unknown,
    None,
    Portal,
    Limited,
    Full,
}

impl From<i64> for Connectivity {
    fn from(state: i64) -> Self {
        match state {
            0 => Connectivity::Unknown,
            1 => Connectivity::None,
            2 => Connectivity::Portal,
            3 => Connectivity::Limited,
            4 => Connectivity::Full,
            _ => Connectivity::Unknown,

        }
    }
}

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

    #[test]
    fn test_get_connections() {
        let manager = NetworkManager::new();
        let connections = manager.get_connections().unwrap();
        assert!(connections.len() > 0);
    }

    #[test]
    fn test_get_devices() {
        let manager = NetworkManager::new();
        let devices = manager.get_devices().unwrap();
        assert!(devices.len() > 0);
    }

    #[test]
    fn test_start_stop_service() {
        let s = NetworkManager::get_service_state().unwrap();

        assert!(s == ServiceState::Active || s == ServiceState::Inactive);

        match s {
            ServiceState::Active => {
                NetworkManager::stop_service(10).unwrap();
                assert_eq!(ServiceState::Inactive,
                           NetworkManager::get_service_state().unwrap());

                NetworkManager::start_service(10).unwrap();
                assert_eq!(ServiceState::Active,
                           NetworkManager::get_service_state().unwrap());
            }
            ServiceState::Inactive => {
                NetworkManager::start_service(10).unwrap();
                assert_eq!(ServiceState::Active,
                           NetworkManager::get_service_state().unwrap());

                NetworkManager::stop_service(10).unwrap();
                assert_eq!(ServiceState::Inactive,
                           NetworkManager::get_service_state().unwrap());
            }
            _ => (),
        }
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::Json;

use super::types::ESType;

#[derive(Debug)]
pub struct FieldMapping {
    data_type: ESType,
    is_indexed: bool,
    is_stored: bool,
    is_in_all: bool,
    boost: f64,
}

impl Default for FieldMapping {
    fn default() -> FieldMapping {
        FieldMapping {
            data_type: ESType::default(),
            is_indexed: true,
            is_stored: false,
            is_in_all: true,
            boost: 1.0f64,
        }
    }
}

impl FieldMapping {
    pub fn from_json(json: &Json) -> FieldMapping {
        let json = json.as_object().unwrap();
        let mut field_mapping = FieldMapping::default();

        for (key, value) in json.iter() {
            match key.as_ref() {
                "type" => {
                    let type_name = value.as_string().unwrap();

                    field_mapping.data_type = match type_name.as_ref() {
                        "string" => ESType::String,
                        "integer" => ESType::Number{bits: 64, is_float: false},
                        "boolean" => ESType::Boolean,
                        "date" => ESType::Date,
                        _ => {
                            // TODO; make this an error
                            println!("unimplemented type name! {}", type_name);
                            ESType::default()
                        }
                    };
                }
                "index" => {

                }
                "index_analyzer" => {

                }
                "boost" => {

                }
                "store" => {

                }
                "include_in_all" => {

                }
                _ => println!("unimplemented field mapping key! {}", key)
            }

        }

        field_mapping
    }
}
<commit_msg>Mapping parsing<commit_after>use rustc_serialize::json::Json;

use super::types::ESType;

#[derive(Debug)]
pub struct FieldMapping {
    data_type: ESType,
    is_indexed: bool,
    is_stored: bool,
    is_in_all: bool,
    boost: f64,
}

impl Default for FieldMapping {
    fn default() -> FieldMapping {
        FieldMapping {
            data_type: ESType::default(),
            is_indexed: true,
            is_stored: false,
            is_in_all: true,
            boost: 1.0f64,
        }
    }
}

fn parse_boolean(json: &Json) -> bool {
    match *json {
        Json::Boolean(val) => val,
        Json::String(ref s) => {
            match s.as_ref() {
                "yes" => true,
                "no" => false,
                _ => {
                    println!("bad boolean value {:?}", s);
                    false
                }
            }
        }
        _ => {
            // TODO: Raise error
            println!("bad boolean value {:?}", json);
            false
        }
    }
}

impl FieldMapping {
    pub fn from_json(json: &Json) -> FieldMapping {
        let json = json.as_object().unwrap();
        let mut field_mapping = FieldMapping::default();

        for (key, value) in json.iter() {
            match key.as_ref() {
                "type" => {
                    let type_name = value.as_string().unwrap();

                    field_mapping.data_type = match type_name.as_ref() {
                        "string" => ESType::String,
                        "integer" => ESType::Number{bits: 64, is_float: false},
                        "boolean" => ESType::Boolean,
                        "date" => ESType::Date,
                        _ => {
                            // TODO; make this an error
                            println!("unimplemented type name! {}", type_name);
                            ESType::default()
                        }
                    };
                }
                "index" => {
                    let index = value.as_string().unwrap();
                    if index == "not_analyzed" {
                        field_mapping.is_indexed = false;
                    } else {
                        // TODO: Implement other variants and make this an error
                        println!("unimplemented index setting! {}", index);
                    }
                }
                "index_analyzer" => {
                    // TODO
                }
                "boost" => {
                    field_mapping.boost = value.as_f64().unwrap();
                }
                "store" => {
                    field_mapping.is_stored = parse_boolean(value);
                }
                "include_in_all" => {
                    field_mapping.is_in_all = parse_boolean(value);
                }
                _ => println!("unimplemented field mapping key! {}", key)
            }

        }

        field_mapping
    }
}
<|endoftext|>


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

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{Deserialize, Deserializer, Unexpected, Error};
use serde_json::{Value, from_value};

#[derive(Debug, Clone, PartialEq, Eq)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

impl Deserialize for Version {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // The version is actually a string
        let parsed: String = Deserialize::deserialize(deserializer)?;
        if parsed == "2.0" {
            Ok(Version)
        } else {
            Err(D::Error::invalid_value(Unexpected::Str(&parsed), &"value 2.0"))
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    // TODO: Make private?
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Message {
    pub fn request(method: String, params: Option<Value>) -> Self {
        Message::Request(Request {
            jsonrpc: Version,
            method: method,
            params: params,
            // TODO!
            id: Value::Null,
        })
    }
    pub fn notification(method: String, params: Option<Value>) -> Self {
        Message::Notification(Notification {
            jsonrpc: Version,
            method: method,
            params: params,
        })
    }
    // TODO: Other constructors
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

macro_rules! deser_branch {
    ($src:expr, $branch:ident) => {
        match from_value($src.clone()) {
            Ok(parsed) => return Message::$branch(parsed),
            Err(_) => (),
        }
    };
}

impl From<Value> for Message {
    fn from(v: Value) -> Self {
        // Try decoding it by each branch in sequence, taking the first one that matches
        deser_branch!(v, Request);
        deser_branch!(v, Response);
        deser_branch!(v, Notification);
        deser_branch!(v, Batch);
        Message::Unmatched(v)
    }
}

impl Deserialize for Message {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // Read it as a JSON (delegate the deserialization)
        let preparsed: Value = Deserialize::deserialize(deserializer)?;
        // Convert it
        Ok(Self::from(preparsed))
    }
}

impl FromStr for Message {
    type Err = ::serde_json::error::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ::serde_json::de::from_str(s)
    }
}

impl Into<String> for Message {
    fn into(self) -> String {
        ::serde_json::ser::to_string(&self).unwrap()
    }
}
<commit_msg>A TODO note about optimisation<commit_after>use std::str::FromStr;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{Deserialize, Deserializer, Unexpected, Error};
use serde_json::{Value, from_value};

#[derive(Debug, Clone, PartialEq, Eq)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

impl Deserialize for Version {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // The version is actually a string
        let parsed: String = Deserialize::deserialize(deserializer)?;
        if parsed == "2.0" {
            Ok(Version)
        } else {
            Err(D::Error::invalid_value(Unexpected::Str(&parsed), &"value 2.0"))
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    // TODO: Make private?
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Message {
    pub fn request(method: String, params: Option<Value>) -> Self {
        Message::Request(Request {
            jsonrpc: Version,
            method: method,
            params: params,
            // TODO!
            id: Value::Null,
        })
    }
    pub fn notification(method: String, params: Option<Value>) -> Self {
        Message::Notification(Notification {
            jsonrpc: Version,
            method: method,
            params: params,
        })
    }
    // TODO: Other constructors
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

macro_rules! deser_branch {
    ($src:expr, $branch:ident) => {
        match from_value($src.clone()) {
            Ok(parsed) => return Message::$branch(parsed),
            Err(_) => (),
        }
    };
}

// TODO: This must be possible to do in less wasteful way. The cloning is stupid :-(
impl From<Value> for Message {
    fn from(v: Value) -> Self {
        // Try decoding it by each branch in sequence, taking the first one that matches
        deser_branch!(v, Request);
        deser_branch!(v, Response);
        deser_branch!(v, Notification);
        deser_branch!(v, Batch);
        Message::Unmatched(v)
    }
}

impl Deserialize for Message {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // Read it as a JSON (delegate the deserialization)
        let preparsed: Value = Deserialize::deserialize(deserializer)?;
        // Convert it
        Ok(Self::from(preparsed))
    }
}

impl FromStr for Message {
    type Err = ::serde_json::error::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ::serde_json::de::from_str(s)
    }
}

impl Into<String> for Message {
    fn into(self) -> String {
        ::serde_json::ser::to_string(&self).unwrap()
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate regex;

use logger;
use env;
use std::process::exit;
use self::regex::Regex;
use blkid;

//////////////////////////////////////////////////////////////////
pub struct Mounter {
    part_label: String,
    part_type:  String
}

impl Mounter {

    pub fn new() -> Mounter {
        Mounter{
            part_label: "".to_string(),
            part_type: "".to_string()
        }
    }

    pub fn mount(&mut self, l: &logger::Logger, e: &env::Env) {
        self.load_part_info(e.getDevice(), l);
        if !self.verify_label(e.getLabel()) {
            let i = format!("Label does not match {}.", e.getLabel());
            l.info(&i);
            exit(0);
        }
        //
        //TODO
        //
        //self.process();
    }

    fn verify_label(&self, templ: &str) -> bool {
        if self.part_label.len() == 0 {
            return false;
        }

        let res = Regex::new(templ);
        match res {
            Ok(re) => re.is_match(&self.part_label),
            _      => false
        }
    }

    fn load_part_info(&mut self, dev: &str, l: &logger::Logger) {
        let prober = blkid::Prober::new(dev);
        let res = prober.probe();
        if let Err(e) = res {
            l.error(&e);
            exit(1);
        }
        self.loadLabel(&prober, l);
        self.loadType(&prober, l);
    }

    fn loadLabel(&mut self, prober: &blkid::Prober,
                 l: &logger::Logger) {
        let lr = prober.getLabel();
        match lr {
            Ok(o) => {
                self.part_label = o;
                let mess = "LABEL=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }

    fn loadType(&mut self, prober: &blkid::Prober,
                l: &logger::Logger) {
        let lr = prober.getType();
        match lr {
            Ok(o) => {
                self.part_type = o;
                let mess = "TYPE=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }
}
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
#[test]
fn test_verify_label_01() {
    let i = Mounter{part_label: "BNC-124".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_02() {
    let i = Mounter{part_label: "XANC-124".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_04() {
    let i = Mounter{part_label: "ANC".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_05() {
    let i = Mounter{part_label: "01234_ ANC".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_06() {
    let i = Mounter{part_label: "01234_ ANC 782883 ".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_07() {
    let i = Mounter{part_label: " ANC 782883 ".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_08() {
    let i = Mounter{part_label: "ANC---!782883 ".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_09() {
    let i = Mounter{part_label: "01234_ NC 782883 ".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_10() {
    let i = Mounter{part_label: "".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}
//////////////////////////////////////////////////////////////////
<commit_msg>add Drop and process for mounter<commit_after>//
// Copyright (c) 2016, Boris Popov <popov@whitekefir.ru>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//

extern crate regex;

use logger;
use env;
use std::process::exit;
use self::regex::Regex;
use blkid;
use mount;
use mount::MountInfo;

//////////////////////////////////////////////////////////////////
pub struct Mounter {
    part_label: String,
    part_type:  String,
    target:     String
}

impl Mounter {
    pub fn new() -> Mounter {
        Mounter{
            part_label: "".to_string(),
            part_type:  "".to_string(),
            target:     "".to_string()
        }
    }

    pub fn mount(&mut self, l: &logger::Logger, e: &env::Env) {
        self.load_part_info(e.getDevice(), l);
        if !self.verify_label(e.getLabel()) {
            let i = format!("Label does not match {}.", e.getLabel());
            l.info(&i);
            exit(0);
        }
        self.process(l, e);
    }

    fn process(&mut self, l: &logger::Logger, e: &env::Env) {
        let source = e.getDevice().to_string();
        self.target = e.getDir().to_string();
        let mi = MountInfo{source: &source,
                           target: &self.target,
                           filesystem: &self.part_type};
        let res = mount::mount(&mi);
        match res {
            Err(e) => {
                l.info(&e);
                exit(0);
            },
            _ => {
                return;
            }
        }
    }

    fn verify_label(&self, templ: &str) -> bool {
        if self.part_label.len() == 0 {
            return false;
        }

        let res = Regex::new(templ);
        match res {
            Ok(re) => re.is_match(&self.part_label),
            _      => false
        }
    }

    fn load_part_info(&mut self, dev: &str, l: &logger::Logger) {
        let prober = blkid::Prober::new(dev);
        let res = prober.probe();
        if let Err(e) = res {
            l.error(&e);
            exit(1);
        }
        self.loadLabel(&prober, l);
        self.loadType(&prober, l);
    }

    fn loadLabel(&mut self, prober: &blkid::Prober,
                 l: &logger::Logger) {
        let lr = prober.getLabel();
        match lr {
            Ok(o) => {
                self.part_label = o;
                let mess = "LABEL=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }

    fn loadType(&mut self, prober: &blkid::Prober,
                l: &logger::Logger) {
        let lr = prober.getType();
        match lr {
            Ok(o) => {
                self.part_type = o;
                let mess = "TYPE=".to_string() + &self.part_label;
                l.info(&mess);
            },
            Err(e) => {
                l.error(&e);
            }
        }
    }
}

impl Drop for Mounter {
    fn drop(&mut self) {
        if self.target.len() != 0 {
            mount::umount(&self.target);
        }
    }
}
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
#[test]
fn test_verify_label_01() {
    let i = Mounter{part_label: "BNC-124".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_02() {
    let i = Mounter{part_label: "XANC-124".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_04() {
    let i = Mounter{part_label: "ANC".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_05() {
    let i = Mounter{part_label: "01234_ ANC".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_06() {
    let i = Mounter{part_label: "01234_ ANC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_07() {
    let i = Mounter{part_label: " ANC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_08() {
    let i = Mounter{part_label: "ANC---!782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(true, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_09() {
    let i = Mounter{part_label: "01234_ NC 782883 ".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}

#[test]
fn test_verify_label_10() {
    let i = Mounter{part_label: "".to_string(),
                    target: "/mnt/temp".to_string(),
                    part_type: "".to_string()};
    assert_eq!(false, i.verify_label(".*ANC.*"));
}
//////////////////////////////////////////////////////////////////
<|endoftext|>