<commit_before>use std::rc::Rc;
use std::ops::Deref;

use ::expr::{Expr,Kint,  Kfloat, Type, Proc, Error as E, Result};
use ::env::Env;

pub fn kint(i: Kint) -> Expr {
    Expr::Int(i)
}

pub fn kfloat(f: Kfloat) -> Expr {
    Expr::Float(f)
}

pub fn kcons(car: Expr, cdr: Expr) -> Expr {
    Expr::Cons(Rc::new(car), Rc::new(cdr))
}

pub fn knil() -> Expr {
    Expr::Nil
}

pub fn ksym<S: Into<String>>(s: S) -> Expr {
    Expr::Sym(s.into())
}

pub fn kstr<S: Into<String>>(s: S) -> Expr {
    Expr::Str(s.into())
}

pub fn kproc(p: Proc) -> Expr {
    Expr::Proc(p)
}

pub fn klambda(param: Expr, body: Expr) -> Proc {
    Proc::Lambda(Rc::new(param), Rc::new(body))
}

pub fn kprim<S: Into<String>, F:'static + Fn(&mut Env, &Expr) -> Result<Expr> + Sized>(name: S, f: F) -> Proc{
    Proc::Prim(name.into(), Rc::new(f))
}

pub fn car(cons: &Expr) -> Result<Expr> {
    match cons {
        &Expr::Cons(ref car, _) => Ok(car.deref().clone()),
        arg => Err(E::Type(Type::Cons, arg.clone()))
    }
}

pub fn cdr(cons: &Expr) -> Result<Expr> {
    match cons {
        &Expr::Cons(_, ref cdr) => Ok(cdr.deref().clone()),
        arg => Err(E::Type(Type::Cons, arg.clone()))
    }
}

#[macro_export]
macro_rules! klist {
    ($car: expr, $($cdr: expr), *) => (
        kcons($crate::expr::Expr::from($car), klist!($($cdr),*))
    );
    ($car: expr) => (
        kcons($crate::expr::Expr::from($car), knil())
    );
    () => (
        knil()
    );
}

macro_rules! get_args_one {
    ($v:expr, Int) => (
        match $v {
            &Expr::Int(x) => Ok(x),
            hd => Err(E::Type(Type::Int, hd.clone()))
        }
    );

    ($v:expr, Float) => {
        match $v {
            &Expr::Float(x) => Ok(x),
            hd => Err(E::Type(Type::Float, hd.clone()))
        }
    };
    ($v:expr, Str) => (
        match $v {
            &Expr::Str(ref x) => Ok(x),
            hd => Err(E::Type(Type::Str, hd.clone()))

        }
    );
    ($v:expr, Sym) => (
        match $v {
            &Expr::Sym(ref x) => Ok(x),
            hd => Err(E::Type(Type::Sym, hd.clone()))
        }
    );
    ($v:expr, Nil) => (
        match $v {
            &Expr::Nil => Ok(()),
            hd => Err(E::Type(Type::Nil, hd.clone()))
        }
    );
    ($v:expr, Bool) => (
        match $v {
            &Expr::Nil => Ok(false),
            _ => Ok(true)
        }
    );
    ($v:expr, Cons) => (
        match $v {
            &Expr::Cons(ref car, ref cdr) => Ok((car.deref(), cdr.deref())),
            hd => Err(E::Type(Type::Cons, hd.clone()))
        }
    );
    ($v:expr, Proc) => (
        match $v {
            &Expr::Proc(ref p) => Ok(p),
            hd => Err(E::Type(Type::Proc, hd.clone()))
        }
    );
    ($v:expr, Any) => (
        match $v {
            hd => if true {
                Ok(hd)
            } else {
                unreachable!()
            }
        };
    )
}

macro_rules! gen_pattern {
    (($var: pat, $ident: tt) $($other:tt) *) => (
        ($var, gen_pattern!($($other)*))
            );
    (&optional ($var: pat, $ident: tt) $($other:tt) *) => (
        ($var, gen_pattern!($($other)*))
            );
    () => (())
}

macro_rules! gen_match {
    ($args: expr, ($var: pat, $ident: tt) $($other:tt) *) =>
        (
            match $args {
                &Expr::Cons(ref hd, ref tl) => {
                    let v = try!(get_args_one!(hd.deref(), $ident));
                    (v, gen_match!(tl.deref(), $($other)*))
                },
                &Expr::Nil => return Err(E::ArityShort),
                args => return Err(E::InvalidArgument(args.clone()))
            };
            );
    ($args: expr, &optional ($var: pat, $ident: tt) $($other:tt) *) =>
        (
            match $args {
                &Expr::Cons(ref hd, ref tl) => {
                    let v = try!(get_args_one!(hd.deref(), $ident));
                    (Some(v), gen_match!(tl.deref(), &optional $($other)*))
                },
                &Expr::Nil => {
                    (None, gen_match!($args, &optional $($other)*))

                },
                args => return Err(E::InvalidArgument(args.clone()))
            };
            );
    ($args: expr, &optional) => (
        match $args {
            &Expr::Nil => (),
            _ => return Err(E::ArityExceed)
        }
        );
    ($args: expr, ) => (
        match $args {
            &Expr::Nil => (),
            _ => return Err(E::ArityExceed)
        }
        );
}

#[macro_export]
macro_rules! get_args {
    ($args: expr, $($other:tt) *) =>
        (
            let gen_pattern!($($other)*) = gen_match!($args, $($other)*)
            ) ;
    ($args: expr, ) => (
        let () = gen_match!($args,)
        );
    ($args: expr) => (
        let () = gen_match!($args,)
        );
}

pub fn f_foldl<F>(mut env: &mut Env, f: &F, init: &Expr, args: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr, &Expr) -> Result<Expr>{
    let mut res = init.clone();
    let mut head = args;
    let nil = &Expr::Nil;
    while head != nil {
        match head {
            &Expr::Cons(ref car, ref cdr) => {
                res = try!(f(env, &res, car));
                head = cdr;
            }
            _ => return Err(E::InvalidArgument(args.clone()))
        }
    }
    Ok(res)
}

// fn f_reverse(mut env: &mut Env, args: &Expr) -> Result<Expr> {
//     f_foldl(env, &|_, acc, x| Ok(Expr::Cons(Rc::new(x.clone()), Rc::new(acc))), Expr::Nil, args)
// }

pub fn f_foldr<F>(mut env: &mut Env, f: &F, init: &Expr, args: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr, &Expr) -> Result<Expr>{
    match args {
        &Expr::Nil => Ok(init.clone()),
        &Expr::Cons(ref car, ref cdr) => {
            let v = try!(f_foldr(env, f, init, cdr));
            f(env, &v, car)
        }
        args => Err(E::InvalidArgument(args.clone()))
    }
}

pub fn f_map<F>(mut env: &mut Env, f: &F, list: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr) -> Result<Expr>{
    f_foldr(env, &|env, acc, x| Ok(kcons(try!(f(env, x)), acc.clone()))
                 , &Expr::Nil, list)
}

// fn f_iter<F>(mut env: &mut Env, f: &F, list: &Expr) -> Result<Expr>
//     where F: Fn(&mut Env, Expr) -> Result<()>{
//     f_foldr(env, &|env, _, x| {try!(f(env,x.clone())); Ok(Expr::Nil)}
//                  , Expr::Nil, list)
// }

<commit_msg>implement nullable annotation<commit_after>use std::rc::Rc;
use std::ops::Deref;

use ::expr::{Expr,Kint,  Kfloat, Type, Proc, Error as E, Result};
use ::env::Env;

pub fn kint(i: Kint) -> Expr {
    Expr::Int(i)
}

pub fn kfloat(f: Kfloat) -> Expr {
    Expr::Float(f)
}

pub fn kcons(car: Expr, cdr: Expr) -> Expr {
    Expr::Cons(Rc::new(car), Rc::new(cdr))
}

pub fn knil() -> Expr {
    Expr::Nil
}

pub fn ksym<S: Into<String>>(s: S) -> Expr {
    Expr::Sym(s.into())
}

pub fn kstr<S: Into<String>>(s: S) -> Expr {
    Expr::Str(s.into())
}

pub fn kproc(p: Proc) -> Expr {
    Expr::Proc(p)
}

pub fn klambda(param: Expr, body: Expr) -> Proc {
    Proc::Lambda(Rc::new(param), Rc::new(body))
}

pub fn kprim<S: Into<String>, F:'static + Fn(&mut Env, &Expr) -> Result<Expr> + Sized>(name: S, f: F) -> Proc{
    Proc::Prim(name.into(), Rc::new(f))
}

pub fn car(cons: &Expr) -> Result<Expr> {
    match cons {
        &Expr::Cons(ref car, _) => Ok(car.deref().clone()),
        arg => Err(E::Type(Type::Cons, arg.clone()))
    }
}

pub fn cdr(cons: &Expr) -> Result<Expr> {
    match cons {
        &Expr::Cons(_, ref cdr) => Ok(cdr.deref().clone()),
        arg => Err(E::Type(Type::Cons, arg.clone()))
    }
}

#[macro_export]
macro_rules! klist {
    ($car: expr, $($cdr: expr), *) => (
        kcons($crate::expr::Expr::from($car), klist!($($cdr),*))
    );
    ($car: expr) => (
        kcons($crate::expr::Expr::from($car), knil())
    );
    () => (
        knil()
    );
}

macro_rules! get_args_one {
    ($v:expr, Nullable $($ident: tt)+) => (
        match $v {
            &Expr::Nil => Ok(None),
            v => Ok(Some(try!(get_args_one!(v, $($ident)+))))
        }
     );
    ($v:expr, Int) => (
        match $v {
            &Expr::Int(x) => Ok(x),
            hd => Err(E::Type(Type::Int, hd.clone()))
        }
    );

    ($v:expr, Float) => {
        match $v {
            &Expr::Float(x) => Ok(x),
            hd => Err(E::Type(Type::Float, hd.clone()))
        }
    };
    ($v:expr, Str) => (
        match $v {
            &Expr::Str(ref x) => Ok(x),
            hd => Err(E::Type(Type::Str, hd.clone()))

        }
    );
    ($v:expr, Sym) => (
        match $v {
            &Expr::Sym(ref x) => Ok(x),
            hd => Err(E::Type(Type::Sym, hd.clone()))
        }
    );
    ($v:expr, Nil) => (
        match $v {
            &Expr::Nil => Ok(()),
            hd => Err(E::Type(Type::Nil, hd.clone()))
        }
    );
    ($v:expr, Bool) => (
        match $v {
            &Expr::Nil => Ok(false),
            _ => Ok(true)
        }
    );
    ($v:expr, Cons) => (
        match $v {
            &Expr::Cons(ref car, ref cdr) => Ok((car.deref(), cdr.deref())),
            hd => Err(E::Type(Type::Cons, hd.clone()))
        }
    );
    ($v:expr, Proc) => (
        match $v {
            &Expr::Proc(ref p) => Ok(p),
            hd => Err(E::Type(Type::Proc, hd.clone()))
        }
    );
    ($v:expr, Any) => (
        match $v {
            hd => if true {
                Ok(hd)
            } else {
                unreachable!()
            }
        };
    )
}

