<commit_before>use parser::parser::{parse};
use expr::Expr;
use expr::Expr::*;
use expr::Val::*;
use expr::UnOp::*;
use expr::BinOp::*;
use expr::Dec::*;
use state::State;
use runtime_error::RuntimeError;
use std::result;

pub type Result<T> = result::Result<T, RuntimeError>;

pub struct Interpreter {
  pub state: State,
}

impl Interpreter {
  pub fn new() -> Interpreter {
    Interpreter {
      state: State::new(),
    }
  }

  pub fn step(&mut self, e: Expr) -> Result<Expr> {
    debug!("step(e) : {:?}", e);
    debug!("step(self.state) : {:?}", self.state.mem);

    let e1 = match e {
      Var(x) => {
        match self.state.get(x.clone()) {
          Some(e) => e,
          None => return Err(RuntimeError::VariableNotFound(x)),
        }
      },
      /**
       * Values are ineligible for step
       */
      Val(_) => {
        debug!("stepping on a value {:?}", e);
        return Err(RuntimeError::SteppingOnValue(e));
      },
      /**
       * Base cases
       */
      Uop(Not, box Val(Bool(b))) => {
        Val(Bool(!b))
      },
      Uop(Neg, box Val(Int(n))) => {
        Val(Int(-1 * n))
      },
      Bop(And, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 && b2))
      },
      Bop(Or, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 || b2))
      },
      Bop(Eq, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 == v2))
      },
      Bop(Ne, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 != v2))
      },
      Bop(Mod, box Val(Int(n1)), box Val(Int(n2))) => {
        // rust % gives the remainder, not modulus
        // let result = ((n1 % n2) + n2) % n2;
        let result = n1.checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?
          .checked_add(n2)
          .ok_or(RuntimeError::IntegerOverflow)?
          .checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?;

        Val(Int(result))
      },
      Bop(Lt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 < n2))
      },
      Bop(Gt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 > n2))
      },
      Bop(Leq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 <= n2))
      },
      Bop(Geq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 >= n2))
      },
      Bop(Plus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_add(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Minus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_sub(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Times, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_mul(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Div, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_div(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Seq, box Val(_), box e1) => {
        e1
      },
      Bop(Assign, box Var(x), box v @ Val(_)) => {
        self.state.assign(x, v.clone())?;
        debug!("done assigning {:?}", self.state.mem);
        v
      },
      Ternary(box Val(Bool(b)), box e1, box e2) => {
        match b {
          true => e1,
          false => e2,
        }
      },
      Decl(DConst, box Var(x), box v1 @ Val(_), box e1) => {
        self.state.alloc_const(x, v1)?;
        e1
      },
      Decl(DVar, box Var(x), box v1 @ Val(_), box e1) => {
        debug!("allocing {:?}", v1);
        self.state.alloc(x, v1)?;
        e1
      },
      // lambda lift so we can use iter() in guard
      // https://github.com/rust-lang/rfcs/issues/1006
      FnCall(ref v1, ref es) if v1.is_func() && (|| es.iter().all(|v| v.is_value()))() => {
        match *v1.clone() {
          box Val(Func(name, e1, xs)) => {
            self.state.begin_scope();

            // alloc the params
            for (xn, en) in xs.iter().zip(es.iter()) {
              self.state.alloc(xn.to_var()?, en.clone())?;
            }

            // alloc the fn body for named functions
            if let Some(s) = name {
              self.state.alloc(s.to_var()?, *v1.clone())?;
            }

            Scope(e1)
          },
          _ => return Err(RuntimeError::UnexpectedExpr("expected Func".to_string(), *v1.clone()))
        }
      },
      Scope(box v @ Val(_)) => {
        self.state.end_scope();
        v
      },
      While(box Val(Bool(b)), e1o, _, e2o, e3) => {
        match b {
          true => While(e1o.clone(), e1o, e2o.clone(), e2o, e3),
          false => *e3,
        }
      },
      Print(box Val(v)) => {
        println!("{}", v);
        Val(Undefined)
      },
      /**
       * Search Cases
       */
      Bop(op, v1 @ box Val(_), box e2) => {
        Bop(
          op,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(Assign, v1 @ box Var(_), box e2) => {
        Bop(
          Assign,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(op, box e1, e2) => {
        Bop(op, Box::new(self.step(e1)?), e2)
      },
      Uop(op, box e1) => {
        Uop(op, Box::new(self.step(e1)?))
      },
      Ternary(box e1, e2, e3) => {
        Ternary(Box::new(self.step(e1)?), e2, e3)
      },
      While(box e1, e1o, v @ box Val(_), e2o, e3) => {
        While(Box::new(self.step(e1)?), e1o, v, e2o, e3)
      },
      While(e1, e1o, box e2, e2o, e3) => {
        While(e1, e1o, Box::new(self.step(e2)?), e2o, e3)
      },
      Decl(dt, box addr, box e1, e2) => {
        Decl(dt, Box::new(addr.clone()), Box::new(self.step(e1)?), e2)
      },
      FnCall(f @ box Val(Func(_, _, _)), mut args) => {
        // find the first nonvalue arg and call step() on it
        if let Some(index) = args.iter().position(|e| {
          match e {
            &Val(_) => false,
            _ => true,
          }
        }) {
          args[index] = self.step(args[index].clone())?
        }

        FnCall(f, args)
      },
      FnCall(box e1, args) => {
        FnCall(Box::new(self.step(e1)?), args)
      },
      Scope(box e1) => {
        Scope(Box::new(self.step(e1)?))
      },
      Print(box e1) => {
        Print(Box::new(self.step(e1)?))
      },
    };

    debug!("returning with mem {:?}" , self.state.mem);
    debug!("returning with e {:?}" , e1);
    Ok(e1)
  }

  pub fn eval(&mut self, input: &str) -> Result<Expr> {
    let mut e = parse(input)?;

    let mut num_iterations = 0;

    loop {
      if num_iterations > 1000000000 {
        return Err(RuntimeError::TooManyIterations(num_iterations))
      }

      debug!("-----------------");
      debug!("--- iterating on e {:?} ", e);
      debug!("--- iterating on m {:?} ", self.state.mem);
      num_iterations += 1;
      if e.is_value() {
        debug!("--- iterations: {}", num_iterations);
        return Ok(e.clone());
      } else {
        e = self.step(e.clone())?;
      }
    }
  }
}
<commit_msg>refactor fn call rule again to use more if let goodness<commit_after>use parser::parser::{parse};
use expr::Expr;
use expr::Expr::*;
use expr::Val::*;
use expr::UnOp::*;
use expr::BinOp::*;
use expr::Dec::*;
use state::State;
use runtime_error::RuntimeError;
use std::result;

pub type Result<T> = result::Result<T, RuntimeError>;

pub struct Interpreter {
  pub state: State,
}

impl Interpreter {
  pub fn new() -> Interpreter {
    Interpreter {
      state: State::new(),
    }
  }

  pub fn step(&mut self, e: Expr) -> Result<Expr> {
    debug!("step(e) : {:?}", e);
    debug!("step(self.state) : {:?}", self.state.mem);

    let e1 = match e {
      Var(x) => {
        match self.state.get(x.clone()) {
          Some(e) => e,
          None => return Err(RuntimeError::VariableNotFound(x)),
        }
      },
      /**
       * Values are ineligible for step
       */
      Val(_) => {
        debug!("stepping on a value {:?}", e);
        return Err(RuntimeError::SteppingOnValue(e));
      },
      /**
       * Base cases
       */
      Uop(Not, box Val(Bool(b))) => {
        Val(Bool(!b))
      },
      Uop(Neg, box Val(Int(n))) => {
        Val(Int(-1 * n))
      },
      Bop(And, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 && b2))
      },
      Bop(Or, box Val(Bool(b1)), box Val(Bool(b2))) => {
        Val(Bool(b1 || b2))
      },
      Bop(Eq, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 == v2))
      },
      Bop(Ne, box Val(v1), box Val(v2)) => {
        Val(Bool(v1 != v2))
      },
      Bop(Mod, box Val(Int(n1)), box Val(Int(n2))) => {
        // rust % gives the remainder, not modulus
        // let result = ((n1 % n2) + n2) % n2;
        let result = n1.checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?
          .checked_add(n2)
          .ok_or(RuntimeError::IntegerOverflow)?
          .checked_rem(n2)
          .ok_or(RuntimeError::IntegerUnderflow)?;

        Val(Int(result))
      },
      Bop(Lt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 < n2))
      },
      Bop(Gt, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 > n2))
      },
      Bop(Leq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 <= n2))
      },
      Bop(Geq, box Val(Int(n1)), box Val(Int(n2))) => {
        Val(Bool(n1 >= n2))
      },
      Bop(Plus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_add(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Minus, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_sub(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Times, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_mul(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerOverflow),
        }
      },
      Bop(Div, box Val(Int(n1)), box Val(Int(n2))) => {
        match n1.checked_div(n2) {
          Some(n) => Val(Int(n)),
          None => return Err(RuntimeError::IntegerUnderflow),
        }
      },
      Bop(Seq, box Val(_), box e1) => {
        e1
      },
      Bop(Assign, box Var(x), box v @ Val(_)) => {
        self.state.assign(x, v.clone())?;
        debug!("done assigning {:?}", self.state.mem);
        v
      },
      Ternary(box Val(Bool(b)), box e1, box e2) => {
        match b {
          true => e1,
          false => e2,
        }
      },
      Decl(DConst, box Var(x), box v1 @ Val(_), box e1) => {
        self.state.alloc_const(x, v1)?;
        e1
      },
      Decl(DVar, box Var(x), box v1 @ Val(_), box e1) => {
        debug!("allocing {:?}", v1);
        self.state.alloc(x, v1)?;
        e1
      },
      // lambda lift so we can use iter() in guard
      // https://github.com/rust-lang/rfcs/issues/1006
      FnCall(ref v1, ref es) if v1.is_func() && (|| es.iter().all(|v| v.is_value()))() => {
        if let box Val(Func(name, e1, xs)) = v1.clone() {
          self.state.begin_scope();

          // alloc the params
          for (xn, en) in xs.iter().zip(es.iter()) {
            self.state.alloc(xn.to_var()?, en.clone())?;
          }

          // alloc the fn body for named functions
          if let Some(s) = name {
            self.state.alloc(s.to_var()?, *v1.clone())?;
          }

          Scope(e1)
        } else {
          return Err(RuntimeError::UnexpectedExpr("expected Func".to_string(), *v1.clone()))
        }
      },
      Scope(box v @ Val(_)) => {
        self.state.end_scope();
        v
      },
      While(box Val(Bool(b)), e1o, _, e2o, e3) => {
        match b {
          true => While(e1o.clone(), e1o, e2o.clone(), e2o, e3),
          false => *e3,
        }
      },
      Print(box Val(v)) => {
        println!("{}", v);
        Val(Undefined)
      },
      /**
       * Search Cases
       */
      Bop(op, v1 @ box Val(_), box e2) => {
        Bop(
          op,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(Assign, v1 @ box Var(_), box e2) => {
        Bop(
          Assign,
          v1,
          Box::new(self.step(e2)?)
        )
      },
      Bop(op, box e1, e2) => {
        Bop(op, Box::new(self.step(e1)?), e2)
      },
      Uop(op, box e1) => {
        Uop(op, Box::new(self.step(e1)?))
      },
      Ternary(box e1, e2, e3) => {
        Ternary(Box::new(self.step(e1)?), e2, e3)
      },
      While(box e1, e1o, v @ box Val(_), e2o, e3) => {
        While(Box::new(self.step(e1)?), e1o, v, e2o, e3)
      },
      While(e1, e1o, box e2, e2o, e3) => {
        While(e1, e1o, Box::new(self.step(e2)?), e2o, e3)
      },
      Decl(dt, box addr, box e1, e2) => {
        Decl(dt, Box::new(addr.clone()), Box::new(self.step(e1)?), e2)
      },
      FnCall(f @ box Val(Func(_, _, _)), mut args) => {
        // find the first nonvalue arg and call step() on it
        if let Some(index) = args.iter().position(|e| {
          match e {
            &Val(_) => false,
            _ => true,
          }
        }) {
          args[index] = self.step(args[index].clone())?
        }

        FnCall(f, args)
      },
      FnCall(box e1, args) => {
        FnCall(Box::new(self.step(e1)?), args)
      },
      Scope(box e1) => {
        Scope(Box::new(self.step(e1)?))
      },
      Print(box e1) => {
        Print(Box::new(self.step(e1)?))
      },
    };

    debug!("returning with mem {:?}" , self.state.mem);
    debug!("returning with e {:?}" , e1);
    Ok(e1)
  }

  pub fn eval(&mut self, input: &str) -> Result<Expr> {
    let mut e = parse(input)?;

    let mut num_iterations = 0;

    loop {
      if num_iterations > 1000000000 {
        return Err(RuntimeError::TooManyIterations(num_iterations))
      }

      debug!("-----------------");
      debug!("--- iterating on e {:?} ", e);
      debug!("--- iterating on m {:?} ", self.state.mem);
      num_iterations += 1;
      if e.is_value() {
        debug!("--- iterations: {}", num_iterations);
        return Ok(e.clone());
      } else {
        e = self.step(e.clone())?;
      }
    }
  }
}
<|endoftext|>


