<commit_before>use traitdefs::{Float, Point, Vector};
use std::convert::{AsRef, AsMut};
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;

use super::traits::BezCurve;

#[derive(Copy, Clone)]
struct RangeSlice {
    start: usize,
    end: usize
}

impl RangeSlice {
    #[inline]
    fn new(start: usize, end: usize) -> RangeSlice {
        RangeSlice {
            start: start,
            end: end
        }
    }

    fn len(&self) -> usize {
        self.end - self.start
    }
}

fn combination(n: usize, k: usize) -> usize {
    factorial(n) / (factorial(k) * factorial(n - k))
}

fn factorial(n: usize) -> usize {
    match n {
        0 => 1,
        _ => n * factorial(n-1)
    }
}

fn order_index(order: usize) -> usize {
    (order*order+order)/2
}

thread_local!{
    static FACTORS: RefCell<(usize, Vec<usize>)> = RefCell::new((0, Vec::with_capacity(order_index(16+1))))
}

fn factors(order: usize) -> RangeSlice {
    FACTORS.with(|f| {
        let max_order = f.borrow().0;
        if order > max_order {
            let mut f = f.borrow_mut();
            f.0 = order;
            for n in max_order..order+1 {
                for k in 0..n+1 {
                    f.1.push(combination(n, k));
                }
            }
        }

        let order_index = order_index(order);
        RangeSlice::new(order_index, order_index+order+1)
    })
}

#[derive(Clone)]
pub struct NBezPoly<F, C = Vec<F>>
        where F: Float,
              C: AsRef<[F]> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,
    phantom: PhantomData<F>
}

impl<F, C> NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    #[inline]
    fn new(points: C, factors: RangeSlice, dfactors: RangeSlice) -> NBezPoly<F, C> {
        NBezPoly {
            points: points,
            factors: Cell::new(factors),
            dfactors: Cell::new(dfactors),
            phantom: PhantomData
        }
    }

    #[inline]
    pub fn from_container(points: C) -> NBezPoly<F, C> {
        NBezPoly::new(points, RangeSlice::new(0, 0), RangeSlice::new(0, 0))
    }

    #[inline]
    pub fn unwrap(self) -> C {
        self.points
    }

    unsafe fn interp_unchecked<I: Iterator<Item=F>>(t: F, factors: RangeSlice, iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = factors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            point *
                            F::from_usize(fs.1[factors.start + factor]).unwrap();
                factor += 1;
            }
        });
        acc
    }

    unsafe fn slope_unchecked<I: Iterator<Item=F>>(t: F, dfactors: RangeSlice, mut iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = dfactors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;
        let mut point_next = iter.next().unwrap();

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            (point_next - point) *
                            F::from_usize(fs.1[dfactors.start + factor] * (order + 1) as usize).unwrap();
                point_next = point;
                factor += 1;
            }
        });
        acc
    }
}

impl<F, C> BezCurve<F> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    type Point = F;
    type Vector = F;

    fn from_slice(_: &[F]) -> Option<NBezPoly<F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        if self.factors.get().len() != self.order() {
            self.factors.set(factors(self.order()))
        }

        unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), points.iter().map(|f| *f)) }
    }

    fn slope_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        let order = self.order() - 1;
        if self.dfactors.get().len() != order {
            self.dfactors.set(factors(order))
        }

        unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), points.iter().map(|f| *f)) }
    }

    fn order(&self) -> usize {
        self.points.as_ref().len()-1
    }

    fn order_static() -> Option<usize> {
        None
    }
}

impl<F, C> AsRef<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C> AsMut<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}

pub struct NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,

    float_phantom: PhantomData<F>,
    point_phantom: PhantomData<P>,
    vector_phantom: PhantomData<V>
}

impl<F, C, P, V> NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    pub fn from_container(container: C) -> NBez<F, C, P, V> {
        NBez {
            points: container,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),

            float_phantom: PhantomData,
            point_phantom: PhantomData,
            vector_phantom: PhantomData
        }
    }
}

impl<F, C, P, V> BezCurve<F> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    type Point = P;
    type Vector = V;

    fn from_slice(_: &[P]) -> Option<NBez<F, C, P, V>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> P {
        let points = self.points.as_ref();
        let mut point = points[0].clone();

        if self.factors.get().len() != self.order() {
            self.factors.set(factors(self.order()))
        }

        for (i, f) in point.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), iter) };
        }

        point
    }

    fn slope_unbounded(&self, t: F) -> V {
        let points = self.points.as_ref();
        let mut vector: V = points[0].clone().into();

        let order = self.order() - 1;
        if self.dfactors.get().len() != order {
            self.dfactors.set(factors(order))
        }

        for (i, f) in vector.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), iter) };
        }

        vector
    }

    fn order(&self) -> usize {
        self.points.as_ref().len() - 1
    }

    fn order_static() -> Option<usize> {
        None
    }
}

impl<F, C, P, V> AsRef<C> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C, P, V> AsMut<C> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}<commit_msg>Simplified NBezPoly internal creation<commit_after>use traitdefs::{Float, Point, Vector};
use std::convert::{AsRef, AsMut};
use std::cell::{Cell, RefCell};
use std::marker::PhantomData;

use super::traits::BezCurve;

#[derive(Copy, Clone)]
struct RangeSlice {
    start: usize,
    end: usize
}

impl RangeSlice {
    #[inline]
    fn new(start: usize, end: usize) -> RangeSlice {
        RangeSlice {
            start: start,
            end: end
        }
    }

    fn len(&self) -> usize {
        self.end - self.start
    }
}

fn combination(n: usize, k: usize) -> usize {
    factorial(n) / (factorial(k) * factorial(n - k))
}

fn factorial(n: usize) -> usize {
    match n {
        0 => 1,
        _ => n * factorial(n-1)
    }
}

fn order_index(order: usize) -> usize {
    (order*order+order)/2
}

thread_local!{
    static FACTORS: RefCell<(usize, Vec<usize>)> = RefCell::new((0, Vec::with_capacity(order_index(16+1))))
}

fn factors(order: usize) -> RangeSlice {
    FACTORS.with(|f| {
        let max_order = f.borrow().0;
        if order > max_order {
            let mut f = f.borrow_mut();
            f.0 = order;
            for n in max_order..order+1 {
                for k in 0..n+1 {
                    f.1.push(combination(n, k));
                }
            }
        }

        let order_index = order_index(order);
        RangeSlice::new(order_index, order_index+order+1)
    })
}

#[derive(Clone)]
pub struct NBezPoly<F, C = Vec<F>>
        where F: Float,
              C: AsRef<[F]> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,
    phantom: PhantomData<F>
}

impl<F, C> NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    #[inline]
    pub fn from_container(points: C) -> NBezPoly<F, C> {
        NBezPoly {
            points: points,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),
            phantom: PhantomData
        }
    }

    #[inline]
    pub fn unwrap(self) -> C {
        self.points
    }

    unsafe fn interp_unchecked<I: Iterator<Item=F>>(t: F, factors: RangeSlice, iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = factors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            point *
                            F::from_usize(fs.1[factors.start + factor]).unwrap();
                factor += 1;
            }
        });
        acc
    }

    unsafe fn slope_unchecked<I: Iterator<Item=F>>(t: F, dfactors: RangeSlice, mut iter: I) -> F {
        let t1 = F::from_f32(1.0).unwrap() - t;
        let order = dfactors.len() - 1;
        let mut acc = F::from_f32(0.0).unwrap();
        let mut factor = 0;
        let mut point_next = iter.next().unwrap();

        FACTORS.with(|fs| {
            let fs = fs.borrow();
            for point in iter {
                acc = acc + t.powi(factor as i32) *
                            t1.powi((order-factor) as i32) *
                            (point_next - point) *
                            F::from_usize(fs.1[dfactors.start + factor] * (order + 1) as usize).unwrap();
                point_next = point;
                factor += 1;
            }
        });
        acc
    }
}

impl<F, C> BezCurve<F> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    type Point = F;
    type Vector = F;

    fn from_slice(_: &[F]) -> Option<NBezPoly<F, C>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        if self.factors.get().len() != self.order() {
            self.factors.set(factors(self.order()))
        }

        unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), points.iter().map(|f| *f)) }
    }

    fn slope_unbounded(&self, t: F) -> F {
        let points = self.points.as_ref();
        let order = self.order() - 1;
        if self.dfactors.get().len() != order {
            self.dfactors.set(factors(order))
        }

        unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), points.iter().map(|f| *f)) }
    }

    fn order(&self) -> usize {
        self.points.as_ref().len()-1
    }

    fn order_static() -> Option<usize> {
        None
    }
}