macro_rules! gen_pattern {
    (($var: pat, $($ident: tt)*) $($other:tt) *) => (
        ($var, gen_pattern!($($other)*))
            );
    (&optional ($var: pat, $($ident: tt)*) $($other:tt) *) => (
        ($var, gen_pattern!($($other)*))
            );
    () => (())
}

macro_rules! gen_match {
    ($args: expr, ($var: pat, $($ident: tt)+) $($other:tt) *) =>
        (
            match $args {
                &Expr::Cons(ref hd, ref tl) => {
                    let v = try!(get_args_one!(hd.deref(), $($ident)+));
                    (v, gen_match!(tl.deref(), $($other)*))
                },
                &Expr::Nil => return Err(E::ArityShort),
                args => return Err(E::InvalidArgument(args.clone()))
            };
            );
    ($args: expr, &optional ($var: pat, $($ident: tt)+) $($other:tt) *) =>
        (
            match $args {
                &Expr::Cons(ref hd, ref tl) => {
                    let v = try!(get_args_one!(hd.deref(), $($ident)+));
                    (Some(v), gen_match!(tl.deref(), &optional $($other)*))
                },
                &Expr::Nil => {
                    (None, gen_match!($args, &optional $($other)*))

                },
                args => return Err(E::InvalidArgument(args.clone()))
            };
            );
    ($args: expr, &optional) => (
        match $args {
            &Expr::Nil => (),
            _ => return Err(E::ArityExceed)
        }
        );
    ($args: expr, ) => (
        match $args {
            &Expr::Nil => (),
            _ => return Err(E::ArityExceed)
        }
        );
}

#[macro_export]
macro_rules! get_args {
    ($args: expr, $($other:tt) *) =>
        (
            let gen_pattern!($($other)*) = gen_match!($args, $($other)*)
            ) ;
    ($args: expr, ) => (
        let () = gen_match!($args,)
        );
    ($args: expr) => (
        let () = gen_match!($args,)
        );
}

pub fn f_foldl<F>(mut env: &mut Env, f: &F, init: &Expr, args: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr, &Expr) -> Result<Expr>{
    let mut res = init.clone();
    let mut head = args;
    let nil = &Expr::Nil;
    while head != nil {
        match head {
            &Expr::Cons(ref car, ref cdr) => {
                res = try!(f(env, &res, car));
                head = cdr;
            }
            _ => return Err(E::InvalidArgument(args.clone()))
        }
    }
    Ok(res)
}

// fn f_reverse(mut env: &mut Env, args: &Expr) -> Result<Expr> {
//     f_foldl(env, &|_, acc, x| Ok(Expr::Cons(Rc::new(x.clone()), Rc::new(acc))), Expr::Nil, args)
// }

pub fn f_foldr<F>(mut env: &mut Env, f: &F, init: &Expr, args: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr, &Expr) -> Result<Expr>{
    match args {
        &Expr::Nil => Ok(init.clone()),
        &Expr::Cons(ref car, ref cdr) => {
            let v = try!(f_foldr(env, f, init, cdr));
            f(env, &v, car)
        }
        args => Err(E::InvalidArgument(args.clone()))
    }
}

pub fn f_map<F>(mut env: &mut Env, f: &F, list: &Expr) -> Result<Expr>
    where F: Fn(&mut Env, &Expr) -> Result<Expr>{
    f_foldr(env, &|env, acc, x| Ok(kcons(try!(f(env, x)), acc.clone()))
                 , &Expr::Nil, list)
}

// fn f_iter<F>(mut env: &mut Env, f: &F, list: &Expr) -> Result<Expr>
//     where F: Fn(&mut Env, Expr) -> Result<()>{
//     f_foldr(env, &|env, _, x| {try!(f(env,x.clone())); Ok(Expr::Nil)}
//                  , Expr::Nil, list)
// }

<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;
use traits::Cross;

/// 3D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec3 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
    /// component of vector
    pub z: f64,
}

impl Vec3 {
    /// Constructs a new `Vec3`.
    pub fn new(x: f64, y: f64, z: f64) -> Vec3 {
        Vec3 { x: x, y: y, z: z }
    }
    /// Constructs a new `Vec3` from spherical coordinates $(r, \theta, \phi)$.
    pub fn from_spherical(r: f64, theta: f64, phi: f64) -> Vec3 {
        Vec3::new(r * f64::sin(theta) * f64::cos(phi),
                  r * f64::sin(theta) * f64::sin(phi),
                  r * f64::cos(theta))
    }
    /// Create a zero `Vec3`
    pub fn zero() -> Vec3 {
        Vec3::new(0.0, 0.0, 0.0)
    }
    /// Scalar product
    pub fn dot(self, rhs: Vec3) -> f64 {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
    /// Vector length
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    pub fn ort(self) -> Vec3 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    pub fn sqr(self) -> Vec3 {
        self * self
    }
    /// Square root of vector coordinates
    pub fn sqrt(self) -> Vec3 {
        Vec3::new(self.x.sqrt(), self.y.sqrt(), self.z.sqrt())
    }
}

impl Add for Vec3 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec3::new(self.x + _rhs.x, self.y + _rhs.y, self.z + _rhs.z)
    }
}

impl Sub for Vec3 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec3::new(self.x - _rhs.x, self.y - _rhs.y, self.z - _rhs.z)
    }
}

impl Mul for Vec3 {
    type Output = Self;

    fn mul(self, _rhs: Vec3) -> Vec3 {
        Vec3::new(self.x * _rhs.x, self.y * _rhs.y, self.z * _rhs.z)
    }
}

impl Mul<f64> for Vec3 {
    type Output = Self;

    fn mul(self, _rhs: f64) -> Vec3 {
        Vec3::new(self.x * _rhs, self.y * _rhs, self.z * _rhs)
    }
}

impl Div<f64> for Vec3 {
    type Output = Self;

    fn div(self, _rhs: f64) -> Vec3 {
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec3::new(self.x / _rhs, self.y / _rhs, self.z / _rhs)
    }
}

impl Neg for Vec3 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y, -self.z)
    }
}

impl Cross for Vec3 {
    type Output = Self;

    fn cross(self, rhs: Vec3) -> Self {
        Self::new(self.y * rhs.z - self.z * rhs.y,
                  self.z * rhs.x - self.x * rhs.z,
                  self.x * rhs.y - self.y * rhs.x)
    }
}

impl PartialEq for Vec3 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

impl fmt::Display for Vec3 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {}", self.x, self.y, self.z)
    }
}

impl FromStr for Vec3 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        let z: f64 = try!(words[2].parse());
        Ok(Self::new(x, y, z))
    }
}

#[cfg(test)]
mod linal_test {
    use super::*;
    use traits::Cross;

    #[test]
    fn vec3_mul() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(3.0, 6.0, 9.0);
        let r = a * 3.0;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec3_div() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let _ = a / 0.0;
    }

    #[test]
    #[ignore]
    fn vec3_from_spherical() {
        // need test
    }

    #[test]
    fn vec3_add() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = Vec3::new(-2.0, 8.0, 7.0);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec3_sub() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = Vec3::new(4.0, -4.0, -1.0);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec3_dot() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = 21.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec3_cross() {
        let a = Vec3::new(4.0, 0.0, 0.0);
        let b = Vec3::new(3.0, 5.0, 0.0);
        let c = Vec3::new(0.0, 0.0, 20.0);
        assert_eq!(a.cross(b), c);
        assert_eq!(b.cross(a), -c);
    }

    #[test]
    fn vec3_neg() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-1.0, -2.0, -3.0);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec3_parse() {
        let a: Vec3 = "1 2 3".parse().unwrap();
        assert_eq!(a, Vec3::new(1.0, 2.0, 3.0));
    }
}
<commit_msg>[add] test for Vec3::from_spherical<commit_after>use std::ops::{Add, Sub, Mul, Div, Neg};
use std::cmp::PartialEq;
use std::str::FromStr;
use std::fmt;
use std::num;
use traits::Cross;

/// 3D vector in cartesian coordinates
#[derive(Debug, Clone, Copy)]
pub struct Vec3 {
    /// component of vector
    pub x: f64,
    /// component of vector
    pub y: f64,
    /// component of vector
    pub z: f64,
}

impl Vec3 {
    /// Constructs a new `Vec3`.
    pub fn new(x: f64, y: f64, z: f64) -> Vec3 {
        Vec3 { x: x, y: y, z: z }
    }
    /// Constructs a new `Vec3` from spherical coordinates $(r, \theta, \phi)$.
    pub fn from_spherical(r: f64, theta: f64, phi: f64) -> Vec3 {
        Vec3::new(r * f64::sin(theta) * f64::cos(phi),
                  r * f64::sin(theta) * f64::sin(phi),
                  r * f64::cos(theta))
    }
    /// Create a zero `Vec3`
    pub fn zero() -> Vec3 {
        Vec3::new(0.0, 0.0, 0.0)
    }
    /// Scalar product
    pub fn dot(self, rhs: Vec3) -> f64 {
        self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
    }
    /// Vector length
    pub fn len(self) -> f64 {
        self.dot(self).sqrt()
    }
    /// Unary vector, co-directed with given
    pub fn ort(self) -> Vec3 {
        self / self.len()
    }
    /// Squares of the vector coordinates
    pub fn sqr(self) -> Vec3 {
        self * self
    }
    /// Square root of vector coordinates
    pub fn sqrt(self) -> Vec3 {
        Vec3::new(self.x.sqrt(), self.y.sqrt(), self.z.sqrt())
    }
}

impl Add for Vec3 {
    type Output = Self;

    fn add(self, _rhs: Self) -> Self {
        Vec3::new(self.x + _rhs.x, self.y + _rhs.y, self.z + _rhs.z)
    }
}

impl Sub for Vec3 {
    type Output = Self;

    fn sub(self, _rhs: Self) -> Self {
        Vec3::new(self.x - _rhs.x, self.y - _rhs.y, self.z - _rhs.z)
    }
}

impl Mul for Vec3 {
    type Output = Self;

    fn mul(self, _rhs: Vec3) -> Vec3 {
        Vec3::new(self.x * _rhs.x, self.y * _rhs.y, self.z * _rhs.z)
    }
}

impl Mul<f64> for Vec3 {
    type Output = Self;

    fn mul(self, _rhs: f64) -> Vec3 {
        Vec3::new(self.x * _rhs, self.y * _rhs, self.z * _rhs)
    }
}

impl Div<f64> for Vec3 {
    type Output = Self;

    fn div(self, _rhs: f64) -> Vec3 {
        if _rhs == 0.0 {
            panic!("Can't divide by zero!");
        }
        Vec3::new(self.x / _rhs, self.y / _rhs, self.z / _rhs)
    }
}

impl Neg for Vec3 {
    type Output = Self;

    fn neg(self) -> Self {
        Self::new(-self.x, -self.y, -self.z)
    }
}

impl Cross for Vec3 {
    type Output = Self;