<commit_before>use rustc::front;
use rustc::middle::ty;
use rustc_mir::repr::{self as mir, Mir};
use rustc_mir::mir_map::MirMap;
use syntax::attr::AttrMetaMethods;

#[derive(Clone, Debug)]
enum Value {
    Uninit,
    Int(i64),
}

struct Interpreter<'tcx> {
    mir: &'tcx Mir<'tcx>,
    var_vals: Vec<Value>,
    temp_vals: Vec<Value>,
    result: Value,
}

impl<'tcx> Interpreter<'tcx> {
    fn new(mir: &'tcx Mir<'tcx>) -> Self {
        Interpreter {
            mir: mir,
            var_vals: vec![Value::Uninit; mir.var_decls.len()],
            temp_vals: vec![Value::Uninit; mir.temp_decls.len()],
            result: Value::Uninit,
        }
    }

    fn run(&mut self) {
        let start_block = self.mir.basic_block_data(mir::START_BLOCK);

        for stmt in &start_block.statements {
            use rustc_mir::repr::Lvalue::*;
            use rustc_mir::repr::StatementKind::*;

            println!("  {:?}", stmt);
            match stmt.kind {
                Assign(ref lv, ref rv) => {
                    let val = self.eval_rvalue(rv);

                    let spot = match *lv {
                        Var(i) => &mut self.var_vals[i as usize],
                        Temp(i) => &mut self.temp_vals[i as usize],
                        ReturnPointer => &mut self.result,
                        _ => unimplemented!(),
                    };

                    *spot = val;
                }
                Drop(_kind, ref _lv) => { /* TODO */ },
            }
        }

        println!("  {:?}", start_block.terminator);
        println!("=> {:?}", self.result);
    }

    fn eval_rvalue(&mut self, rv: &mir::Rvalue) -> Value {
        use rustc_mir::repr::Rvalue::*;

        match *rv {
            Use(ref op) => self.eval_operand(op),
            BinaryOp(mir::BinOp::Add, ref left, ref right) => {
                let left_val = self.eval_operand(left);
                let right_val = self.eval_operand(right);
                match (left_val, right_val) {
                    (Value::Int(l), Value::Int(r)) => Value::Int(l + r),
                    _ => unimplemented!(),
                }
            }
            _ => unimplemented!(),
        }
    }

    fn eval_operand(&mut self, op: &mir::Operand) -> Value {
        use rustc::middle::const_eval::ConstVal::*;
        use rustc_mir::repr::Lvalue::*;
        use rustc_mir::repr::Operand::*;

        match *op {
            Consume(Var(i)) => self.var_vals[i as usize].clone(),
            Consume(Temp(i)) => self.temp_vals[i as usize].clone(),
            Constant(ref constant) => {
                match constant.literal {
                    mir::Literal::Value { value: Int(n) } => Value::Int(n),
                    _ => unimplemented!(),
                }
            }
            _ => unimplemented!(),
        }
    }
}

pub fn interpret_start_points<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &MirMap<'tcx>) {
    for (&id, mir) in mir_map {
        for attr in tcx.map.attrs(id) {
            if attr.check_name("miri_run") {
                let item = match tcx.map.get(id) {
                    front::map::NodeItem(item) => item,
                    _ => panic!(),
                };
                println!("Interpreting: {}", item.name);
                let mut interpreter = Interpreter::new(mir);
                interpreter.run();
            }
        }
    }
}
<commit_msg>Sort uses.<commit_after>use rustc::front;
use rustc::middle::ty;
use rustc_mir::mir_map::MirMap;
use rustc_mir::repr::{self as mir, Mir};
use syntax::attr::AttrMetaMethods;

#[derive(Clone, Debug)]
enum Value {
    Uninit,
    Int(i64),
}

struct Interpreter<'tcx> {
    mir: &'tcx Mir<'tcx>,
    var_vals: Vec<Value>,
    temp_vals: Vec<Value>,
    result: Value,
}