impl<F, C> AsRef<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C> AsMut<C> for NBezPoly<F, C>
        where F: Float,
              C: AsRef<[F]> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}

pub struct NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    points: C,
    factors: Cell<RangeSlice>,
    dfactors: Cell<RangeSlice>,

    float_phantom: PhantomData<F>,
    point_phantom: PhantomData<P>,
    vector_phantom: PhantomData<V>
}

impl<F, C, P, V> NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    pub fn from_container(container: C) -> NBez<F, C, P, V> {
        NBez {
            points: container,
            factors: Cell::new(RangeSlice::new(0, 0)),
            dfactors: Cell::new(RangeSlice::new(0, 0)),

            float_phantom: PhantomData,
            point_phantom: PhantomData,
            vector_phantom: PhantomData
        }
    }
}

impl<F, C, P, V> BezCurve<F> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    type Point = P;
    type Vector = V;

    fn from_slice(_: &[P]) -> Option<NBez<F, C, P, V>> {
        None
    }

    fn interp_unbounded(&self, t: F) -> P {
        let points = self.points.as_ref();
        let mut point = points[0].clone();

        if self.factors.get().len() != self.order() {
            self.factors.set(factors(self.order()))
        }

        for (i, f) in point.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::interp_unchecked(t, self.factors.get(), iter) };
        }

        point
    }

    fn slope_unbounded(&self, t: F) -> V {
        let points = self.points.as_ref();
        let mut vector: V = points[0].clone().into();

        let order = self.order() - 1;
        if self.dfactors.get().len() != order {
            self.dfactors.set(factors(order))
        }

        for (i, f) in vector.as_mut().iter_mut().enumerate() {
            let iter = points.iter().map(|p| p.as_ref()[i]);
            *f = unsafe{ NBezPoly::<_, &[_]>::slope_unchecked(t, self.dfactors.get(), iter) };
        }

        vector
    }

    fn order(&self) -> usize {
        self.points.as_ref().len() - 1
    }

    fn order_static() -> Option<usize> {
        None
    }
}

impl<F, C, P, V> AsRef<C> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_ref(&self) -> &C {
        &self.points
    }
}

impl<F, C, P, V> AsMut<C> for NBez<F, C, P, V>
        where F: Float,
              C: AsRef<[P]>,
              P: Point<F>,
              V: Vector<F, P> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.points
    }
}<|endoftext|>


<commit_before>use std::collections::HashMap;
use vm_state::VMState;
use prog_state::{ProgState, ProgOutput};

/// The Brainfuck VM
pub struct VM {
    vms : VMState,
    prg : ProgState,
    jmps : HashMap<u16, u16>,
}
impl VM {
    /// parses the imput string, only keeping valid characters.
    /// Also generates the jump table used for the '[' and ']' characters.
    fn parse(input: &str) -> Option<(Vec<u8>,HashMap<u16,u16>)> {
        let mut out_str : Vec<u8> = Vec::new();
        let mut jump_tbl: HashMap<u16,u16> = HashMap::new();
        let mut jmps = Vec::new(); // used to store the intermediate locations
                                   // for the jumps.
        for chr in input.chars() {
            match chr {
                '+' => out_str.push(chr as u8),
                '-' => out_str.push(chr as u8),
                '>' => out_str.push(chr as u8),
                '<' => out_str.push(chr as u8),
                '.' => out_str.push(chr as u8),
                ',' => out_str.push(chr as u8),
                '[' => {
                        out_str.push(chr as u8);
                        jmps.push(out_str.len()-1);
                       },
                ']' => {
                        out_str.push(chr as u8);
                        //TODO: Error recovery
                        let jmp = jmps.pop().unwrap() as u16;
                        jump_tbl.insert(jmp, (out_str.len()-1) as u16 );
                       },
                _ => (),
            }
        }
        Some((out_str,jump_tbl))
    }
    /// runs the VM with the specified input string.
    /// Returns and output object containing the final runtime status of
    /// the program as well as any collected output.
    pub fn run_with_input (input: &str) -> ProgOutput {
        let (prg_str, jmp_tbl) = VM::parse(input).unwrap();
        let mut bf_prog = VM {
            vms: VMState::new(),
            prg: ProgState::new( Vec::<u8>::from(&*prg_str) ),
            jmps: jmp_tbl,
        };
        let output = bf_prog.run();
        output
    }
    fn run (&mut self) -> ProgOutput {
        let mut std_out : Vec<u8> = Vec::new();
        let mut output = ProgOutput {
            status: None,
            std_out: std_out,
        };
        let mut running = true;
        let mut jump_back = 0u16;
        while(running){
            // Stop if we can't get the next char of the program.
            // This probably means we're at the end.
            let next_char = self.prg.get_val();
            // We'll increment our program pointer regardless
            self.prg.inc_pp();
            // And see if there is an instruction to execute
            if next_char.is_some() {
                // Execute the current instruction
                match next_char.unwrap() as char {
                    '+' => self.vms.inc_val(),
                    '-' => self.vms.dec_val(),
                    '>' => self.vms.inc_ptr(),
                    '<' => self.vms.dec_ptr(),
                    ',' => self.vms.load(0),
                    '.' => output.std_out.push(self.vms.store()),
                    '[' => { // Jumps to matching bracket if val at ptr is 0
                            if self.vms.store() == 0 {
                                println!("jump [");
                            }
                            ()
                           },
                    ']' => { // Jumps to matching bracket if val at ptr is non-0
                            if self.vms.store() != 0 {
                                println!("jump ]");
                            }
                            ()
                           },
                    _ => (),
                }
            } else {
                running = false;
            }
        }
        output
    }
}

#[cfg(test)]
mod test {
    use super::VM;
    #[test]
    fn test_parse_invalid_symbols() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res : Vec<u8> = Vec::from(out_str);
        let (res,jmp_tbl) = VM::parse(in_str).unwrap();
        assert_eq!(res, o_res);
    }
    #[test]
    fn test_run_with_input() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res : Vec<u8> = Vec::from(out_str);
        let output = VM::run_with_input(in_str);
        println!("{:?}", output);
        assert!(false);
    }
}
<commit_msg>added jump instructions<commit_after>use std::collections::HashMap;
use vm_state::VMState;
use prog_state::{ProgState, ProgOutput};

/// The Brainfuck VM
pub struct VM {
    vms : VMState,
    prg : ProgState,
    jmps : HashMap<u16, u16>,
}
impl VM {
    /// parses the imput string, only keeping valid characters.
    /// Also generates the jump table used for the '[' and ']' characters.
    fn parse(input: &str) -> Option<(Vec<u8>,HashMap<u16,u16>)> {
        let mut out_str : Vec<u8> = Vec::new();
        let mut jump_tbl: HashMap<u16,u16> = HashMap::new();
        let mut jmps = Vec::new(); // used to store the intermediate locations
                                   // for the jumps.
        for chr in input.chars() {
            match chr {
                '+' => out_str.push(chr as u8),
                '-' => out_str.push(chr as u8),
                '>' => out_str.push(chr as u8),
                '<' => out_str.push(chr as u8),
                '.' => out_str.push(chr as u8),
                ',' => out_str.push(chr as u8),
                '[' => {
                        out_str.push(chr as u8);
                        jmps.push(out_str.len()-1);
                       },
                ']' => {
                        out_str.push(chr as u8);
                        //TODO: Error recovery
                        let jmp = jmps.pop().unwrap() as u16;
                        jump_tbl.insert(jmp, (out_str.len()-1) as u16 );
                       },
                _ => (),
            }
        }
        Some((out_str,jump_tbl))
    }
    /// runs the VM with the specified input string.
    /// Returns and output object containing the final runtime status of
    /// the program as well as any collected output.
    pub fn run_with_input (input: &str) -> ProgOutput {
        let (prg_str, jmp_tbl) = VM::parse(input).unwrap();
        let mut bf_prog = VM {
            vms: VMState::new(),
            prg: ProgState::new( Vec::<u8>::from(&*prg_str) ),
            jmps: jmp_tbl,
        };
        let output = bf_prog.run();
        output
    }
    fn run (&mut self) -> ProgOutput {
        let mut std_out : Vec<u8> = Vec::new();
        let mut output = ProgOutput {
            status: None,
            std_out: std_out,
        };
        let mut running = true;
        while(running){
            // Get the program instruction
            let prog_inst = self.prg.get_val();
            // And see if there is an instruction to execute
            if prog_inst.is_some() {
                // Execute the current instruction
                match prog_inst.unwrap() as char {
                    '+' => self.vms.inc_val(),
                    '-' => self.vms.dec_val(),
                    '>' => self.vms.inc_ptr(),
                    '<' => self.vms.dec_ptr(),
                    ',' => self.vms.load(0),
                    '.' => output.std_out.push(self.vms.store()),
                    '[' => {
                            // Set the return pointer for the jump
                            // Jumps to matching bracket if val at ptr is 0
                            if self.vms.store() == 0 {
                                // Find the jump point in the program pointer
                                let jump_back = self.prg.get_pp() as u16;
                                let jmp = self.jmps.get(&jump_back).unwrap();
                                // Jump to the given pointer location
                                self.prg.set_pp(*jmp);
                            }
                           },
                    ']' => {
                            // Jumps to matching bracket if val at ptr is non-0
                            if self.vms.store() != 0 {
                                // Find the correct return pointer
                                let mut ret_ptr = 0;
                                let pp = self.prg.get_pp();
                                for (key, val) in self.jmps.iter() {
                                    if *val == pp as u16 { ret_ptr = *key; break; }
                                }
                                // Set the program pointer back to the orig. val
                                self.prg.set_pp(ret_ptr);
                            }
                           },
                    _ => (),
                }
            } else {
                running = false;
            }
            // We'll increment our program pointer regardless
            self.prg.inc_pp();
        }
        output
    }
}