    fn cross(self, rhs: Vec3) -> Self {
        Self::new(self.y * rhs.z - self.z * rhs.y,
                  self.z * rhs.x - self.x * rhs.z,
                  self.x * rhs.y - self.y * rhs.x)
    }
}

impl PartialEq for Vec3 {
    fn eq(&self, other: &Self) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

impl fmt::Display for Vec3 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {} {}", self.x, self.y, self.z)
    }
}

impl FromStr for Vec3 {
    type Err = num::ParseFloatError;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let words: Vec<&str> = s.split_whitespace().collect();
        let x: f64 = try!(words[0].parse());
        let y: f64 = try!(words[1].parse());
        let z: f64 = try!(words[2].parse());
        Ok(Self::new(x, y, z))
    }
}

#[cfg(test)]
mod linal_test {
    use super::*;
    use traits::Cross;

    #[test]
    fn vec3_mul() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(3.0, 6.0, 9.0);
        let r = a * 3.0;
        assert_eq!(r, b);
    }

    #[test]
    #[should_panic]
    fn vec3_div() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let _ = a / 0.0;
    }

    #[test]
    fn vec3_from_spherical() {
        use std::f64::consts::PI;
        let a = Vec3::from_spherical(5.0, PI / 2.0, 3f64.atan2(4.0));
        let b = Vec3::new(4.0, 3.0, 0.0);
        assert!((a - b).len() < 1e-10);
    }

    #[test]
    fn vec3_add() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = Vec3::new(-2.0, 8.0, 7.0);
        assert_eq!(a + b, c);
    }

    #[test]
    fn vec3_sub() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = Vec3::new(4.0, -4.0, -1.0);
        assert_eq!(a - b, c);
    }

    #[test]
    fn vec3_dot() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-3.0, 6.0, 4.0);
        let c = 21.0;
        assert_eq!(a.dot(b), c);
        assert_eq!(b.dot(a), c);
    }

    #[test]
    fn vec3_cross() {
        let a = Vec3::new(4.0, 0.0, 0.0);
        let b = Vec3::new(3.0, 5.0, 0.0);
        let c = Vec3::new(0.0, 0.0, 20.0);
        assert_eq!(a.cross(b), c);
        assert_eq!(b.cross(a), -c);
    }

    #[test]
    fn vec3_neg() {
        let a = Vec3::new(1.0, 2.0, 3.0);
        let b = Vec3::new(-1.0, -2.0, -3.0);
        assert_eq!(-a, b);
    }

    #[test]
    fn vec3_parse() {
        let a: Vec3 = "1 2 3".parse().unwrap();
        assert_eq!(a, Vec3::new(1.0, 2.0, 3.0));
    }
}
<|endoftext|>


<commit_before>use super::arch::{Arch};

#[derive(Debug, Clone)]
pub enum XrefType {
    // mov eax, eax
    // push ebp
    Fallthrough,
    // call [0x401000]
    Call,
    // call [eax]
    //IndirectCall { src: Rva },
    // jmp 0x401000
    UnconditionalJump,
    // jmp eax
    //UnconditionalIndirectJump { src: Rva, dst: Rva },
    // jnz 0x401000
    ConditionalJump,
    // jnz eax
    //ConditionalIndirectJump { src: Rva },
    // cmov 0x1
    ConditionalMove,
}

#[derive(Debug, Clone)]
pub struct Xref<A: Arch> {
    src: A::RVA,
    dst: A::RVA,
    typ: XrefType,
}
<commit_msg>xref: add clone to xref types<commit_after>use super::arch::{Arch};

#[derive(Debug, Copy, Clone)]
pub enum XrefType {
    // mov eax, eax
    // push ebp
    Fallthrough,
    // call [0x401000]
    Call,
    // call [eax]
    //IndirectCall { src: Rva },
    // jmp 0x401000
    UnconditionalJump,
    // jmp eax
    //UnconditionalIndirectJump { src: Rva, dst: Rva },
    // jnz 0x401000
    ConditionalJump,
    // jnz eax
    //ConditionalIndirectJump { src: Rva },
    // cmov 0x1
    ConditionalMove,
}

#[derive(Debug, Copy, Clone)]
pub struct Xref<A: Arch> {
    src: A::RVA,
    dst: A::RVA,
    typ: XrefType,
}
<|endoftext|>


<commit_before>//! A module that describes a logical term in a formula
//!
//! A term consists of a series of symbol values that can have
//! new values pushed into it. Insertions will make sure that the
//! term is symbol is unique in a term

/// A logical symbol in a term
#[derive(Copy, Clone, Debug)]
pub struct Symbol {
    pub val: char,
    pub state: bool,
}

impl PartialEq for Symbol {
    fn eq(&self, other: &Symbol) -> bool {
        self.val == other.val && self.state == other.state
    }
}

/// Represents a list of symbols in OR operator chain which in a LRS notation
///   would make up something like { A, B, ¬C }. Insertions are sanitised to
///   make sure that there are never two contradicting symbols in the same term.
pub struct Term {
    pub symbols: Vec<Symbol>,
}

impl Term {
    /// Very simple constructor that initialises a term with one symbol
    pub fn new(symbol: Symbol) -> Term {
        let mut t = Term {
            symbols: Vec::new(),
        };

        t.symbols.push(symbol);
        return t;
    }

    /// Simple linear `contains` function for a Term. Avoid using this
    ///   as it can lead to high runtimes on longer terms.
    pub fn contains(&self, sym: &Symbol) -> bool {
        for symbol in self.symbols.iter() {
            if symbol == sym {
                return true;
            }
        }
        return false;
    }

    /// Insert a new symbol at the end of the term. Returns a boolean
    ///   indicating if the insert was successful!
    pub fn insert(&mut self, sym: Symbol) -> bool {
        if self.contains(&sym) {
            return false;
        }

        self.symbols.push(sym);
        return true;
    }

    /// Removes a symbol from this term if it exists in linear time
    pub fn remove(&mut self, sym: Symbol) -> bool {
        if !self.contains(&sym) {
            return false;
        }

        /* Only push to new vector if value is right */
        let mut newvec: Vec<Symbol> = Vec::new();
        for s in &self.symbols {
            if sym != *s {
                newvec.push(*s);
            }
        }

        /* Then use the new vector instead */
        self.symbols = newvec;
        return true;
    }

    /// Merge two terms together in a very naive way. This function will only check
    /// for same duplicates (to avoid { A, A, B } situations). This will however allow
    /// { A, ¬A } scenarios. Those need to be removed manually
    pub fn merge(&mut self, other: Term) {
        let ovec: Vec<Symbol> = other.symbols;
        for sym in ovec.iter() {
            self.insert(sym.clone());
        }
    }
}

/// A helper macro that creates terms with a variable amount of symbols
///   based on the more user friendly syntax
///
/// term!["A", "!B", "C"]
///
/// Please note that your symbols aren't allowed to be multi-character
/// but can include all utf-8 symbols (including emoji 🔥🎉)
#[macro_export]
macro_rules! term {
    ( $( $x:expr ),* ) => {{
        let mut ts: Vec<Symbol> = Vec::new();

        $(
            if $x.starts_with('!') {
                let ch = $x.chars().nth(1).unwrap();
                ts.push( Symbol { val: ch, state: false });
            } else {
                let ch = $x.chars().nth(0).unwrap();
                ts.push( Symbol { val: ch, state: true });
            }
        )*

        Term { symbols: ts }
    }};
}

/// A slightly smaller helper macro that creates a symbol based on a string
#[macro_export]
macro_rules! symbol {
    ($x:expr) => {{
        if $x.starts_with('!') {
            let ch = $x.chars().nth(1).unwrap();
            Symbol { val: ch, state: false }
        } else {
            let ch = $x.chars().nth(0).unwrap();
            Symbol { val: ch, state: true }
        }
    }};
}
<commit_msg>Reducing macro compexity<commit_after>//! A module that describes a logical term in a formula
//!
//! A term consists of a series of symbol values that can have
//! new values pushed into it. Insertions will make sure that the
//! term is symbol is unique in a term

/// A logical symbol in a term
#[derive(Copy, Clone, Debug)]
pub struct Symbol {
    pub val: char,
    pub state: bool,
}

impl PartialEq for Symbol {
    fn eq(&self, other: &Symbol) -> bool {
        self.val == other.val && self.state == other.state
    }
}

/// Represents a list of symbols in OR operator chain which in a LRS notation
///   would make up something like { A, B, ¬C }. Insertions are sanitised to
///   make sure that there are never two contradicting symbols in the same term.
pub struct Term {
    pub symbols: Vec<Symbol>,
}

impl Term {
    /// Very simple constructor that initialises a term with one symbol
    pub fn new(symbol: Symbol) -> Term {
        let mut t = Term {
            symbols: Vec::new(),
        };

        t.symbols.push(symbol);
        return t;
    }

    /// Simple linear `contains` function for a Term. Avoid using this
    ///   as it can lead to high runtimes on longer terms.
    pub fn contains(&self, sym: &Symbol) -> bool {
        for symbol in self.symbols.iter() {
            if symbol == sym {
                return true;
            }
        }
        return false;
    }

    /// Insert a new symbol at the end of the term. Returns a boolean
    ///   indicating if the insert was successful!
    pub fn insert(&mut self, sym: Symbol) -> bool {
        if self.contains(&sym) {
            return false;
        }

        self.symbols.push(sym);
        return true;
    }

    /// Removes a symbol from this term if it exists in linear time
    pub fn remove(&mut self, sym: Symbol) -> bool {
        if !self.contains(&sym) {
            return false;
        }

        /* Only push to new vector if value is right */
        let mut newvec: Vec<Symbol> = Vec::new();
        for s in &self.symbols {
            if sym != *s {
                newvec.push(*s);
            }
        }

        /* Then use the new vector instead */
        self.symbols = newvec;
        return true;
    }

    /// Merge two terms together in a very naive way. This function will only check
    /// for same duplicates (to avoid { A, A, B } situations). This will however allow
    /// { A, ¬A } scenarios. Those need to be removed manually
    pub fn merge(&mut self, other: Term) {
        let ovec: Vec<Symbol> = other.symbols;
        for sym in ovec.iter() {
            self.insert(sym.clone());
        }
    }
}

/// A helper macro that creates terms with a variable amount of symbols
///   based on the more user friendly syntax
///
/// term!["A", "!B", "C"]
///
/// Please note that your symbols aren't allowed to be multi-character
/// but can include all utf-8 symbols (including emoji 🔥🎉)
#[macro_export]
macro_rules! term {
    ( $( $x:expr ),* ) => {{
        let mut ts: Vec<Symbol> = Vec::new();
        $( ts.push(symbol!($x)); )*
        Term { symbols: ts }
    }};
}