impl<'tcx> Interpreter<'tcx> {
    fn new(mir: &'tcx Mir<'tcx>) -> Self {
        Interpreter {
            mir: mir,
            var_vals: vec![Value::Uninit; mir.var_decls.len()],
            temp_vals: vec![Value::Uninit; mir.temp_decls.len()],
            result: Value::Uninit,
        }
    }

    fn run(&mut self) {
        let start_block = self.mir.basic_block_data(mir::START_BLOCK);

        for stmt in &start_block.statements {
            use rustc_mir::repr::Lvalue::*;
            use rustc_mir::repr::StatementKind::*;

            println!("  {:?}", stmt);
            match stmt.kind {
                Assign(ref lv, ref rv) => {
                    let val = self.eval_rvalue(rv);

                    let spot = match *lv {
                        Var(i) => &mut self.var_vals[i as usize],
                        Temp(i) => &mut self.temp_vals[i as usize],
                        ReturnPointer => &mut self.result,
                        _ => unimplemented!(),
                    };

                    *spot = val;
                }
                Drop(_kind, ref _lv) => { /* TODO */ },
            }
        }

        println!("  {:?}", start_block.terminator);
        println!("=> {:?}", self.result);
    }

    fn eval_rvalue(&mut self, rv: &mir::Rvalue) -> Value {
        use rustc_mir::repr::Rvalue::*;

        match *rv {
            Use(ref op) => self.eval_operand(op),
            BinaryOp(mir::BinOp::Add, ref left, ref right) => {
                let left_val = self.eval_operand(left);
                let right_val = self.eval_operand(right);
                match (left_val, right_val) {
                    (Value::Int(l), Value::Int(r)) => Value::Int(l + r),
                    _ => unimplemented!(),
                }
            }
            _ => unimplemented!(),
        }
    }

    fn eval_operand(&mut self, op: &mir::Operand) -> Value {
        use rustc::middle::const_eval::ConstVal::*;
        use rustc_mir::repr::Lvalue::*;
        use rustc_mir::repr::Operand::*;

        match *op {
            Consume(Var(i)) => self.var_vals[i as usize].clone(),
            Consume(Temp(i)) => self.temp_vals[i as usize].clone(),
            Constant(ref constant) => {
                match constant.literal {
                    mir::Literal::Value { value: Int(n) } => Value::Int(n),
                    _ => unimplemented!(),
                }
            }
            _ => unimplemented!(),
        }
    }
}

pub fn interpret_start_points<'tcx>(tcx: &ty::ctxt<'tcx>, mir_map: &MirMap<'tcx>) {
    for (&id, mir) in mir_map {
        for attr in tcx.map.attrs(id) {
            if attr.check_name("miri_run") {
                let item = match tcx.map.get(id) {
                    front::map::NodeItem(item) => item,
                    _ => panic!(),
                };
                println!("Interpreting: {}", item.name);
                let mut interpreter = Interpreter::new(mir);
                interpreter.run();
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::noop::NoopConsumer;
use super::{IntoParallelIterator, ParallelExtend, ParallelIterator};

use std::borrow::Cow;
use std::collections::LinkedList;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::{BinaryHeap, VecDeque};
use std::hash::{BuildHasher, Hash};

/// Perform a generic `par_extend` by collecting to a `LinkedList<Vec<_>>` in
/// parallel, then extending the collection sequentially.
fn extend<C, I, F>(collection: &mut C, par_iter: I, reserve: F)
where
    I: IntoParallelIterator,
    F: FnOnce(&mut C, &LinkedList<Vec<I::Item>>),
    C: Extend<I::Item>,
{
    let list = collect(par_iter);
    reserve(collection, &list);
    for vec in list {
        collection.extend(vec);
    }
}

pub(super) fn collect<I>(par_iter: I) -> LinkedList<Vec<I::Item>>
where
    I: IntoParallelIterator,
{
    par_iter
        .into_par_iter()
        .fold(Vec::new, vec_push)
        .map(as_list)
        .reduce(LinkedList::new, list_append)
}

fn vec_push<T>(mut vec: Vec<T>, elem: T) -> Vec<T> {
    vec.push(elem);
    vec
}

fn as_list<T>(item: T) -> LinkedList<T> {
    let mut list = LinkedList::new();
    list.push_back(item);
    list
}

fn list_append<T>(mut list1: LinkedList<T>, mut list2: LinkedList<T>) -> LinkedList<T> {
    list1.append(&mut list2);
    list1
}

/// Compute the total length of a `LinkedList<Vec<_>>`.
pub(super) fn len<T>(list: &LinkedList<Vec<T>>) -> usize {
    list.iter().map(Vec::len).sum()
}

fn no_reserve<C, T>(_: &mut C, _: &LinkedList<Vec<T>>) {}

fn heap_reserve<T: Ord, U>(heap: &mut BinaryHeap<T>, list: &LinkedList<Vec<U>>) {
    heap.reserve(len(list));
}

/// Extend a binary heap with items from a parallel iterator.
impl<T> ParallelExtend<T> for BinaryHeap<T>
where
    T: Ord + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, heap_reserve);
    }
}

/// Extend a binary heap with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for BinaryHeap<T>
where
    T: 'a + Copy + Ord + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, heap_reserve);
    }
}

/// Extend a B-tree map with items from a parallel iterator.
impl<K, V> ParallelExtend<(K, V)> for BTreeMap<K, V>
where
    K: Ord + Send,
    V: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (K, V)>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree map with copied items from a parallel iterator.
impl<'a, K: 'a, V: 'a> ParallelExtend<(&'a K, &'a V)> for BTreeMap<K, V>
where
    K: Copy + Ord + Send + Sync,
    V: Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree set with items from a parallel iterator.
impl<T> ParallelExtend<T> for BTreeSet<T>
where
    T: Ord + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree set with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for BTreeSet<T>
where
    T: 'a + Copy + Ord + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, no_reserve);
    }
}

fn map_reserve<K, V, S, U>(map: &mut HashMap<K, V, S>, list: &LinkedList<Vec<U>>)
where
    K: Eq + Hash,
    S: BuildHasher,
{
    map.reserve(len(list));
}

/// Extend a hash map with items from a parallel iterator.
impl<K, V, S> ParallelExtend<(K, V)> for HashMap<K, V, S>
where
    K: Eq + Hash + Send,
    V: Send,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (K, V)>,
    {
        // See the map_collect benchmarks in rayon-demo for different strategies.
        extend(self, par_iter, map_reserve);
    }
}

/// Extend a hash map with copied items from a parallel iterator.
impl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S>
where
    K: Copy + Eq + Hash + Send + Sync,
    V: Copy + Send + Sync,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
    {
        extend(self, par_iter, map_reserve);
    }
}

fn set_reserve<T, S, U>(set: &mut HashSet<T, S>, list: &LinkedList<Vec<U>>)
where
    T: Eq + Hash,
    S: BuildHasher,
{
    set.reserve(len(list));
}

/// Extend a hash set with items from a parallel iterator.
impl<T, S> ParallelExtend<T> for HashSet<T, S>
where
    T: Eq + Hash + Send,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, set_reserve);
    }
}

/// Extend a hash set with copied items from a parallel iterator.
impl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S>
where
    T: 'a + Copy + Eq + Hash + Send + Sync,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, set_reserve);
    }
}

fn list_push_back<T>(mut list: LinkedList<T>, elem: T) -> LinkedList<T> {
    list.push_back(elem);
    list
}

/// Extend a linked list with items from a parallel iterator.
impl<T> ParallelExtend<T> for LinkedList<T>
where
    T: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        let mut list = par_iter
            .into_par_iter()
            .fold(LinkedList::new, list_push_back)
            .reduce(LinkedList::new, list_append);
        self.append(&mut list);
    }
}

/// Extend a linked list with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for LinkedList<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

fn string_push(mut string: String, ch: char) -> String {
    string.push(ch);
    string
}

/// Extend a string with characters from a parallel iterator.
impl ParallelExtend<char> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = char>,
    {
        // This is like `extend`, but `Vec<char>` is less efficient to deal
        // with than `String`, so instead collect to `LinkedList<String>`.
        let list: LinkedList<_> = par_iter
            .into_par_iter()
            .fold(String::new, string_push)
            .map(as_list)
            .reduce(LinkedList::new, list_append);

        self.reserve(list.iter().map(String::len).sum());
        self.extend(list)
    }
}

/// Extend a string with copied characters from a parallel iterator.
impl<'a> ParallelExtend<&'a char> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a char>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

fn string_reserve<T: AsRef<str>>(string: &mut String, list: &LinkedList<Vec<T>>) {
    let len = list
        .iter()
        .flat_map(|vec| vec)
        .map(T::as_ref)
        .map(str::len)
        .sum();
    string.reserve(len);
}

