<commit_before>use ast::AST;
use env::CellEnv;
use memory::Memory;
use values::{Value, RcValue, ArgumentsType};
use runtime::Error;
use eval::{eval, eval_sequence};

pub fn quote(list: &[AST], mem: &mut Memory) -> Result<RcValue, Error> {
    let value = Value::from_ast(&list[0], mem);

    match *value {
        Value::Bool(b) =>
            Ok(mem.boolean(b)),
        Value::Nil =>
            Ok(mem.nil()),
        _ =>
            Ok(value.clone()),
    }
}

pub fn and(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let mut last = mem.b_true();

    for val in args.iter() {
        let val = try!(eval(val, env.clone(), mem));

        if val == mem.b_false() {
            return Ok(val)
        }

        last = val;
    }

    Ok(last)
}

pub fn or(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let mut last = mem.b_false();

    for val in args.iter() {
        let val = try!(eval(val, env.clone(), mem));

        if val != mem.b_false() {
            return Ok(val)
        }

        last = val;
    }

    Ok(last)
}

pub fn if_(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 1 || args.len() > 3 {
        return Err(Error::BadArity(Some("if".to_string())))
    }

    let condition = try!(eval(&args[0], env.clone(), mem));

    let result = if condition != mem.b_false() {
        try!(eval(&args[1], env.clone(), mem))
    } else {
        if args.len() == 2 {
            mem.b_false()
        } else {
            try!(eval(&args[2], env.clone(), mem))
        }
    };

    Ok(result)
}

pub fn define(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 1 {
        return Err(Error::BadArity(Some("define".to_string())))
    }

    match args[0] {
        AST::Atom(ref name) => {
            let body = if args.len() == 1 { None } else { Some(&args[1]) };
            define_variable(name, body, env, mem)
        }
        AST::List(ref list) if list.len() > 0 => {
            let body = args.tail().to_vec();
            define_procedure(list.as_slice(), &body, env, mem)
        }
        AST::DottedList(ref list, ref extra) => {
            let body = args.tail().to_vec();
            define_procedure_var(list.as_slice(), &**extra, &body, env, mem)
        }
        _ =>
            Err(Error::MalformedExpression),
    }
}

pub fn lambda(list: &[AST], name: Option<String>, closure: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if list.len() < 2 {
        return Err(Error::BadArity(Some("lambda".to_string())));
    }

    let args = list.first().unwrap();
    let body = list.tail().to_vec();
    create_fn(args, &body, name, closure, mem)
}

pub fn set(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("set!".to_string())));
    }

    let variable_name = try!(atom_or_error(&args[0], mem));
    let expr = try!(eval(&args[1], env.clone(), mem));

    match env.replace(variable_name.clone(), expr.clone()) {
        Some(expr) => Ok(expr),
        None       => Err(Error::UnboundVariable(variable_name)),
    }
}

pub fn let_(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 2 {
        return Err(Error::BadArity(Some("let".to_string())));
    }

    let inner_env = CellEnv::wraps(env.clone());

    if let &AST::List(ref bindings) = args.first().unwrap() {
        for binding in bindings.iter() {
            match binding {
                &AST::List(ref binding) if binding.len() == 2 => {
                    let name = try!(atom_or_error(&binding[0], mem));
                    let expr = try!(eval(&binding[1], env.clone(), mem));
                    inner_env.set(name, expr);
                }
                _ =>
                    return Err(Error::MalformedExpression)
            }
        }
    } else {
        return Err(Error::MalformedExpression);
    };

    let body = args.tail();
    eval_sequence(body, inner_env, mem)
}

fn define_variable(name: &String, body: Option<&AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if body.is_none() {
        return Ok(mem.intern(name.clone()));
    }

    let value = match body.unwrap() {
        &AST::List(ref list) if list[0] == AST::Atom("lambda".to_string()) =>
            try!(lambda(list.tail(), Some(name.clone()), env.clone(), mem)),
        value =>
            try!(eval(value, env.clone(), mem))
    };

    env.set(name.clone(), value.clone());

    Ok(value)
}

fn define_procedure(args: &[AST], body: &Vec<AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let procedure_name = try!(atom_or_error(&args[0], mem));

    let args = AST::List(args.tail().to_vec());
    let procedure = try!(create_fn(&args, body, Some(procedure_name.clone()), env.clone(), mem));
    env.set(procedure_name.clone(), procedure);

    Ok(mem.intern(procedure_name))
}

fn define_procedure_var(args: &[AST], extra_arg: &AST, body: &Vec<AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let procedure_name = try!(atom_or_error(&args[0], mem));

    let procedure = if args.len() == 1 {
        try!(create_fn(extra_arg, body, Some(procedure_name.clone()), env.clone(), mem))
    } else {
        let args = AST::DottedList(args.tail().to_vec(), Box::new(extra_arg.clone()));
        try!(create_fn(&args, body, Some(procedure_name.clone()), env.clone(), mem))
    };
    env.set(procedure_name.clone(), procedure);

    Ok(mem.intern(procedure_name))
}

fn create_fn(args: &AST, body: &Vec<AST>, name: Option<String>, closure: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    match args {
        &AST::List(ref list) => {
            let args_list = try!(compose_args_list(list.as_slice(), None, mem));
            Ok(mem.lambda(name, ArgumentsType::Fixed, args_list, closure, body.clone()))
        },
        &AST::DottedList(ref list, ref extra) => {
            let args_list = try!(compose_args_list(list.as_slice(), Some(&**extra), mem));
            Ok(mem.lambda(name, ArgumentsType::Variable, args_list, closure, body.clone()))
        }
        &AST::Atom(ref atom) =>
            Ok(mem.lambda(name, ArgumentsType::Any, vec!(atom.clone()), closure, body.clone())),
        _ => {
            let value = Value::from_ast(args, mem);
            Err(Error::WrongArgumentType(value))
        }
    }
}

fn compose_args_list(args: &[AST], extra: Option<&AST>, mem: &mut Memory) -> Result<Vec<String>, Error> {
    let length = args.len() + if extra.is_some() { 1 } else { 0 };
    let mut list = Vec::with_capacity(length);

    for arg in args.iter() {
        let arg = try!(atom_or_error(arg, mem));
        list.push(arg);
    }

    if extra.is_some() {
        let arg = try!(atom_or_error(extra.unwrap(), mem));
        list.push(arg);
    }

    Ok(list)
}

fn atom_or_error(value: &AST, mem: &mut Memory) -> Result<String, Error> {
    if let &AST::Atom(ref atom) = value {
        Ok(atom.to_string())
    } else {
        let value = Value::from_ast(value, mem);
        Err(Error::WrongArgumentType(value))
    }
}
<commit_msg>Simplified quoting primitive.<commit_after>use ast::AST;
use env::CellEnv;
use memory::Memory;
use values::{Value, RcValue, ArgumentsType};
use runtime::Error;
use eval::{eval, eval_sequence};

pub fn quote(list: &[AST], mem: &mut Memory) -> Result<RcValue, Error> {
    Ok(Value::from_ast(&list[0], mem))
}

pub fn and(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let mut last = mem.b_true();

    for val in args.iter() {
        let val = try!(eval(val, env.clone(), mem));

        if val == mem.b_false() {
            return Ok(val)
        }

        last = val;
    }

    Ok(last)
}