/// A slightly smaller helper macro that creates a symbol based on a string
#[macro_export]
macro_rules! symbol {
    ($x:expr) => {{
        if $x.starts_with('!') {
            let ch = $x.chars().nth(1).unwrap();
            Symbol { val: ch, state: false }
        } else {
            let ch = $x.chars().nth(0).unwrap();
            Symbol { val: ch, state: true }
        }
    }};
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Utilities for the implementation of JSAPI proxy handlers.

#![deny(missing_docs)]

use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id;
use js::glue::{GetProxyHandler, GetProxyHandlerFamily, SetProxyExtra};
use js::glue::GetProxyExtra;
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::jsapi::{DOMProxyShadowsResult, JSContext, JSObject, JSPROP_GETTER, PropertyDescriptor};
use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult};
use js::jsapi::{JSErrNum, JS_AlreadyHasOwnPropertyById, JS_StrictPropertyStub};
use js::jsapi::{JS_DefinePropertyById, JS_NewObjectWithGivenProto, SetDOMProxyInformation};
use js::jsapi::GetObjectProto;
use js::jsapi::GetStaticPrototype;
use js::jsapi::JS_GetPropertyDescriptorById;
use js::jsapi::MutableHandleObject;
use js::jsval::ObjectValue;
use libc;
use std::{mem, ptr};

static JSPROXYSLOT_EXPANDO: u32 = 0;

/// Determine if this id shadows any existing properties for this proxy.
pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
                                               object: HandleObject,
                                               id: HandleId)
                                               -> DOMProxyShadowsResult {
    // TODO: support OverrideBuiltins when #12978 is fixed.

    rooted!(in(cx) let mut expando = ptr::null_mut());
    get_expando_object(object, expando.handle_mut());
    if !expando.get().is_null() {
        let mut has_own = false;
        if !JS_AlreadyHasOwnPropertyById(cx, expando.handle(), id, &mut has_own) {
            return DOMProxyShadowsResult::ShadowCheckFailed;
        }

        if has_own {
            return DOMProxyShadowsResult::ShadowsViaDirectExpando;
        }
    }

    // Our expando, if any, didn't shadow, so we're not shadowing at all.
    DOMProxyShadowsResult::DoesntShadow
}

/// Initialize the infrastructure for DOM proxy objects.
pub unsafe fn init() {
    SetDOMProxyInformation(GetProxyHandlerFamily(),
                           JSPROXYSLOT_EXPANDO,
                           Some(shadow_check_callback));
}

/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// with argument `id` and return the result, if it is not `undefined`.
/// Otherwise, walk along the prototype chain to find a property with that
/// name.
pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 id: HandleId,
                                                 desc: MutableHandle<PropertyDescriptor>)
                                                 -> bool {
    let handler = GetProxyHandler(proxy.get());
    if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
        return false;
    }
    if !desc.obj.is_null() {
        return true;
    }

    rooted!(in(cx) let mut proto = ptr::null_mut());
    if !GetObjectProto(cx, proxy, proto.handle_mut()) {
        // FIXME(#11868) Should assign to desc.obj, desc.get() is a copy.
        desc.get().obj = ptr::null_mut();
        return true;
    }

    JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
}

/// Defines an expando on the given `proxy`.
pub unsafe extern "C" fn define_property(cx: *mut JSContext,
                                         proxy: HandleObject,
                                         id: HandleId,
                                         desc: Handle<PropertyDescriptor>,
                                         result: *mut ObjectOpResult)
                                         -> bool {
    // FIXME: Workaround for https://github.com/rust-lang/rfcs/issues/718
    let setter: *const libc::c_void = mem::transmute(desc.get().setter);
    let setter_stub: unsafe extern fn(_, _, _, _, _) -> _ = JS_StrictPropertyStub;
    let setter_stub: *const libc::c_void = mem::transmute(setter_stub);
    if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub {
        (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as ::libc::uintptr_t;
        return true;
    }

    rooted!(in(cx) let mut expando = ptr::null_mut());
    ensure_expando_object(cx, proxy, expando.handle_mut());
    JS_DefinePropertyById(cx, expando.handle(), id, desc, result)
}

/// Deletes an expando off the given `proxy`.
pub unsafe extern "C" fn delete(cx: *mut JSContext,
                                proxy: HandleObject,
                                id: HandleId,
                                bp: *mut ObjectOpResult)
                                -> bool {
    rooted!(in(cx) let mut expando = ptr::null_mut());
    get_expando_object(proxy, expando.handle_mut());
    if expando.is_null() {
        (*bp).code_ = 0 /* OkCode */;
        return true;
    }

    delete_property_by_id(cx, expando.handle(), id, bp)
}

/// Controls whether the Extensible bit can be changed
pub unsafe extern "C" fn prevent_extensions(_cx: *mut JSContext,
                                            _proxy: HandleObject,
                                            result: *mut ObjectOpResult)
                                            -> bool {
    (*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t;
    true
}

/// Reports whether the object is Extensible
pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
                                       _proxy: HandleObject,
                                       succeeded: *mut bool)
                                       -> bool {
    *succeeded = true;
    true
}

/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as
/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior
/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s
/// prototype in `proto`.  Otherwise set `*isOrdinary` to false. In case of
/// error, both outparams have unspecified value.
///
/// This implementation always handles the case of the ordinary
/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
/// necessary for the Location object.
pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
                                                   proxy: HandleObject,
                                                   is_ordinary: *mut bool,
                                                   proto: MutableHandleObject)
                                                   -> bool {
    *is_ordinary = true;
    proto.set(GetStaticPrototype(proxy.get()));
    true
}

/// Get the expando object, or null if there is none.
pub unsafe fn get_expando_object(obj: HandleObject, expando: MutableHandleObject) {
    assert!(is_dom_proxy(obj.get()));
    let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
    expando.set(if val.is_undefined() {
        ptr::null_mut()
    } else {
        val.to_object()
    });
}

/// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure.
pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject, expando: MutableHandleObject) {
    assert!(is_dom_proxy(obj.get()));
    get_expando_object(obj, expando);
    if expando.is_null() {
        expando.set(JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null()));
        assert!(!expando.is_null());

        SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, &ObjectValue(expando.get()));
    }
}

/// Set the property descriptor's object to `obj` and set it to enumerable,
/// and writable if `readonly` is true.
pub fn fill_property_descriptor(mut desc: MutableHandle<PropertyDescriptor>,
                                obj: *mut JSObject,
                                attrs: u32) {
    desc.obj = obj;
    desc.attrs = attrs;
    desc.getter = None;
    desc.setter = None;
}
<commit_msg>Remove a workaround for https://github.com/rust-lang/rfcs/issues/718<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Utilities for the implementation of JSAPI proxy handlers.

#![deny(missing_docs)]

use dom::bindings::conversions::is_dom_proxy;
use dom::bindings::utils::delete_property_by_id;
use js::glue::{GetProxyHandler, GetProxyHandlerFamily, SetProxyExtra};
use js::glue::GetProxyExtra;
use js::glue::InvokeGetOwnPropertyDescriptor;
use js::jsapi::{DOMProxyShadowsResult, JSContext, JSObject, JSPROP_GETTER, PropertyDescriptor};
use js::jsapi::{Handle, HandleId, HandleObject, MutableHandle, ObjectOpResult};
use js::jsapi::{JSErrNum, JS_AlreadyHasOwnPropertyById, JS_StrictPropertyStub};
use js::jsapi::{JS_DefinePropertyById, JS_NewObjectWithGivenProto, SetDOMProxyInformation};
use js::jsapi::GetObjectProto;
use js::jsapi::GetStaticPrototype;
use js::jsapi::JS_GetPropertyDescriptorById;
use js::jsapi::MutableHandleObject;
use js::jsval::ObjectValue;
use std::ptr;

static JSPROXYSLOT_EXPANDO: u32 = 0;

/// Determine if this id shadows any existing properties for this proxy.
pub unsafe extern "C" fn shadow_check_callback(cx: *mut JSContext,
                                               object: HandleObject,
                                               id: HandleId)
                                               -> DOMProxyShadowsResult {
    // TODO: support OverrideBuiltins when #12978 is fixed.

    rooted!(in(cx) let mut expando = ptr::null_mut());
    get_expando_object(object, expando.handle_mut());
    if !expando.get().is_null() {
        let mut has_own = false;
        if !JS_AlreadyHasOwnPropertyById(cx, expando.handle(), id, &mut has_own) {
            return DOMProxyShadowsResult::ShadowCheckFailed;
        }

        if has_own {
            return DOMProxyShadowsResult::ShadowsViaDirectExpando;
        }
    }

    // Our expando, if any, didn't shadow, so we're not shadowing at all.
    DOMProxyShadowsResult::DoesntShadow
}

/// Initialize the infrastructure for DOM proxy objects.
pub unsafe fn init() {
    SetDOMProxyInformation(GetProxyHandlerFamily(),
                           JSPROXYSLOT_EXPANDO,
                           Some(shadow_check_callback));
}

/// Invoke the [[GetOwnProperty]] trap (`getOwnPropertyDescriptor`) on `proxy`,
/// with argument `id` and return the result, if it is not `undefined`.
/// Otherwise, walk along the prototype chain to find a property with that
/// name.
pub unsafe extern "C" fn get_property_descriptor(cx: *mut JSContext,
                                                 proxy: HandleObject,
                                                 id: HandleId,
                                                 desc: MutableHandle<PropertyDescriptor>)
                                                 -> bool {
    let handler = GetProxyHandler(proxy.get());
    if !InvokeGetOwnPropertyDescriptor(handler, cx, proxy, id, desc) {
        return false;
    }
    if !desc.obj.is_null() {
        return true;
    }

    rooted!(in(cx) let mut proto = ptr::null_mut());
    if !GetObjectProto(cx, proxy, proto.handle_mut()) {
        // FIXME(#11868) Should assign to desc.obj, desc.get() is a copy.
        desc.get().obj = ptr::null_mut();
        return true;
    }

    JS_GetPropertyDescriptorById(cx, proto.handle(), id, desc)
}