/// Extend a string with string slices from a parallel iterator.
impl<'a> ParallelExtend<&'a str> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a str>,
    {
        extend(self, par_iter, string_reserve);
    }
}

/// Extend a string with strings from a parallel iterator.
impl ParallelExtend<String> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = String>,
    {
        extend(self, par_iter, string_reserve);
    }
}

/// Extend a string with string slices from a parallel iterator.
impl<'a> ParallelExtend<Cow<'a, str>> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = Cow<'a, str>>,
    {
        extend(self, par_iter, string_reserve);
    }
}

fn deque_reserve<T, U>(deque: &mut VecDeque<T>, list: &LinkedList<Vec<U>>) {
    deque.reserve(len(list));
}

/// Extend a deque with items from a parallel iterator.
impl<T> ParallelExtend<T> for VecDeque<T>
where
    T: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, deque_reserve);
    }
}

/// Extend a deque with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for VecDeque<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, deque_reserve);
    }
}

// See the `collect` module for the `Vec<T>` implementation.
// impl<T> ParallelExtend<T> for Vec<T>

/// Extend a vector with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for Vec<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

/// Collapses all unit items from a parallel iterator into one.
impl ParallelExtend<()> for () {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = ()>,
    {
        par_iter.into_par_iter().drive_unindexed(NoopConsumer)
    }
}
<commit_msg>Fix clippy::flat_map_identity<commit_after>use super::noop::NoopConsumer;
use super::{IntoParallelIterator, ParallelExtend, ParallelIterator};

use std::borrow::Cow;
use std::collections::LinkedList;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::{BinaryHeap, VecDeque};
use std::hash::{BuildHasher, Hash};

/// Perform a generic `par_extend` by collecting to a `LinkedList<Vec<_>>` in
/// parallel, then extending the collection sequentially.
fn extend<C, I, F>(collection: &mut C, par_iter: I, reserve: F)
where
    I: IntoParallelIterator,
    F: FnOnce(&mut C, &LinkedList<Vec<I::Item>>),
    C: Extend<I::Item>,
{
    let list = collect(par_iter);
    reserve(collection, &list);
    for vec in list {
        collection.extend(vec);
    }
}

pub(super) fn collect<I>(par_iter: I) -> LinkedList<Vec<I::Item>>
where
    I: IntoParallelIterator,
{
    par_iter
        .into_par_iter()
        .fold(Vec::new, vec_push)
        .map(as_list)
        .reduce(LinkedList::new, list_append)
}

fn vec_push<T>(mut vec: Vec<T>, elem: T) -> Vec<T> {
    vec.push(elem);
    vec
}

fn as_list<T>(item: T) -> LinkedList<T> {
    let mut list = LinkedList::new();
    list.push_back(item);
    list
}

fn list_append<T>(mut list1: LinkedList<T>, mut list2: LinkedList<T>) -> LinkedList<T> {
    list1.append(&mut list2);
    list1
}

/// Compute the total length of a `LinkedList<Vec<_>>`.
pub(super) fn len<T>(list: &LinkedList<Vec<T>>) -> usize {
    list.iter().map(Vec::len).sum()
}

fn no_reserve<C, T>(_: &mut C, _: &LinkedList<Vec<T>>) {}

fn heap_reserve<T: Ord, U>(heap: &mut BinaryHeap<T>, list: &LinkedList<Vec<U>>) {
    heap.reserve(len(list));
}

/// Extend a binary heap with items from a parallel iterator.
impl<T> ParallelExtend<T> for BinaryHeap<T>
where
    T: Ord + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, heap_reserve);
    }
}

/// Extend a binary heap with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for BinaryHeap<T>
where
    T: 'a + Copy + Ord + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, heap_reserve);
    }
}

/// Extend a B-tree map with items from a parallel iterator.
impl<K, V> ParallelExtend<(K, V)> for BTreeMap<K, V>
where
    K: Ord + Send,
    V: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (K, V)>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree map with copied items from a parallel iterator.
impl<'a, K: 'a, V: 'a> ParallelExtend<(&'a K, &'a V)> for BTreeMap<K, V>
where
    K: Copy + Ord + Send + Sync,
    V: Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree set with items from a parallel iterator.
impl<T> ParallelExtend<T> for BTreeSet<T>
where
    T: Ord + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, no_reserve);
    }
}

/// Extend a B-tree set with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for BTreeSet<T>
where
    T: 'a + Copy + Ord + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, no_reserve);
    }
}

fn map_reserve<K, V, S, U>(map: &mut HashMap<K, V, S>, list: &LinkedList<Vec<U>>)
where
    K: Eq + Hash,
    S: BuildHasher,
{
    map.reserve(len(list));
}

/// Extend a hash map with items from a parallel iterator.
impl<K, V, S> ParallelExtend<(K, V)> for HashMap<K, V, S>
where
    K: Eq + Hash + Send,
    V: Send,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (K, V)>,
    {
        // See the map_collect benchmarks in rayon-demo for different strategies.
        extend(self, par_iter, map_reserve);
    }
}

/// Extend a hash map with copied items from a parallel iterator.
impl<'a, K: 'a, V: 'a, S> ParallelExtend<(&'a K, &'a V)> for HashMap<K, V, S>
where
    K: Copy + Eq + Hash + Send + Sync,
    V: Copy + Send + Sync,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = (&'a K, &'a V)>,
    {
        extend(self, par_iter, map_reserve);
    }
}

fn set_reserve<T, S, U>(set: &mut HashSet<T, S>, list: &LinkedList<Vec<U>>)
where
    T: Eq + Hash,
    S: BuildHasher,
{
    set.reserve(len(list));
}

/// Extend a hash set with items from a parallel iterator.
impl<T, S> ParallelExtend<T> for HashSet<T, S>
where
    T: Eq + Hash + Send,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, set_reserve);
    }
}

/// Extend a hash set with copied items from a parallel iterator.
impl<'a, T, S> ParallelExtend<&'a T> for HashSet<T, S>
where
    T: 'a + Copy + Eq + Hash + Send + Sync,
    S: BuildHasher + Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, set_reserve);
    }
}

fn list_push_back<T>(mut list: LinkedList<T>, elem: T) -> LinkedList<T> {
    list.push_back(elem);
    list
}

/// Extend a linked list with items from a parallel iterator.
impl<T> ParallelExtend<T> for LinkedList<T>
where
    T: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        let mut list = par_iter
            .into_par_iter()
            .fold(LinkedList::new, list_push_back)
            .reduce(LinkedList::new, list_append);
        self.append(&mut list);
    }
}

/// Extend a linked list with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for LinkedList<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

fn string_push(mut string: String, ch: char) -> String {
    string.push(ch);
    string
}

/// Extend a string with characters from a parallel iterator.
impl ParallelExtend<char> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = char>,
    {
        // This is like `extend`, but `Vec<char>` is less efficient to deal
        // with than `String`, so instead collect to `LinkedList<String>`.
        let list: LinkedList<_> = par_iter
            .into_par_iter()
            .fold(String::new, string_push)
            .map(as_list)
            .reduce(LinkedList::new, list_append);

        self.reserve(list.iter().map(String::len).sum());
        self.extend(list)
    }
}

/// Extend a string with copied characters from a parallel iterator.
impl<'a> ParallelExtend<&'a char> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a char>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

fn string_reserve<T: AsRef<str>>(string: &mut String, list: &LinkedList<Vec<T>>) {
    let len = list
        .iter()
        .flatten()
        .map(T::as_ref)
        .map(str::len)
        .sum();
    string.reserve(len);
}

/// Extend a string with string slices from a parallel iterator.
impl<'a> ParallelExtend<&'a str> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a str>,
    {
        extend(self, par_iter, string_reserve);
    }
}

/// Extend a string with strings from a parallel iterator.
impl ParallelExtend<String> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = String>,
    {
        extend(self, par_iter, string_reserve);
    }
}

/// Extend a string with string slices from a parallel iterator.
impl<'a> ParallelExtend<Cow<'a, str>> for String {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = Cow<'a, str>>,
    {
        extend(self, par_iter, string_reserve);
    }
}

fn deque_reserve<T, U>(deque: &mut VecDeque<T>, list: &LinkedList<Vec<U>>) {
    deque.reserve(len(list));
}

/// Extend a deque with items from a parallel iterator.
impl<T> ParallelExtend<T> for VecDeque<T>
where
    T: Send,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = T>,
    {
        extend(self, par_iter, deque_reserve);
    }
}

/// Extend a deque with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for VecDeque<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        extend(self, par_iter, deque_reserve);
    }
}