pub fn or(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let mut last = mem.b_false();

    for val in args.iter() {
        let val = try!(eval(val, env.clone(), mem));

        if val != mem.b_false() {
            return Ok(val)
        }

        last = val;
    }

    Ok(last)
}

pub fn if_(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 1 || args.len() > 3 {
        return Err(Error::BadArity(Some("if".to_string())))
    }

    let condition = try!(eval(&args[0], env.clone(), mem));

    let result = if condition != mem.b_false() {
        try!(eval(&args[1], env.clone(), mem))
    } else {
        if args.len() == 2 {
            mem.b_false()
        } else {
            try!(eval(&args[2], env.clone(), mem))
        }
    };

    Ok(result)
}

pub fn define(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 1 {
        return Err(Error::BadArity(Some("define".to_string())))
    }

    match args[0] {
        AST::Atom(ref name) => {
            let body = if args.len() == 1 { None } else { Some(&args[1]) };
            define_variable(name, body, env, mem)
        }
        AST::List(ref list) if list.len() > 0 => {
            let body = args.tail().to_vec();
            define_procedure(list.as_slice(), &body, env, mem)
        }
        AST::DottedList(ref list, ref extra) => {
            let body = args.tail().to_vec();
            define_procedure_var(list.as_slice(), &**extra, &body, env, mem)
        }
        _ =>
            Err(Error::MalformedExpression),
    }
}

pub fn lambda(list: &[AST], name: Option<String>, closure: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if list.len() < 2 {
        return Err(Error::BadArity(Some("lambda".to_string())));
    }

    let args = list.first().unwrap();
    let body = list.tail().to_vec();
    create_fn(args, &body, name, closure, mem)
}

pub fn set(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() != 2 {
        return Err(Error::BadArity(Some("set!".to_string())));
    }

    let variable_name = try!(atom_or_error(&args[0], mem));
    let expr = try!(eval(&args[1], env.clone(), mem));

    match env.replace(variable_name.clone(), expr.clone()) {
        Some(expr) => Ok(expr),
        None       => Err(Error::UnboundVariable(variable_name)),
    }
}

pub fn let_(args: &[AST], env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if args.len() < 2 {
        return Err(Error::BadArity(Some("let".to_string())));
    }

    let inner_env = CellEnv::wraps(env.clone());

    if let &AST::List(ref bindings) = args.first().unwrap() {
        for binding in bindings.iter() {
            match binding {
                &AST::List(ref binding) if binding.len() == 2 => {
                    let name = try!(atom_or_error(&binding[0], mem));
                    let expr = try!(eval(&binding[1], env.clone(), mem));
                    inner_env.set(name, expr);
                }
                _ =>
                    return Err(Error::MalformedExpression)
            }
        }
    } else {
        return Err(Error::MalformedExpression);
    };

    let body = args.tail();
    eval_sequence(body, inner_env, mem)
}

fn define_variable(name: &String, body: Option<&AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    if body.is_none() {
        return Ok(mem.intern(name.clone()));
    }

    let value = match body.unwrap() {
        &AST::List(ref list) if list[0] == AST::Atom("lambda".to_string()) =>
            try!(lambda(list.tail(), Some(name.clone()), env.clone(), mem)),
        value =>
            try!(eval(value, env.clone(), mem))
    };

    env.set(name.clone(), value.clone());

    Ok(value)
}

fn define_procedure(args: &[AST], body: &Vec<AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let procedure_name = try!(atom_or_error(&args[0], mem));

    let args = AST::List(args.tail().to_vec());
    let procedure = try!(create_fn(&args, body, Some(procedure_name.clone()), env.clone(), mem));
    env.set(procedure_name.clone(), procedure);

    Ok(mem.intern(procedure_name))
}

fn define_procedure_var(args: &[AST], extra_arg: &AST, body: &Vec<AST>, env: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    let procedure_name = try!(atom_or_error(&args[0], mem));

    let procedure = if args.len() == 1 {
        try!(create_fn(extra_arg, body, Some(procedure_name.clone()), env.clone(), mem))
    } else {
        let args = AST::DottedList(args.tail().to_vec(), Box::new(extra_arg.clone()));
        try!(create_fn(&args, body, Some(procedure_name.clone()), env.clone(), mem))
    };
    env.set(procedure_name.clone(), procedure);

    Ok(mem.intern(procedure_name))
}

fn create_fn(args: &AST, body: &Vec<AST>, name: Option<String>, closure: CellEnv, mem: &mut Memory) -> Result<RcValue, Error> {
    match args {
        &AST::List(ref list) => {
            let args_list = try!(compose_args_list(list.as_slice(), None, mem));
            Ok(mem.lambda(name, ArgumentsType::Fixed, args_list, closure, body.clone()))
        },
        &AST::DottedList(ref list, ref extra) => {
            let args_list = try!(compose_args_list(list.as_slice(), Some(&**extra), mem));
            Ok(mem.lambda(name, ArgumentsType::Variable, args_list, closure, body.clone()))
        }
        &AST::Atom(ref atom) =>
            Ok(mem.lambda(name, ArgumentsType::Any, vec!(atom.clone()), closure, body.clone())),
        _ => {
            let value = Value::from_ast(args, mem);
            Err(Error::WrongArgumentType(value))
        }
    }
}

fn compose_args_list(args: &[AST], extra: Option<&AST>, mem: &mut Memory) -> Result<Vec<String>, Error> {
    let length = args.len() + if extra.is_some() { 1 } else { 0 };
    let mut list = Vec::with_capacity(length);

    for arg in args.iter() {
        let arg = try!(atom_or_error(arg, mem));
        list.push(arg);
    }

    if extra.is_some() {
        let arg = try!(atom_or_error(extra.unwrap(), mem));
        list.push(arg);
    }

    Ok(list)
}

fn atom_or_error(value: &AST, mem: &mut Memory) -> Result<String, Error> {
    if let &AST::Atom(ref atom) = value {
        Ok(atom.to_string())
    } else {
        let value = Value::from_ast(value, mem);
        Err(Error::WrongArgumentType(value))
    }
}
<|endoftext|>


<commit_before>// while a WIP
#![allow(unused_variables)]
use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};
use serde::{Serialize, Deserialize, Serializer, Deserializer};

use storage::*;
use ::*;
pub use tensor::tensor_ops::*;
use rand;
use {Ixs, RcMut};

pub enum TensorType {
    Float,
    Double,
    Byte,
    Char,
    Short,
    Int,
    Long,
}

#[derive(Hash, Serialize, Deserialize)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}
pub enum NumKind {
    Float(f32),
    Double(f64),
    Long(i64),
}

impl NumKind {
    pub fn intof32(&self) -> f32 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => v,
            Double(v) => unimplemented!(),
            Long(v) => unimplemented!(),
        }
    }
    pub fn intoi64(&self) -> i64 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => unimplemented!(),
            Double(v) => unimplemented!(),
            Long(v) => v,
        }
    }
}