/// Defines an expando on the given `proxy`.
pub unsafe extern "C" fn define_property(cx: *mut JSContext,
                                         proxy: HandleObject,
                                         id: HandleId,
                                         desc: Handle<PropertyDescriptor>,
                                         result: *mut ObjectOpResult)
                                         -> bool {
    if (desc.get().attrs & JSPROP_GETTER) != 0 && desc.get().setter == Some(JS_StrictPropertyStub) {
        (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as ::libc::uintptr_t;
        return true;
    }

    rooted!(in(cx) let mut expando = ptr::null_mut());
    ensure_expando_object(cx, proxy, expando.handle_mut());
    JS_DefinePropertyById(cx, expando.handle(), id, desc, result)
}

/// Deletes an expando off the given `proxy`.
pub unsafe extern "C" fn delete(cx: *mut JSContext,
                                proxy: HandleObject,
                                id: HandleId,
                                bp: *mut ObjectOpResult)
                                -> bool {
    rooted!(in(cx) let mut expando = ptr::null_mut());
    get_expando_object(proxy, expando.handle_mut());
    if expando.is_null() {
        (*bp).code_ = 0 /* OkCode */;
        return true;
    }

    delete_property_by_id(cx, expando.handle(), id, bp)
}

/// Controls whether the Extensible bit can be changed
pub unsafe extern "C" fn prevent_extensions(_cx: *mut JSContext,
                                            _proxy: HandleObject,
                                            result: *mut ObjectOpResult)
                                            -> bool {
    (*result).code_ = JSErrNum::JSMSG_CANT_PREVENT_EXTENSIONS as ::libc::uintptr_t;
    true
}

/// Reports whether the object is Extensible
pub unsafe extern "C" fn is_extensible(_cx: *mut JSContext,
                                       _proxy: HandleObject,
                                       succeeded: *mut bool)
                                       -> bool {
    *succeeded = true;
    true
}

/// If `proxy` (underneath any functionally-transparent wrapper proxies) has as
/// its `[[GetPrototypeOf]]` trap the ordinary `[[GetPrototypeOf]]` behavior
/// defined for ordinary objects, set `*is_ordinary` to true and store `obj`'s
/// prototype in `proto`.  Otherwise set `*isOrdinary` to false. In case of
/// error, both outparams have unspecified value.
///
/// This implementation always handles the case of the ordinary
/// `[[GetPrototypeOf]]` behavior. An alternative implementation will be
/// necessary for the Location object.
pub unsafe extern "C" fn get_prototype_if_ordinary(_: *mut JSContext,
                                                   proxy: HandleObject,
                                                   is_ordinary: *mut bool,
                                                   proto: MutableHandleObject)
                                                   -> bool {
    *is_ordinary = true;
    proto.set(GetStaticPrototype(proxy.get()));
    true
}

/// Get the expando object, or null if there is none.
pub unsafe fn get_expando_object(obj: HandleObject, expando: MutableHandleObject) {
    assert!(is_dom_proxy(obj.get()));
    let val = GetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO);
    expando.set(if val.is_undefined() {
        ptr::null_mut()
    } else {
        val.to_object()
    });
}

/// Get the expando object, or create it if it doesn't exist yet.
/// Fails on JSAPI failure.
pub unsafe fn ensure_expando_object(cx: *mut JSContext, obj: HandleObject, expando: MutableHandleObject) {
    assert!(is_dom_proxy(obj.get()));
    get_expando_object(obj, expando);
    if expando.is_null() {
        expando.set(JS_NewObjectWithGivenProto(cx, ptr::null_mut(), HandleObject::null()));
        assert!(!expando.is_null());

        SetProxyExtra(obj.get(), JSPROXYSLOT_EXPANDO, &ObjectValue(expando.get()));
    }
}

/// Set the property descriptor's object to `obj` and set it to enumerable,
/// and writable if `readonly` is true.
pub fn fill_property_descriptor(mut desc: MutableHandle<PropertyDescriptor>,
                                obj: *mut JSObject,
                                attrs: u32) {
    desc.obj = obj;
    desc.attrs = attrs;
    desc.getter = None;
    desc.setter = None;
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use rustc_serialize::json;
use std::mem;
use std::net::TcpStream;
use time::precise_time_ns;

use actor::{Actor, ActorRegistry};

pub struct FramerateActor {
    name: String,
    start_time: Option<u64>,
    is_recording: bool,
    ticks: Vec<u64>,
}

impl Actor for FramerateActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      _registry: &ActorRegistry,
                      _msg_type: &str,
                      _msg: &json::Object,
                      _stream: &mut TcpStream) -> Result<bool, ()> {
        Ok(false)
    }
}

impl FramerateActor {
    /// return name of actor
    pub fn create(registry: &ActorRegistry) -> String {
        let actor_name = registry.new_name("framerate");
        let mut actor = FramerateActor {
            name: actor_name.clone(),
            start_time: None,
            is_recording: false,
            ticks: Vec::new(),
        };

        actor.start_recording();
        registry.register_later(box actor);
        actor_name
    }

    // callback on request animation frame
    pub fn on_refresh_driver_tick(&mut self) {
        if !self.is_recording {
            return;
        }
        // TODO: Need implement requesting animation frame
        // http://hg.mozilla.org/mozilla-central/file/0a46652bd992/dom/base/nsGlobalWindow.cpp#l5314

        let start_time = self.start_time.as_ref().unwrap();
        self.ticks.push(*start_time - precise_time_ns());
    }

    pub fn take_pending_ticks(&mut self) -> Vec<u64> {
        mem::replace(&mut self.ticks, Vec::new())
    }

    fn start_recording(&mut self) {
        self.is_recording = true;
        self.start_time = Some(precise_time_ns());

        // TODO: Need implement requesting animation frame
        // http://hg.mozilla.org/mozilla-central/file/0a46652bd992/dom/base/nsGlobalWindow.cpp#l5314
    }

    fn stop_recording(&mut self) {
        if !self.is_recording {
            return;
        }
        self.is_recording = false;
        self.start_time = None;
    }

}

impl Drop for FramerateActor {
    fn drop(&mut self) {
        self.stop_recording();
    }
}
<commit_msg>Mention #5681 in a TODO comment.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use rustc_serialize::json;
use std::mem;
use std::net::TcpStream;
use time::precise_time_ns;

use actor::{Actor, ActorRegistry};

pub struct FramerateActor {
    name: String,
    start_time: Option<u64>,
    is_recording: bool,
    ticks: Vec<u64>,
}

impl Actor for FramerateActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      _registry: &ActorRegistry,
                      _msg_type: &str,
                      _msg: &json::Object,
                      _stream: &mut TcpStream) -> Result<bool, ()> {
        Ok(false)
    }
}

impl FramerateActor {
    /// return name of actor
    pub fn create(registry: &ActorRegistry) -> String {
        let actor_name = registry.new_name("framerate");
        let mut actor = FramerateActor {
            name: actor_name.clone(),
            start_time: None,
            is_recording: false,
            ticks: Vec::new(),
        };

        actor.start_recording();
        registry.register_later(box actor);
        actor_name
    }

    // callback on request animation frame
    #[allow(dead_code)]
    pub fn on_refresh_driver_tick(&mut self) {
        if !self.is_recording {
            return;
        }
        // TODO: Need implement requesting animation frame
        // http://hg.mozilla.org/mozilla-central/file/0a46652bd992/dom/base/nsGlobalWindow.cpp#l5314

        let start_time = self.start_time.as_ref().unwrap();
        self.ticks.push(*start_time - precise_time_ns());
    }

    pub fn take_pending_ticks(&mut self) -> Vec<u64> {
        mem::replace(&mut self.ticks, Vec::new())
    }

    fn start_recording(&mut self) {
        self.is_recording = true;
        self.start_time = Some(precise_time_ns());

        // TODO(#5681): Need implement requesting animation frame
        // http://hg.mozilla.org/mozilla-central/file/0a46652bd992/dom/base/nsGlobalWindow.cpp#l5314
    }

    fn stop_recording(&mut self) {
        if !self.is_recording {
            return;
        }
        self.is_recording = false;
        self.start_time = None;
    }

}

impl Drop for FramerateActor {
    fn drop(&mut self) {
        self.stop_recording();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::conversions::native_from_handleobject;
use dom::bindings::conversions::{ToJSValConvertible};
use dom::bindings::js::{JS, Root};
use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor};
use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::bindings::utils::get_array_index_from_id;
use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::window::Window;
use dom::window::WindowHelpers;

use js::jsapi::{JSContext, JSObject, JSPropertyDescriptor, JSErrNum};
use js::jsapi::{HandleObject, HandleId, MutableHandle, MutableHandleValue};
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetPropertyDescriptorById, JS_DefinePropertyById6};
use js::jsapi::{JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue, Handle, HandleValue, Heap};
use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::{ObjectValue, UndefinedValue};
use js::glue::{GetProxyPrivate};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::{JSTrue, JSFalse};

use std::ptr;
use std::default::Default;

#[derive(JSTraceable, HeapSizeOf)]
#[privatize]
#[allow(raw_pointer_derive)]
#[must_root]
pub struct BrowsingContext {
    history: Vec<SessionHistoryEntry>,
    active_index: usize,
    window_proxy: Heap<*mut JSObject>,
    frame_element: Option<JS<Element>>,
}

impl BrowsingContext {
    pub fn new(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
        BrowsingContext {
            history: vec!(SessionHistoryEntry::new(document)),
            active_index: 0,
            window_proxy: Heap::default(),
            frame_element: frame_element.map(JS::from_ref),
        }
    }

    pub fn active_document(&self) -> Root<Document> {
        self.history[self.active_index].document.root()
    }

    pub fn active_window(&self) -> Root<Window> {
        let doc = self.active_document();
        doc.r().window()
    }

    pub fn frame_element(&self) -> Option<Root<Element>> {
        self.frame_element.map(Root::from_rooted)
    }

    pub fn window_proxy(&self) -> *mut JSObject {
        assert!(!self.window_proxy.get().is_null());
        self.window_proxy.get()
    }

    #[allow(unsafe_code)]
    pub fn create_window_proxy(&mut self) {
        let win = self.active_window();
        let win = win.r();

        let WindowProxyHandler(handler) = win.windowproxy_handler();
        assert!(!handler.is_null());

        let cx = win.get_cx();
        let _ar = JSAutoRequest::new(cx);
        let parent = win.reflector().get_jsobject();
        let _ac = JSAutoCompartment::new(cx, parent.get());
        let wrapper = unsafe { WrapperNew(cx, parent, handler) };
        assert!(!wrapper.is_null());
        self.window_proxy.set(wrapper);
    }
}

// This isn't a DOM struct, just a convenience struct
// without a reflector, so we don't mark this as #[dom_struct]
#[must_root]
#[privatize]
#[derive(JSTraceable, HeapSizeOf)]
pub struct SessionHistoryEntry {
    document: JS<Document>,
    children: Vec<BrowsingContext>
}

impl SessionHistoryEntry {
    fn new(document: &Document) -> SessionHistoryEntry {
        SessionHistoryEntry {
            document: JS::from_ref(document),
            children: vec!()
        }
    }
}

#[allow(unsafe_code)]
unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> Option<Root<Window>> {
    let index = get_array_index_from_id(cx, id);
    if let Some(index) = index {
        let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
        let win: Root<Window> = native_from_handleobject(target.handle()).unwrap();
        let mut found = false;
        return win.r().IndexedGetter(index, &mut found);
    }

    None
}

#[allow(unsafe_code)]
unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
                                          desc: MutableHandle<JSPropertyDescriptor>) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if let Some(window) = window {
        let mut val = RootedValue::new(cx, UndefinedValue());
        window.to_jsval(cx, val.handle_mut());
        (*desc.ptr).value = val.ptr;
        fill_property_descriptor(&mut *desc.ptr, *proxy.ptr, true);
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    // XXX This should be JS_GetOwnPropertyDescriptorById
    if JS_GetPropertyDescriptorById(cx, target.handle(), id, desc) == 0 {
        return JSFalse;
    }

    if (*desc.ptr).obj != target.ptr {
        // Not an own property
        (*desc.ptr).obj = ptr::null_mut();
    } else {
        (*desc.ptr).obj = *proxy.ptr;
    }

    JSTrue
}