// See the `collect` module for the `Vec<T>` implementation.
// impl<T> ParallelExtend<T> for Vec<T>

/// Extend a vector with copied items from a parallel iterator.
impl<'a, T> ParallelExtend<&'a T> for Vec<T>
where
    T: 'a + Copy + Send + Sync,
{
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = &'a T>,
    {
        self.par_extend(par_iter.into_par_iter().cloned())
    }
}

/// Collapses all unit items from a parallel iterator into one.
impl ParallelExtend<()> for () {
    fn par_extend<I>(&mut self, par_iter: I)
    where
        I: IntoParallelIterator<Item = ()>,
    {
        par_iter.into_par_iter().drive_unindexed(NoopConsumer)
    }
}
<|endoftext|>


<commit_before>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

use observable::Observable;
use observer::Observer;
use std::marker::PhantomData;

struct MapObserver<T, U, E, O, F>
where O: Observer<U, E>,
      F: Fn(T) -> U {
    observer: O,
    f: F,
    _phantom_t: PhantomData<*mut T>,
    _phantom_u: PhantomData<*mut U>,
    _phantom_e: PhantomData<*mut E>,
}

impl<T, U, E, O, F> Observer<T, E> for MapObserver<T, U, E, O, F>
where T: Clone,
      U: Clone,
      E: Clone,
      O: Observer<U, E>,
      F: Fn(T) -> U {
    fn on_next(&mut self, item: T) {
        self.observer.on_next(self.f.call((item,)));
    }

    fn on_completed(self) {
        self.observer.on_completed();
    }

    fn on_error(self, error: E) {
        self.observer.on_error(error);
    }
}

/// The result of calling `map()` on an observable.
pub struct MapObservable<'a, Source: 'a + ?Sized, F> {
    source: &'a mut Source,
    f: F
}

impl<'a, Source: 'a + ?Sized, F> MapObservable<'a, Source, F> {
    pub fn new(source: &'a mut Source, f: F) -> MapObservable<'a, Source, F> {
        MapObservable {
            source: source,
            f: f,
        }
    }
}

impl<'a, Source, U, F> Observable for MapObservable<'a, Source, F>
where Source: Observable,
      U: Clone,
      F: Fn(<Source as Observable>::Item) -> U {
    type Item = U;
    type Error = <Source as Observable>::Error;
    type Subscription = <Source as Observable>::Subscription;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error> {
        let mapped_observer = MapObserver {
            observer: observer,
            f: &self.f,
            _phantom_t: PhantomData,
            _phantom_u: PhantomData,
            _phantom_e: PhantomData,
        };
        self.source.subscribe(mapped_observer)
    }
}

struct MapErrorObserver<T, E, F, O, G>
where O: Observer<T, F>,
      G: Fn(E) -> F {
    observer: O,
    f: G,
    _phantom_t: PhantomData<*mut T>,
    _phantom_e: PhantomData<*mut E>,
    _phantom_f: PhantomData<*mut F>,
}

impl<T, E, F, O, G> Observer<T, E> for MapErrorObserver<T, E, F, O, G>
where T: Clone,
      E: Clone,
      F: Clone,
      O: Observer<T, F>,
      G: Fn(E) -> F {
    fn on_next(&mut self, item: T) {
        self.observer.on_next(item);
    }

    fn on_completed(self) {
        self.observer.on_completed();
    }

    fn on_error(self, error: E) {
        self.observer.on_error(self.f.call((error,)));
    }
}

/// The result of calling `map_error()` on an observable.
pub struct MapErrorObservable<'a, Source: 'a + ?Sized, G> {
    source: &'a mut Source,
    f: G
}

impl<'a, Source: 'a + ?Sized, G> MapErrorObservable<'a, Source, G> {
    pub fn new(source: &'a mut Source, f: G) -> MapErrorObservable<'a, Source, G> {
        MapErrorObservable {
            source: source,
            f: f,
        }
    }
}

impl<'a, Source, F, G> Observable for MapErrorObservable<'a, Source, G>
where Source: Observable,
      F: Clone,
      // TODO: This can be FnOnce.
      G: Fn(<Source as Observable>::Error) -> F {
    type Item = <Source as Observable>::Item;
    type Error = F;
    type Subscription = <Source as Observable>::Subscription;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error> {
        let mapped_observer = MapErrorObserver {
            observer: observer,
            f: &self.f,
            _phantom_t: PhantomData,
            _phantom_e: PhantomData,
            _phantom_f: PhantomData,
        };
        self.source.subscribe(mapped_observer)
    }
}
<commit_msg>Add note about FnOnce in map_error()<commit_after>// Rx -- Reactive programming for Rust
// Copyright 2016 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

use observable::Observable;
use observer::Observer;
use std::marker::PhantomData;

struct MapObserver<T, U, E, O, F>
where O: Observer<U, E>,
      F: Fn(T) -> U {
    observer: O,
    f: F,
    _phantom_t: PhantomData<*mut T>,
    _phantom_u: PhantomData<*mut U>,
    _phantom_e: PhantomData<*mut E>,
}

impl<T, U, E, O, F> Observer<T, E> for MapObserver<T, U, E, O, F>
where T: Clone,
      U: Clone,
      E: Clone,
      O: Observer<U, E>,
      F: Fn(T) -> U {
    fn on_next(&mut self, item: T) {
        self.observer.on_next(self.f.call((item,)));
    }

    fn on_completed(self) {
        self.observer.on_completed();
    }

    fn on_error(self, error: E) {
        self.observer.on_error(error);
    }
}

/// The result of calling `map()` on an observable.
pub struct MapObservable<'a, Source: 'a + ?Sized, F> {
    source: &'a mut Source,
    f: F
}

impl<'a, Source: 'a + ?Sized, F> MapObservable<'a, Source, F> {
    pub fn new(source: &'a mut Source, f: F) -> MapObservable<'a, Source, F> {
        MapObservable {
            source: source,
            f: f,
        }
    }
}

impl<'a, Source, U, F> Observable for MapObservable<'a, Source, F>
where Source: Observable,
      U: Clone,
      F: Fn(<Source as Observable>::Item) -> U {
    type Item = U;
    type Error = <Source as Observable>::Error;
    type Subscription = <Source as Observable>::Subscription;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error> {
        let mapped_observer = MapObserver {
            observer: observer,
            f: &self.f,
            _phantom_t: PhantomData,
            _phantom_u: PhantomData,
            _phantom_e: PhantomData,
        };
        self.source.subscribe(mapped_observer)
    }
}

struct MapErrorObserver<T, E, F, O, G>
where O: Observer<T, F>,
      G: Fn(E) -> F {
    observer: O,
    f: G,
    _phantom_t: PhantomData<*mut T>,
    _phantom_e: PhantomData<*mut E>,
    _phantom_f: PhantomData<*mut F>,
}

impl<T, E, F, O, G> Observer<T, E> for MapErrorObserver<T, E, F, O, G>
where T: Clone,
      E: Clone,
      F: Clone,
      O: Observer<T, F>,
      G: Fn(E) -> F {
    fn on_next(&mut self, item: T) {
        self.observer.on_next(item);
    }

    fn on_completed(self) {
        self.observer.on_completed();
    }

    fn on_error(self, error: E) {
        self.observer.on_error(self.f.call((error,)));
    }
}

/// The result of calling `map_error()` on an observable.
pub struct MapErrorObservable<'a, Source: 'a + ?Sized, G> {
    source: &'a mut Source,
    f: G
}

impl<'a, Source: 'a + ?Sized, G> MapErrorObservable<'a, Source, G> {
    pub fn new(source: &'a mut Source, f: G) -> MapErrorObservable<'a, Source, G> {
        MapErrorObservable {
            source: source,
            f: f,
        }
    }
}

impl<'a, Source, F, G> Observable for MapErrorObservable<'a, Source, G>
where Source: Observable,
      F: Clone,
      G: Fn(<Source as Observable>::Error) -> F {
    type Item = <Source as Observable>::Item;
    type Error = F;
    type Subscription = <Source as Observable>::Subscription;

    fn subscribe<O>(&mut self, observer: O) -> Self::Subscription
        where O: Observer<Self::Item, Self::Error> {
        // Note that the function `G` cannot be `FnOnce` because every observer
        // receives a copy of it. Alternatively, `map_error` could be
        // implemented with a subject to only call the mapping function once,
        // but that would prevent stream fusion and require memory and a virtual
        // function call.
        let mapped_observer = MapErrorObserver {
            observer: observer,
            f: &self.f,
            _phantom_t: PhantomData,
            _phantom_e: PhantomData,
            _phantom_f: PhantomData,
        };
        self.source.subscribe(mapped_observer)
    }
}
<|endoftext|>