impl<T: Copy> From<T> for NumKind {
    #[allow(unused_variables)]
    default fn from(input: T) -> Self {
        unreachable!()
    }
}
impl From<f32> for NumKind {
    fn from(input: f32) -> Self {
        NumKind::Float(input)
    }
}
impl From<f64> for NumKind {
    fn from(input: f64) -> Self {
        NumKind::Double(input)
    }
}
impl From<i64> for NumKind {
    fn from(input: i64) -> Self {
        NumKind::Long(input)
    }
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type OptTensorKindList = Vec<Option<TensorKind>>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = usize;

impl TensorKind {
    pub fn backend(&self) -> Box<nn::BackendIntf> {
        unimplemented!()
    }
    pub fn inner(&self) -> *mut ::std::os::raw::c_void {
        unimplemented!()
    }
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl Index<usize> for TensorKind {
    type Output = NumKind;
    fn index(&self, idx: usize) -> &Self::Output {
        unimplemented!()
    }
}
impl PartialEq for TensorKind {
    fn eq(&self, other: &Self) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id() == t2.id(),
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id() == t2.id(),
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> Self {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> Self {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

pub struct Tensor<T> {
    pub value: RcMut<TensorImpl<T, Output = T>>,
}

impl<T> Serialize for Tensor<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de, T> Deserialize<'de> for Tensor<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

impl<T: Copy> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id().hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
}
pub trait NewSelf<D, T> {
    fn new(&self, args: D) -> T;
}

impl<T> NewSelf<usize, Tensor<T>> for Tensor<T> {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<(), Tensor<T>> for Tensor<T> {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<usize, TensorKind> for TensorKind {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl NewSelf<(), TensorKind> for TensorKind {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl NewSelf<Vec<usize>, TensorKind> for TensorKind {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<[usize; 2], TensorKind> for TensorKind {
    fn new(&self, args: [usize; 2]) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

type RefTI<T> = RcMut<TensorImpl<T, Output = T>>;
pub type TIArg<T> = TensorImpl<T, Output = T>;
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
    fn new(&self) -> RefTI<T>;
    fn add(&self, value: T, output: &TIArg<T>);
    fn addt(&self, value: T, rhs: &TIArg<T>, output: &TIArg<T>);
    fn inner(&self) -> *mut ::std::os::raw::c_void;
}

impl TensorImpl<f32> for FloatTensor {
    fn new(&self) -> RefTI<f32> {
        // XXX place holder implementation
        RcMutNew(FloatTensor::new())
    }
    fn add(&self, value: f32, output: &TIArg<f32>) {
        let out = typecast!(output.inner(), THFloatTensor);
        unsafe {
            THFloatTensor_add(out, self.t, value);
        };
    }
    fn inner(&self) -> *mut ::std::os::raw::c_void {
        self.t as *mut ::std::os::raw::c_void
    }
    fn addt(&self, value: f32, rhs: &TIArg<f32>, output: &TIArg<f32>) {
        let rhsp = typecast!(rhs.inner(), THFloatTensor);
    }
}

impl Index<isize> for FloatTensor {
    type Output = f32;
    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl Serialize for FloatTensor {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de> Deserialize<'de> for FloatTensor {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

pub fn make_vec(val: usize, count: usize) -> Vec<isize> {
    let mut vec = Vec::new();
    for _ in 0..count {
        vec.push(val as isize)
    }
    vec
}
<commit_msg>simply use default for bad match<commit_after>// while a WIP
#![allow(unused_variables)]
use rutorch::*;
use std::ops::{Index, IndexMut};
use std::convert::From;
use std::cmp::max;
use std::hash::{Hash, Hasher};
use serde::{Serialize, Deserialize, Serializer, Deserializer};

use storage::*;
use ::*;
pub use tensor::tensor_ops::*;
use rand;
use {Ixs, RcMut};

pub enum TensorType {
    Float,
    Double,
    Byte,
    Char,
    Short,
    Int,
    Long,
}

#[derive(Hash, Serialize, Deserialize)]
pub enum TensorKind {
    FloatTensor(Tensor<f32>),
    LongTensor(Tensor<i64>),
}
pub enum NumKind {
    Float(f32),
    Double(f64),
    Long(i64),
}

impl NumKind {
    pub fn intof32(&self) -> f32 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Float(v) => v,
            _ => unimplemented!(),
        }
    }
    pub fn intoi64(&self) -> i64 {
        use self::NumKind::{Float, Double, Long};
        match *self {
            Long(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl<T: Copy> From<T> for NumKind {
    #[allow(unused_variables)]
    default fn from(input: T) -> Self {
        unreachable!()
    }
}
impl From<f32> for NumKind {
    fn from(input: f32) -> Self {
        NumKind::Float(input)
    }
}
impl From<f64> for NumKind {
    fn from(input: f64) -> Self {
        NumKind::Double(input)
    }
}
impl From<i64> for NumKind {
    fn from(input: i64) -> Self {
        NumKind::Long(input)
    }
}

pub type TensorList<T> = Vec<Tensor<T>>;
pub type TensorKindList = Vec<TensorKind>;
pub type OptTensorKindList = Vec<Option<TensorKind>>;
pub type RefTensorList<'a, T> = Vec<&'a mut Tensor<T>>;
pub type RefTensorKindList<'a> = Vec<&'a TensorKind>;
pub type TensorId = usize;

impl TensorKind {
    pub fn backend(&self) -> Box<nn::BackendIntf> {
        unimplemented!()
    }
    pub fn inner(&self) -> *mut ::std::os::raw::c_void {
        unimplemented!()
    }
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl Index<usize> for TensorKind {
    type Output = NumKind;
    fn index(&self, idx: usize) -> &Self::Output {
        unimplemented!()
    }
}
impl PartialEq for TensorKind {
    fn eq(&self, other: &Self) -> bool {
        use self::TensorKind::{FloatTensor, LongTensor};
        match (self, other) {
            (&FloatTensor(ref t1), &FloatTensor(ref t2)) => t1.id() == t2.id(),
            (&LongTensor(ref t1), &LongTensor(ref t2)) => t1.id() == t2.id(),
            _ => false,
        }
    }
}
impl Eq for TensorKind {}
impl Clone for TensorKind {
    fn clone(&self) -> Self {
        use self::TensorKind::{FloatTensor, LongTensor};
        match *self {
            FloatTensor(ref t) => FloatTensor(t.clone()),
            LongTensor(ref t) => LongTensor(t.clone()),
        }
    }
}

impl<T> From<Tensor<T>> for TensorKind {
    #[allow(unused_variables)]
    default fn from(input: Tensor<T>) -> Self {
        unreachable!()
    }
}

impl From<Tensor<f32>> for TensorKind {
    fn from(input: Tensor<f32>) -> Self {
        TensorKind::FloatTensor(input)
    }
}

impl From<Tensor<i64>> for TensorKind {
    fn from(input: Tensor<i64>) -> Self {
        TensorKind::LongTensor(input)
    }
}

impl<T> From<TensorKind> for Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a, T> From<&'a TensorKind> for &'a Tensor<T> {
    #[allow(unused_variables)]
    default fn from(input: &'a TensorKind) -> Self {
        panic!("bad cast")
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<f32> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::FloatTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl<'a> From<&'a TensorKind> for &'a Tensor<i64> {
    fn from(input: &'a TensorKind) -> Self {
        match *input {
            TensorKind::LongTensor(ref t) => t,
            _ => unreachable!(),
        }
    }
}

impl From<TensorKind> for Tensor<f32> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::FloatTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

impl From<TensorKind> for Tensor<i64> {
    fn from(input: TensorKind) -> Self {
        match input {
            TensorKind::LongTensor(v) => v,
            _ => unimplemented!(),
        }
    }
}

pub struct Tensor<T> {
    pub value: RcMut<TensorImpl<T, Output = T>>,
}

impl<T> Serialize for Tensor<T> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de, T> Deserialize<'de> for Tensor<T> {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

impl<T: Copy> Hash for Tensor<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.id().hash(state)
    }
}

impl<T: Copy> Index<usize> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: usize) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

impl<T: Copy> Index<i32> for Tensor<T> {
    type Output = T;
    fn index(&self, idx: i32) -> &Self::Output {

        //        self.value.borrow_mut().index(idx as isize)
        unimplemented!()
    }
}

pub trait New<D, T> {
    fn new(args: D) -> T;
}
pub trait NewSelf<D, T> {
    fn new(&self, args: D) -> T;
}

impl<T> NewSelf<usize, Tensor<T>> for Tensor<T> {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<(), Tensor<T>> for Tensor<T> {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl<T> NewSelf<Vec<usize>, Tensor<T>> for Tensor<T> {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<usize, TensorKind> for TensorKind {
    fn new(&self, args: usize) -> Self {
        unimplemented!()
    }
}
impl NewSelf<(), TensorKind> for TensorKind {
    fn new(&self, args: ()) -> Self {
        unimplemented!()
    }
}
impl NewSelf<Vec<usize>, TensorKind> for TensorKind {
    fn new(&self, args: Vec<usize>) -> Self {
        unimplemented!()
    }
}
impl NewSelf<[usize; 2], TensorKind> for TensorKind {
    fn new(&self, args: [usize; 2]) -> Self {
        unimplemented!()
    }
}

impl<T> Tensor<T> {
    pub fn len(&self) -> usize {
        unimplemented!()
    }
    pub fn s(&self, dim: usize) -> Self {
        unimplemented!()
    }
}

impl<T> Default for Tensor<T> {
    fn default() -> Self {
        unimplemented!()
    }
}

impl<T> Clone for Tensor<T> {
    fn clone(&self) -> Self {
        Tensor { value: self.value.clone() }
    }
}

impl<T: Copy> Index<isize> for Tensor<T> {
    type Output = T;

    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

type RefTI<T> = RcMut<TensorImpl<T, Output = T>>;
pub type TIArg<T> = TensorImpl<T, Output = T>;
pub trait TensorImpl<T>: Index<Ixs, Output = T> {
    //fn view<'a>(&self, dims: &[i32]) -> Tensor<'a>;
    fn new(&self) -> RefTI<T>;
    fn add(&self, value: T, output: &TIArg<T>);
    fn addt(&self, value: T, rhs: &TIArg<T>, output: &TIArg<T>);
    fn inner(&self) -> *mut ::std::os::raw::c_void;
}

impl TensorImpl<f32> for FloatTensor {
    fn new(&self) -> RefTI<f32> {
        // XXX place holder implementation
        RcMutNew(FloatTensor::new())
    }
    fn add(&self, value: f32, output: &TIArg<f32>) {
        let out = typecast!(output.inner(), THFloatTensor);
        unsafe {
            THFloatTensor_add(out, self.t, value);
        };
    }
    fn inner(&self) -> *mut ::std::os::raw::c_void {
        self.t as *mut ::std::os::raw::c_void
    }
    fn addt(&self, value: f32, rhs: &TIArg<f32>, output: &TIArg<f32>) {
        let rhsp = typecast!(rhs.inner(), THFloatTensor);
    }
}

impl Index<isize> for FloatTensor {
    type Output = f32;
    fn index(&self, idx: isize) -> &Self::Output {
        unimplemented!()
    }
}

impl Serialize for FloatTensor {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        unimplemented!()
    }
}
impl<'de> Deserialize<'de> for FloatTensor {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        unimplemented!()
    }
}

pub struct FloatTensor {
    t: *mut THFloatTensor,
    storage: FloatStorage,
    dims: Vec<isize>,
}

impl Default for FloatTensor {
    fn default() -> Self {
        FloatTensor::new()
    }
}

impl FloatTensor {
    pub fn new() -> Self {
        unsafe {
            FloatTensor {
                t: THFloatTensor_new(),
                storage: FloatStorage::new(),
                dims: Vec::new(),
            }
        }
    }
    pub fn with_capacity(dims: &[isize]) -> Self {
        let size = dims.iter().product();
        let storage = FloatStorage::with_capacity(size);
        let strides = vec![1; dims.len()];
        let mut t = THFloatTensor {
            size: dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
            stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
            nDimension: dims.len() as i32,
            storage: storage.t,
            storageOffset: 0,
            refcount: 1,
            flag: TH_TENSOR_REFCOUNTED as i8,
        };
        FloatTensor {
            t: &mut t,
            storage: storage,
            dims: Vec::from(dims),
        }
    }
    pub fn randn(dims: &[isize]) -> Self {
        /* XXX */
        let mut t = FloatTensor::with_capacity(dims);
        for x in t.storage.iter_mut() {
            *x = rand::random::<f32>()
        }
        t
    }
}

impl<'a> Index<&'a [isize]> for FloatTensor {
    type Output = f32;

    fn index(&self, idx: &'a [isize]) -> &Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &self.storage[index]
    }
}

impl<'a> IndexMut<&'a [isize]> for FloatTensor {
    fn index_mut(&mut self, idx: &'a [isize]) -> &mut Self::Output {
        let mut index: isize = 0;
        let lastidx = max(0, idx.len() as isize - 1) as usize;
        if idx.len() != self.dims.len() {
            panic!("bad dimlen")
        }
        for i in 0..lastidx {
            if idx[i] >= self.dims[i] {
                panic!("bad dimlen")
            }
            index += idx[i] * self.dims[i]
        }
        if idx[lastidx] >= self.dims[lastidx] {
            panic!("bad dimlen")
        }
        index += idx[lastidx];
        &mut self.storage[index]
    }
}

pub fn make_vec(val: usize, count: usize) -> Vec<isize> {
    let mut vec = Vec::new();
    for _ in 0..count {
        vec.push(val as isize)
    }
    vec
}
<|endoftext|>


<commit_before>use rustc_serialize::base64::{Config, Newline, CharacterSet};
use hyper::header::Headers;
use utils::squeeze_path;
use std::ascii::AsciiExt;

pub mod auth13;
use authentication::auth13::Auth13;

pub static BASE64_AUTH: Config = Config {
    char_set: CharacterSet::Standard,
    newline: Newline::LF,
    pad: true,
    line_length: Some(60),
};

#[derive(Clone)]
pub struct Authentication {
    api_version: Option<String>,
    body: Option<String>,
    keypath: String,
    method: String,
    path: String,
    userid: String,
    version: String,
}

impl Authentication {
    pub fn new<P, K, M, U, V>(path: P, key: K, method: M, userid: U, version: V) -> Authentication
        where P: Into<String>,
              K: Into<String>,
              M: Into<String>,
              U: Into<String>,
              V: Into<String>
              {
                  Authentication {
                      api_version: None,
                      body: None,
                      keypath: key.into(),
                      method: method.into().to_ascii_uppercase(),
                      path: squeeze_path(path.into()),
                      userid: userid.into(),
                      version: version.into(),
                  }

              }

    pub fn api_version<S>(mut self, api_version: S) -> Authentication
        where S: Into<String>
        {
            self.api_version = Some(api_version.into());
            self
        }

    pub fn body<S>(mut self, body: S) -> Authentication
        where S: Into<String>
        {
            self.body = Some(body.into());
            self
        }

    pub fn headers(self) -> Headers {
        Auth13::new(&self.path,
                    &self.keypath,
                    &self.method,
                    &self.userid,
                    &self.api_version.unwrap(),
                    self.body)
            .headers()
    }
}

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

    const PATH: &'static str = "/organizations/clownco";
    const BODY: &'static str = "Spec Body";
    const USER: &'static str = "spec-user";
    const DT: &'static str = "2009-01-01T12:00:00Z";

    const PRIVATE_KEY: &'static str = "fixtures/spec-user.pem";

    #[test]
    fn test_auth_return() {
        let auth = Authentication::new(PATH, PRIVATE_KEY, "POST", USER, "1.1");
        let headers = auth.body(BODY).headers();
        let first = "UfZD9dRz6rFu6LbP5Mo1oNHcWYxpNIcUfFCffJS1FQa0GtfU/vkt3/O5HuCM";
        let out = headers.get_raw("x-ops-authorization-1").unwrap();
        assert_eq!(first.to_owned(), String::from_utf8(out[0].clone()).unwrap())
    }
}
<commit_msg>tidy up auth tests<commit_after>use rustc_serialize::base64::{Config, Newline, CharacterSet};
use hyper::header::Headers;
use utils::squeeze_path;
use std::ascii::AsciiExt;

pub mod auth13;
use authentication::auth13::Auth13;

pub static BASE64_AUTH: Config = Config {
    char_set: CharacterSet::Standard,
    newline: Newline::LF,
    pad: true,
    line_length: Some(60),
};

#[derive(Clone)]
pub struct Authentication {
    api_version: Option<String>,
    body: Option<String>,
    keypath: String,
    method: String,
    path: String,
    userid: String,
    version: String,
}

impl Authentication {
    pub fn new<P, K, M, U, V>(path: P, key: K, method: M, userid: U, version: V) -> Authentication
        where P: Into<String>,
              K: Into<String>,
              M: Into<String>,
              U: Into<String>,
              V: Into<String>
              {
                  Authentication {
                      api_version: None,
                      body: None,
                      keypath: key.into(),
                      method: method.into().to_ascii_uppercase(),
                      path: squeeze_path(path.into()),
                      userid: userid.into(),
                      version: version.into(),
                  }

              }

    pub fn api_version<S>(mut self, api_version: S) -> Authentication
        where S: Into<String>
        {
            self.api_version = Some(api_version.into());
            self
        }

    pub fn body<S>(mut self, body: S) -> Authentication
        where S: Into<String>
        {
            self.body = Some(body.into());
            self
        }

    pub fn headers(self) -> Headers {
        Auth13::new(&self.path,
                    &self.keypath,
                    &self.method,
                    &self.userid,
                    &self.api_version.unwrap(),
                    self.body)
            .headers()
    }
}

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

    const PATH: &'static str = "/organizations/clownco";
    const BODY: &'static str = "Spec Body";
    const USER: &'static str = "spec-user";

    const PRIVATE_KEY: &'static str = "fixtures/spec-user.pem";

    #[test]
    fn test_auth_return() {
        let auth = Authentication::new(PATH, PRIVATE_KEY, "GET", USER, "1.3");
        let headers = auth.body(BODY).api_version("1").headers();
        assert!(headers.get_raw("x-ops-authorization-1").is_some())
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(unix)]
mod imp {
    use std::{ptr, slice};
    use std::sync::Arc;

    use libc::{self, c_void, c_char};
    use rocksdb::DB;

    use tikv::server::Msg;
    use tikv::util::transport::SendCh;
    use prometheus::{self, Encoder, TextEncoder};

    use profiling;

    const ROCKSDB_DB_STATS_KEY: &'static str = "rocksdb.dbstats";
    const ROCKSDB_CF_STATS_KEY: &'static str = "rocksdb.cfstats";

    extern "C" {
        #[cfg_attr(target_os = "macos", link_name = "je_malloc_stats_print")]
        fn malloc_stats_print(write_cb: extern "C" fn(*mut c_void, *const c_char),
                              cbopaque: *mut c_void,
                              opts: *const c_char);
    }

    extern "C" fn write_cb(printer: *mut c_void, msg: *const c_char) {
        unsafe {
            let buf = &mut *(printer as *mut Vec<u8>);
            let len = libc::strlen(msg);
            let bytes = slice::from_raw_parts(msg as *const u8, len);
            buf.extend_from_slice(bytes);
        }
    }

    fn print_malloc_stats() {
        let mut buf = Vec::new();
        unsafe {
            malloc_stats_print(write_cb,
                               &mut buf as *mut Vec<u8> as *mut c_void,
                               ptr::null())
        }
        info!("{}", String::from_utf8_lossy(&buf));
    }

    // TODO: remove backup_path from configuration
    pub fn handle_signal(ch: SendCh<Msg>, engine: Arc<DB>, _: &str) {
        use signal::trap::Trap;
        use nix::sys::signal::{SIGTERM, SIGINT, SIGUSR1, SIGUSR2};
        let trap = Trap::trap(&[SIGTERM, SIGINT, SIGUSR1, SIGUSR2]);
        for sig in trap {
            match sig {
                SIGTERM | SIGINT => {
                    info!("receive signal {}, stopping server...", sig);
                    ch.send(Msg::Quit).unwrap();
                    break;
                }
                SIGUSR1 => {
                    // Use SIGUSR1 to log metrics.
                    let mut buffer = vec![];
                    let metric_familys = prometheus::gather();
                    let encoder = TextEncoder::new();
                    encoder.encode(&metric_familys, &mut buffer).unwrap();
                    info!("{}", String::from_utf8(buffer).unwrap());

                    // Log common rocksdb stats.
                    for name in engine.cf_names() {
                        let handler = engine.cf_handle(name).unwrap();
                        if let Some(v) =
                               engine.get_property_value_cf(handler, ROCKSDB_CF_STATS_KEY) {
                            info!("{}", v)
                        }
                    }

                    if let Some(v) = engine.get_property_value(ROCKSDB_DB_STATS_KEY) {
                        info!("{}", v)
                    }

                    // Log more stats if enable_statistics is true.
                    if let Some(v) = engine.get_statistics() {
                        info!("{}", v)
                    }
                    print_malloc_stats();
                }
                SIGUSR2 => profiling::dump_prof(None),
                // TODO: handle more signal
                _ => unreachable!(),
            }
        }
    }

    #[cfg(test)]
    mod tests {
        #[test]
        fn test_stats_print() {
            // just print the data, ensure it doesn't core.
            super::print_malloc_stats()
        }
    }
}

#[cfg(not(unix))]
mod imp {
    use std::sync::Arc;

    use rocksdb::DB;

    use tikv::server::Msg;
    use tikv::util::transport::SendCh;

    pub fn handle_signal(_: SendCh<Msg>, _: Arc<DB>, _: &str) {}
}

pub use self::imp::handle_signal;
<commit_msg>bin: capture SIGHUP (#1889)<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(unix)]
mod imp {
    use std::{ptr, slice};
    use std::sync::Arc;

    use libc::{self, c_void, c_char};
    use rocksdb::DB;

    use tikv::server::Msg;
    use tikv::util::transport::SendCh;
    use prometheus::{self, Encoder, TextEncoder};

    use profiling;

    const ROCKSDB_DB_STATS_KEY: &'static str = "rocksdb.dbstats";
    const ROCKSDB_CF_STATS_KEY: &'static str = "rocksdb.cfstats";

    extern "C" {
        #[cfg_attr(target_os = "macos", link_name = "je_malloc_stats_print")]
        fn malloc_stats_print(write_cb: extern "C" fn(*mut c_void, *const c_char),
                              cbopaque: *mut c_void,
                              opts: *const c_char);
    }

    extern "C" fn write_cb(printer: *mut c_void, msg: *const c_char) {
        unsafe {
            let buf = &mut *(printer as *mut Vec<u8>);
            let len = libc::strlen(msg);
            let bytes = slice::from_raw_parts(msg as *const u8, len);
            buf.extend_from_slice(bytes);
        }
    }

    fn print_malloc_stats() {
        let mut buf = Vec::new();
        unsafe {
            malloc_stats_print(write_cb,
                               &mut buf as *mut Vec<u8> as *mut c_void,
                               ptr::null())
        }
        info!("{}", String::from_utf8_lossy(&buf));
    }

    // TODO: remove backup_path from configuration
    pub fn handle_signal(ch: SendCh<Msg>, engine: Arc<DB>, _: &str) {
        use signal::trap::Trap;
        use nix::sys::signal::{SIGTERM, SIGINT, SIGHUP, SIGUSR1, SIGUSR2};
        let trap = Trap::trap(&[SIGTERM, SIGINT, SIGHUP, SIGUSR1, SIGUSR2]);
        for sig in trap {
            match sig {
                SIGTERM | SIGINT | SIGHUP => {
                    info!("receive signal {}, stopping server...", sig);
                    ch.send(Msg::Quit).unwrap();
                    break;
                }
                SIGUSR1 => {
                    // Use SIGUSR1 to log metrics.
                    let mut buffer = vec![];
                    let metric_familys = prometheus::gather();
                    let encoder = TextEncoder::new();
                    encoder.encode(&metric_familys, &mut buffer).unwrap();
                    info!("{}", String::from_utf8(buffer).unwrap());

                    // Log common rocksdb stats.
                    for name in engine.cf_names() {
                        let handler = engine.cf_handle(name).unwrap();
                        if let Some(v) =
                               engine.get_property_value_cf(handler, ROCKSDB_CF_STATS_KEY) {
                            info!("{}", v)
                        }
                    }

                    if let Some(v) = engine.get_property_value(ROCKSDB_DB_STATS_KEY) {
                        info!("{}", v)
                    }

                    // Log more stats if enable_statistics is true.
                    if let Some(v) = engine.get_statistics() {
                        info!("{}", v)
                    }
                    print_malloc_stats();
                }
                SIGUSR2 => profiling::dump_prof(None),
                // TODO: handle more signal
                _ => unreachable!(),
            }
        }
    }

    #[cfg(test)]
    mod tests {
        #[test]
        fn test_stats_print() {
            // just print the data, ensure it doesn't core.
            super::print_malloc_stats()
        }
    }
}

#[cfg(not(unix))]
mod imp {
    use std::sync::Arc;

    use rocksdb::DB;

    use tikv::server::Msg;
    use tikv::util::transport::SendCh;

    pub fn handle_signal(_: SendCh<Msg>, _: Arc<DB>, _: &str) {}
}

pub use self::imp::handle_signal;
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;
            let gl : &mut _ = $gl;

            let gl_buffer = bind_array_buffer!(gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<commit_msg>Tweak the `bind_vertex_buffer!` macro<commit_after>use std::marker::PhantomData;
use super::context::Context;
use super::vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use super::buffer::{Buffer, BufferBinding, ArrayBufferBinding};
use super::types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }

    pub fn draw_arrays_range(&self,
                             mode: DrawingMode,
                             start: u32,
                             length: usize)
    {
        debug_assert!((start as usize) + length <= self.vbo.count);

        unsafe {
            self.gl_buffer.draw_arrays_range(mode, start, length);
        }
    }

    pub fn draw_arrays(&self, mode: DrawingMode) {
        unsafe {
            self.gl_buffer.draw_arrays_range(mode, 0, self.vbo.count);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::ContextOf;
use framebuffer::FramebufferBinding;
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinderOf, BufferBinding,
             ArrayBufferBinder, ElementArrayBufferBinder,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, B, F, P, R, T>(&self, gl: &ContextOf<B, F, P, R, T>)
        -> Result<(), AttribError>
        where V: VertexData
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V: VertexData>(&self, gl_buffer: &ArrayBufferBinding)
        -> Result<(), AttribError>
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                gl_buffer.vertex_attrib_pointer(
                    program_attrib,
                    vertex_attrib.ty.components,
                    vertex_attrib.ty.data,
                    vertex_attrib.ty.normalize,
                    vertex_attrib.stride,
                    vertex_attrib.offset
                );
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind<BA, BE, F, P, R, T>(&mut self,
                                    gl: ContextOf<BufferBinderOf<BA, BE>,
                                                  F,
                                                  P,
                                                  R,
                                                  T>)
        -> Result<(), VertexBindError>
        where BA: BorrowMut<ArrayBufferBinder>
    {
        match self.attrib_binder {
            Some(ref binder) => {
                let (mut buffers, mut gl) = gl.split_buffers();
                let (mut ba_binder, buf) = buffers.split_array();
                let mut ba_binder = ba_binder.borrow_mut();
                let mut gl = gl.join_buffers(buf);
                let gl_buffer = ba_binder.bind(&mut self.buffer);
                try!(binder.enable::<V, _, _, _, _, _>(&mut gl));
                try!(binder.bind::<V>(&gl_buffer));
                Ok(())
            },
            None => { Err(VertexBindError::NoAttributeBindings) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData + 'a> VertexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<V>(&mut self,
                                    gl_vbo: &VertexBufferBinding<V>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<V>(&mut self,
                              gl_vbo: &VertexBufferBinding<V>,
                              mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<V, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<V>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<V, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<V>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<V, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, V>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    pub fn draw_elements_vbo<V, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, V>,
                                   mode: DrawingMode,
                                   indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

// TODO: Refactor to work with less restrictive generic params
impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn bind_vertex_buffer<'a, V>(mut self, vbo: &'a mut VertexBuffer<V>)
        -> (
            VertexBufferBinding<V>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where V: VertexData,
              BA: BorrowMut<ArrayBufferBinder>
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        {
            let gl = self.borrowed_mut();
            let (buffers, gl) = gl.split_buffers();
            let gl = gl.join_buffers(buffers.borrowed_mut());
            vbo.bind(gl).unwrap();
        }
        let (buffers, gl) = self.split_buffers();
        let (mut ba_binder, rest_buffers) = buffers.split_array();
        let mut ba_binder = ba_binder.borrow_mut();
        let gl = gl.join_buffers(rest_buffers);
        let buffer = unsafe { mem::transmute(vbo.buffer_mut() as *mut Buffer) };
        let gl_array_buffer = ba_binder.bind(buffer);
        (VertexBufferBinding::new(gl_array_buffer, vbo), gl)
    }

    pub fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (
            IndexBufferBinding<I>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where I: IndexDatum + 'a,
              BE: BorrowMut<ElementArrayBufferBinder> + 'a
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        let (mut buffers, gl) = self.split_buffers();
        let (mut be_binder, rest_buffers) = buffers.split_element_array();
        let gl = gl.join_buffers(rest_buffers);
        let be_binder = be_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(ibo.buffer_mut() as *mut Buffer) };
        let gl_be = be_binder.bind(buffer);
        (IndexBufferBinding::new(gl_be, ibo), gl)
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = {
                attrib_pointers!($gl, vbo, {
                    $($field_name => $field_attrib),*
                })
            };
            vbo.bind_attrib_pointers(binder);
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut vbo = $vbo;

            let (gl_vbo, _) = $gl.bind_vertex_buffer(vbo.borrow_mut());
            gl_vbo
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut ibo = $ibo;

            let (gl_ibo, _) = $gl.bind_index_buffer(ibo.borrow_mut());
            gl_ibo
        }
    }
}
<commit_msg>Use `Context.split_{array,element_array}_buffer` where applicable<commit_after>use std::mem;
use std::borrow::BorrowMut;
use std::marker::PhantomData;
use std::collections::{HashMap, HashSet};
use context::ContextOf;
use framebuffer::FramebufferBinding;
use program::ProgramAttrib;
use vertex_data::{VertexData, VertexBytes, VertexAttribute};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinderOf, BufferBinding,
             ArrayBufferBinder, ElementArrayBufferBinder,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

#[derive(Debug)]
pub enum AttribAddError {
    DuplicateAttrib(String)
}

#[derive(Debug)]
pub struct AttribError {
    missing_attribs: Vec<String>,
    unknown_attribs: Vec<String>
}

pub struct AttribBinder {
    attribs: HashMap<String, ProgramAttrib>
}

impl AttribBinder {
    pub fn new() -> Self {
        AttribBinder {
            attribs: HashMap::new()
        }
    }

    pub fn add(&mut self, name: &str, attrib: ProgramAttrib)
        -> Result<(), AttribAddError>
    {
        match self.attribs.insert(name.into(), attrib) {
            None => Ok(()),
            Some(_) => Err(AttribAddError::DuplicateAttrib(name.into()))
        }
    }

    fn for_each<T, F>(&self, mut f: F) -> Result<(), AttribError>
        where T: VertexData, F: FnMut(VertexAttribute, ProgramAttrib)
    {
        // TODO: Avoid heap allocations
        // TODO: Avoid redundant calls to T::visit_attributes
        let mut attribs =
            HashMap::<String, (VertexAttribute, ProgramAttrib)>::new();
        let mut missing = Vec::<String>::new();

        T::visit_attributes(|vertex_attrib| {
            match self.attribs.get(&vertex_attrib.name) {
                Some(program_attrib) => {
                    let pair = (vertex_attrib.clone(), *program_attrib);
                    attribs.insert(vertex_attrib.name, pair);
                },
                None => {
                    missing.push(vertex_attrib.name);
                }
            }
        });

        let unknown: Vec<_> = {
            let expected: HashSet<_> = self.attribs.keys().collect();
            let actual: HashSet<_> = attribs.keys().collect();
            expected.difference(&actual).cloned().cloned().collect()
        };

        if missing.is_empty() && unknown.is_empty() {
            for (_, (vertex_attrib, program_attrib)) in attribs.into_iter() {
                f(vertex_attrib, program_attrib);
            }
            Ok(())
        }
        else {
            Err(AttribError {
                missing_attribs: missing,
                unknown_attribs: unknown
            })
        }
    }

    pub fn enable<V, B, F, P, R, T>(&self, gl: &ContextOf<B, F, P, R, T>)
        -> Result<(), AttribError>
        where V: VertexData
    {
        self.for_each::<V, _>(|_, program_attrib| {
            gl.enable_vertex_attrib_array(program_attrib);
        })
    }

    pub fn bind<V: VertexData>(&self, gl_buffer: &ArrayBufferBinding)
        -> Result<(), AttribError>
    {
        self.for_each::<V, _>(|vertex_attrib, program_attrib| {
            unsafe {
                gl_buffer.vertex_attrib_pointer(
                    program_attrib,
                    vertex_attrib.ty.components,
                    vertex_attrib.ty.data,
                    vertex_attrib.ty.normalize,
                    vertex_attrib.stride,
                    vertex_attrib.offset
                );
            }
        })
    }
}

#[derive(Debug)]
pub enum VertexBindError {
    BindingError(AttribError),
    NoAttributeBindings
}

impl From<AttribError> for VertexBindError {
    fn from(attrib_error: AttribError) -> VertexBindError {
        VertexBindError::BindingError(attrib_error)
    }
}

pub struct VertexBuffer<T: VertexData> {
    attrib_binder: Option<AttribBinder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<V: VertexData> VertexBuffer<V> {
    pub fn bind_attrib_pointers(&mut self, binder: AttribBinder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind<BA, BE, F, P, R, T>(&mut self,
                                    gl: ContextOf<BufferBinderOf<BA, BE>,
                                                  F,
                                                  P,
                                                  R,
                                                  T>)
        -> Result<(), VertexBindError>
        where BA: BorrowMut<ArrayBufferBinder>
    {
        match self.attrib_binder {
            Some(ref binder) => {
                let (mut ba_binder, mut gl) = gl.split_array_buffer();
                let mut ba_binder = ba_binder.borrow_mut();
                let gl_buffer = ba_binder.bind(&mut self.buffer);
                try!(binder.enable::<V, _, _, _, _, _>(&mut gl));
                try!(binder.bind::<V>(&gl_buffer));
                Ok(())
            },
            None => { Err(VertexBindError::NoAttributeBindings) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData + 'a> {
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData + 'a> VertexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<V>(&mut self,
                                    gl_vbo: &VertexBufferBinding<V>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where V: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<V>(&mut self,
                              gl_vbo: &VertexBufferBinding<V>,
                              mode: DrawingMode)
        where V: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<V, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<V>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where V: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<V, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<V>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where V: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<V, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, V>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indices);
        }
    }

    pub fn draw_elements_vbo<V, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, V>,
                                   mode: DrawingMode,
                                   indices: &[I])
        where V: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indices);
        }
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_vertex_buffer<V: VertexData>(&self) -> VertexBuffer<V> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

// TODO: Refactor to work with less restrictive generic params
impl<BA, BE, F, P, R, T> ContextOf<BufferBinderOf<BA, BE>, F, P, R, T> {
    pub fn bind_vertex_buffer<'a, V>(mut self, vbo: &'a mut VertexBuffer<V>)
        -> (
            VertexBufferBinding<V>,
            ContextOf<BufferBinderOf<(), BE>, F, P, R, T>
        )
        where V: VertexData,
              BA: BorrowMut<ArrayBufferBinder>
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        {
            let gl = self.borrowed_mut();
            let (buffers, gl) = gl.split_buffers();
            let gl = gl.join_buffers(buffers.borrowed_mut());
            vbo.bind(gl).unwrap();
        }
        let (mut ba_binder, gl) = self.split_array_buffer();
        let mut ba_binder = ba_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(vbo.buffer_mut() as *mut Buffer) };
        let gl_array_buffer = ba_binder.bind(buffer);
        (VertexBufferBinding::new(gl_array_buffer, vbo), gl)
    }

    pub fn bind_index_buffer<'a, I>(self, ibo: &'a mut IndexBuffer<I>)
        -> (
            IndexBufferBinding<I>,
            ContextOf<BufferBinderOf<BA, ()>, F, P, R, T>
        )
        where I: IndexDatum + 'a,
              BE: BorrowMut<ElementArrayBufferBinder> + 'a
    {
        // NOTE: The mem::transmute here unsafely extends the borrow of
        //       ibo.buffer_mut()
        // TODO: Find a safe(r) way to do this
        let (mut be_binder, gl) = self.split_element_array_buffer();
        let be_binder = be_binder.borrow_mut();
        let buffer = unsafe { mem::transmute(ibo.buffer_mut() as *mut Buffer) };
        let gl_be = be_binder.bind(buffer);
        (IndexBufferBinding::new(gl_be, ibo), gl)
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl<B, F, P, R, T> ContextOf<B, F, P, R, T> {
    pub fn new_index_buffer<I: IndexDatum>(&self) -> IndexBuffer<I> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let mut binder = $crate::AttribBinder::new();
            $(binder.add(stringify!($field_name), $field_attrib).unwrap());*;
            binder
        }
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = {
                attrib_pointers!($gl, vbo, {
                    $($field_name => $field_attrib),*
                })
            };
            vbo.bind_attrib_pointers(binder);
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut vbo = $vbo;

            let (gl_vbo, _) = $gl.bind_vertex_buffer(vbo.borrow_mut());
            gl_vbo
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            use std::borrow::BorrowMut;
            let mut ibo = $ibo;

            let (gl_ibo, _) = $gl.bind_index_buffer(ibo.borrow_mut());
            gl_ibo
        }
    }
}
<|endoftext|>


<commit_before>/// Tries to fit a curve where t is in the range [0, 1] and
/// a is t=0, b is t=0.33.., c is t=0.66.., and d is t=1.0
#[derive(Clone)]
pub struct Easing {
    pub a: f64,
    pub b: f64,
    pub c: f64,
    pub d: f64
}

impl Easing {
    pub fn linear() -> Easing {
        Easing {
            a: 0.0,
            b: 1.0 / 3.0,
            c: 2.0 / 3.0,
            d: 1.0
        }
    }

    pub fn t(&self, t: f64) -> f64 {
        Easing::interpolate_cubic(self.a, self.b, self.c, self.d, t)
    }

    fn interpolate_cubic(a: f64, b: f64, c: f64, d: f64, t: f64) -> f64 {
        let abc = Easing::interpolate_quadratic(a, b, c, t);
        let bcd = Easing::interpolate_quadratic(b, c, d, t);

        Easing::interpolate_linear(abc, bcd, t)
    }

    fn interpolate_quadratic(a: f64, b: f64, c: f64, t: f64) -> f64 {
        let ab = Easing::interpolate_linear(a, b, t);
        let bc = Easing::interpolate_linear(b, c, t);

        Easing::interpolate_linear(ab, bc, t)
    }

    fn interpolate_linear(a: f64, b: f64, t: f64) -> f64 {
        (1.0 - t) * a + t * b
    }
}

#[test]
fn test_interpolate_linear_easing() {
    let linear_easing = Easing::linear();;
    assert_eq!(linear_easing.t(0.0), 0.0);
    assert_eq!(linear_easing.t(0.25), 0.25);
    assert_eq!(linear_easing.t(0.5), 0.5);
    assert_eq!(linear_easing.t(0.75), 0.75);
    assert_eq!(linear_easing.t(1.0), 1.0);
}

#[test]
fn test_interpolate_bezier_easing() {
    let one_third = 1.0 / 3.0;
    let two_thirds = 2.0 / 3.0;
    let bezier_easing = Easing { a: 0.0, b: one_third, c: two_thirds, d: 1.0 };

    assert_eq!(bezier_easing.t(0.0), 0.0);

    let abs_diff_third = (bezier_easing.t(one_third) - one_third).abs();
    assert!(abs_diff_third < 1e-10);

    assert_eq!(bezier_easing.t(0.5), 0.5);

    let abs_diff_two_thirds = (bezier_easing.t(two_thirds) - two_thirds).abs();
    assert!(abs_diff_two_thirds < 1e-10);

    assert_eq!(bezier_easing.t(1.0), 1.0);
}
<commit_msg>Remove pointless easing test<commit_after>/// Tries to fit a curve where t is in the range [0, 1] and
/// a is t=0, b is t=0.33.., c is t=0.66.., and d is t=1.0
#[derive(Clone)]
pub struct Easing {
    pub a: f64,
    pub b: f64,
    pub c: f64,
    pub d: f64
}

impl Easing {
    pub fn linear() -> Easing {
        Easing {
            a: 0.0,
            b: 1.0 / 3.0,
            c: 2.0 / 3.0,
            d: 1.0
        }
    }

    pub fn t(&self, t: f64) -> f64 {
        Easing::interpolate_cubic(self.a, self.b, self.c, self.d, t)
    }

    fn interpolate_cubic(a: f64, b: f64, c: f64, d: f64, t: f64) -> f64 {
        let abc = Easing::interpolate_quadratic(a, b, c, t);
        let bcd = Easing::interpolate_quadratic(b, c, d, t);

        Easing::interpolate_linear(abc, bcd, t)
    }

    fn interpolate_quadratic(a: f64, b: f64, c: f64, t: f64) -> f64 {
        let ab = Easing::interpolate_linear(a, b, t);
        let bc = Easing::interpolate_linear(b, c, t);

        Easing::interpolate_linear(ab, bc, t)
    }

    fn interpolate_linear(a: f64, b: f64, t: f64) -> f64 {
        (1.0 - t) * a + t * b
    }
}

#[test]
fn test_easing() {
    // This also tests Bezier easing as linear easing
    // is implemented using Bezier easing.
    let linear_easing = Easing::linear();;
    assert_eq!(linear_easing.t(0.0), 0.0);
    assert_eq!(linear_easing.t(0.25), 0.25);
    assert_eq!(linear_easing.t(0.5), 0.5);
    assert_eq!(linear_easing.t(0.75), 0.75);
    assert_eq!(linear_easing.t(1.0), 1.0);
}
<|endoftext|>