#[allow(unsafe_code)]
unsafe extern fn defineProperty(cx: *mut JSContext,
                                proxy: HandleObject,
                                id: HandleId,
                                desc: Handle<JSPropertyDescriptor>,
                                res: *mut ObjectOpResult) -> u8 {
    if get_array_index_from_id(cx, id).is_some() {
        // Spec says to Reject whether this is a supported index or not,
        // since we have no indexed setter or indexed creator.  That means
        // throwing in strict mode (FIXME: Bug 828137), doing nothing in
        // non-strict mode.
       (*res).code_ = JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT as u32;
       return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    JS_DefinePropertyById6(cx, target.handle(), id, desc, res)
}

#[allow(unsafe_code)]
unsafe extern fn hasOwn(cx: *mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut u8) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if window.is_some() {
        *bp = JSTrue;
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    let mut found = 0;
    if JS_AlreadyHasOwnPropertyById(cx, target.handle(), id, &mut found) == 0 {
        return JSFalse;
    }

    *bp = (found != 0) as u8;
    return JSTrue;
}

#[allow(unsafe_code)]
unsafe extern fn get(cx: *mut JSContext,
                     proxy: HandleObject,
                     receiver: HandleObject,
                     id: HandleId,
                     vp: MutableHandleValue) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if let Some(window) = window {
        window.to_jsval(cx, vp);
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    JS_ForwardGetPropertyTo(cx, target.handle(), id, receiver, vp)
}

#[allow(unsafe_code)]
unsafe extern fn set(cx: *mut JSContext,
                     proxy: HandleObject,
                     receiver: HandleObject,
                     id: HandleId,
                     vp: MutableHandleValue,
                     res: *mut ObjectOpResult) -> u8 {
    if get_array_index_from_id(cx, id).is_some() {
        // Reject (which means throw if and only if strict) the set.
        (*res).code_ = JSErrNum::JSMSG_READ_ONLY as u32;
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    let receiver = RootedValue::new(cx, ObjectValue(&**receiver.ptr));
    JS_ForwardSetPropertyTo(cx, target.handle(), id, HandleValue { ptr: vp.ptr }, receiver.handle(), res)
}

static PROXY_HANDLER: ProxyTraps = ProxyTraps {
    enter: None,
    getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
    defineProperty: Some(defineProperty),
    ownPropertyKeys: None,
    delete_: None,
    enumerate: None,
    preventExtensions: None,
    isExtensible: None,
    has: None,
    get: Some(get),
    set: Some(set),
    call: None,
    construct: None,
    getPropertyDescriptor: Some(get_property_descriptor),
    hasOwn: Some(hasOwn),
    getOwnEnumerablePropertyKeys: None,
    nativeCall: None,
    hasInstance: None,
    objectClassIs: None,
    className: None,
    fun_toString: None,
    boxedValue_unbox: None,
    defaultValue: None,
    trace: None,
    finalize: None,
    objectMoved: None,
    isCallable: None,
    isConstructor: None,
};

#[allow(unsafe_code)]
pub fn new_window_proxy_handler() -> WindowProxyHandler {
    unsafe {
        WindowProxyHandler(CreateWrapperProxyHandler(&PROXY_HANDLER))
    }
}
<commit_msg>Use JS_GetOwnPropertyDescriptorById in BrowserContext<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::conversions::native_from_handleobject;
use dom::bindings::conversions::{ToJSValConvertible};
use dom::bindings::js::{JS, Root};
use dom::bindings::proxyhandler::{get_property_descriptor, fill_property_descriptor};
use dom::bindings::utils::{Reflectable, WindowProxyHandler};
use dom::bindings::utils::get_array_index_from_id;
use dom::document::{Document, DocumentHelpers};
use dom::element::Element;
use dom::window::Window;
use dom::window::WindowHelpers;

use js::jsapi::{JSContext, JSObject, JSPropertyDescriptor, JSErrNum};
use js::jsapi::{HandleObject, HandleId, MutableHandle, MutableHandleValue};
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
use js::jsapi::{JS_GetOwnPropertyDescriptorById, JS_DefinePropertyById6};
use js::jsapi::{JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue, Handle, HandleValue, Heap};
use js::jsapi::{JSAutoRequest, JSAutoCompartment};
use js::jsval::{ObjectValue, UndefinedValue};
use js::glue::{GetProxyPrivate};
use js::glue::{WrapperNew, CreateWrapperProxyHandler, ProxyTraps};
use js::{JSTrue, JSFalse};

use std::ptr;
use std::default::Default;

#[derive(JSTraceable, HeapSizeOf)]
#[privatize]
#[allow(raw_pointer_derive)]
#[must_root]
pub struct BrowsingContext {
    history: Vec<SessionHistoryEntry>,
    active_index: usize,
    window_proxy: Heap<*mut JSObject>,
    frame_element: Option<JS<Element>>,
}

impl BrowsingContext {
    pub fn new(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
        BrowsingContext {
            history: vec!(SessionHistoryEntry::new(document)),
            active_index: 0,
            window_proxy: Heap::default(),
            frame_element: frame_element.map(JS::from_ref),
        }
    }

    pub fn active_document(&self) -> Root<Document> {
        self.history[self.active_index].document.root()
    }

    pub fn active_window(&self) -> Root<Window> {
        let doc = self.active_document();
        doc.r().window()
    }

    pub fn frame_element(&self) -> Option<Root<Element>> {
        self.frame_element.map(Root::from_rooted)
    }

    pub fn window_proxy(&self) -> *mut JSObject {
        assert!(!self.window_proxy.get().is_null());
        self.window_proxy.get()
    }

    #[allow(unsafe_code)]
    pub fn create_window_proxy(&mut self) {
        let win = self.active_window();
        let win = win.r();

        let WindowProxyHandler(handler) = win.windowproxy_handler();
        assert!(!handler.is_null());

        let cx = win.get_cx();
        let _ar = JSAutoRequest::new(cx);
        let parent = win.reflector().get_jsobject();
        let _ac = JSAutoCompartment::new(cx, parent.get());
        let wrapper = unsafe { WrapperNew(cx, parent, handler) };
        assert!(!wrapper.is_null());
        self.window_proxy.set(wrapper);
    }
}

// This isn't a DOM struct, just a convenience struct
// without a reflector, so we don't mark this as #[dom_struct]
#[must_root]
#[privatize]
#[derive(JSTraceable, HeapSizeOf)]
pub struct SessionHistoryEntry {
    document: JS<Document>,
    children: Vec<BrowsingContext>
}

impl SessionHistoryEntry {
    fn new(document: &Document) -> SessionHistoryEntry {
        SessionHistoryEntry {
            document: JS::from_ref(document),
            children: vec!()
        }
    }
}

#[allow(unsafe_code)]
unsafe fn GetSubframeWindow(cx: *mut JSContext, proxy: HandleObject, id: HandleId) -> Option<Root<Window>> {
    let index = get_array_index_from_id(cx, id);
    if let Some(index) = index {
        let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
        let win: Root<Window> = native_from_handleobject(target.handle()).unwrap();
        let mut found = false;
        return win.r().IndexedGetter(index, &mut found);
    }

    None
}

#[allow(unsafe_code)]
unsafe extern fn getOwnPropertyDescriptor(cx: *mut JSContext, proxy: HandleObject, id: HandleId,
                                          desc: MutableHandle<JSPropertyDescriptor>) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if let Some(window) = window {
        let mut val = RootedValue::new(cx, UndefinedValue());
        window.to_jsval(cx, val.handle_mut());
        (*desc.ptr).value = val.ptr;
        fill_property_descriptor(&mut *desc.ptr, *proxy.ptr, true);
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());

    if JS_GetOwnPropertyDescriptorById(cx, target.handle(), id, desc) == 0 {
        return JSFalse;
    }

    if (*desc.ptr).obj != target.ptr {
        // Not an own property
        (*desc.ptr).obj = ptr::null_mut();
    } else {
        (*desc.ptr).obj = *proxy.ptr;
    }

    JSTrue
}

#[allow(unsafe_code)]
unsafe extern fn defineProperty(cx: *mut JSContext,
                                proxy: HandleObject,
                                id: HandleId,
                                desc: Handle<JSPropertyDescriptor>,
                                res: *mut ObjectOpResult) -> u8 {
    if get_array_index_from_id(cx, id).is_some() {
        // Spec says to Reject whether this is a supported index or not,
        // since we have no indexed setter or indexed creator.  That means
        // throwing in strict mode (FIXME: Bug 828137), doing nothing in
        // non-strict mode.
       (*res).code_ = JSErrNum::JSMSG_CANT_DEFINE_WINDOW_ELEMENT as u32;
       return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    JS_DefinePropertyById6(cx, target.handle(), id, desc, res)
}

#[allow(unsafe_code)]
unsafe extern fn hasOwn(cx: *mut JSContext, proxy: HandleObject, id: HandleId, bp: *mut u8) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if window.is_some() {
        *bp = JSTrue;
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    let mut found = 0;
    if JS_AlreadyHasOwnPropertyById(cx, target.handle(), id, &mut found) == 0 {
        return JSFalse;
    }

    *bp = (found != 0) as u8;
    return JSTrue;
}

#[allow(unsafe_code)]
unsafe extern fn get(cx: *mut JSContext,
                     proxy: HandleObject,
                     receiver: HandleObject,
                     id: HandleId,
                     vp: MutableHandleValue) -> u8 {
    let window = GetSubframeWindow(cx, proxy, id);
    if let Some(window) = window {
        window.to_jsval(cx, vp);
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    JS_ForwardGetPropertyTo(cx, target.handle(), id, receiver, vp)
}

#[allow(unsafe_code)]
unsafe extern fn set(cx: *mut JSContext,
                     proxy: HandleObject,
                     receiver: HandleObject,
                     id: HandleId,
                     vp: MutableHandleValue,
                     res: *mut ObjectOpResult) -> u8 {
    if get_array_index_from_id(cx, id).is_some() {
        // Reject (which means throw if and only if strict) the set.
        (*res).code_ = JSErrNum::JSMSG_READ_ONLY as u32;
        return JSTrue;
    }

    let target = RootedObject::new(cx, GetProxyPrivate(*proxy.ptr).to_object());
    let receiver = RootedValue::new(cx, ObjectValue(&**receiver.ptr));
    JS_ForwardSetPropertyTo(cx, target.handle(), id, HandleValue { ptr: vp.ptr }, receiver.handle(), res)
}

static PROXY_HANDLER: ProxyTraps = ProxyTraps {
    enter: None,
    getOwnPropertyDescriptor: Some(getOwnPropertyDescriptor),
    defineProperty: Some(defineProperty),
    ownPropertyKeys: None,
    delete_: None,
    enumerate: None,
    preventExtensions: None,
    isExtensible: None,
    has: None,
    get: Some(get),
    set: Some(set),
    call: None,
    construct: None,
    getPropertyDescriptor: Some(get_property_descriptor),
    hasOwn: Some(hasOwn),
    getOwnEnumerablePropertyKeys: None,
    nativeCall: None,
    hasInstance: None,
    objectClassIs: None,
    className: None,
    fun_toString: None,
    boxedValue_unbox: None,
    defaultValue: None,
    trace: None,
    finalize: None,
    objectMoved: None,
    isCallable: None,
    isConstructor: None,
};

#[allow(unsafe_code)]
pub fn new_window_proxy_handler() -> WindowProxyHandler {
    unsafe {
        WindowProxyHandler(CreateWrapperProxyHandler(&PROXY_HANDLER))
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 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.

use raftstore::store::keys;
use raftstore::store::engine::Iterable;
use util::worker::Runnable;
use util::rocksdb;
use storage::CF_RAFT;

use rocksdb::{DB, WriteBatch, Writable};
use std::sync::Arc;
use std::fmt::{self, Formatter, Display};
use std::error;
use std::sync::mpsc::Sender;

pub struct Task {
    pub engine: Arc<DB>,
    pub region_id: u64,
    pub start_idx: u64,
    pub end_idx: u64,
}

pub struct TaskRes {
    pub collected: u64,
}

impl Display for Task {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f,
               "GC Raft Log Task [region: {}, from: {}, to: {}]",
               self.region_id,
               self.start_idx,
               self.end_idx)
    }
}

quick_error! {
    #[derive(Debug)]
    enum Error {
        Other(err: Box<error::Error + Sync + Send>) {
            from()
            cause(err.as_ref())
            description(err.description())
            display("raftlog gc failed {:?}", err)
        }
    }
}

pub struct Runner {
    ch: Option<Sender<TaskRes>>,
}

impl Runner {
    pub fn new(ch: Option<Sender<TaskRes>>) -> Runner {
        Runner { ch: ch }
    }

    /// Do the gc job and return the count of log collected.
    fn gc_raft_log(&mut self,
                   engine: Arc<DB>,
                   region_id: u64,
                   start_idx: u64,
                   end_idx: u64)
                   -> Result<u64, Error> {
        let mut first_idx = start_idx;
        if first_idx == 0 {
            let start_key = keys::raft_log_key(region_id, 0);
            first_idx = end_idx;
            if let Some((k, _)) = box_try!(engine.seek_cf(CF_RAFT, &start_key)) {
                first_idx = box_try!(keys::raft_log_index(&k));
            }
        }
        if first_idx >= end_idx {
            info!("[region {}] no need to gc", region_id);
            return Ok(0);
        }
        let wb = WriteBatch::new();
        let handle = box_try!(rocksdb::get_cf_handle(&engine, CF_RAFT));
        for idx in first_idx..end_idx {
            let key = keys::raft_log_key(region_id, idx);
            box_try!(wb.delete_cf(handle, &key));
        }
        // TODO: disable WAL here.
        engine.write(wb).unwrap();
        Ok(end_idx - first_idx)
    }

    fn report_collected(&self, collected: u64) {
        if self.ch.is_none() {
            return;
        }
        self.ch.as_ref().unwrap().send(TaskRes { collected: collected }).unwrap();
    }
}

impl Runnable<Task> for Runner {
    fn run(&mut self, task: Task) {
        debug!("[region {}] execute gc log to {}",
               task.region_id,
               task.end_idx);
        match self.gc_raft_log(task.engine, task.region_id, task.start_idx, task.end_idx) {
            Err(e) => {
                error!("[region {}] failed to gc: {:?}", task.region_id, e);
                self.report_collected(0);
            }
            Ok(n) => {
                info!("[region {}] collected {} log entries", task.region_id, n);
                self.report_collected(n);
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc;
    use std::time::Duration;
    use util::rocksdb::new_engine;
    use tempdir::TempDir;
    use storage::{CF_DEFAULT, CF_RAFT};
    use super::*;

    #[test]
    fn test_gc_raft_log() {
        let path = TempDir::new("gc-raft-log-test").unwrap();
        let db = new_engine(path.path().to_str().unwrap(), &[CF_DEFAULT, CF_RAFT]).unwrap();
        let db = Arc::new(db);

        let (tx, rx) = mpsc::channel();
        let mut runner = Runner::new(Some(tx));

        // generate raft logs
        let raft_handle = rocksdb::get_cf_handle(&db, CF_RAFT).unwrap();
        let region_id = 1;
        let wb = WriteBatch::new();
        for i in 0..100 {
            let k = keys::raft_log_key(region_id, i);
            wb.put_cf(raft_handle, &k, b"entry").unwrap();
        }
        db.write(wb).unwrap();

        let tbls = vec![(Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 0,
                            end_idx: 10,
                        },
                         10,
                         (0, 10),
                         (10, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 0,
                            end_idx: 50,
                        },
                         40,
                         (0, 50),
                         (50, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 50,
                            end_idx: 50,
                        },
                         0,
                         (0, 50),
                         (50, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 50,
                            end_idx: 60,
                        },
                         10,
                         (0, 60),
                         (60, 100))];

        for (task, expected_collectd, not_exist_range, exist_range) in tbls {
            runner.run(task);
            let res = rx.recv_timeout(Duration::from_secs(3)).unwrap();
            assert_eq!(res.collected, expected_collectd);
            raft_log_must_not_exist(&db, 1, not_exist_range.0, not_exist_range.1);
            raft_log_must_exist(&db, 1, exist_range.0, exist_range.1);
        }
    }

    fn raft_log_must_not_exist(engine: &DB, region_id: u64, start_idx: u64, end_idx: u64) {
        let raft_handle = rocksdb::get_cf_handle(engine, CF_RAFT).unwrap();
        for i in start_idx..end_idx {
            let k = keys::raft_log_key(region_id, i);
            assert!(engine.get_cf(raft_handle, &k).unwrap().is_none());
        }
    }

    fn raft_log_must_exist(engine: &DB, region_id: u64, start_idx: u64, end_idx: u64) {
        let raft_handle = rocksdb::get_cf_handle(engine, CF_RAFT).unwrap();
        for i in start_idx..end_idx {
            let k = keys::raft_log_key(region_id, i);
            assert!(engine.get_cf(raft_handle, &k).unwrap().is_some());
        }
    }
}
<commit_msg>raftstore: suppress compact log (#1944)<commit_after>// Copyright 2016 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.

use raftstore::store::keys;
use raftstore::store::engine::Iterable;
use util::worker::Runnable;
use util::rocksdb;
use storage::CF_RAFT;

use rocksdb::{DB, WriteBatch, Writable};
use std::sync::Arc;
use std::fmt::{self, Formatter, Display};
use std::error;
use std::sync::mpsc::Sender;

pub struct Task {
    pub engine: Arc<DB>,
    pub region_id: u64,
    pub start_idx: u64,
    pub end_idx: u64,
}

pub struct TaskRes {
    pub collected: u64,
}

impl Display for Task {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f,
               "GC Raft Log Task [region: {}, from: {}, to: {}]",
               self.region_id,
               self.start_idx,
               self.end_idx)
    }
}

quick_error! {
    #[derive(Debug)]
    enum Error {
        Other(err: Box<error::Error + Sync + Send>) {
            from()
            cause(err.as_ref())
            description(err.description())
            display("raftlog gc failed {:?}", err)
        }
    }
}

pub struct Runner {
    ch: Option<Sender<TaskRes>>,
}

impl Runner {
    pub fn new(ch: Option<Sender<TaskRes>>) -> Runner {
        Runner { ch: ch }
    }

    /// Do the gc job and return the count of log collected.
    fn gc_raft_log(&mut self,
                   engine: Arc<DB>,
                   region_id: u64,
                   start_idx: u64,
                   end_idx: u64)
                   -> Result<u64, Error> {
        let mut first_idx = start_idx;
        if first_idx == 0 {
            let start_key = keys::raft_log_key(region_id, 0);
            first_idx = end_idx;
            if let Some((k, _)) = box_try!(engine.seek_cf(CF_RAFT, &start_key)) {
                first_idx = box_try!(keys::raft_log_index(&k));
            }
        }
        if first_idx >= end_idx {
            info!("[region {}] no need to gc", region_id);
            return Ok(0);
        }
        let wb = WriteBatch::new();
        let handle = box_try!(rocksdb::get_cf_handle(&engine, CF_RAFT));
        for idx in first_idx..end_idx {
            let key = keys::raft_log_key(region_id, idx);
            box_try!(wb.delete_cf(handle, &key));
        }
        // TODO: disable WAL here.
        engine.write(wb).unwrap();
        Ok(end_idx - first_idx)
    }

    fn report_collected(&self, collected: u64) {
        if self.ch.is_none() {
            return;
        }
        self.ch.as_ref().unwrap().send(TaskRes { collected: collected }).unwrap();
    }
}

impl Runnable<Task> for Runner {
    fn run(&mut self, task: Task) {
        debug!("[region {}] execute gc log to {}",
               task.region_id,
               task.end_idx);
        match self.gc_raft_log(task.engine, task.region_id, task.start_idx, task.end_idx) {
            Err(e) => {
                error!("[region {}] failed to gc: {:?}", task.region_id, e);
                self.report_collected(0);
            }
            Ok(n) => {
                debug!("[region {}] collected {} log entries", task.region_id, n);
                self.report_collected(n);
            }
        }
    }
}

#[cfg(test)]
mod test {
    use std::sync::mpsc;
    use std::time::Duration;
    use util::rocksdb::new_engine;
    use tempdir::TempDir;
    use storage::{CF_DEFAULT, CF_RAFT};
    use super::*;

    #[test]
    fn test_gc_raft_log() {
        let path = TempDir::new("gc-raft-log-test").unwrap();
        let db = new_engine(path.path().to_str().unwrap(), &[CF_DEFAULT, CF_RAFT]).unwrap();
        let db = Arc::new(db);

        let (tx, rx) = mpsc::channel();
        let mut runner = Runner::new(Some(tx));

        // generate raft logs
        let raft_handle = rocksdb::get_cf_handle(&db, CF_RAFT).unwrap();
        let region_id = 1;
        let wb = WriteBatch::new();
        for i in 0..100 {
            let k = keys::raft_log_key(region_id, i);
            wb.put_cf(raft_handle, &k, b"entry").unwrap();
        }
        db.write(wb).unwrap();

        let tbls = vec![(Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 0,
                            end_idx: 10,
                        },
                         10,
                         (0, 10),
                         (10, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 0,
                            end_idx: 50,
                        },
                         40,
                         (0, 50),
                         (50, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 50,
                            end_idx: 50,
                        },
                         0,
                         (0, 50),
                         (50, 100)),
                        (Task {
                            engine: db.clone(),
                            region_id: region_id,
                            start_idx: 50,
                            end_idx: 60,
                        },
                         10,
                         (0, 60),
                         (60, 100))];

        for (task, expected_collectd, not_exist_range, exist_range) in tbls {
            runner.run(task);
            let res = rx.recv_timeout(Duration::from_secs(3)).unwrap();
            assert_eq!(res.collected, expected_collectd);
            raft_log_must_not_exist(&db, 1, not_exist_range.0, not_exist_range.1);
            raft_log_must_exist(&db, 1, exist_range.0, exist_range.1);
        }
    }

    fn raft_log_must_not_exist(engine: &DB, region_id: u64, start_idx: u64, end_idx: u64) {
        let raft_handle = rocksdb::get_cf_handle(engine, CF_RAFT).unwrap();
        for i in start_idx..end_idx {
            let k = keys::raft_log_key(region_id, i);
            assert!(engine.get_cf(raft_handle, &k).unwrap().is_none());
        }
    }

    fn raft_log_must_exist(engine: &DB, region_id: u64, start_idx: u64, end_idx: u64) {
        let raft_handle = rocksdb::get_cf_handle(engine, CF_RAFT).unwrap();
        for i in start_idx..end_idx {
            let k = keys::raft_log_key(region_id, i);
            assert!(engine.get_cf(raft_handle, &k).unwrap().is_some());
        }
    }
}
<|endoftext|>


<commit_before>/// Implements all outgoing status packets

use std::io::Write;

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::GameConnection; //It's super super super effective!
use super::super::{ ID_STATUS_STC_RESPONSE, ID_STATUS_STC_PONG };

use rustc_serialize::json;

mod response {

    use super::super::super::super::super::super::{get_version, MINECRAFT_PROTOCOL_VERSION};
    use super::super::super::super::super::super::universe::{MAX_PLAYERS};

    /// A response to be sent by the server list response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Response {

        /// The player data contained in this response
        pub players: Players,

        /// The version data contained in this response
        pub version: Version,

        /// The description contained in this response
        pub description: Description

    }

    impl Response {

        /// Constructs a new Response
        pub fn construct() -> Response {

            Response { players: Players::construct(), version: Version::construct(), description: Description::construct() }

        }

    }

    /// A struct defining the players portion of the StatusResponsePacket
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Players {

        /// The maximum number of players allowed on this server
        pub max: i32, //Yes, I know. But Java only supports signed integers

        /// The current number of online players
        pub online: i32

    }

    impl Players {

        /// Constructs a new Players struct
        ///
        /// TODO: Make this use real data for online
        pub fn construct() -> Players {

            Players { max: MAX_PLAYERS, online: 0 }

        }

    }

    /// The version part of the response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Version {

        /// The name of the version (This may or may not be ignored)
        pub name: String,

        /// The Minecraft protocol number being used
        pub protocol: u32

    }

    impl Version {

        /// Constructs a new Version struct
        ///
        /// TODO: Make name use a defined value
        pub fn construct() -> Version {

            Version { name: "1.8.8".to_string(), protocol: MINECRAFT_PROTOCOL_VERSION }

        }

    }

    /// The description part of the response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Description {

        /// The text to display
        pub text: String

    }

    impl Description {

        /// Constructs a new Description.
        ///
        /// In the future, this will get the description from a (cached) file
        pub fn construct() -> Description {
            Description { text: format!("A Netherrack {} server", get_version()) }
        }

    }

}