<commit_before>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        r.retain(|e|
                 match e.status().ok().expect("error getting event status") {
                     EventStatus::Complete => false,
                     _ => true,
        });
        println!("buffer {:?} has {} events in its read list", self.id, r.len());
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<commit_msg>reverts debugging code<commit_after>use low_level as ll;
use error::Error;
use event::{Event, EventStatus, EventLike};

use std::sync::Arc;
use std::cell::RefCell;

struct MemEvents {
    last_write: RefCell<Option<Event>>,
    last_read: RefCell<Vec<Event>>,
}

pub struct Mem {
    pub id: ll::Mem,
    events: Arc<MemEvents>,
}

impl Mem {
    pub fn new(id: ll::Mem) -> Mem {
        let events = MemEvents{
            last_write: RefCell::new(None),
            last_read: RefCell::new(Vec::new()),
        };
        Mem{
            id: id,
            events: Arc::new(events),
        }
    }

    pub fn write_events(self: &Self) -> Vec<ll::Event> {
        let mut tr: Vec<ll::Event> = Vec::with_capacity(2);
        if let Some(ref evt) = *self.events.last_write.borrow() {
            tr.push(evt.id);
        }
        tr.extend(self.events.last_read.borrow().iter().map(|e| e.id));
        tr
    }

    pub fn read_events(self: &Self) -> Vec<ll::Event> {
        if let Some(ref evt) = *self.events.last_write.borrow() {
            vec!(evt.id)
        } else {
            vec!()
        }
    }

    pub fn register_write(self: &mut Self, evt: Event) -> () {
        *self.events.last_write.borrow_mut() = Some(evt);
    }

    pub fn register_read(self: &Self, evt: Event) -> () {
        let mut r = self.events.last_read.borrow_mut();
        r.retain(|e|
                 match e.status().ok().expect("error getting event status") {
                     EventStatus::Complete => false,
                     _ => true,
        });
        r.push(evt);
    }
}

impl Drop for Mem {
    fn drop(self: &mut Self) -> () {
        unsafe {
            Error::check(ll::clReleaseMemObject(self.id))
                .ok().expect("error releasing mem object");
        }
    }
}

impl Clone for Mem {
    fn clone(self: &Self) -> Self {
        unsafe {
            Error::check(ll::clRetainMemObject(self.id))
                .ok().expect("error retaining mem object");
        }
        Mem{ id: self.id, events: self.events.clone() }
    }
}

<|endoftext|>


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

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `as_ref` methods, to test if the contained value is of a given type, and to
//! get a reference to the inner value as a type. As`&mut Any`, there is also
//! the `as_mut` method, for getting a mutable reference to the inner value.
//! `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the
//! object.  See the extension traits (`*Ext`) for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use marker::Send;
use mem::transmute;
use option::Option::{self, Some, None};
use raw::TraitObject;
use intrinsics;
use marker::{Reflect, Sized};

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Every type with no non-`'static` references implements `Any`.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: Reflect + 'static {
    /// Gets the `TypeId` of `self`.
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static")]
    fn get_type_id(&self) -> TypeId;
}

impl<T: Reflect + 'static> Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<commit_msg>Auto merge of #26725 - tshepang:patch-2, r=bluss<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `as_ref` methods, to test if the contained value is of a given type, and to
//! get a reference to the inner value as a type. As `&mut Any`, there is also
//! the `as_mut` method, for getting a mutable reference to the inner value.
//! `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the
//! object.  See the extension traits (`*Ext`) for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use marker::Send;
use mem::transmute;
use option::Option::{self, Some, None};
use raw::TraitObject;
use intrinsics;
use marker::{Reflect, Sized};

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Every type with no non-`'static` references implements `Any`.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: Reflect + 'static {
    /// Gets the `TypeId` of `self`.
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static")]
    fn get_type_id(&self) -> TypeId;
}

impl<T: Reflect + 'static> Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute(self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<|endoftext|>


<commit_before>#[doc = "Misc low level stuff"];

export type_desc;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;

enum type_desc = {
    first_param: **libc::c_int,
    size: libc::size_t,
    align: libc::size_t
    // Remaining fields not listed
};