#[cfg(test)]
mod test {
    use super::VM;
    #[test]
    fn test_parse_invalid_symbols() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res : Vec<u8> = Vec::from(out_str);
        let (res,jmp_tbl) = VM::parse(in_str).unwrap();
        assert_eq!(res, o_res);
    }
    #[test]
    fn test_run_with_input() {
        let in_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-]
            "A*$";?@![#>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let out_str = r#"[]++++++++++[>>+>+>++++++[<<+<+++>>>-]<<<<-][>>+<<]>[>>]<<<<[>++<[-]]>.>."#;
        let o_res : Vec<u8> = Vec::from(out_str);
        let output = VM::run_with_input(in_str);
        println!("{:?}", output);
        assert!(false);
    }
}
<|endoftext|>


<commit_before>extern crate hyper;

use std::sync::mpsc::channel;
use std::thread;
use args::Config;
use run_info::RunInfo;
use misc::split_number;
use tokio_core::reactor::Core;
use chrono::Local;
use hyper::{Client, Url};
use std::str::FromStr;

use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use futures_utils::stopwatch;
use request_result::RequestResult;

/// Delegates and manages all the work.
pub struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self, config: &Config) -> RunInfo {
        let (tx, rx) = channel();
        let desired_connections_per_worker_iter = split_number(config.num_connections,
                                                                     self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = config.url.clone();
            let duration = config.duration;
            let timeout = config.timeout.to_std().unwrap();
            thread::spawn(move || {

                let mut lp = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let hyper_client = hyper::Client::configure()
                    .keep_alive_timeout(Some(timeout))
                    .build(&lp.handle());
                let hyper_url = Url::from_str(&url).expect("Invalid URL");

                let iterator = (0..desired_connections_per_worker).map(|_| {

                    let runinfo = RunInfo::new(duration);

                    loop_fn((runinfo), |mut runinfo| {
                        send_request(hyper_url.clone(), &hyper_client)
                            .then(|res| -> Result<_, ()> { match res {
                                // on request success
                                Ok(request_res) => {
                                    // update histogram
                                    request_res.latency.num_nanoseconds()
                                        .map(|x| runinfo.histogram.increment(x as u64).ok());
                                    runinfo.requests_completed += 1;

                                    let state = runinfo;

                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                                // on request failure
                                Err(_) => {
                                    runinfo.num_failed_requests += 1;
                                    let state = runinfo;
                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                            }})
                    })
                        // Extract latency histogram
                        .map(|histogram| histogram)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                        runinfo_acc.merge(&runinfo);
                        ok(runinfo_acc)
                    });
                let res = lp.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }
        // collect information from all workers
        rx.iter()
            .take(self.num_threads)
            .fold(RunInfo::new(config.duration), |mut runinfo_acc, runinfo| {
                runinfo_acc.merge(&runinfo);
                runinfo_acc
            })
    }
}

fn send_request<C>(url: Url,
                   hyper_client: &Client<C>)
                   -> impl Future<Item = RequestResult, Error = hyper::Error>
    where C: hyper::client::Connect
{
    stopwatch(hyper_client.get(url)).and_then(|(_, latency)| {
        let request_result = RequestResult::new(latency);
        Ok(request_result)
    })
}<commit_msg>move collect_workers out of start_workforce<commit_after>extern crate hyper;

use std::sync::mpsc::{Receiver, channel};
use std::thread;
use args::Config;
use run_info::RunInfo;
use misc::split_number;
use tokio_core::reactor::Core;
use chrono::{Duration, Local};
use hyper::{Client, Url};
use std::str::FromStr;

use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use futures_utils::stopwatch;
use request_result::RequestResult;

/// Delegates and manages all the work.
pub struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self, config: &Config) -> RunInfo {
        let (tx, rx) = channel();
        let desired_connections_per_worker_iter = split_number(config.num_connections,
                                                                     self.num_threads);
        // start num_threads workers
        for desired_connections_per_worker in desired_connections_per_worker_iter {
            let tx = tx.clone();
            let url = config.url.clone();
            let duration = config.duration;
            let timeout = config.timeout.to_std().unwrap();
            thread::spawn(move || {

                let mut core = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let hyper_client = hyper::Client::configure()
                    .keep_alive_timeout(Some(timeout))
                    .build(&core.handle());
                let hyper_url = Url::from_str(&url).expect("Invalid URL");

                let iterator = (0..desired_connections_per_worker).map(|_| {

                    let runinfo = RunInfo::new(duration);

                    loop_fn((runinfo), |mut runinfo| {
                        send_request(hyper_url.clone(), &hyper_client)
                            .then(|res| -> Result<_, ()> { match res {
                                // on request success
                                Ok(request_res) => {
                                    // update histogram
                                    request_res.latency.num_nanoseconds()
                                        .map(|x| runinfo.histogram.increment(x as u64).ok());
                                    runinfo.requests_completed += 1;

                                    let state = runinfo;

                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                                // on request failure
                                Err(_) => {
                                    runinfo.num_failed_requests += 1;
                                    let state = runinfo;
                                    let now_time = Local::now();
                                    if now_time < wanted_end_time {
                                        Ok(Loop::Continue(state))
                                    } else {
                                        Ok(Loop::Break(state))
                                    }
                                }
                            }})
                    })
                        // Extract latency histogram
                        .map(|histogram| histogram)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(RunInfo::new(duration), |mut runinfo_acc, runinfo| {
                        runinfo_acc.merge(&runinfo);
                        ok(runinfo_acc)
                    });
                let res = core.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }

        self.collect_workers(rx, config.duration)
    }

    /// Collects information from all workers
    fn collect_workers(&self, rx: Receiver<RunInfo>, run_duration: Duration) -> RunInfo {
        rx.iter()
                .take(self.num_threads)
                .fold(RunInfo::new(run_duration), |mut runinfo_acc, runinfo| {
                    runinfo_acc.merge(&runinfo);
                    runinfo_acc
                })
    }
}

fn send_request<C>(url: Url,
                   hyper_client: &Client<C>)
                   -> impl Future<Item = RequestResult, Error = hyper::Error>
    where C: hyper::client::Connect
{
    stopwatch(hyper_client.get(url)).and_then(|(_, latency)| {
        let request_result = RequestResult::new(latency);
        Ok(request_result)
    })
}<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;
use self::libc::{c_int, c_ulong, c_void};
pub type Pvoid_t = *mut c_void;
pub type PPvoid_t = *mut Pvoid_t;
pub type Pcvoid_t = *const c_void;
pub type Word_t = c_ulong;
//pub type PWord_t = *mut Word_t;

pub type JU_Errno_t = c_int;

pub static JU_ERRNO_NONE: JU_Errno_t = 0;
pub static JU_ERRNO_FULL: JU_Errno_t = 1;
pub static JU_ERRNO_NFMAX: JU_Errno_t = 1; // JU_ERRNO_FULL
pub static JU_ERRNO_NOMEM: JU_Errno_t = 2;
pub static JU_ERRNO_NULLPPARRAY: JU_Errno_t = 3;
pub static JU_ERRNO_NONNULLPARRAY: JU_Errno_t = 10;
pub static JU_ERRNO_NULLPINDEX: JU_Errno_t = 4;
pub static JU_ERRNO_NULLPVALUE: JU_Errno_t = 11;
pub static JU_ERRNO_NOTJUDY1: JU_Errno_t = 5;
pub static JU_ERRNO_NOTJUDYL: JU_Errno_t = 6;
pub static JU_ERRNO_NOTJUDYSL: JU_Errno_t = 7;
pub static JU_ERRNO_UNSORTED: JU_Errno_t = 12;
pub static JU_ERRNO_OVERRUN: JU_Errno_t = 8;
pub static JU_ERRNO_CORRUPT: JU_Errno_t = 9;

#[repr(C)]
pub struct JError_t {
    je_Errno: JU_Errno_t,
    je_ErrID: c_int,
    je_reserved: [Word_t; 4],
}
pub type PJError_t = *mut JError_t;

impl JError_t {
    pub fn new() -> JError_t {
        JError_t {
            je_Errno: JU_ERRNO_NONE,
            je_ErrID: 0,
            je_reserved: [0; 4],
        }
    }
}

extern "C" {
    pub fn JudyHSGet(array: Pcvoid_t, key: *const c_void, size: Word_t) -> PPvoid_t;
    pub fn JudyHSIns(array: PPvoid_t, key: *const c_void, size: Word_t, err: PJError_t)
        -> PPvoid_t;
    pub fn JudyHSDel(array: PPvoid_t, key: *const c_void, size: Word_t, err: PJError_t) -> c_int;
    pub fn JudyHSFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;

    pub fn JudyLIns(array: PPvoid_t, index: Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLDel(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn JudyLGet(array: Pcvoid_t, index: Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLCount(array: Pcvoid_t, index1: Word_t, index2: Word_t, err: PJError_t) -> Word_t;
    pub fn JudyLByCount(
        array: Pcvoid_t,
        nth: Word_t,
        pindex: *mut Word_t,
        err: PJError_t,
    ) -> PPvoid_t;
    pub fn JudyLFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn JudyLMemUsed(array: Pcvoid_t) -> Word_t;
    pub fn JudyLFirst(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLNext(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLLast(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLPrev(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLFirstEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLNextEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLLastEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLPrevEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;

    pub fn Judy1Set(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Unset(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Test(array: Pcvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Count(array: Pcvoid_t, index1: Word_t, index2: Word_t, err: PJError_t) -> Word_t;
    pub fn Judy1ByCount(
        array: Pcvoid_t,
        nth: Word_t,
        pindex: *mut Word_t,
        err: PJError_t,
    ) -> PPvoid_t;
    pub fn Judy1FreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn Judy1MemUsed(array: Pcvoid_t) -> Word_t;
    pub fn Judy1First(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Next(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Last(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Prev(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1FirstEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1NextEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1LastEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1PrevEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;

    pub fn JudySLGet(array: Pcvoid_t, index: *const u8) -> PPvoid_t;
    pub fn JudySLIns(array: PPvoid_t, index: *const u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLDel(array: PPvoid_t, index: *const u8, err: PJError_t) -> c_int;
    pub fn JudySLFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn JudySLFirst(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLNext(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLLast(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLPrev(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
}
<commit_msg>Add JudyLInsArray to capi.rs<commit_after>#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]

extern crate libc;
use self::libc::{c_int, c_ulong, c_void};
pub type Pvoid_t = *mut c_void;
pub type PPvoid_t = *mut Pvoid_t;
pub type Pcvoid_t = *const c_void;
pub type Word_t = c_ulong;
//pub type PWord_t = *mut Word_t;

pub type JU_Errno_t = c_int;

pub static JU_ERRNO_NONE: JU_Errno_t = 0;
pub static JU_ERRNO_FULL: JU_Errno_t = 1;
pub static JU_ERRNO_NFMAX: JU_Errno_t = 1; // JU_ERRNO_FULL
pub static JU_ERRNO_NOMEM: JU_Errno_t = 2;
pub static JU_ERRNO_NULLPPARRAY: JU_Errno_t = 3;
pub static JU_ERRNO_NONNULLPARRAY: JU_Errno_t = 10;
pub static JU_ERRNO_NULLPINDEX: JU_Errno_t = 4;
pub static JU_ERRNO_NULLPVALUE: JU_Errno_t = 11;
pub static JU_ERRNO_NOTJUDY1: JU_Errno_t = 5;
pub static JU_ERRNO_NOTJUDYL: JU_Errno_t = 6;
pub static JU_ERRNO_NOTJUDYSL: JU_Errno_t = 7;
pub static JU_ERRNO_UNSORTED: JU_Errno_t = 12;
pub static JU_ERRNO_OVERRUN: JU_Errno_t = 8;
pub static JU_ERRNO_CORRUPT: JU_Errno_t = 9;

#[repr(C)]
pub struct JError_t {
    je_Errno: JU_Errno_t,
    je_ErrID: c_int,
    je_reserved: [Word_t; 4],
}
pub type PJError_t = *mut JError_t;

impl JError_t {
    pub fn new() -> JError_t {
        JError_t {
            je_Errno: JU_ERRNO_NONE,
            je_ErrID: 0,
            je_reserved: [0; 4],
        }
    }
}

extern "C" {
    pub fn JudyHSGet(array: Pcvoid_t, key: *const c_void, size: Word_t) -> PPvoid_t;
    pub fn JudyHSIns(array: PPvoid_t, key: *const c_void, size: Word_t, err: PJError_t)
        -> PPvoid_t;
    pub fn JudyHSDel(array: PPvoid_t, key: *const c_void, size: Word_t, err: PJError_t) -> c_int;
    pub fn JudyHSFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;

    pub fn JudyLIns(array: PPvoid_t, index: Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLInsArray(array: PPvoid_t, count: Word_t, keys: *const Word_t, vals: *const Word_t, err: PJError_t) -> c_int;
    pub fn JudyLDel(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn JudyLGet(array: Pcvoid_t, index: Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLCount(array: Pcvoid_t, index1: Word_t, index2: Word_t, err: PJError_t) -> Word_t;
    pub fn JudyLByCount(
        array: Pcvoid_t,
        nth: Word_t,
        pindex: *mut Word_t,
        err: PJError_t,
    ) -> PPvoid_t;
    pub fn JudyLFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn JudyLMemUsed(array: Pcvoid_t) -> Word_t;
    pub fn JudyLFirst(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLNext(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLLast(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLPrev(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> PPvoid_t;
    pub fn JudyLFirstEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLNextEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLLastEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn JudyLPrevEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;

    pub fn Judy1Set(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Unset(array: PPvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Test(array: Pcvoid_t, index: Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Count(array: Pcvoid_t, index1: Word_t, index2: Word_t, err: PJError_t) -> Word_t;
    pub fn Judy1ByCount(
        array: Pcvoid_t,
        nth: Word_t,
        pindex: *mut Word_t,
        err: PJError_t,
    ) -> PPvoid_t;
    pub fn Judy1FreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn Judy1MemUsed(array: Pcvoid_t) -> Word_t;
    pub fn Judy1First(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Next(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Last(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1Prev(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1FirstEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1NextEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1LastEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;
    pub fn Judy1PrevEmpty(array: Pcvoid_t, pindex: *mut Word_t, err: PJError_t) -> c_int;

    pub fn JudySLGet(array: Pcvoid_t, index: *const u8) -> PPvoid_t;
    pub fn JudySLIns(array: PPvoid_t, index: *const u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLDel(array: PPvoid_t, index: *const u8, err: PJError_t) -> c_int;
    pub fn JudySLFreeArray(array: PPvoid_t, err: PJError_t) -> Word_t;
    pub fn JudySLFirst(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLNext(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLLast(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
    pub fn JudySLPrev(array: Pcvoid_t, pindex: *mut u8, err: PJError_t) -> PPvoid_t;
}
<|endoftext|>


<commit_before>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame<u16>>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context<u16>,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSamplePosition=rav1e::ChromaSamplePosition;
type ChromaSampling=rav1e::ChromaSampling;
type MatrixCoefficients=rav1e::MatrixCoefficients;
type ColorPrimaries=rav1e::ColorPrimaries;
type TransferCharacteristics=rav1e::TransferCharacteristics;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default() -> *mut Config {
    let cfg = rav1e::Config {
        enc: rav1e::EncoderConfig::default(),
        threads: 0,
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_color_description(cfg: *mut Config,
                                                            matrix: MatrixCoefficients,
                                                            primaries: ColorPrimaries,
                                                            transfer: TransferCharacteristics)
{
    (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription {
        matrix_coefficients: matrix,
        color_primaries: primaries,
        transfer_characteristics: transfer,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_content_light(cfg: *mut Config,
                                                        max_content_light_level: u16,
                                                        max_frame_average_light_level: u16)
{
    (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight {
        max_content_light_level,
        max_frame_average_light_level,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_mastering_display(cfg: *mut Config,
                                                            primaries: [rav1e::Point; 3],
                                                            white_point: rav1e::Point,
                                                            max_luminance: u32,
                                                            min_luminance: u32)
{
    (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay {
        primaries,
        white_point,
        max_luminance,
        min_luminance,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    if !cfg.is_null() {
        let _ = Box::from_raw(cfg);
    }
}

unsafe fn option_match(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char
) -> Result<(), ()> {
    let key = CStr::from_ptr(key).to_str().map_err(|_| ())?;
    let value = CStr::from_ptr(value).to_str().map_err(|_| ())?;
    let enc = &mut(*cfg).cfg.enc;

    match key {
        "width" => enc.width = value.parse().map_err(|_| ())?,
        "height" => enc.height = value.parse().map_err(|_| ())?,
        "speed" => enc.speed_settings = rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?),

        "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?,

        "tune" => enc.tune = value.parse().map_err(|_| ())?,
        "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?,

        "key_frame_interval" => enc.max_key_frame_interval = value.parse().map_err(|_| ())?,
        "min_key_frame_interval" => enc.min_key_frame_interval = value.parse().map_err(|_| ())?,
        "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?,

        _ => return Err(())
    }

    Ok(())
}

/// Set a configuration parameter using its key and value
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    if option_match(cfg, key, value) == Ok(()) { 0 } else { -1 }
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    if !ctx.is_null() {
        let _ = Box::from_raw(ctx);
    }
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    if !frame.is_null() {
        let _ = Box::from_raw(frame);
    }
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
///
/// Returns:
/// - `0` on success,
/// - `> 0` if the input queue is full
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                EnoughData => 1,
                NeedMoreData | NeedMoreFrames => unreachable!(),
                _ => -1,
            }
        })
}

/// Receive encoded data
///
/// Returns:
/// - `0` on success
/// - `> 0` if additional frame data is required
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let rav1e::Packet { data, number, frame_type, .. } = p;
            let len  = data.len();
            let data = Box::into_raw(data.into_boxed_slice()) as *const u8;
            let packet = Packet {
                data,
                len,
                number,
                frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                NeedMoreData |
                    NeedMoreFrames => 1,
                EnoughData => unreachable!(),
                _ => -1,
            }
        })
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    if !pkt.is_null() {
        let pkt = Box::from_raw(pkt);
        let _ = Box::from_raw(pkt.data as *mut u8);
    }
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    if !sequence.is_null() {
        let _ = Box::from_raw(sequence);
    }
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<commit_msg>crav1e: lib: Introduce a new function to parse options as integer<commit_after>//! # C API for rav1e
//!
//! [rav1e](https://github.com/xiph/rav1e/) is an [AV1](https://aomediacodec.github.io/av1-spec/)
//! encoder written in [Rust](https://rust-lang.org)
//!
//! This is the C-compatible API

extern crate rav1e;
extern crate libc;

use std::slice;
use std::sync::Arc;

use std::ffi::CStr;
use std::ffi::CString;
use std::os::raw::c_char;
use std::os::raw::c_int;

use libc::size_t;
use libc::ptrdiff_t;

/// Raw video Frame
///
/// It can be allocated throught rav1e_frame_new(), populated using rav1e_frame_fill_plane()
/// and freed using rav1e_frame_unref().
pub struct Frame(Arc<rav1e::Frame<u16>>);

type EncoderStatus=rav1e::EncoderStatus;

/// Encoder configuration
///
/// Instantiate it using rav1e_config_default() and fine-tune it using
/// rav1e_config_parse().
///
/// Use rav1e_config_unref() to free its memory.
pub struct Config {
    cfg: rav1e::Config,
    last_err: Option<EncoderStatus>,
}

/// Encoder context
///
/// Contains the encoding state, it is created by rav1e_context_new() using an
/// Encoder configuration.
///
/// Use rav1e_context_unref() to free its memory.
pub struct Context {
    ctx: rav1e::Context<u16>,
    last_err: Option<EncoderStatus>,
}

type FrameType = rav1e::FrameType;

/// Encoded Packet
///
/// The encoded packets are retrieved using rav1e_receive_packet().
///
/// Use rav1e_packet_unref() to free its memory.
#[repr(C)]
pub struct Packet {
    /// Encoded data buffer
    pub data: *const u8,
    /// Encoded data buffer size
    pub len: size_t,
    /// Frame sequence number
    pub number: u64,
    /// Frame type
    pub frame_type: FrameType,
}

type ChromaSamplePosition=rav1e::ChromaSamplePosition;
type ChromaSampling=rav1e::ChromaSampling;
type MatrixCoefficients=rav1e::MatrixCoefficients;
type ColorPrimaries=rav1e::ColorPrimaries;
type TransferCharacteristics=rav1e::TransferCharacteristics;
type Rational=rav1e::Rational;

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_default() -> *mut Config {
    let cfg = rav1e::Config {
        enc: rav1e::EncoderConfig::default(),
        threads: 0,
    };

    let c = Box::new(Config {
        cfg,
        last_err: None,
    });

    Box::into_raw(c)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_color_description(cfg: *mut Config,
                                                            matrix: MatrixCoefficients,
                                                            primaries: ColorPrimaries,
                                                            transfer: TransferCharacteristics)
{
    (*cfg).cfg.enc.color_description = Some(rav1e::ColorDescription {
        matrix_coefficients: matrix,
        color_primaries: primaries,
        transfer_characteristics: transfer,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_content_light(cfg: *mut Config,
                                                        max_content_light_level: u16,
                                                        max_frame_average_light_level: u16)
{
    (*cfg).cfg.enc.content_light = Some(rav1e::ContentLight {
        max_content_light_level,
        max_frame_average_light_level,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_set_mastering_display(cfg: *mut Config,
                                                            primaries: [rav1e::Point; 3],
                                                            white_point: rav1e::Point,
                                                            max_luminance: u32,
                                                            min_luminance: u32)
{
    (*cfg).cfg.enc.mastering_display = Some(rav1e::MasteringDisplay {
        primaries,
        white_point,
        max_luminance,
        min_luminance,
    });
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_config_unref(cfg: *mut Config) {
    if !cfg.is_null() {
        let _ = Box::from_raw(cfg);
    }
}

unsafe fn option_match(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char
) -> Result<(), ()> {
    let key = CStr::from_ptr(key).to_str().map_err(|_| ())?;
    let value = CStr::from_ptr(value).to_str().map_err(|_| ())?;
    let enc = &mut(*cfg).cfg.enc;

    match key {
        "width" => enc.width = value.parse().map_err(|_| ())?,
        "height" => enc.height = value.parse().map_err(|_| ())?,
        "speed" => enc.speed_settings = rav1e::SpeedSettings::from_preset(value.parse().map_err(|_| ())?),

        "threads" => (*cfg).cfg.threads = value.parse().map_err(|_| ())?,

        "tune" => enc.tune = value.parse().map_err(|_| ())?,
        "quantizer" => enc.quantizer = value.parse().map_err(|_| ())?,

        "key_frame_interval" => enc.max_key_frame_interval = value.parse().map_err(|_| ())?,
        "min_key_frame_interval" => enc.min_key_frame_interval = value.parse().map_err(|_| ())?,
        "low_latency" => enc.low_latency = value.parse().map_err(|_| ())?,

        _ => return Err(())
    }

    Ok(())
}

/// Set a configuration parameter using its key and value as string.
///
/// Available keys and values
/// - "quantizer": 0-255, default 100
/// - "speed": 0-10, default 3
/// - "tune": "psnr"-"psychovisual", default "psnr"
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse(
    cfg: *mut Config,
    key: *const c_char,
    value: *const c_char,
) -> c_int {
    if option_match(cfg, key, value) == Ok(()) { 0 } else { -1 }
}

/// Set a configuration parameter using its key and value as integer.
///
/// Available keys and values are the same as rav1e_config_parse()
///
/// Return a negative value on error or 0.
#[no_mangle]
pub unsafe extern "C" fn rav1e_config_parse_int(
    cfg: *mut Config,
    key: *const c_char,
    value: c_int,
) -> c_int {
    let val = CString::new(value.to_string()).unwrap();
    if option_match(cfg, key, val.as_ptr()) == Ok(()) { 0 } else { -1 }
}

/// Generate a new encoding context from a populated encoder configuration
///
/// Multiple contexts can be generated through it.
#[no_mangle]
pub unsafe extern "C" fn rav1e_context_new(cfg: *const Config) -> *mut Context {
    let ctx = Context {
        ctx: (*cfg).cfg.new_context(),
        last_err: None,
    };

    Box::into_raw(Box::new(ctx))
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_context_unref(ctx: *mut Context) {
    if !ctx.is_null() {
        let _ = Box::from_raw(ctx);
    }
}

/// Produce a new frame from the encoding context
///
/// It must be populated using rav1e_frame_fill_plane().
///
/// The frame is reference counted and must be released passing it to rav1e_frame_unref(),
/// see rav1e_send_frame().
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_new(ctx: *const Context) -> *mut Frame {
    let f = (*ctx).ctx.new_frame();
    let frame = Box::new(Frame(f));

    Box::into_raw(frame)
}

#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_unref(frame: *mut Frame) {
    if !frame.is_null() {
        let _ = Box::from_raw(frame);
    }
}

/// Send the frame for encoding
///
/// The function increases the frame internal reference count and it can be passed multiple
/// times to different rav1e_send_frame().
///
/// Returns:
/// - `0` on success,
/// - `> 0` if the input queue is full
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_send_frame(ctx: *mut Context, frame: *const Frame) -> c_int {
    let frame = if frame.is_null() {
        None
    } else {
        Some((*frame).0.clone())
    };

    (*ctx)
        .ctx
        .send_frame(frame)
        .map(|_v| {
            (*ctx).last_err = None;
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                EnoughData => 1,
                NeedMoreData | NeedMoreFrames => unreachable!(),
                _ => -1,
            }
        })
}

/// Receive encoded data
///
/// Returns:
/// - `0` on success
/// - `> 0` if additional frame data is required
/// - `< 0` on unrecoverable failure
#[no_mangle]
pub unsafe extern "C" fn rav1e_receive_packet(
    ctx: *mut Context,
    pkt: *mut *mut Packet,
) -> c_int {
    (*ctx)
        .ctx
        .receive_packet()
        .map(|p| {
            (*ctx).last_err = None;
            let rav1e::Packet { data, number, frame_type, .. } = p;
            let len  = data.len();
            let data = Box::into_raw(data.into_boxed_slice()) as *const u8;
            let packet = Packet {
                data,
                len,
                number,
                frame_type,
            };
            *pkt = Box::into_raw(Box::new(packet));
            0
        }).unwrap_or_else(|e| {
            use rav1e::EncoderStatus::*;
            (*ctx).last_err = Some(e);
            match e {
                NeedMoreData |
                    NeedMoreFrames => 1,
                EnoughData => unreachable!(),
                _ => -1,
            }
        })
}

#[no_mangle]
pub unsafe extern fn rav1e_packet_unref(pkt: *mut Packet) {
    if !pkt.is_null() {
        let pkt = Box::from_raw(pkt);
        let _ = Box::from_raw(pkt.data as *mut u8);
    }
}

/// Produce a sequence header matching the current encoding context
///
/// Its format is compatible with the AV1 Matroska and ISOBMFF specification.
///
/// Use rav1e_container_sequence_header_unref() to free it.
#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header(ctx: *mut Context, buf_size: *mut size_t) -> *mut u8 {
    let buf = (*ctx).ctx.container_sequence_header();

    *buf_size = buf.len();
    Box::into_raw(buf.into_boxed_slice()) as *mut u8
}

#[no_mangle]
pub unsafe extern fn rav1e_container_sequence_header_unref(sequence: *mut u8) {
    if !sequence.is_null() {
        let _ = Box::from_raw(sequence);
    }
}

/// Fill a frame plane
///
/// Currently the frame contains 3 planes, the first is luminance followed by
/// chrominance.
///
/// The data is copied and this function has to be called for each plane.
///
/// frame: A frame provided by rav1e_frame_new()
/// plane: The index of the plane starting from 0
/// data: The data to be copied
/// data_len: Lenght of the buffer
/// stride: Plane line in bytes, including padding
/// bytewidth: Number of bytes per component, either 1 or 2
#[no_mangle]
pub unsafe extern "C" fn rav1e_frame_fill_plane(
    frame: *mut Frame,
    plane: c_int,
    data: *const u8,
    data_len: size_t,
    stride: ptrdiff_t,
    bytewidth: c_int,
) {
    let input = Arc::get_mut(&mut (*frame).0).unwrap();
    let data_slice = slice::from_raw_parts(data, data_len as usize);

    input.planes[plane as usize].copy_from_raw_u8(data_slice, stride as usize, bytewidth as usize);
}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Card {
    pub suit: Suit,
    pub rank: Rank
}

impl Card {
    pub fn new(suit: Suit, rank: Rank) -> Card {
        Card { suit: suit, rank: rank }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Suit {
    Club,
    Diamond,
    Heart,
    Spade
}

impl Suit {
    pub fn from_number(num: &u32) -> Option<Suit> {
        match *num {
            1 => Some(Suit::Heart),
            2 => Some(Suit::Diamond),
            3 => Some(Suit::Spade),
            4 => Some(Suit::Club),
            _ => None
        }
    }
}

impl Into<u32> for Suit {
    fn into(self) -> u32 {
        match self {
            Suit::Heart => 1,
            Suit::Diamond => 2,
            Suit::Spade => 3,
            Suit::Club => 4
        }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Rank {
    Ace,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King
}

impl Rank {
    pub fn from_number(num: &u32) -> Option<Rank> {
        match *num {
            1 => Some(Rank::Ace),
            2 => Some(Rank::Two),
            3 => Some(Rank::Three),
            4 => Some(Rank::Four),
            5 => Some(Rank::Five),
            6 => Some(Rank::Six),
            7 => Some(Rank::Seven),
            8 => Some(Rank::Eight),
            9 => Some(Rank::Nine),
            10 => Some(Rank::Ten),
            11 => Some(Rank::Jack),
            12 => Some(Rank::Queen),
            13 => Some(Rank::King),
            _ => None
        }
    }
}

impl Into<u32> for Rank {
    fn into(self) -> u32 {
        match self {
            Rank::Ace => 1,
            Rank::Two => 2,
            Rank::Three => 3,
            Rank::Four => 4,
            Rank::Five => 5,
            Rank::Six => 6,
            Rank::Seven => 7,
            Rank::Eight => 8,
            Rank::Nine => 9,
            Rank::Ten => 10,
            Rank::Jack => 11,
            Rank::Queen => 12,
            Rank::King => 13
        }
    }
}

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

    #[test]
    fn reversible_suit() {
        assert_eq!(Some(Suit::Heart), Suit::from_number(&Suit::Heart.into()));
    }

    #[test]
    fn reversible_rank() {
        assert_eq!(Some(Rank::Ace), Rank::from_number(&Rank::Ace.into()));
    }
}
<commit_msg>fix ace rank<commit_after>#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Card {
    pub suit: Suit,
    pub rank: Rank
}

impl Card {
    pub fn new(suit: Suit, rank: Rank) -> Card {
        Card { suit: suit, rank: rank }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Suit {
    Club,
    Diamond,
    Heart,
    Spade
}

impl Suit {
    pub fn from_number(num: &u32) -> Option<Suit> {
        match *num {
            1 => Some(Suit::Heart),
            2 => Some(Suit::Diamond),
            3 => Some(Suit::Spade),
            4 => Some(Suit::Club),
            _ => None
        }
    }
}

impl Into<u32> for Suit {
    fn into(self) -> u32 {
        match self {
            Suit::Heart => 1,
            Suit::Diamond => 2,
            Suit::Spade => 3,
            Suit::Club => 4
        }
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace,
}

impl Rank {
    pub fn from_number(num: &u32) -> Option<Rank> {
        match *num {
            2 => Some(Rank::Two),
            3 => Some(Rank::Three),
            4 => Some(Rank::Four),
            5 => Some(Rank::Five),
            6 => Some(Rank::Six),
            7 => Some(Rank::Seven),
            8 => Some(Rank::Eight),
            9 => Some(Rank::Nine),
            10 => Some(Rank::Ten),
            11 => Some(Rank::Jack),
            12 => Some(Rank::Queen),
            13 => Some(Rank::King),
            14 => Some(Rank::Ace),
            _ => None
        }
    }
}

impl Into<u32> for Rank {
    fn into(self) -> u32 {
        match self {
            Rank::Two => 2,
            Rank::Three => 3,
            Rank::Four => 4,
            Rank::Five => 5,
            Rank::Six => 6,
            Rank::Seven => 7,
            Rank::Eight => 8,
            Rank::Nine => 9,
            Rank::Ten => 10,
            Rank::Jack => 11,
            Rank::Queen => 12,
            Rank::King => 13,
            Rank::Ace => 14,
        }
    }
}

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

    #[test]
    fn reversible_suit() {
        assert_eq!(Some(Suit::Heart), Suit::from_number(&Suit::Heart.into()));
    }

    #[test]
    fn reversible_rank() {
        assert_eq!(Some(Rank::Ace), Rank::from_number(&Rank::Ace.into()));
    }

    #[test]
    fn invalid_rank() {
        assert_eq!(None, Rank::from_number(&1));
    }

}
<|endoftext|>


<commit_before>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;

use ::nalgebra::Origin;
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;
use ::std::ops::Deref;

use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 31;
pub const MIN_WIDTH: RootWidth = 4;

pub type Point = nalgebra::Point3<u32>;
pub type Vector = nalgebra::Vector3<u32>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

pub trait Clamp<T>
    where T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self;
}

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T> Clamp<T> for nalgebra::Point3<T>
    where T: Copy,
          T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self {
        nalgebra::Point3::new(nalgebra::clamp(self.x, min, max),
                              nalgebra::clamp(self.y, min, max),
                              nalgebra::clamp(self.z, min, max))
    }
}

pub trait Mask<T>
    where T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self;
}

impl<T> Mask<T> for nalgebra::Point3<T>
    where T: Copy,
          T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self {
        nalgebra::Point3::new(self.x & value, self.y & value, self.z & value)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!0u32 << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        assert!(index < 8);
        if self.width > MIN_WIDTH {
            let index = index as u32;
            let width = self.width - 1;
            let exp = 1u32 << width;
            Some(Partition {
                origin: self.origin + Vector::new(
                    ((index >> 0) & 1u32) * exp,
                    ((index >> 1) & 1u32) * exp,
                    ((index >> 2) & 1u32) * exp),
                width: width,
            })
        }
        else {
            None
        }
    }

    pub fn origin(&self) -> &Point {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }
}

pub trait Traversal: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

pub trait TraversalMut: Traversal + ops::DerefMut {}

#[derive(Clone)]
pub struct Cursor<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Cursor<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Cursor {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CursorIter {
        CursorIter::new(self.clone())
    }

    pub fn resolve(&self, point: &Point, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (1u32 << self.root.width()) - 1);
        let width = 1u32 << width.clamp(MIN_WIDTH, depth);

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Cursor::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> Traversal for Cursor<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Cursor<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CursorIter<'a> {
    cursors: Vec<Cursor<'a>>,
}

impl<'a> CursorIter<'a> {
    fn new(cursor: Cursor<'a>) -> Self {
        CursorIter {
            cursors: vec![cursor],
        }
    }
}

impl<'a> Iterator for CursorIter<'a> {
    type Item = Cursor<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(cursor) = self.cursors.pop() {
            match *cursor.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.cursors.push(Cursor::new(
                            cube,
                            cursor.root,
                            cursor.partition().at_index(index).unwrap()));
                    }
                },
                _ => {},
            }
            Some(cursor)
        }
        else {
            None
        }
    }
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub struct CursorMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> CursorMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        CursorMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn resolve(&'a mut self, point: &Point, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (1u32 << self.root.width()) - 1);
        let width = 1u32 << width.clamp(MIN_WIDTH, depth);

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        CursorMut::new(cube.take().unwrap(),
                       self.root,
                       Partition::at_point(&point, depth))
    }

    pub fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.cube.join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    pub fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition.width() > MIN_WIDTH {
            try!(self.cube.subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

impl<'a> Traversal for CursorMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> TraversalMut for CursorMut<'a> {}

impl<'a> ops::Deref for CursorMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for CursorMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point::origin(), width),
        }
    }

    pub fn cursor(&self) -> Cursor {
        Cursor::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn cursor_mut(&mut self) -> CursorMut {
        CursorMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl Traversal for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl TraversalMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

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

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: [u32; 3],
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

trait Geometry {
    fn full() -> Self;
    fn empty() -> Self;
}

impl Geometry for [u32; 3] {
    fn full() -> Self {
        [0x0F0F0F0F; 3]
    }

    fn empty() -> Self {
        [0x00000000; 3]
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point, width: RootWidth) -> usize {
    ((((point.x >> width) & 1u32) << 0) |
     (((point.y >> width) & 1u32) << 1) |
     (((point.z >> width) & 1u32) << 2)) as usize
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Fix exponentiation of widths.<commit_after>//! This module provides an oct-tree of cubes. Each leaf cube describes a
//! spatial partition, its properties, and a deformable geometry.

extern crate nalgebra;

use ::nalgebra::Origin;
use ::std::error;
use ::std::error::Error;
use ::std::fmt;
use ::std::mem;
use ::std::ops;
use ::std::ops::Deref;

use resource::ResourceId;

pub const MAX_WIDTH: RootWidth = 32;
pub const MIN_WIDTH: RootWidth = 4;

pub type Point = nalgebra::Point3<u32>;
pub type Vector = nalgebra::Vector3<u32>;
pub type RootWidth = u8; // TODO: https://github.com/rust-lang/rfcs/issues/671

pub trait Clamp<T>
    where T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self;
}

impl Clamp<RootWidth> for RootWidth {
    fn clamp(&self, min: RootWidth, max: RootWidth) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T> Clamp<T> for nalgebra::Point3<T>
    where T: Copy,
          T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self {
        nalgebra::Point3::new(nalgebra::clamp(self.x, min, max),
                              nalgebra::clamp(self.y, min, max),
                              nalgebra::clamp(self.z, min, max))
    }
}

pub trait Mask<T>
    where T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self;
}

impl<T> Mask<T> for nalgebra::Point3<T>
    where T: Copy,
          T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self {
        nalgebra::Point3::new(self.x & value, self.y & value, self.z & value)
    }
}

#[derive(Clone)]
pub struct Partition {
    origin: Point,
    width: RootWidth,
}

impl Partition {
    fn at_point(point: &Point, width: RootWidth) -> Self {
        Partition {
            origin: point.mask(!0u32 << width),
            width: width,
        }
    }

    fn at_index(&self, index: usize) -> Option<Self> {
        if self.width > MIN_WIDTH {
            let width = self.width - 1;
            Some(Partition {
                origin: self.origin + vector_at_index(index, width),
                width: width,
            })
        }
        else {
            None
        }
    }

    pub fn origin(&self) -> &Point {
        &self.origin
    }

    pub fn width(&self) -> RootWidth {
        self.width
    }
}

pub trait Traversal: ops::Deref<Target = Cube> {
    fn partition(&self) -> &Partition;

    fn depth(&self) -> u8;
}

pub trait TraversalMut: Traversal + ops::DerefMut {}

#[derive(Clone)]
pub struct Cursor<'a> {
    cube: &'a Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> Cursor<'a> {
    fn new(cube: &'a Cube, root: &'a Partition, partition: Partition) -> Self {
        Cursor {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn iter(&self) -> CursorIter {
        CursorIter::new(self.clone())
    }

    pub fn resolve(&self, point: &Point, width: RootWidth) -> Self {
        let mut cube = self.cube;
        let mut depth = self.partition.width();

        // Clamp the inputs.
        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            match *cube {
                Cube::Branch(ref branch) => {
                    depth = depth - 1;
                    cube = &branch.cubes[index_at_point(&point, depth)]
                }
                _ => break,
            }
        }

        Cursor::new(cube, self.root, Partition::at_point(&point, depth))
    }
}

impl<'a> Traversal for Cursor<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> ops::Deref for Cursor<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

pub struct CursorIter<'a> {
    cursors: Vec<Cursor<'a>>,
}

impl<'a> CursorIter<'a> {
    fn new(cursor: Cursor<'a>) -> Self {
        CursorIter {
            cursors: vec![cursor],
        }
    }
}

impl<'a> Iterator for CursorIter<'a> {
    type Item = Cursor<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(cursor) = self.cursors.pop() {
            match *cursor.cube {
                Cube::Branch(ref branch) => {
                    for (index, cube) in branch.iter().enumerate() {
                        self.cursors.push(Cursor::new(
                            cube,
                            cursor.root,
                            cursor.partition().at_index(index).unwrap()));
                    }
                },
                _ => {},
            }
            Some(cursor)
        }
        else {
            None
        }
    }
}

#[derive(Debug)]
pub enum JoinError {
    LeafJoined,
}

impl fmt::Display for JoinError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for JoinError {
    fn description(&self) -> &str {
        match *self {
            JoinError::LeafJoined => "attempted to join leaf",
        }
    }
}

#[derive(Debug)]
pub enum SubdivideError {
    LimitExceeded,
    BranchSubdivided,
}

impl fmt::Display for SubdivideError {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.description())
    }
}

impl error::Error for SubdivideError {
    fn description(&self) -> &str {
        match *self {
            SubdivideError::LimitExceeded => "minimum width limit exceeded",
            SubdivideError::BranchSubdivided => "attempted to subdivide branch",
        }
    }
}

pub struct CursorMut<'a> {
    cube: &'a mut Cube,
    root: &'a Partition,
    partition: Partition,
}

impl<'a> CursorMut<'a> {
    fn new(cube: &'a mut Cube, root: &'a Partition, partition: Partition) -> Self {
        CursorMut {
            cube: cube,
            root: root,
            partition: partition,
        }
    }

    pub fn resolve(&'a mut self, point: &Point, width: RootWidth) -> Self {
        let mut cube: Option<&mut Cube> = Some(self.cube);
        let mut depth = self.partition.width();

        let point = point.clamp(0, (exp(self.root.width())) - 1);
        let width = exp(width.clamp(MIN_WIDTH, depth));

        while (width >> depth) == 0 {
            let inner = cube.take().unwrap();
            match *inner {
                Cube::Branch(ref mut branch) => {
                    depth = depth - 1;
                    cube = Some(&mut branch.cubes[index_at_point(&point, depth)]);
                }
                _ => {
                    cube = Some(inner);
                    break;
                }
            }
        }

        CursorMut::new(cube.take().unwrap(),
                       self.root,
                       Partition::at_point(&point, depth))
    }

    pub fn join(&mut self) -> Result<&mut Self, JoinError> {
        try!(self.cube.join().ok_or(JoinError::LeafJoined));
        Ok(self)
    }

    pub fn subdivide(&mut self) -> Result<&mut Self, SubdivideError> {
        if self.partition.width() > MIN_WIDTH {
            try!(self.cube.subdivide().ok_or(SubdivideError::BranchSubdivided));
            Ok(self)
        } else {
            Err(SubdivideError::LimitExceeded)
        }
    }
}

impl<'a> Traversal for CursorMut<'a> {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        self.root.width() - self.partition.width()
    }
}

impl<'a> TraversalMut for CursorMut<'a> {}

impl<'a> ops::Deref for CursorMut<'a> {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        self.cube
    }
}

impl<'a> ops::DerefMut for CursorMut<'a> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.cube
    }
}

pub struct Tree {
    cube: Cube,
    partition: Partition,
}

impl Tree {
    pub fn new(width: RootWidth) -> Self {
        Tree {
            cube: Cube::new(),
            partition: Partition::at_point(&Point::origin(), width),
        }
    }

    pub fn cursor(&self) -> Cursor {
        Cursor::new(&self.cube, &self.partition, self.partition.clone())
    }

    pub fn cursor_mut(&mut self) -> CursorMut {
        CursorMut::new(&mut self.cube, &self.partition, self.partition.clone())
    }
}

impl Traversal for Tree {
    fn partition(&self) -> &Partition {
        &self.partition
    }

    fn depth(&self) -> u8 {
        0
    }
}

impl TraversalMut for Tree {}

impl ops::Deref for Tree {
    type Target = Cube;

    fn deref(&self) -> &Self::Target {
        &self.cube
    }
}

impl ops::DerefMut for Tree {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.cube
    }
}

#[derive(Clone)]
pub enum Cube {
    Leaf(LeafNode),
    Branch(BranchNode),
}

impl Cube {
    fn new() -> Self {
        Cube::Leaf(LeafNode::new())
    }

    fn join(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Branch(branch) => {
                *self = branch.join().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    fn subdivide(&mut self) -> Option<&mut Self> {
        let cube = mem::replace(self, Cube::default());
        match cube {
            Cube::Leaf(leaf) => {
                *self = leaf.subdivide().into();
                Some(self)
            }
            _ => {
                *self = cube;
                None
            }
        }
    }

    pub fn is_leaf(&self) -> bool {
        match *self {
            Cube::Leaf(_) => true,
            _ => false,
        }
    }
}

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

impl From<LeafNode> for Cube {
    fn from(leaf: LeafNode) -> Self {
        Cube::Leaf(leaf)
    }
}

impl From<BranchNode> for Cube {
    fn from(branch: BranchNode) -> Self {
        Cube::Branch(branch)
    }
}

#[derive(Clone, Copy)]
pub struct LeafNode {
    pub geometry: [u32; 3],
    pub material: ResourceId,
}

impl LeafNode {
    fn new() -> Self {
        LeafNode {
            geometry: Geometry::full(),
            material: 0,
        }
    }

    fn subdivide(self) -> BranchNode {
        // TODO: Transform the geometry of the parent into the children.
        let cube: Cube = self.into();
        BranchNode {
            cubes: Box::new([cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube.clone(),
                             cube]),
        }
    }
}

pub struct BranchNode {
    cubes: Box<[Cube; 8]>,
}

impl BranchNode {
    fn join(self) -> LeafNode {
        // TODO: Copy data from one of the original leaves.
        LeafNode::new()
    }
}

impl Clone for BranchNode {
    fn clone(&self) -> Self {
        BranchNode {
            cubes: Box::new([self.cubes[0].clone(),
                             self.cubes[1].clone(),
                             self.cubes[2].clone(),
                             self.cubes[3].clone(),
                             self.cubes[4].clone(),
                             self.cubes[5].clone(),
                             self.cubes[6].clone(),
                             self.cubes[7].clone()]),
        }
    }
}

impl ops::Deref for BranchNode {
    type Target = [Cube];

    fn deref(&self) -> &Self::Target {
        &*self.cubes
    }
}

trait Geometry {
    fn full() -> Self;
    fn empty() -> Self;
}

impl Geometry for [u32; 3] {
    fn full() -> Self {
        [0x0F0F0F0F; 3]
    }

    fn empty() -> Self {
        [0x00000000; 3]
    }
}

trait Subdivision {}

impl Subdivision for [Cube; 8] {}

trait Storage {}

impl Storage for Box<[Cube; 8]> {}

#[cfg_attr(rustfmt, rustfmt_skip)]
fn index_at_point(point: &Point, width: RootWidth) -> usize {
    ((((point.x >> width) & 1u32) << 0) |
     (((point.y >> width) & 1u32) << 1) |
     (((point.z >> width) & 1u32) << 2)) as usize
}

fn vector_at_index(index: usize, width: RootWidth) -> Vector {
    assert!(index < 8);
    let index = index as u32;
    let width = exp(width);
    Vector::new(
        ((index >> 0) & 1u32) * width,
        ((index >> 1) & 1u32) * width,
        ((index >> 2) & 1u32) * width)
}

fn exp(width: RootWidth) -> u32 {
    if width > 0 {
        1u32 << (width - 1)
    }
    else {
        0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>
use libc::c_void;
use libc::funcs::c95::stdlib::free;
use std::slice;
use std::mem::transmute;

/// Horrible kludge to free memory allocated by lodepng
pub struct CVec<T> {
    length: usize,
    ptr: *mut T,
}

impl<T> CVec<T> {
    pub fn new(ptr: *mut T, length: usize) -> CVec<T> {
        CVec {ptr:ptr, length:length}
    }

    /// *Copies* elements into a Vec
    pub fn to_vec(&self) -> Vec<T> {
        unsafe {
            Vec::from_raw_buf(self.ptr, self.length)
        }
    }

    /// Exposes memory as slice without copying
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            slice::from_raw_mut_buf(&mut self.ptr, self.length)
        }
    }

    /// Exposes memory as slice without copying
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            slice::from_raw_buf(transmute(&self.ptr), self.length)
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        unsafe {
            free(self.ptr as *mut c_void);
        }
    }
}
<commit_msg>Expose length<commit_after>
use libc::c_void;
use libc::funcs::c95::stdlib::free;
use std::slice;
use std::mem::transmute;

/// Horrible kludge to free memory allocated by lodepng
pub struct CVec<T> {
    elements: usize,
    ptr: *mut T,
}

impl<T> CVec<T> {
    pub fn new(ptr: *mut T, elements: usize) -> CVec<T> {
        CVec {ptr:ptr, elements:elements}
    }

    /// Number of elements (pixels for pixel type, bytes for u8 type only)
    pub fn len(&self) -> usize {
        self.elements
    }

    /// *Copies* elements into a Vec
    pub fn to_vec(&self) -> Vec<T> {
        unsafe {
            Vec::from_raw_buf(self.ptr, self.elements)
        }
    }

    /// Exposes memory as slice without copying
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        unsafe {
            slice::from_raw_mut_buf(&mut self.ptr, self.elements)
        }
    }

    /// Exposes memory as slice without copying
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        unsafe {
            slice::from_raw_buf(transmute(&self.ptr), self.elements)
        }
    }
}

#[unsafe_destructor]
impl<T> Drop for CVec<T> {
    fn drop(&mut self) {
        unsafe {
            free(self.ptr as *mut c_void);
        }
    }
}
<|endoftext|>