/// A packet sent from the server to
pub struct StatusResponsePacket;

impl StatusResponsePacket {

    /// Gets this StatusResponsePacket's ID
    pub fn get_id(&self) -> u32 {

        ID_STATUS_STC_RESPONSE

    }

    /// Gets the JSON response
    fn get_json_response(&self) -> String {
        json::encode(&response::Response::construct()).unwrap()
    }

    /// Creates a new Packet
    pub fn new() -> StatusResponsePacket {

        StatusResponsePacket

    }

    /// Encodes and sends this StatusResponsePacket
    pub fn send(&self, connection: &mut GameConnection) {
        info!("Sending a server status response packet!");

        let mut data_buffer = DequeBuffer::new();

        data_buffer.write_unsigned_varint_32(self.get_id());

        data_buffer.write_utf8_string(self.get_json_response());

        let mut length_buffer = DequeBuffer::new();

        length_buffer.write_unsigned_varint_32(data_buffer.remaining() as u32); //TODO: Try to get this as write_unsigned_varint_32_front

        let buffer: Vec<u8> = length_buffer.data.into_iter().chain(data_buffer.data.into_iter()).collect();

        let _buffer: &[u8] = &buffer[..];

        if connection.stream.write(_buffer).is_ok() {
            let _ = connection.stream.flush();
        }

    }

}