#[abi = "cdecl"]
native mod rustrt {
    fn refcount(t: *()) -> libc::intptr_t;
    fn unsupervise();
    fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

#[doc = "
Returns a pointer to a type descriptor.

Useful for calling certain function in the Rust runtime or otherwise
performing dark magick.
"]
fn get_type_desc<T>() -> *type_desc {
    rusti::get_tydesc::<T>() as *type_desc
}

#[doc = "Returns the size of a type"]
fn size_of<T>() -> uint unsafe {
    rusti::size_of::<T>()
}

#[doc = "
Returns the ABI-required minimum alignment of a type

This is the alignment used for struct fields. It may be smaller
than the preferred alignment.
"]
fn min_align_of<T>() -> uint unsafe {
    rusti::min_align_of::<T>()
}

#[doc = "Returns the preferred alignment of a type"]
fn pref_align_of<T>() -> uint unsafe {
    rusti::pref_align_of::<T>()
}

#[doc = "Returns the refcount of a shared box"]
fn refcount<T>(t: @T) -> uint {
    unsafe {
        ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint;
    }
}

fn log_str<T>(t: T) -> str {
    unsafe {
        let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
        rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>add misc. pure modifiers in core<commit_after>#[doc = "Misc low level stuff"];

export type_desc;
export get_type_desc;
export size_of;
export min_align_of;
export pref_align_of;
export refcount;
export log_str;

enum type_desc = {
    first_param: **libc::c_int,
    size: libc::size_t,
    align: libc::size_t
    // Remaining fields not listed
};

#[abi = "cdecl"]
native mod rustrt {
    pure fn refcount(t: *()) -> libc::intptr_t;
    fn unsupervise();
    pure fn shape_log_str(t: *sys::type_desc, data: *()) -> str;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn get_tydesc<T>() -> *();
    fn size_of<T>() -> uint;
    fn pref_align_of<T>() -> uint;
    fn min_align_of<T>() -> uint;
}

#[doc = "
Returns a pointer to a type descriptor.

Useful for calling certain function in the Rust runtime or otherwise
performing dark magick.
"]
pure fn get_type_desc<T>() -> *type_desc {
    unchecked { rusti::get_tydesc::<T>() as *type_desc }
}

#[doc = "Returns the size of a type"]
pure fn size_of<T>() -> uint unsafe {
    unchecked { rusti::size_of::<T>() }
}

#[doc = "
Returns the ABI-required minimum alignment of a type

This is the alignment used for struct fields. It may be smaller
than the preferred alignment.
"]
pure fn min_align_of<T>() -> uint unsafe {
    unchecked { rusti::min_align_of::<T>() }
}

#[doc = "Returns the preferred alignment of a type"]
pure fn pref_align_of<T>() -> uint unsafe {
    unchecked { rusti::pref_align_of::<T>() }
}

#[doc = "Returns the refcount of a shared box"]
pure fn refcount<T>(t: @T) -> uint {
    unsafe {
        ret rustrt::refcount(unsafe::reinterpret_cast(t)) as uint;
    }
}

pure fn log_str<T>(t: T) -> str {
    unsafe {
        let data_ptr: *() = unsafe::reinterpret_cast(ptr::addr_of(t));
        rustrt::shape_log_str(get_type_desc::<T>(), data_ptr)
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn size_of_basic() {
        assert size_of::<u8>() == 1u;
        assert size_of::<u16>() == 2u;
        assert size_of::<u32>() == 4u;
        assert size_of::<u64>() == 8u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn size_of_32() {
        assert size_of::<uint>() == 4u;
        assert size_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn size_of_64() {
        assert size_of::<uint>() == 8u;
        assert size_of::<*uint>() == 8u;
    }

    #[test]
    fn align_of_basic() {
        assert pref_align_of::<u8>() == 1u;
        assert pref_align_of::<u16>() == 2u;
        assert pref_align_of::<u32>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86")]
    #[cfg(target_arch = "arm")]
    fn align_of_32() {
        assert pref_align_of::<uint>() == 4u;
        assert pref_align_of::<*uint>() == 4u;
    }

    #[test]
    #[cfg(target_arch = "x86_64")]
    fn align_of_64() {
        assert pref_align_of::<uint>() == 8u;
        assert pref_align_of::<*uint>() == 8u;
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


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

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};

use default::Default;
use rand::Rng;
use rand;

/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
/// initialized with random keys.
#[deriving(Clone)]
pub struct RandomSipHasher {
    hasher: sip::SipHasher,
}

impl RandomSipHasher {
    /// Construct a new `RandomSipHasher` that is initialized with random keys.
    #[inline]
    pub fn new() -> RandomSipHasher {
        let mut r = rand::task_rng();
        let r0 = r.gen();
        let r1 = r.gen();
        RandomSipHasher {
            hasher: sip::SipHasher::new_with_keys(r0, r1),
        }
    }
}

impl Hasher<sip::SipState> for RandomSipHasher {
    #[inline]
    fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
        self.hasher.hash(value)
    }
}

impl Default for RandomSipHasher {
    #[inline]
    fn default() -> RandomSipHasher {
        RandomSipHasher::new()
    }
}
<commit_msg>mark std::hash experimental<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: String,
 *     phone: u64,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

#![experimental]

pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};

use default::Default;
use rand::Rng;
use rand;

/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
/// initialized with random keys.
#[deriving(Clone)]
pub struct RandomSipHasher {
    hasher: sip::SipHasher,
}

impl RandomSipHasher {
    /// Construct a new `RandomSipHasher` that is initialized with random keys.
    #[inline]
    pub fn new() -> RandomSipHasher {
        let mut r = rand::task_rng();
        let r0 = r.gen();
        let r1 = r.gen();
        RandomSipHasher {
            hasher: sip::SipHasher::new_with_keys(r0, r1),
        }
    }
}

impl Hasher<sip::SipState> for RandomSipHasher {
    #[inline]
    fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
        self.hasher.hash(value)
    }
}

impl Default for RandomSipHasher {
    #[inline]
    fn default() -> RandomSipHasher {
        RandomSipHasher::new()
    }
}
<|endoftext|>


<commit_before>//! Rust 版管理人形

// TODO: 最終的には外すこと
#![allow(dead_code)]
#![allow(unused_variables)]

mod sys;
mod sysmod;

extern crate getopts;
#[macro_use] extern crate log;
extern crate simplelog;
extern crate daemonize;
extern crate chrono;

use std::{env, fs};
use std::fs::{File, OpenOptions};
use std::os::unix::fs::OpenOptionsExt;
use std::io::Write;
use getopts::Options;
use simplelog::*;
use daemonize::Daemonize;
use sys::taskserver::{TaskServer, Control};
use sysmod::SystemModules;

/// デーモン化の際に指定する stdout のリダイレクト先。
const STDOUT_FILE: &str = "stdout.txt";
/// デーモン化の際に指定する stderr のリダイレクト先。
const STDERR_FILE: &str = "stderr.txt";
/// デーモン化の際に指定する pid ファイルパス。
const PID_FILE: &str = "rshanghai.pid";
/// ログのファイル出力先。
const LOG_FILE: &str = "rshanghai.log";

/// デフォルトの設定データ(json source)。
/// [include_str!] でバイナリに含める。
const DEF_CONFIG_JSON: &str = include_str!("res/config_default.json");
const CONFIG_FILE: &str = "config.json";
const CONFIG_DEF_FILE: &str = "config_default.json";

/// stdout, stderr をリダイレクトし、デーモン化する。
///
/// ファイルオープンに失敗したら exit(1) する。
/// デーモン化に失敗したら exit(1) する。
/// 成功した場合は元の親プロセスは正常終了し、子プロセスが以降の処理を続行する。
fn daemon() {
    let stdout = match File::create(STDOUT_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDOUT_FILE, e);
            std::process::exit(1);
        }
    };
    let stderr = match File::create(STDERR_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDERR_FILE, e);
            std::process::exit(1);
        }
    };

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        .stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

/// ロギングシステムを有効化する。
///
/// デーモンならファイルへの書き出しのみ、
/// そうでないならファイルと stdout へ書き出す。
///
/// ログレベルは Error, Warn, Info, Debug, Trace の5段階である。
/// ファイルへは Info 以上、stdout へは Trace 以上のログが出力される。
///
/// * `is_daemon` - デーモンかどうか。
fn init_log(is_daemon: bool) {
    let config = ConfigBuilder::new()
        .set_time_format_custom(format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"))
        .build();
    let file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(LOG_FILE)
        .unwrap();

    // filter = Off, Error, Warn, Info, Debug, Trace
    let loggers: Vec<Box<dyn SharedLogger>> = if is_daemon {
        vec![
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    }
    else {
        vec![
            TermLogger::new(LevelFilter::Trace, config.clone(), TerminalMode::Stdout, ColorChoice::Never),
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    };
    CombinedLogger::init(loggers).unwrap();
}

async fn test_task(ctrl: Control) {
    info!("task1");
    ctrl.spawn_oneshot_task("task1-1", test_task_sub);
}

async fn test_task_sub(_ctrl: Control) {
    info!("task1-1");
}

/// 設定データをロードする。
fn load_config() -> Result<(), String> {
    {
        info!("Remove {}", CONFIG_DEF_FILE);
        if let Err(e) = fs::remove_file(CONFIG_DEF_FILE) {
            warn!("Removing {} failed (the first time execution?): {}",
                CONFIG_DEF_FILE, e);
        }

        info!("Writing default config to {}", CONFIG_DEF_FILE);
        let f = fs::OpenOptions::new()
            .write(true)
            .create_new(true)
            .mode(0o600)
            .open(CONFIG_DEF_FILE);
        let mut f = match f {
            Ok(f) => f,
            Err(e) => {
                error!("Writing {} failed: {}", CONFIG_DEF_FILE, e);
                return Err(e.to_string())
            },
        };
        f.write_all(DEF_CONFIG_JSON.as_bytes()).unwrap();
        info!("OK: written to {}", CONFIG_DEF_FILE);
        // close
    }
    let json_str;
    {
        info!("Loading config: {}", CONFIG_FILE);
        json_str = match std::fs::read_to_string(CONFIG_FILE) {
            Ok(str) => str,
            Err(e) => {
                error!("Loading {} failed: {}", CONFIG_FILE, e);
                info!("HINT: Create {} and try again", CONFIG_FILE);
                return Err(e.to_string())
            }
        };
        info!("OK: {} loaded", CONFIG_FILE);
    }
    sys::config::init_and_load(DEF_CONFIG_JSON, &json_str)?;

    Ok(())
}

/// システムメイン処理。
/// コマンドラインとデーモン化、ログの初期化の後に入る。
///
/// 設定データをロードする。
/// その後、システムモジュールとタスクサーバを初期化し、システムの実行を開始する。
fn system_main() {
    load_config().expect("Load config failed");
    {
        let sysmods = SystemModules::new();
        let ts = TaskServer::new(sysmods);

        ts.sysmod_start();
        ts.spawn_oneshot_task("task1", test_task);
        ts.run();
    }
    info!("task server dropped")
}

/// コマンドラインのヘルプを表示する。
///
/// * `program` - プログラム名 (argv\[0\])。
/// * `opts` - パーサオブジェクト。
fn print_help(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

/// エントリポイント。
///
/// コマンドラインとデーモン化、ログの初期化処理をしたのち、[system_main] を呼ぶ。
fn main() {
    // コマンドライン引数のパース
    let args: Vec<String> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optflag("d", "daemon", "Run as daemon");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(fail) => {
            eprintln!("{}", fail);
            std::process::exit(1);
        }
    };

    // --help がある場合は出力して終了
    if matches.opt_present("h") {
        print_help(program, opts);
        std::process::exit(0);
    }

    if matches.opt_present("d") {
        daemon();
        init_log(true);
    }
    else {
        init_log(false);
    }

    system_main();
}
<commit_msg>設定ファイルロード時にパーミッションをチェックする<commit_after>//! Rust 版管理人形

// TODO: 最終的には外すこと
#![allow(dead_code)]
#![allow(unused_variables)]

mod sys;
mod sysmod;

extern crate getopts;
#[macro_use] extern crate log;
extern crate simplelog;
extern crate daemonize;
extern crate chrono;

use std::env;
use std::fs::{remove_file, File, OpenOptions};
use std::os::unix::fs::{OpenOptionsExt, PermissionsExt};
use std::io::{Write, Read};
use getopts::Options;
use simplelog::*;
use daemonize::Daemonize;
use sys::taskserver::{TaskServer, Control};
use sysmod::SystemModules;

/// デーモン化の際に指定する stdout のリダイレクト先。
const STDOUT_FILE: &str = "stdout.txt";
/// デーモン化の際に指定する stderr のリダイレクト先。
const STDERR_FILE: &str = "stderr.txt";
/// デーモン化の際に指定する pid ファイルパス。
const PID_FILE: &str = "rshanghai.pid";
/// ログのファイル出力先。
const LOG_FILE: &str = "rshanghai.log";

/// デフォルトの設定データ(json source)。
/// [include_str!] でバイナリに含める。
const DEF_CONFIG_JSON: &str = include_str!("res/config_default.json");
const CONFIG_FILE: &str = "config.json";
const CONFIG_DEF_FILE: &str = "config_default.json";

/// stdout, stderr をリダイレクトし、デーモン化する。
///
/// ファイルオープンに失敗したら exit(1) する。
/// デーモン化に失敗したら exit(1) する。
/// 成功した場合は元の親プロセスは正常終了し、子プロセスが以降の処理を続行する。
fn daemon() {
    let stdout = match File::create(STDOUT_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDOUT_FILE, e);
            std::process::exit(1);
        }
    };
    let stderr = match File::create(STDERR_FILE) {
        Ok(f) => f,
        Err(e) => {
            eprintln!("Open {} error: {}", STDERR_FILE, e);
            std::process::exit(1);
        }
    };

    let daemonize = Daemonize::new()
        .pid_file(PID_FILE)
        //.chown_pid_file(true)
        .working_directory(".")
        //.user("nobody")
        //.group("daemon")
        .stdout(stdout)
        .stderr(stderr);

    if let Err(e) = daemonize.start() {
        eprintln!("Daemonize error: {}", e);
        std::process::exit(1);
    }
}

/// ロギングシステムを有効化する。
///
/// デーモンならファイルへの書き出しのみ、
/// そうでないならファイルと stdout へ書き出す。
///
/// ログレベルは Error, Warn, Info, Debug, Trace の5段階である。
/// ファイルへは Info 以上、stdout へは Trace 以上のログが出力される。
///
/// * `is_daemon` - デーモンかどうか。
fn init_log(is_daemon: bool) {
    let config = ConfigBuilder::new()
        .set_time_format_custom(format_description!("[year]-[month]-[day] [hour]:[minute]:[second]"))
        .build();
    let file = OpenOptions::new()
        .append(true)
        .create(true)
        .open(LOG_FILE)
        .unwrap();

    // filter = Off, Error, Warn, Info, Debug, Trace
    let loggers: Vec<Box<dyn SharedLogger>> = if is_daemon {
        vec![
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    }
    else {
        vec![
            TermLogger::new(LevelFilter::Trace, config.clone(), TerminalMode::Stdout, ColorChoice::Never),
            WriteLogger::new(LevelFilter::Info, config, file),
        ]
    };
    CombinedLogger::init(loggers).unwrap();
}

async fn test_task(ctrl: Control) {
    info!("task1");
    ctrl.spawn_oneshot_task("task1-1", test_task_sub);
}

async fn test_task_sub(_ctrl: Control) {
    info!("task1-1");
}

/// 設定データをロードする。
fn load_config() -> Result<(), ()> {
    {
        // デフォルト設定ファイルを削除する
        info!("Remove {}", CONFIG_DEF_FILE);
        if let Err(e) = remove_file(CONFIG_DEF_FILE) {
            warn!("Removing {} failed (the first time execution?): {}",
                CONFIG_DEF_FILE, e);
        }
        // デフォルト設定を書き出す
        // 600 でアトミックに必ず新規作成する、失敗したらエラー
        info!("Writing default config to {}", CONFIG_DEF_FILE);
        let f = OpenOptions::new()
            .write(true)
            .create_new(true)
            .mode(0o600)
            .open(CONFIG_DEF_FILE);
        let mut f = match f {
            Ok(f) => f,
            Err(e) => {
                error!("Writing {} failed: {}", CONFIG_DEF_FILE, e);
                return Err(())
            },
        };
        f.write_all(DEF_CONFIG_JSON.as_bytes()).unwrap();
        info!("OK: written to {}", CONFIG_DEF_FILE);
        // close
    }

    let mut json_str = String::new();
    {
        // 設定ファイルを読む
        // open 後パーミッションを確認し、危険ならエラーとする
        info!("Loading config: {}", CONFIG_FILE);
        let f = OpenOptions::new()
            .read(true)
            .open(CONFIG_FILE);
        let mut f = match f {
            Ok(f) => f,
            Err(e) => {
                error!("Opening {} failed: {}", CONFIG_FILE, e);
                info!("HINT: Create {} and try again", CONFIG_FILE);
                return Err(())
            },
        };
        let metadata = f.metadata().expect("Cannot get metadata");
        let permissions = metadata.permissions();
        if permissions.mode() != 600 {
            error!("Config file permission is not 600");
            return Err(());
        }
        if let Err(e) = f.read_to_string(&mut json_str) {
            error!("Read error: {}", e.to_string());
            return Err(());
        }
        info!("OK: {} loaded", CONFIG_FILE);
        // close
    }
    // json パースして設定システムを初期化
    if let Err(msg) = sys::config::init_and_load(
        DEF_CONFIG_JSON, &json_str)
    {
        error!("Config load failed: {}", msg);
        return Err(());
    }

    Ok(())
}

/// システムメイン処理。
/// コマンドラインとデーモン化、ログの初期化の後に入る。
///
/// 設定データをロードする。
/// その後、システムモジュールとタスクサーバを初期化し、システムの実行を開始する。
fn system_main() {
    load_config().expect("Load config failed");
    {
        let sysmods = SystemModules::new();
        let ts = TaskServer::new(sysmods);

        ts.sysmod_start();
        ts.spawn_oneshot_task("task1", test_task);
        ts.run();
    }
    info!("task server dropped")
}

/// コマンドラインのヘルプを表示する。
///
/// * `program` - プログラム名 (argv\[0\])。
/// * `opts` - パーサオブジェクト。
fn print_help(program: &str, opts: Options) {
    let brief = format!("Usage: {} [options]", program);
    print!("{}", opts.usage(&brief));
}

/// エントリポイント。
///
/// コマンドラインとデーモン化、ログの初期化処理をしたのち、[system_main] を呼ぶ。
fn main() {
    // コマンドライン引数のパース
    let args: Vec<String> = env::args().collect();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "Print this help");
    opts.optflag("d", "daemon", "Run as daemon");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(fail) => {
            eprintln!("{}", fail);
            std::process::exit(1);
        }
    };

    // --help がある場合は出力して終了
    if matches.opt_present("h") {
        print_help(program, opts);
        std::process::exit(0);
    }

    if matches.opt_present("d") {
        daemon();
        init_log(true);
    }
    else {
        init_log(false);
    }

    system_main();
}
<|endoftext|>


<commit_before>extern crate regex;
use self::regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::convert::AsRef;
use std::path::Path;
use std::io::Error;
use std::process::Command;

pub struct LsbRelease {
    pub distro: Option<String>,
    pub version: Option<String>
}

pub fn retrieve() -> Option<LsbRelease> {
    let output = match Command::new("lsb_release").arg("-a").output() {
        Ok(o)  => o,
        Err(_) =>return None
    };
    let stdout = String::from_utf8_lossy(&output.stdout);
    Some(parse(stdout.to_string()))
}

pub fn is_available() -> bool {
    match Command::new("lsb_release").output() {
        Ok(_) => true,
        Err(_) => false
    }
}

pub fn parse(file: String) -> LsbRelease {
    let distrib_regex = Regex::new(r"Distributor ID:\s(\w+)").unwrap();
    let distrib_release_regex = Regex::new(r"Release:\s([\w\.]+)").unwrap();

    let distro = match distrib_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(distro) => {
                    Some(distro.to_string())
                },
                None => None
            }
        },
        None => None
    };

    let version = match distrib_release_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(version) => Some(version.to_string()),
                None => None
            }
        },
        None => None
    };

    LsbRelease {
        distro: distro,
        version: version
    }
}
<commit_msg>remove unused fs and io imports<commit_after>extern crate regex;
use self::regex::Regex;
use std::process::Command;

pub struct LsbRelease {
    pub distro: Option<String>,
    pub version: Option<String>
}

pub fn retrieve() -> Option<LsbRelease> {
    let output = match Command::new("lsb_release").arg("-a").output() {
        Ok(o)  => o,
        Err(_) =>return None
    };
    let stdout = String::from_utf8_lossy(&output.stdout);
    Some(parse(stdout.to_string()))
}

pub fn is_available() -> bool {
    match Command::new("lsb_release").output() {
        Ok(_) => true,
        Err(_) => false
    }
}

pub fn parse(file: String) -> LsbRelease {
    let distrib_regex = Regex::new(r"Distributor ID:\s(\w+)").unwrap();
    let distrib_release_regex = Regex::new(r"Release:\s([\w\.]+)").unwrap();

    let distro = match distrib_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(distro) => {
                    Some(distro.to_string())
                },
                None => None
            }
        },
        None => None
    };

    let version = match distrib_release_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(version) => Some(version.to_string()),
                None => None
            }
        },
        None => None
    };

    LsbRelease {
        distro: distro,
        version: version
    }
}
<|endoftext|>