/// A packet sent from the server to the client responding to a ping
pub struct ListPongPacket {

    pub payload: i64

}

impl ListPongPacket {

    /// Gets this ListPongPacket's ID
    pub fn get_id(&self) -> u32 {

        ID_STATUS_STC_PONG

    }

    /// Creates a new ListPongPacket
    pub fn new(payload: i64) -> ListPongPacket {

        ListPongPacket { payload: payload }

    }

    /// Encodes and sends this ListPongPacket
    pub fn send(&self, connection: &mut GameConnection) {

        let mut data_buffer = DequeBuffer::new();

        data_buffer.write_unsigned_varint_32(self.get_id());

        data_buffer.write_signed_long(self.payload);

        let mut length_buffer = DequeBuffer::new();

        length_buffer.write_unsigned_varint_32(data_buffer.remaining() as u32); //TODO: Try to get this as write_unsigned_varint_32_front

        let buffer: Vec<u8> = length_buffer.data.into_iter().chain(data_buffer.data.into_iter()).collect();

        let _buffer: &[u8] = &buffer[..];

        if connection.stream.write(_buffer).is_ok() {
            let _ = connection.stream.flush();
        }

    }

}
<commit_msg>Add forge compatibility to the server status packet. For now, use an example name for the mod list<commit_after>/// Implements all outgoing status packets

use std::io::Write;

use super::super::super::deque_buffer::DequeBuffer;
use super::super::super::game_connection::GameConnection; //It's super super super effective!
use super::super::{ ID_STATUS_STC_RESPONSE, ID_STATUS_STC_PONG };

use rustc_serialize::json;

mod response {

    use super::super::super::super::super::super::{get_version, MINECRAFT_PROTOCOL_VERSION};
    use super::super::super::super::super::super::universe::{MAX_PLAYERS};

    use super::super::super::super::game_connection::GameConnection;

    /// A response to be sent by the server list response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Response {

        /// The player data contained in this response
        pub players: Players,

        /// The version data contained in this response
        pub version: Version,

        /// The description contained in this response
        pub description: Description,

        /// The optional / Forge-only mod information
        pub modinfo: Option<ModInfo>

    }

    impl Response {

        /// Constructs a new Response
        pub fn construct(connection: &GameConnection) -> Response {

            return Response { players: Players::construct(), version: Version::construct(), description: Description::construct(), modinfo: Some(ModInfo::construct())};

        }

    }

    /// A struct containing mod (forge) information
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct ModInfo {

        /// The type of mod loader compatibility being used
        pub _type: String,

        /// The list of mods currently in use on the server
        pub modList: Vec<ModDescriptor>

    }

    impl ModInfo {

        /// Constructs a new ModInfo struct
        pub fn construct() -> ModInfo {

            ModInfo { _type: "FML".to_string(), modList: ModDescriptor::construct() }

        }

    }

    /// A struct containing mod information
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct ModDescriptor {

        /// The mod's ID
        pub modid: String,

        /// The mod's version
        pub version: String

    }

    impl ModDescriptor {

        /// Constructs a new list of ModDescriptors
        pub fn construct() -> Vec<ModDescriptor> {

            //TODO: One day, replace this with names of mods added
            vec!(
                ModDescriptor { modid: "ExampleMod".to_string(), version: "0.0.1-pre".to_string() }
            )

        }

    }

    /// A struct defining the players portion of the StatusResponsePacket
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Players {

        /// The maximum number of players allowed on this server
        pub max: i32, //Yes, I know. But Java only supports signed integers

        /// The current number of online players
        pub online: i32

    }

    impl Players {

        /// Constructs a new Players struct
        ///
        /// TODO: Make this use real data for online
        pub fn construct() -> Players {

            Players { max: MAX_PLAYERS, online: 0 }

        }

    }

    /// The version part of the response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Version {

        /// The name of the version (This may or may not be ignored)
        pub name: String,

        /// The Minecraft protocol number being used
        pub protocol: u32

    }

    impl Version {

        /// Constructs a new Version struct
        ///
        /// TODO: Make name use a defined value
        pub fn construct() -> Version {

            Version { name: "1.8.8".to_string(), protocol: MINECRAFT_PROTOCOL_VERSION }

        }

    }

    /// The description part of the response packet
    #[derive(Debug, RustcDecodable, RustcEncodable)]
    pub struct Description {

        /// The text to display
        pub text: String

    }

    impl Description {

        /// Constructs a new Description.
        ///
        /// In the future, this will get the description from a (cached) file
        pub fn construct() -> Description {
            Description { text: format!("A Netherrack {} server", get_version()) }
        }

    }

}

/// A packet sent from the server to
pub struct StatusResponsePacket;

impl StatusResponsePacket {

    /// Gets this StatusResponsePacket's ID
    pub fn get_id(&self) -> u32 {

        ID_STATUS_STC_RESPONSE

    }

    /// Creates a new Packet
    pub fn new() -> StatusResponsePacket {

        StatusResponsePacket

    }

    /// Encodes and sends this StatusResponsePacket
    pub fn send(&self, connection: &mut GameConnection) {
        info!("Sending a server status response packet!");

        let mut data_buffer = DequeBuffer::new();

        data_buffer.write_unsigned_varint_32(self.get_id());

        data_buffer.write_utf8_string(json::encode(&response::Response::construct(&connection)).unwrap().replace("_type", "type"));

        let mut length_buffer = DequeBuffer::new();

        length_buffer.write_unsigned_varint_32(data_buffer.remaining() as u32); //TODO: Try to get this as write_unsigned_varint_32_front

        let buffer: Vec<u8> = length_buffer.data.into_iter().chain(data_buffer.data.into_iter()).collect();

        let _buffer: &[u8] = &buffer[..];

        if connection.stream.write(_buffer).is_ok() {
            let _ = connection.stream.flush();
        }

    }

}

/// A packet sent from the server to the client responding to a ping
pub struct ListPongPacket {

    pub payload: i64

}

impl ListPongPacket {

    /// Gets this ListPongPacket's ID
    pub fn get_id(&self) -> u32 {

        ID_STATUS_STC_PONG

    }

    /// Creates a new ListPongPacket
    pub fn new(payload: i64) -> ListPongPacket {

        ListPongPacket { payload: payload }

    }

    /// Encodes and sends this ListPongPacket
    pub fn send(&self, connection: &mut GameConnection) {

        let mut data_buffer = DequeBuffer::new();

        data_buffer.write_unsigned_varint_32(self.get_id());

        data_buffer.write_signed_long(self.payload);

        let mut length_buffer = DequeBuffer::new();

        length_buffer.write_unsigned_varint_32(data_buffer.remaining() as u32); //TODO: Try to get this as write_unsigned_varint_32_front

        let buffer: Vec<u8> = length_buffer.data.into_iter().chain(data_buffer.data.into_iter()).collect();

        let _buffer: &[u8] = &buffer[..];

        if connection.stream.write(_buffer).is_ok() {
            let _ = connection.stream.flush();
        }

    }

}
<|endoftext|>