<commit_before>use std::ops::{Mul, Add};

/// Structure for computing the B-spline with the given control points
/// and knots.
pub struct BSpline<T: Mul<f32, Output = T> + Add<Output = T> + Copy> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// TODO: What is a good description for the knots?
    knots: Vec<f32>,
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> BSpline<T> {
    /// Create a new B-spline curve of the desired degree that will blend between
    /// the passed control points using the knots. The knots should be sorted in ascending
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`
    /// TODO: Handling of out of bounds t values? Are t values not in the domain considered
    /// out of range? The extra `degree` values are just for when we're going down the tree
    /// to find the interpolated values there right?
    pub fn point(&self, t: f32) -> T {
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let (mut i, _) = self.knots.iter().take_while(|&x| !(*x > t)).enumerate().last().unwrap();
        i = i + 1;
        if i == self.knots.len() {
            i = self.knots.len() - self.degree - 1;
        } else if i == 0 {
            i = self.degree;
        }
        /*
        let i = match upper_bounds(&self.knots[self.degree - 1..self.knots.len() - self.degree], t) {
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        */
        println!("Found i = {} for t = {}\n\tknots = {:?}", i, t, self.knots);
        println!("degree = {}", self.degree);
        self.de_boors(t, self.degree, i)
    }
    /// Recursively compute de Boor's B-spline algorithm. TODO: This is terrible,
    /// compute it iteratively! Recursive version is just for a simple formualation
    /// of the initial implementation.
    fn de_boors(&self, t: f32, k: usize, i: usize) -> T {
        if k == 0 {
            println!("Returning control point {}", i);
            self.control_points[i - 1]
        } else {
            println!("Looking at k = {}, i = {}, t = {}", k, i, t);
            println!("\tknots[i + self.degree - k] = {}, self.knots[i - 1] = {}",
                     self.knots[i + self.degree - k], self.knots[i - 1]);
            // TODO: This is still broken
            let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
            self.de_boors(t, k - 1, i - 1) * (1.0 - alpha) + self.de_boors(t, k - 1, i) * alpha
        }
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Mul, Add};
    use std::iter;

    use super::BSpline;

    #[derive(Copy, Clone, Debug)]
    struct Point {
        x: f32,
        y: f32,
    }
    impl Point {
        fn new(x: f32, y: f32) -> Point {
            Point { x: x, y: y }
        }
    }
    impl Mul<f32> for Point {
        type Output = Point;
        fn mul(self, rhs: f32) -> Point {
            Point { x: self.x * rhs, y: self.y * rhs }
        }
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, rhs: Point) -> Point {
            Point { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    #[derive(Copy, Clone, Debug)]
    struct Pointi {
        x: i32,
        y: i32,
    }
    impl Pointi {
        fn new(x: i32, y: i32) -> Pointi {
            Pointi { x: x, y: y }
        }
    }
    impl Mul<f32> for Pointi {
        type Output = Pointi;
        fn mul(self, rhs: f32) -> Pointi {
            Pointi { x: (self.x as f32 * rhs) as i32,
                    y: (self.y as f32 * rhs) as i32 }
        }
    }
    impl Add for Pointi {
        type Output = Pointi;
        fn add(self, rhs: Pointi) -> Pointi {
            Pointi { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    //#[test]
    fn linear_bspline(){
        let points = vec![Point::new(-1.0, 0.0), Point::new(0.0, 1.0),
                          Point::new(1.0, 1.0), Point::new(1.0, 2.0)];
        let knots = vec![0.0, 0.0, 1.0, 2.0, 3.0, 3.0];
        let spline = BSpline::new(1, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 0.5 && x.y == 1.0);
    }
    //#[test]
    fn quadratic_bspline(){
        let points = vec![Point::new(-2.0, 0.0), Point::new(0.0, 2.0),
                          Point::new(2.0, 0.0), Point::new(0.0, -2.0)];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0];
        let spline = BSpline::new(3, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 1.25 && x.y == -0.25);
    }
    //#[test]
    fn bspline_plot(){
        let points = vec![Pointi::new(0, 5), Pointi::new(10, 20),
                          Pointi::new(30, 20), Pointi::new(39, 5)];
        let knots = vec![0.0, 0.0, 0.1, 1.0, 1.9, 2.0, 2.0];

        // TODO: This doesn't compute or plot the correct curve
        let plot_w = 80;
        let plot_h = 50;
        let mut plot: Vec<_> = iter::repeat(' ').take(plot_w * plot_h).collect();

        let t_start = knots[2];
        let t_end = knots[4];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points.clone(), knots);

        let steps = 20;
        let step_size = (t_end - t_start) / steps as f32;
        for s in 0..steps {
            let t = step_size * s as f32 + t_start;
            println!("t = {}", t);
            let x = spline.point(t);
            println!("x = {:?}", x);
            if x.x > -1 && x.x < plot_w as i32 && x.y > -1 && x.y < plot_h as i32 {
                plot[(plot_h - 1 - x.y as usize) * plot_w + x.x as usize] = 'X';
            }
        }
        for i in 0..points.len() {
            let symbol = match i {
                x if x == 0 => 'S',
                x if x == points.len() - 1 => 'E',
                _ => 'C',
            };
            plot[(plot_h - 1 - points[i].y as usize) * plot_w + points[i].x as usize] = symbol;
        }

        for y in 0..plot_h {
            for x in 0..plot_w {
                print!("{}", plot[y * plot_w + x]);
            }
            println!("");
        }
    }
    //#[test]
    fn quadratic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    //#[test]
    fn cubic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(3, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    #[test]
    fn quartic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(4, points, knots);
        let t = 3.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
}

<commit_msg>tAking out some debug logging, things kind of appear to work?<commit_after>use std::ops::{Mul, Add};

/// Structure for computing the B-spline with the given control points
/// and knots.
pub struct BSpline<T: Mul<f32, Output = T> + Add<Output = T> + Copy> {
    /// Degree of the polynomial that we use to make the curve segments
    degree: usize,
    /// Control points for the curve
    control_points: Vec<T>,
    /// TODO: What is a good description for the knots?
    knots: Vec<f32>,
}

impl<T: Mul<f32, Output = T> + Add<Output = T> + Copy> BSpline<T> {
    /// Create a new B-spline curve of the desired degree that will blend between
    /// the passed control points using the knots. The knots should be sorted in ascending
    /// order, otherwise they will be sorted for you which may lead to undesired knots
    /// for control points
    pub fn new(degree: usize, control_points: Vec<T>, mut knots: Vec<f32>) -> BSpline<T> {
        // TODO: Maybe a ctor for cardinal curves that will check we have the right number of
        // knots? Is this check correct?
        if control_points.len() < degree {
            panic!("Too few control points for curve");
        }
        knots.sort_by(|a, b| a.partial_cmp(b).unwrap());
        BSpline { degree: degree, control_points: control_points, knots: knots }
    }
    /// Compute a point on the curve at `t`
    /// TODO: Handling of out of bounds t values? Are t values not in the domain considered
    /// out of range? The extra `degree` values are just for when we're going down the tree
    /// to find the interpolated values there right?
    pub fn point(&self, t: f32) -> T {
        // Find the first index with a knot value greater than the t we're searching for. We want
        // to find i such that: knot[i] <= t < knot[i + 1]
        let (mut i, _) = self.knots.iter().take_while(|&x| !(*x > t)).enumerate().last().unwrap();
        i = i + 1;
        if i == self.knots.len() {
            i = self.knots.len() - self.degree - 1;
        } else if i == 0 {
            i = self.degree;
        }
        /*
        let i = match upper_bounds(&self.knots[self.degree - 1..self.knots.len() - self.degree], t) {
            Some(x) => x,
            None => self.knots.len() - self.degree - 1,
        };
        */
        //println!("Found i = {} for t = {}\n\tknots = {:?}", i, t, self.knots);
        //println!("degree = {}", self.degree);
        self.de_boors(t, self.degree, i)
    }
    /// Recursively compute de Boor's B-spline algorithm. TODO: This is terrible,
    /// compute it iteratively! Recursive version is just for a simple formualation
    /// of the initial implementation.
    fn de_boors(&self, t: f32, k: usize, i: usize) -> T {
        if k == 0 {
            //println!("Returning control point {}", i);
            self.control_points[i - 1]
        } else {
            //println!("Looking at k = {}, i = {}, t = {}", k, i, t);
            //println!("\tknots[i + self.degree - k] = {}, self.knots[i - 1] = {}",
            //         self.knots[i + self.degree - k], self.knots[i - 1]);
            // TODO: This is still broken
            let alpha = (t - self.knots[i - 1]) / (self.knots[i + self.degree - k] - self.knots[i - 1]);
            self.de_boors(t, k - 1, i - 1) * (1.0 - alpha) + self.de_boors(t, k - 1, i) * alpha
        }
    }
}

/// Return the index of the first element greater than the value passed.
/// The data **must** be sorted.
/// If no element greater than the value passed is found the function returns None.
fn upper_bounds(data: &[f32], value: f32) -> Option<usize> {
    let mut first = 0usize;
    let mut step;
    let mut count = data.len() as isize;
    while count > 0 {
        step = count / 2;
        let it = first + step as usize;
        if !value.lt(&data[it]) {
            first = it + 1;
            count -= step + 1;
        } else {
            count = step;
        }
    }
    // If we didn't find an element greater than value
    if first == data.len() {
        None
    } else {
        Some(first)
    }
}

#[cfg(test)]
mod test {
    use std::ops::{Mul, Add};
    use std::iter;

    use super::BSpline;

    #[derive(Copy, Clone, Debug)]
    struct Point {
        x: f32,
        y: f32,
    }
    impl Point {
        fn new(x: f32, y: f32) -> Point {
            Point { x: x, y: y }
        }
    }
    impl Mul<f32> for Point {
        type Output = Point;
        fn mul(self, rhs: f32) -> Point {
            Point { x: self.x * rhs, y: self.y * rhs }
        }
    }
    impl Add for Point {
        type Output = Point;
        fn add(self, rhs: Point) -> Point {
            Point { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    #[derive(Copy, Clone, Debug)]
    struct Pointi {
        x: i32,
        y: i32,
    }
    impl Pointi {
        fn new(x: i32, y: i32) -> Pointi {
            Pointi { x: x, y: y }
        }
    }
    impl Mul<f32> for Pointi {
        type Output = Pointi;
        fn mul(self, rhs: f32) -> Pointi {
            Pointi { x: (self.x as f32 * rhs) as i32,
                    y: (self.y as f32 * rhs) as i32 }
        }
    }
    impl Add for Pointi {
        type Output = Pointi;
        fn add(self, rhs: Pointi) -> Pointi {
            Pointi { x: self.x + rhs.x, y: self.y + rhs.y }
        }
    }

    //#[test]
    fn linear_bspline() {
        let points = vec![Point::new(-1.0, 0.0), Point::new(0.0, 1.0),
                          Point::new(1.0, 1.0), Point::new(1.0, 2.0)];
        let knots = vec![0.0, 0.0, 1.0, 2.0, 3.0, 3.0];
        let spline = BSpline::new(1, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 0.5 && x.y == 1.0);
    }
    //#[test]
    fn quadratic_bspline() {
        let points = vec![Point::new(-2.0, 0.0), Point::new(0.0, 2.0),
                          Point::new(2.0, 0.0), Point::new(0.0, -2.0)];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0];
        let spline = BSpline::new(3, points, knots);
        let x = spline.point(1.5);
        println!("spline(1.5) = {:?}", x);
        assert!(x.x == 1.25 && x.y == -0.25);
    }
    #[test]
    fn bspline_plot() {
        let points = vec![Pointi::new(0, 5), Pointi::new(9, 20),
                          Pointi::new(29, 20), Pointi::new(39, 5)];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 2.0, 2.0];

        // TODO: This doesn't compute or plot the correct curve
        let plot_w = 80;
        let plot_h = 50;
        let mut plot: Vec<_> = iter::repeat(' ').take(plot_w * plot_h).collect();

        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points.clone(), knots);

        let steps = 20;
        let step_size = (t_end - t_start) / steps as f32;
        for s in 0..steps {
            let t = step_size * s as f32 + t_start;
            println!("t = {}", t);
            let x = spline.point(t);
            println!("x = {:?}", x);
            if x.x > -1 && x.x < plot_w as i32 && x.y > -1 && x.y < plot_h as i32 {
                plot[(plot_h - 1 - x.y as usize) * plot_w + x.x as usize] = 'X';
            }
        }
        for i in 0..points.len() {
            let symbol = match i {
                x if x == 0 => 'S',
                x if x == points.len() - 1 => 'E',
                _ => 'C',
            };
            plot[(plot_h - 1 - points[i].y as usize) * plot_w + points[i].x as usize] = symbol;
        }

        for y in 0..plot_h {
            for x in 0..plot_w {
                print!("{}", plot[y * plot_w + x]);
            }
            println!("");
        }
    }
    //#[test]
    fn quadratic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 1.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(2, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    //#[test]
    fn cubic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 6.0, 0.0, 0.0, 0.0];
        let knots = vec![-2.0, -2.0, -2.0, -2.0, -1.0, 0.0, 1.0, 2.0, 2.0, 2.0, 2.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(3, points, knots);
        let t = 0.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
    //#[test]
    fn quartic_bspline_plot1d() {
        let points = vec![0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
        let knots = vec![0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0];
        let t_start = knots[0];
        let t_end = knots[knots.len() - 1];
        println!("Starting at {}, ending at {}", t_start, t_end);
        let spline = BSpline::new(4, points, knots);
        let t = 3.5;
        println!("spline({}) = {}", t, spline.point(t));
    }
}

<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Scene infrastructure to be used with Gfx phases.

extern crate gfx_phase;
extern crate gfx;
extern crate cgmath;
extern crate hprof;

mod cull;

pub use gfx_phase::AbstractPhase;
pub use self::cull::{Culler, Frustum, Context};

/// Scene drawing error.
#[derive(Debug)]
pub enum Error {
    /// Error in creating a batch.
    Batch(gfx::batch::Error),
    /// Error in sending a batch for drawing.
    Flush(gfx_phase::FlushError),
}

/// Type of the call counter.
pub type Count = u32;

/// Rendering success report.
#[derive(Clone, Debug)]
pub struct Report {
    /// Number of calls in invisible entities.
    pub calls_invisible: Count,
    /// Number of calls that got culled out.
    pub calls_culled: Count,
    /// Number of calls that the phase doesn't apply to.
    pub calls_rejected: Count,
    /// Number of calls that failed to link batches.
    pub calls_failed: Count,
    /// Number of calls issued to the GPU.
    pub calls_passed: Count,
    /// Number of primitives rendered.
    pub primitives_rendered: Count,
}

impl Report {
    /// Create an empty `Report`.
    pub fn new() -> Report {
        Report {
            calls_rejected: 0,
            calls_failed: 0,
            calls_culled: 0,
            calls_invisible: 0,
            calls_passed: 0,
            primitives_rendered: 0,
        }
    }

    /// Get total number of draw calls.
    pub fn get_calls_total(&self) -> Count {
        self.calls_invisible + self.calls_culled +
        self.calls_rejected  + self.calls_failed +
        self.calls_passed
    }

    /// Get the rendered/submitted calls ratio.
    pub fn get_calls_ratio(&self) -> f32 {
        self.calls_passed as f32 / self.get_calls_total() as f32
    }
}

/// Abstract scene that can be drawn into something.
pub trait AbstractScene<R: gfx::Resources> {
    /// A type of the view information.
    type ViewInfo;
    /// A type of the material.
    type Material;
    /// A type of the camera.
    type Camera;
    /// the status information from the render results
    /// this can be used to communicate meta from the render
    type Status;

    /// Draw the contents of the scene with a specific phase into a stream.
    fn draw<H, S>(&self, &mut H, &Self::Camera, &mut S)
            -> Result<Self::Status, Error> where
        H: gfx_phase::AbstractPhase<R, Self::Material, Self::ViewInfo>,
        S: gfx::Stream<R>;
}

/// A fragment of an entity, contains a single draw call.
#[derive(Clone, Debug)]
pub struct Fragment<R: gfx::Resources, M> {
    /// Fragment material.
    pub material: M,
    /// Mesh slice.
    pub slice: gfx::Slice<R>,
}

impl<R: gfx::Resources, M> Fragment<R, M> {
    /// Create a new fragment.
    pub fn new(mat: M, slice: gfx::Slice<R>) -> Fragment<R, M> {
        Fragment {
            material: mat,
            slice: slice,
        }
    }
}

/// An abstract node in space.
pub trait Node {
    /// Associated abstract transformation (affine matrix, decomposed, etc).
    type Transform;
    /// Get local -> world transform.
    fn get_transform(&self) -> Self::Transform;
}

/// An abstract entity.
pub trait Entity<R: gfx::Resources, M>: Node {
    /// Type of the spatial bound (box, sphere, etc).
    type Bound;
    /// Check if it's visible.
    fn is_visible(&self) -> bool { true }
    /// Get the local bound.
    fn get_bound(&self) -> Self::Bound;
    /// Get the mesh.
    fn get_mesh(&self) -> &gfx::Mesh<R>;
    /// Get the drawable fragments of this entity.
    fn get_fragments(&self) -> &[Fragment<R, M>];
}

/// An abstract camera.
pub trait Camera<S>: Node {
    /// Associated projection type (perspective, ortho, etc)
    type Projection: cgmath::Projection<S>;
    /// Get the projection.
    fn get_projection(&self) -> Self::Projection;
    /// Compute the view-projection matrix.
    fn get_view_projection(&self) -> cgmath::Matrix4<S> where
        S: cgmath::BaseFloat,
        Self::Transform : cgmath::Transform3<S>
    {
        use cgmath::{Matrix, Transform};
        let view = self.get_transform().invert().unwrap();
        self.get_projection().into().mul_m(&view.into())
    }
}

/// Abstract information about the view. Supposed to containt at least
/// Model-View-Projection transform for the shader.
pub trait ViewInfo<S, T>: gfx_phase::ToDepth<Depth = S> {
    /// Construct a new information block.
    fn new(mvp: cgmath::Matrix4<S>, view: T, model: T) -> Self;
}
<commit_msg>Relax requirements for Projection<commit_after>#![deny(missing_docs)]

//! Scene infrastructure to be used with Gfx phases.

extern crate gfx_phase;
extern crate gfx;
extern crate cgmath;
extern crate hprof;

mod cull;

pub use gfx_phase::AbstractPhase;
pub use self::cull::{Culler, Frustum, Context};

/// Scene drawing error.
#[derive(Debug)]
pub enum Error {
    /// Error in creating a batch.
    Batch(gfx::batch::Error),
    /// Error in sending a batch for drawing.
    Flush(gfx_phase::FlushError),
}

/// Type of the call counter.
pub type Count = u32;

/// Rendering success report.
#[derive(Clone, Debug)]
pub struct Report {
    /// Number of calls in invisible entities.
    pub calls_invisible: Count,
    /// Number of calls that got culled out.
    pub calls_culled: Count,
    /// Number of calls that the phase doesn't apply to.
    pub calls_rejected: Count,
    /// Number of calls that failed to link batches.
    pub calls_failed: Count,
    /// Number of calls issued to the GPU.
    pub calls_passed: Count,
    /// Number of primitives rendered.
    pub primitives_rendered: Count,
}

impl Report {
    /// Create an empty `Report`.
    pub fn new() -> Report {
        Report {
            calls_rejected: 0,
            calls_failed: 0,
            calls_culled: 0,
            calls_invisible: 0,
            calls_passed: 0,
            primitives_rendered: 0,
        }
    }

    /// Get total number of draw calls.
    pub fn get_calls_total(&self) -> Count {
        self.calls_invisible + self.calls_culled +
        self.calls_rejected  + self.calls_failed +
        self.calls_passed
    }

    /// Get the rendered/submitted calls ratio.
    pub fn get_calls_ratio(&self) -> f32 {
        self.calls_passed as f32 / self.get_calls_total() as f32
    }
}

/// Abstract scene that can be drawn into something.
pub trait AbstractScene<R: gfx::Resources> {
    /// A type of the view information.
    type ViewInfo;
    /// A type of the material.
    type Material;
    /// A type of the camera.
    type Camera;
    /// the status information from the render results
    /// this can be used to communicate meta from the render
    type Status;

    /// Draw the contents of the scene with a specific phase into a stream.
    fn draw<H, S>(&self, &mut H, &Self::Camera, &mut S)
            -> Result<Self::Status, Error> where
        H: gfx_phase::AbstractPhase<R, Self::Material, Self::ViewInfo>,
        S: gfx::Stream<R>;
}

/// A fragment of an entity, contains a single draw call.
#[derive(Clone, Debug)]
pub struct Fragment<R: gfx::Resources, M> {
    /// Fragment material.
    pub material: M,
    /// Mesh slice.
    pub slice: gfx::Slice<R>,
}

impl<R: gfx::Resources, M> Fragment<R, M> {
    /// Create a new fragment.
    pub fn new(mat: M, slice: gfx::Slice<R>) -> Fragment<R, M> {
        Fragment {
            material: mat,
            slice: slice,
        }
    }
}

/// An abstract node in space.
pub trait Node {
    /// Associated abstract transformation (affine matrix, decomposed, etc).
    type Transform;
    /// Get local -> world transform.
    fn get_transform(&self) -> Self::Transform;
}

/// An abstract entity.
pub trait Entity<R: gfx::Resources, M>: Node {
    /// Type of the spatial bound (box, sphere, etc).
    type Bound;
    /// Check if it's visible.
    fn is_visible(&self) -> bool { true }
    /// Get the local bound.
    fn get_bound(&self) -> Self::Bound;
    /// Get the mesh.
    fn get_mesh(&self) -> &gfx::Mesh<R>;
    /// Get the drawable fragments of this entity.
    fn get_fragments(&self) -> &[Fragment<R, M>];
}

/// An abstract camera.
pub trait Camera<S>: Node {
    /// Associated projection type (perspective, ortho, etc)
    type Projection: std::convert::Into<cgmath::Matrix4<S>>;
    /// Get the projection.
    fn get_projection(&self) -> Self::Projection;
    /// Compute the view-projection matrix.
    fn get_view_projection(&self) -> cgmath::Matrix4<S> where
        S: cgmath::BaseFloat,
        Self::Transform : cgmath::Transform3<S>
    {
        use cgmath::{Matrix, Transform};
        let view = self.get_transform().invert().unwrap();
        self.get_projection().into().mul_m(&view.into())
    }
}

/// Abstract information about the view. Supposed to containt at least
/// Model-View-Projection transform for the shader.
pub trait ViewInfo<S, T>: gfx_phase::ToDepth<Depth = S> {
    /// Construct a new information block.
    fn new(mvp: cgmath::Matrix4<S>, view: T, model: T) -> Self;
}
<|endoftext|>


<commit_before>use std::cast;
use libc::c_int;
use std::ptr;

#[deriving(Eq)]
#[deriving(Clone)]
pub struct Point{
    pub x: i32,
    pub y: i32
}

#[deriving(Eq)]
#[deriving(Clone)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32
}

#[allow(non_camel_case_types)]
pub mod ll {

    use libc::{c_int};
    use rect::Rect;
    use rect::Point;

    pub type SDL_Rect = Rect;
    pub type SDL_Point = Point;
    pub type SDL_bool = c_int;

    extern "C" {
        pub fn SDL_HasIntersection(A: *SDL_Rect, B: *SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRect(A: *SDL_Rect, B: *SDL_Rect, result: *SDL_Rect) -> SDL_bool;
        pub fn SDL_UnionRect(A: *SDL_Rect, B: *SDL_Rect, result: *SDL_Rect);
        pub fn SDL_EnclosePoints(points: *SDL_Point, count: c_int, clip: *SDL_Rect, result: *SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRectAndLine(rect: *SDL_Rect, X1: *c_int, Y1: *c_int, X2: *c_int, Y2: *c_int) -> SDL_bool;
    }
}

pub fn Point(x: i32, y: i32) -> Point {
    Point { x: x, y: y }
}

impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point {
            x: x,
            y: y
        }
    }
}

pub fn Rect(x: i32, y: i32, w: i32, h: i32) -> Rect {
    Rect { x: x, y: y, w: w, h: h }
}

impl Rect {
    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
        Rect {
            x: x,
            y: y,
            w: w,
            h: h
        }
    }

    pub fn enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_EnclosePoints(
                cast::transmute(points.as_ptr()),
                points.len() as c_int,
                match clip { Some(ref rect) => cast::transmute(rect), None => ptr::null() },
                &out
            ) == 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    pub fn empty(&self) -> bool {
        (self.w <= 0) || (self.h <= 0)
    }

    pub fn has_intersection(&self, other: &Rect) -> bool {
        unsafe {
            ll::SDL_HasIntersection(self, other) == 0
        }
    }

    pub fn intersection(&self, other: &Rect) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_IntersectRect(self, other, &out) == 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    pub fn union(&self, other: &Rect) -> Rect {
        let out: Rect = Rect::new(0, 0, 0, 0);

        unsafe {
            ll::SDL_UnionRect(self, other, &out)
        };

        out
    }

    pub fn intersect_line(&self, start: &Point, end: &Point) -> Option<(Point, Point)> {
        let out_start: Point = start.clone();
        let out_end: Point = end.clone();

        let result = unsafe {
            ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) == 0
        };

        if result {
            Some((out_start, out_end))
        } else {
            None
        }
    }
}
<commit_msg>rect: fix bug in rect; add doc; rename method.<commit_after>/*!
Rectangle Functions
 */

use std::cast;
use libc::c_int;

/// A structure that defines a two dimensional point.
#[deriving(Eq, Clone, Show)]
pub struct Point {
    pub x: i32,
    pub y: i32
}

/// A structure that defines a rectangle, with the origin at the upper left.
#[deriving(Eq, Clone, Show)]
pub struct Rect {
    pub x: i32,
    pub y: i32,
    pub w: i32,
    pub h: i32
}

#[doc(hidden)]
#[allow(non_camel_case_types)]
pub mod ll {

    use libc::c_int;
    use super::Rect;
    use super::Point;

    pub type SDL_Rect = Rect;
    pub type SDL_Point = Point;
    pub type SDL_bool = c_int;

    extern "C" {
        pub fn SDL_HasIntersection(A: *SDL_Rect, B: *SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRect(A: *SDL_Rect, B: *SDL_Rect, result: *SDL_Rect) -> SDL_bool;
        pub fn SDL_UnionRect(A: *SDL_Rect, B: *SDL_Rect, result: *SDL_Rect);
        pub fn SDL_EnclosePoints(points: *SDL_Point, count: c_int, clip: *SDL_Rect, result: *SDL_Rect) -> SDL_bool;
        pub fn SDL_IntersectRectAndLine(rect: *SDL_Rect, X1: *c_int, Y1: *c_int, X2: *c_int, Y2: *c_int) -> SDL_bool;
    }
}

impl Point {
    pub fn new(x: i32, y: i32) -> Point {
        Point {
            x: x,
            y: y
        }
    }
}

impl Rect {
    pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
        Rect {
            x: x,
            y: y,
            w: w,
            h: h
        }
    }

    /// Calculate a minimal rectangle enclosing a set of points.
    pub fn from_enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_EnclosePoints(
                cast::transmute(points.as_ptr()),
                points.len() as c_int,
                cast::transmute(clip.as_ref()),
                &out
            ) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Check whether a rectangle has no area.
    pub fn is_empty(&self) -> bool {
        (self.w <= 0) || (self.h <= 0)
    }

    /// Determine whether two rectangles intersect.
    pub fn has_intersection(&self, other: &Rect) -> bool {
        unsafe {
            ll::SDL_HasIntersection(self, other) != 0
        }
    }

    /// Calculate the intersection of two rectangles.
    pub fn intersection(&self, other: &Rect) -> Option<Rect> {
        let out: Rect = Rect::new(0, 0, 0, 0);

        let result = unsafe {
            ll::SDL_IntersectRect(self, other, &out) != 0
        };

        if result {
            Some(out)
        } else {
            None
        }
    }

    /// Calculate the union of two rectangles.
    pub fn union(&self, other: &Rect) -> Rect {
        let out: Rect = Rect::new(0, 0, 0, 0);

        unsafe {
            ll::SDL_UnionRect(self, other, &out)
        };

        out
    }

    /// Calculate the intersection of a rectangle and line segment. return points of intersection.
    pub fn intersect_line(&self, start: &Point, end: &Point) -> Option<(Point, Point)> {
        let out_start: Point = start.clone();
        let out_end: Point = end.clone();

        let result = unsafe {
            ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) != 0
        };

        if result {
            Some((out_start, out_end))
        } else {
            None
        }
    }
}

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

    #[test]
    fn test_from_enclose_points() {
        assert_eq!(Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5,9)], None),
                   Some(Rect::new(2, 4, 4, 6)));
        assert!(Rect::from_enclose_points(&[Point::new(0, 0), Point::new(10,10)],
                                          Some(Rect::new(3, 3, 1, 1))).is_none());
    }

    #[test]
    fn test_has_intersection() {
        assert!(Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(9, 9, 10, 10)));
        // edge
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(10, 10, 10, 10)));
        // out
        assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(11, 11, 10, 10)));
    }

    #[test]
    fn test_intersection() {
        assert_eq!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(9, 9, 10, 10)),
                   Some(Rect::new(9, 9, 1, 1)));
        assert!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(11, 11, 10, 10)).is_none());
    }

    #[test]
    fn test_union() {
        assert_eq!(Rect::new(0, 0, 1, 1).union(&Rect::new(9, 9, 1, 1)),
                   Rect::new(0, 0, 10, 10));
    }

    #[test]
    fn test_intersect_line() {
        assert_eq!(Rect::new(1, 1, 5, 5).intersect_line(&Point::new(0, 0), &Point::new(10, 10)),
                   Some((Point::new(1, 1), Point::new(5, 5))));
    }
 }
<|endoftext|>


<commit_before>#![feature(associated_consts)]
extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue, DbFlags, DbHandle, Database, Environment, Transaction, ReadonlyTransaction, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

/// For encoding the name of the Table in the type system.
pub trait TableName {
    fn as_str() -> &'static str;
}

#[macro_export]
macro_rules! def_tablename {
    (
        $structname:ident as $str:expr
    ) => {
        #[derive(Clone)]
        struct $structname;
        impl TableName for $structname {
            fn as_str() -> &'static str { $str }
        }
    };
}

/// A TableClass describes the types of key/value and the behaviour (sort function) of a Table.
pub trait TableClass: Sized {
    type Key: ToMdbValue + FromMdbValue;
    type Value: ToMdbValue + FromMdbValue;

    /// Flags used for creation/open
    fn dbflags() -> DbFlags;

    /// Is called before accessing a database. Used to setup custom sort functions etc.
    fn prepare_database(db: &Database);

    fn create_table<N: TableName>(env: &Environment) -> MdbResult<TableHandle<Self, N>> {
        env.create_db(N::as_str(), Self::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tableclass: PhantomData,
                tablename: PhantomData
            }
        })
    }

    fn open_table<N: TableName>(env: &Environment) -> MdbResult<TableHandle<Self, N>> {
        env.get_db(N::as_str(), Self::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tableclass: PhantomData,
                tablename: PhantomData
            }
        })
    }
}

/// Wraps a lmdb::DbHandle, keeping the TableClass and TableName in the type signature.
pub struct TableHandle<C: TableClass, N: TableName> {
    dbh: DbHandle,
    tableclass: PhantomData<C>,
    tablename: PhantomData<N>,
}

impl<C: TableClass, N: TableName> TableHandle<C, N> {
    /// Bind a TableHandle towards a transaction. Returns a Table which you can use to
    /// modify the database.
    #[inline(always)]
    pub fn bind_transaction<'txn>(&self, txn: &'txn Transaction) -> Table<'txn, C, N> {
        let db = txn.bind(&self.dbh);
        C::prepare_database(&db);
        Table {
            db: db,
            tableclass: PhantomData,
            tablename: PhantomData
        }
    }

    /// Bind a TableHandle towards a readonly transaction.
    /// XXX: This should return a ReadonlyTable?
    #[inline(always)]
    pub fn bind_reader<'txn>(&self, txn: &'txn ReadonlyTransaction) -> Table<'txn, C, N> {
        let db = txn.bind(&self.dbh);
        C::prepare_database(&db);
        Table {
            db: db,
            tableclass: PhantomData,
            tablename: PhantomData
        }
    }

}

/// Wraps a lmdb::Database, keeping the TableClass and TableName in the type signature.
pub struct Table<'db, C: TableClass, N: TableName> {
    db: Database<'db>,
    tableclass: PhantomData<C>,
    tablename: PhantomData<N>,
}

impl<'db, C: TableClass, N: TableName> Table<'db, C, N> {
    #[inline(always)]
    pub fn set(&self, key: &C::Key, value: &C::Value) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, C, N>> {
        self.db.new_cursor().map(|c| TypedCursor {cursor: c, tableclass: PhantomData, tablename: PhantomData})
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, C: TableClass, N: TableName> {
    cursor: Cursor<'table>,
    tableclass: PhantomData<C>,
    tablename: PhantomData<N>,
}

impl<'table, C: TableClass, N: TableName> TypedCursor<'table, C, N> {
    #[inline(always)]
    pub fn to_item(&mut self, key: &C::Key, value: &C::Value) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn get<'a>(&'a mut self) -> MdbResult<(C::Key, C::Value)> where C::Key: 'a, C::Value: 'a {
        self.cursor.get()
    }
}

extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

#[test]
fn test_simple_table() {
    use std::path::Path;
    use lmdb::MdbError;

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    def_tablename!(MyfirstTable_TableName as "myfirst_table");

    type Id64 = u64;
    struct SortedSet_Id64_Id64Rev;
    impl TableClass for SortedSet_Id64_Id64Rev {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> lmdb::DbFlags {
            lmdb::core::DbIntKey | lmdb::core::DbAllowDups | lmdb::core::DbAllowIntDups | lmdb::core::DbDupFixed
        }
        // XXX: pass MdbResult back
        fn prepare_database(db: &lmdb::Database) {
            db.set_dupsort(sort_reverse::<Id64>).unwrap()
        }
    }

    // A Unique(Id64, Id64 DESC) table
    let table_handle = SortedSet_Id64_Id64Rev::create_table::<MyfirstTable_TableName>(&env).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = table_handle.bind_transaction(&txn);
            let key = 1u64;
            table.set(&key, &200u64).unwrap();
            table.set(&key, &100u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &1u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &3u64).unwrap();
            table.set(&key, &100u64).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();
        let table = table_handle.bind_reader(&rdr);

        let key = 1u64;

/*
        let mut iter = db.item_iter(&key).unwrap();

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 200u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 100u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 3u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 2u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 1u64)), kv);

        let kv: Option<(u64,u64)> = iter.next().map(|c| c.get());
        assert_eq!(None, kv);
*/

        let mut cursor = table.new_cursor().unwrap();
        {
            cursor.to_item(&1u64, &3u64).unwrap();
            assert_eq!((1u64, 3u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 2u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 1u64), cursor.get().unwrap());

            let err = cursor.to_next_item();
            match err {
                Err(MdbError::NotFound) => assert!(true),
                _ => assert!(false),
            }
        }
    }
}

<commit_msg>Encapsulate TableClass and TableName inside TableDef.<commit_after>#![feature(associated_consts)]
extern crate lmdb_rs as lmdb;

use lmdb::{FromMdbValue, ToMdbValue, MdbValue, DbFlags, DbHandle, Database, Environment, Transaction, ReadonlyTransaction, Cursor, MDB_val};
use lmdb::core::MdbResult;
use std::marker::PhantomData;

#[macro_export]
macro_rules! table_def {
    (
        $structname:ident, $tableclass:ty, $str:expr
    ) => {
        #[derive(Clone)]
        struct $structname;
        impl TableDef for $structname {
            type C = $tableclass;
            fn table_name() -> &'static str { $str }
        }
    };
}

/// A TableClass describes the types of key/value and the behaviour (sort function) of a Table.
pub trait TableClass: Sized {
    type Key: ToMdbValue + FromMdbValue;
    type Value: ToMdbValue + FromMdbValue;

    /// Flags used for creation/open
    fn dbflags() -> DbFlags;

    /// Is called before accessing a database. Used to setup custom sort functions etc.
    fn prepare_database(db: &Database);
}

/// A TableDef is a concrete instance of a TableClass with a given table name.
pub trait TableDef: Sized {
    type C: TableClass;
    fn table_name() -> &'static str;

    fn create_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.create_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

    fn open_table(env: &Environment) -> MdbResult<TableHandle<Self>> {
        env.get_db(Self::table_name(), Self::C::dbflags()).map(|dbh| {
            TableHandle {
                dbh: dbh,
                tabledef: PhantomData,
            }
        })
    }

}

/// Wraps a lmdb::DbHandle, keeping the TableDef in the type signature.
pub struct TableHandle<D: TableDef> {
    dbh: DbHandle,
    tabledef: PhantomData<D>,
}

impl<D: TableDef> TableHandle<D> {
    /// Bind a TableHandle towards a transaction. Returns a Table which you can use to
    /// modify the database.
    #[inline(always)]
    pub fn bind_transaction<'txn>(&self, txn: &'txn Transaction) -> Table<'txn, D> {
        let db = txn.bind(&self.dbh);
        D::C::prepare_database(&db);
        Table {
            db: db,
            tabledef: PhantomData,
        }
    }

    /// Bind a TableHandle towards a readonly transaction.
    /// XXX: This should return a ReadonlyTable?
    #[inline(always)]
    pub fn bind_reader<'txn>(&self, txn: &'txn ReadonlyTransaction) -> Table<'txn, D> {
        let db = txn.bind(&self.dbh);
        D::C::prepare_database(&db);
        Table {
            db: db,
            tabledef: PhantomData,
        }
    }

}

/// Wraps a lmdb::Database, keeping the TableDef in the type signature.
pub struct Table<'db, D: TableDef> {
    db: Database<'db>,
    tabledef: PhantomData<D>,
}

impl<'db, D: TableDef> Table<'db, D> {
    #[inline(always)]
    pub fn set(&self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.db.set(key, value)
    }

    #[inline(always)]
    pub fn new_cursor<'table>(&'table self) -> MdbResult<TypedCursor<'table, D>> {
        self.db.new_cursor().map(|c| TypedCursor {cursor: c, tabledef: PhantomData})
    }
}

/// Is a typed version of lmdb::Cursor.
pub struct TypedCursor<'table, D: TableDef> {
    cursor: Cursor<'table>,
    tabledef: PhantomData<D>,
}

impl<'table, D: TableDef> TypedCursor<'table, D> {
    #[inline(always)]
    pub fn to_item(&mut self, key: &<<D as TableDef>::C as TableClass>::Key, value: &<<D as TableDef>::C as TableClass>::Value) -> MdbResult<()> {
        self.cursor.to_item(key, value)
    }

    #[inline(always)]
    pub fn to_next_item(&mut self) -> MdbResult<()> {
        self.cursor.to_next_item()
    }

    #[inline(always)]
    pub fn get<'a>(&'a mut self) -> MdbResult<(<<D as TableDef>::C as TableClass>::Key, <<D as TableDef>::C as TableClass>::Value)> /*where D::C::Key: 'a, D::C::Value: 'a*/ {
        self.cursor.get()
    }
}

extern "C" fn sort<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});

    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs)) };
    order as lmdb::c_int
}

extern "C" fn sort_reverse<T:FromMdbValue+Ord>(lhs_val: *const MDB_val, rhs_val: *const MDB_val) -> lmdb::c_int {
    let lhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(lhs_val)});
    let rhs = T::from_mdb_value(&unsafe{MdbValue::from_raw(rhs_val)});
    let order: i8 = unsafe { std::mem::transmute(lhs.cmp(&rhs).reverse()) };
    order as lmdb::c_int
}

#[test]
fn test_simple_table() {
    use std::path::Path;
    use lmdb::MdbError;

    let env = lmdb::EnvBuilder::new().max_dbs(2).autocreate_dir(true).open(&Path::new("./test/db1"), 0o777).unwrap();

    //def_tablename!(MyfirstTable_TableName as "myfirst_table");

    type Id64 = u64;
    struct SortedSet_Id64_Id64Rev;
    impl TableClass for SortedSet_Id64_Id64Rev {
        type Key = Id64;
        type Value = Id64;

        fn dbflags() -> lmdb::DbFlags {
            lmdb::core::DbIntKey | lmdb::core::DbAllowDups | lmdb::core::DbAllowIntDups | lmdb::core::DbDupFixed
        }
        // XXX: pass MdbResult back
        fn prepare_database(db: &lmdb::Database) {
            db.set_dupsort(sort_reverse::<Id64>).unwrap()
        }
    }

    table_def!(MyFirstTable, SortedSet_Id64_Id64Rev, "my_first_table");

/*
    struct MyFirstTable;
    impl TableDef for MyFirstTable {
        // The TableClass
        type C = SortedSet_Id64_Id64Rev;

        fn table_name() -> &'static str { "my_first_table" }
    }
*/

    // A Unique(Id64, Id64 DESC) table
    let table_handle = MyFirstTable::create_table(&env).unwrap();

    // prepare database
    {
        let txn = env.new_transaction().unwrap();
        {
            let table = table_handle.bind_transaction(&txn);
            let key = 1u64;
            table.set(&key, &200u64).unwrap();
            table.set(&key, &100u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &1u64).unwrap();
            table.set(&key, &2u64).unwrap();
            table.set(&key, &3u64).unwrap();
            table.set(&key, &100u64).unwrap();
        }
        txn.commit().unwrap();
    }
    // read
    {
        let rdr = env.get_reader().unwrap();
        let table = table_handle.bind_reader(&rdr);

        let key = 1u64;

/*
        let mut iter = db.item_iter(&key).unwrap();

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 200u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 100u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 3u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 2u64)), kv);

        let kv = iter.next().map(|c| c.get());
        assert_eq!(Some((1u64, 1u64)), kv);

        let kv: Option<(u64,u64)> = iter.next().map(|c| c.get());
        assert_eq!(None, kv);
*/

        let mut cursor = table.new_cursor().unwrap();
        {
            cursor.to_item(&1u64, &3u64).unwrap();
            assert_eq!((1u64, 3u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 2u64), cursor.get().unwrap());

            cursor.to_next_item().unwrap();
            assert_eq!((1u64, 1u64), cursor.get().unwrap());

            let err = cursor.to_next_item();
            match err {
                Err(MdbError::NotFound) => assert!(true),
                _ => assert!(false),
            }
        }
    }
}

<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/ipnet/2.0.1")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
//! [`Ipv6Subnets`] types for interating over the subnets contained in
//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
//! addition, subtraction, bitwise-and, and bitwise-or operations that
//! are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These can be created
//!   using their constructors. They are also returned by the
//!   [`subnets()`] methods and used within the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
//!   iterators that generate IP addresses. These can be created using
//!   their constructors. They are also returned by the [`hosts()`]
//!   methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//! * The [`Contains`] trait provides a method to test if a network
//!   address contains either another network address or an IP address.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrRange.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.htmll
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but
//! it's not enabled by default. Use the `serde` [feature] to enable.
//!
//! ```toml
//! [dependencies]
//! ipnet = { version = "2", features = ["serde"] }
//! ```
//!
//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
//! `Ipv6Net` types will serialize to their `Display` strings.
//!
//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
//! consist of the network address octects followed by the prefix
//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
//! variant index prepending the above string of 5 or 17 bytes.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;

pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "serde")]
mod ipnet_serde;
<commit_msg>Remove invalid documentation for Contains trait<commit_after>#![doc(html_root_url = "https://docs.rs/ipnet/2.0.1")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
//! [`Ipv6Subnets`] types for interating over the subnets contained in
//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
//! addition, subtraction, bitwise-and, and bitwise-or operations that
//! are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These can be created
//!   using their constructors. They are also returned by the
//!   [`subnets()`] methods and used within the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
//!   iterators that generate IP addresses. These can be created using
//!   their constructors. They are also returned by the [`hosts()`]
//!   methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrRange.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.htmll
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but
//! it's not enabled by default. Use the `serde` [feature] to enable.
//!
//! ```toml
//! [dependencies]
//! ipnet = { version = "2", features = ["serde"] }
//! ```
//!
//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
//! `Ipv6Net` types will serialize to their `Display` strings.
//!
//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
//! consist of the network address octects followed by the prefix
//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
//! variant index prepending the above string of 5 or 17 bytes.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;

pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "serde")]
mod ipnet_serde;
<|endoftext|>


<commit_before><commit_msg>Add module<commit_after><|endoftext|>


<commit_before>pub struct HNil;

pub struct HCons<H, T> {
    pub head: H,
    pub tail: T
}

pub trait Contains<A> {
    fn get(&self) -> &A;
    fn get_mut(&mut self) -> &mut A;
}

macro_rules! hlist_type_internal {
    ($hlist_name:ident, $hlist_current:ty, $th:ty, $($tr:ty,)*) => {
       hlist_type_internal!($hlist_name, HCons<$th, $hlist_current>, $($tr,)*);
    };
    ($hlist_name:ident, $hlist_current:ty,) => {
        type $hlist_name = $hlist_current;
    }
}

#[macro_export]
macro_rules! hlist_type {
    ($hlist:ident) => {hlist_type_internal!($hlist, HNil,)};
    ($hlist:ident, $($types:ty),* ) => {hlist_type_internal!($hlist, $crate::HNil, $($types,)*);}
}

macro_rules! generate_hlist_contains {

    ($hlist:ty) => {{}};
    ($hlist:ty,) => {{}};

    ($hlist:ty, $last:ty, $($init:ty,)*) => {{

        impl $crate::Contains<$last> for $hlist {

            fn get(&self) -> &$last {
                let cur_cell = self;
                $(
                    let _head: &$init; // Only used to refer to $init
                    let cur_cell = &cur_cell.tail;
                )*
                &cur_cell.head
            }

            fn get_mut(&mut self) -> &mut $last {
                let cur_cell = self;
                $(
                    let _head: &$init;
                    let cur_cell = &mut cur_cell.tail;
                )*
                &mut cur_cell.head
            }
        }

        generate_hlist_contains!($hlist, $($init,)*);
    }}
}

/// Test comment
#[macro_export]
macro_rules! generate_contains_impls {
    ($($types:ty),*) => {{
        hlist_type!(TheHList, $($types),*);
        generate_hlist_contains!(TheHList, $($types,)*);
    }}
}

pub trait HList: Sized {
    fn push<A: Sized>(self, a: A) -> HCons<A, Self> {
        HCons { head: a, tail: self }
    }
}

impl HList for HNil {}
impl<H, T: HList> HList for HCons<H, T> {}

#[test]
fn hlist_type_tests() {
    hlist_type!(Zero);
    hlist_type!(One, i32);
    hlist_type!(Two, i32, i64);
    let _: Zero = HNil;
    let _: One = HNil.push(0i32);
    let _: Two = HNil.push(0i32).push(0i64);
}

#[test]
fn contains_tests() {
    generate_contains_impls!();
    generate_contains_impls!(i32);
    generate_contains_impls!(i32, i64);
    let _zero: HNil = HNil;
    let one: HCons<i32, HNil> = HNil.push(1i32);
    let two: HCons<i64, HCons<i32, HNil>> = HNil.push(1i32).push(2i64);
    let one_val: &i32 = one.get();
    let two_val_one: &i32 = two.get();
    let two_val_two: &i64 = two.get();
    assert!(one_val == &1i32);
    assert!(two_val_one == &1i32);
    assert!(two_val_two == &2i64);
}

<commit_msg>Add test for get_mut();<commit_after>pub struct HNil;

pub struct HCons<H, T> {
    pub head: H,
    pub tail: T
}

pub trait Contains<A> {
    fn get(&self) -> &A;
    fn get_mut(&mut self) -> &mut A;
}

macro_rules! hlist_type_internal {
    ($hlist_name:ident, $hlist_current:ty, $th:ty, $($tr:ty,)*) => {
       hlist_type_internal!($hlist_name, HCons<$th, $hlist_current>, $($tr,)*);
    };
    ($hlist_name:ident, $hlist_current:ty,) => {
        type $hlist_name = $hlist_current;
    }
}

#[macro_export]
macro_rules! hlist_type {
    ($hlist:ident) => {hlist_type_internal!($hlist, HNil,)};
    ($hlist:ident, $($types:ty),* ) => {hlist_type_internal!($hlist, $crate::HNil, $($types,)*);}
}

macro_rules! generate_hlist_contains {

    ($hlist:ty) => {{}};
    ($hlist:ty,) => {{}};

    ($hlist:ty, $last:ty, $($init:ty,)*) => {{

        impl $crate::Contains<$last> for $hlist {

            fn get(&self) -> &$last {
                let cur_cell = self;
                $(
                    let _head: &$init; // Only used to refer to $init
                    let cur_cell = &cur_cell.tail;
                )*
                &cur_cell.head
            }

            fn get_mut(&mut self) -> &mut $last {
                let cur_cell = self;
                $(
                    let _head: &$init;
                    let cur_cell = &mut cur_cell.tail;
                )*
                &mut cur_cell.head
            }
        }

        generate_hlist_contains!($hlist, $($init,)*);
    }}
}

/// Test comment
#[macro_export]
macro_rules! generate_contains_impls {
    ($($types:ty),*) => {{
        hlist_type!(TheHList, $($types),*);
        generate_hlist_contains!(TheHList, $($types,)*);
    }}
}

pub trait HList: Sized {
    fn push<A: Sized>(self, a: A) -> HCons<A, Self> {
        HCons { head: a, tail: self }
    }
}

impl HList for HNil {}
impl<H, T: HList> HList for HCons<H, T> {}

#[test]
fn hlist_type_tests() {
    hlist_type!(Zero);
    hlist_type!(One, i32);
    hlist_type!(Two, i32, i64);
    let _: Zero = HNil;
    let _: One = HNil.push(0i32);
    let _: Two = HNil.push(0i32).push(0i64);
}

#[test]
fn contains_tests() {
    generate_contains_impls!();
    generate_contains_impls!(i32);
    generate_contains_impls!(i32, i64);
    let _zero: HNil = HNil;
    let one: HCons<i32, HNil> = HNil.push(1i32);
    let two: HCons<i64, HCons<i32, HNil>> = HNil.push(1i32).push(2i64);
    let one_val: &i32 = one.get();
    let two_val_one: &i32 = two.get();
    let two_val_two: &i64 = two.get();
    assert!(one_val == &1i32);
    assert!(two_val_one == &1i32);
    assert!(two_val_two == &2i64);
}

#[test]
fn contains_mut_test() {
    struct Local;
    generate_contains_impls!(Local, i32, i64);
    let mut list = HNil.push(Local).push(0i32).push(1i64);
    {
        let m: &mut i32 = list.get_mut();
        *m = 5
    }
    let val: &i32 = list.get();
    assert!(val == &5);
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate log;

#[cfg(unix)]
extern crate libc;

extern crate net2;
extern crate futures;

#[cfg(target_pointer_width = "32")]
macro_rules! word_len {
    () => { 4 }
}

#[cfg(target_pointer_width = "64")]
macro_rules! word_len {
    () => { 8 }
}

macro_rules! cache_line_pad { ($N:expr) => { 64 / word_len!() - 1 - $N }}

#[inline]
fn unreachable() -> ! {
    extern crate unreachable;
    unsafe { unreachable::unreachable() }
}

use std::fmt::Display;
use std::io;

#[inline]
fn other_io_err<E: Display>(e: E) -> io::Error {
    io::Error::new(io::ErrorKind::Other, e.to_string())
}

pub mod slab;
pub mod buf;
pub mod nio;
pub mod reactor;
pub mod channel;
pub mod net;
<commit_msg>Use unreachable!() on debug build while unreachable::unreachable() on release build<commit_after>#[macro_use]
extern crate log;

#[cfg(unix)]
extern crate libc;

extern crate net2;
extern crate futures;

#[cfg(target_pointer_width = "32")]
macro_rules! word_len {
    () => { 4 }
}

#[cfg(target_pointer_width = "64")]
macro_rules! word_len {
    () => { 8 }
}

macro_rules! cache_line_pad { ($N:expr) => { 64 / word_len!() - 1 - $N }}

#[inline]
fn unreachable() -> ! {
    if cfg!(debug_assertions) {
        unreachable!();
    } else {
        extern crate unreachable;
        unsafe { unreachable::unreachable() }
    }
}

use std::fmt::Display;
use std::io;

#[inline]
fn other_io_err<E: Display>(e: E) -> io::Error {
    io::Error::new(io::ErrorKind::Other, e.to_string())
}

pub mod slab;
pub mod buf;
pub mod nio;
pub mod reactor;
pub mod channel;
pub mod net;
<|endoftext|>


<commit_before>extern crate hyper;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

pub use assets::match_assets;
pub use log::LogEntry;
pub use input::{SessionsManager, Session, generate_session_id};

use std::io;
use std::io::Cursor;
use std::io::Read;
use std::fs::File;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::thread;

pub mod input;

mod assets;
mod find_route;
mod log;
mod router;

/// An error that one of your routes can return.
///
/// This is just a convenience enum and you don't need to use it in your project
/// if you don't want to.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    /// The user input is wrong.
    WrongInput,

    /// The user must be logged in.
    LoginRequired,

    /// The user entered a wrong login or password.
    WrongLoginPassword,

    /// The user is logged in but shouldn't be there.
    NotAuthorized,
}

/// Starts a server and uses the given requests handler.
///
/// The request handler takes a `&Request` and must return a `Response` to send to the user.
///
/// # Common mistakes
///
/// The handler must capture its environment by value and not by reference (`'static`). If you
/// use closure, don't forget to put `move` in front of the closure.
///
/// The handler must also be thread-safe (`Send` and `Sync`).
/// For example this handler isn't thread-safe:
///
/// ```ignore
/// let mut requests_counter = 0;
///
/// rouille::start_server("localhost:80", move |request| {
///     requests_counter += 1;
///
///     // rest of the handler
/// })
/// ```
///
/// Multiple requests can be processed simultaneously, therefore you can't mutably access
/// variables from the outside.
///
/// Instead you must use a `Mutex`:
///
/// ```no_run
/// use std::sync::Mutex;
/// let requests_counter = Mutex::new(0);
///
/// rouille::start_server("localhost:80", move |request| {
///     *requests_counter.lock().unwrap() += 1;
///
///     // rest of the handler
/// # panic!()
/// })
/// ```
///
/// # Panic handling
///
/// If your request handler panicks, a 500 error will automatically be sent to the client.
///
pub fn start_server<A, F>(addr: A, handler: F) -> !
                          where A: ToSocketAddrs,
                                F: Send + Sync + 'static + Fn(&Request) -> Response
{
    // TODO: unused result?!?
    // TODO: does this block forever or not?
    hyper::server::Server::http(addr).unwrap().handle(Handler(handler));

    struct Handler<H>(H);
    impl<H> hyper::server::Handler for Handler<H>
            where H: Send + Sync + 'static + Fn(&Request) -> Response
    {
        fn handle<'a, 'k>(&'a self, mut hrequest: hyper::server::request::Request<'a, 'k>,
                          mut hresponse: hyper::server::response::Response<'a, hyper::net::Fresh>)
        {
            *hresponse.status_mut() = hyper::status::StatusCode::InternalServerError;

            // TODO: don't read the body in memory immediately
            let mut data = Vec::new();
            hrequest.read_to_end(&mut data);     // TODO: handle error

            // building the `Request` object
            let request = Request {
                url: format!("{}", hrequest.uri),   // TODO: handle this properly?
                method: hrequest.method.as_ref().to_owned(),
                headers: hrequest.headers.iter().map(|h| (h.name().to_owned(), h.value_string()))
                                                .collect(),
                https: false,
                data: data,
                remote_addr: hrequest.remote_addr.clone(),
            };

            // calling the handler ; this most likely takes a lot of time
            let mut response = (self.0)(&request);

            // writing the status code
            *hresponse.status_mut() = hyper::status::StatusCode::from_u16(response.status_code);

            // writing headers
            for (key, value) in response.headers {
                // FIXME: multiple headers with the same key
                hresponse.headers_mut().set_raw(key, vec![value.into_bytes()]);
            }

            if let Some(len) = response.data.data_length {
                hresponse.headers_mut().set(hyper::header::ContentLength(len as u64));
            }

            // sending status code and headers
            let mut hresponse = match hresponse.start() {
                Err(_) => return,
                Ok(r) => r
            };

            let _ = io::copy(response.data.data.by_ref(), &mut hresponse);
            let _ = hresponse.end();
        }
    }

    unreachable!()      // TODO: ?!?
}

/// Represents a request made by the client.
pub struct Request {
    method: String,
    url: String,
    headers: Vec<(String, String)>,
    https: bool,
    data: Vec<u8>,
    remote_addr: SocketAddr,
}

impl Request {
    /// Builds a fake HTTP request to be used during tests.
    pub fn fake_http<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
                           -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: false,
            data: data,
            headers: headers,
            remote_addr: "127.0.0.1:12345".parse().unwrap(),
        }
    }

    /// Builds a fake HTTP request to be used during tests.
    pub fn fake_http_from<U, M>(from: SocketAddr, method: M, url: U,
                                headers: Vec<(String, String)>, data: Vec<u8>)
                                -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: false,
            data: data,
            headers: headers,
            remote_addr: from,
        }
    }

    /// Builds a fake HTTPS request to be used during tests.
    pub fn fake_https<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
                            -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: true,
            data: data,
            headers: headers,
            remote_addr: "127.0.0.1:12345".parse().unwrap(),
        }
    }

    /// Builds a fake HTTPS request to be used during tests.
    pub fn fake_https_from<U, M>(from: SocketAddr, method: M, url: U,
                                 headers: Vec<(String, String)>, data: Vec<u8>)
                                 -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: true,
            data: data,
            headers: headers,
            remote_addr: from,
        }
    }

    /// Returns `true` if the request uses HTTPS instead of HTTP.
    #[inline]
    pub fn secure(&self) -> bool {
        self.https
    }

    /// Returns the method of the request (`GET`, `POST`, etc.).
    #[inline]
    pub fn method(&self) -> &str {
        &self.method
    }

    /// Returns the URL requested by the client. It is not decoded and thus can contain strings
    /// such as `%20`.
    ///
    /// See also `url`.
    #[inline]
    pub fn raw_url(&self) -> &str {
        &self.url
    }

    /// Returns the URL requested by the client.
    ///
    /// Contrary to `raw_url`, special characters have been decoded.
    /// If there is any non-unicode character in the URL, it will be replaced with `U+FFFD`.
    pub fn url(&self) -> String {
        url::percent_encoding::lossy_utf8_percent_decode(self.url.as_bytes())
    }

    /// Returns the value of a header of the request.
    #[inline]
    pub fn header(&self, key: &str) -> Option<String> {
        self.headers.iter().find(|&&(ref k, _)| k == key).map(|&(_, ref v)| v.clone())
    }

    /// Returns the data of the request.
    pub fn data(&self) -> Vec<u8> {
        self.data.clone()
    }

    /// Returns the address of the client.
    #[inline]
    pub fn remote_addr(&self) -> &SocketAddr {
        &self.remote_addr
    }
}

/// Contains a prototype of a response.
/// The response is only sent when you call `Request::respond`.
pub struct Response {
    /// The status code to return to the user.
    pub status_code: u16,

    /// List of headers to be returned in the response.
    ///
    /// Note that important headers such as `Connection` or `Content-Length` will be ignored
    /// from this list.
    // TODO: document precisely which headers
    pub headers: Vec<(String, String)>,

    /// An opaque type that contains the body of the response.
    pub data: ResponseBody,
}

impl Response {
    /// UNSTABLE. Builds a default response to handle the given route error.
    ///
    /// Important: don't use this in a real website. This function is just a convenience when
    /// prototyping.
    ///
    /// For authentication-related errors, you are strongly encouraged to handle them yourself.
    #[inline]
    pub fn from_error(err: &RouteError) -> Response {
        match err {
            &RouteError::NoRouteFound => Response {
                status_code: 404, headers: vec![], data: ResponseBody::empty()
            },
            &RouteError::WrongInput => Response {
                status_code: 400, headers: vec![], data: ResponseBody::empty()
            },
            &RouteError::LoginRequired => Response {
                status_code: 401, headers: vec![], data: ResponseBody::empty()
            },     // TODO: www-auth header?
            &RouteError::WrongLoginPassword => Response {
                status_code: 401, headers: vec![], data: ResponseBody::empty()
            },     // TODO: www-auth header?
            &RouteError::NotAuthorized => Response {
                status_code: 403, headers: vec![], data: ResponseBody::empty()
            },
        }
    }

    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        Response {
            status_code: 303,
            headers: vec![("Location".to_owned(), target.to_owned())],
            data: ResponseBody::empty(),
        }
    }

    /// Builds a `Response` that outputs HTML.
    #[inline]
    pub fn html<D>(content: D) -> Response where D: Into<Vec<u8>> {
        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "text/html; charset=utf8".to_owned())],
            data: ResponseBody::from_data(content),
        }
    }

    /// Builds a `Response` that outputs plain text.
    #[inline]
    pub fn text<S>(text: S) -> Response where S: Into<String> {
        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "text/plain; charset=utf8".to_owned())],
            data: ResponseBody::from_string(text),
        }
    }

    /// Builds a `Response` that outputs JSON.
    #[inline]
    pub fn json<T>(content: &T) -> Response where T: rustc_serialize::Encodable {
        let data = rustc_serialize::json::encode(content).unwrap();

        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "application/json".to_owned())],
            data: ResponseBody::from_data(data),
        }
    }

    /// Builds a `Response` that returns a `401 Not Authorized` status
    /// and a `WWW-Authenticate` header.
    #[inline]
    pub fn basic_http_auth_login_required(realm: &str) -> Response {
        // TODO: escape the realm
        Response {
            status_code: 401,
            headers: vec![("WWW-Authenticate".to_owned(), format!("Basic realm=\"{}\"", realm))],
            data: ResponseBody::empty(),
        }
    }
}

/// An opaque type that represents the body of a response.
pub struct ResponseBody {
    data: Box<Read + Send>,
    data_length: Option<usize>,
}

impl ResponseBody {
    /// Builds a `ResponseBody` that doesn't return any data.
    #[inline]
    pub fn empty() -> ResponseBody {
        ResponseBody {
            data: Box::new(io::empty()),
            data_length: Some(0),
        }
    }

    /// Builds a new `ResponseBody` that will read the data from a `Read`.
    ///
    /// Note that this is suboptimal compared to other constructors because the length
    /// isn't known in advance.
    #[inline]
    pub fn from_reader<R>(data: R) -> ResponseBody where R: Read + Send + 'static {
        ResponseBody {
            data: Box::new(data),
            data_length: None,
        }
    }

    /// Builds a new `ResponseBody` that returns the given data.
    #[inline]
    pub fn from_data<D>(data: D) -> ResponseBody where D: Into<Vec<u8>> {
        let data = data.into();
        let len = data.len();

        ResponseBody {
            data: Box::new(Cursor::new(data)),
            data_length: Some(len),
        }
    }

    /// Builds a new `ResponseBody` that returns the content of the given file.
    #[inline]
    pub fn from_file(file: File) -> ResponseBody {
        let len = file.metadata().map(|metadata| metadata.len() as usize).ok();

        ResponseBody {
            data: Box::new(file),
            data_length: len,
        }
    }

    /// Builds a new `ResponseBody` that returns an UTF-8 string.
    #[inline]
    pub fn from_string<S>(data: S) -> ResponseBody where S: Into<String> {
        ResponseBody::from_data(data.into().into_bytes())
    }
}
<commit_msg>Add some docs<commit_after>extern crate hyper;
extern crate rand;
extern crate rustc_serialize;
extern crate time;
extern crate url;

pub use assets::match_assets;
pub use log::LogEntry;
pub use input::{SessionsManager, Session, generate_session_id};

use std::io;
use std::io::Cursor;
use std::io::Read;
use std::fs::File;
use std::net::SocketAddr;
use std::net::ToSocketAddrs;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use std::thread;

pub mod input;

mod assets;
mod find_route;
mod log;
mod router;

/// An error that one of your routes can return.
///
/// This is just a convenience enum and you don't need to use it in your project
/// if you don't want to.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RouteError {
    /// Couldn't find a way to handle this request.
    NoRouteFound,

    /// The user input is wrong.
    WrongInput,

    /// The user must be logged in.
    LoginRequired,

    /// The user entered a wrong login or password.
    WrongLoginPassword,

    /// The user is logged in but shouldn't be there.
    NotAuthorized,
}

/// Starts a server and uses the given requests handler.
///
/// The request handler takes a `&Request` and must return a `Response` to send to the user.
///
/// # Common mistakes
///
/// The handler must capture its environment by value and not by reference (`'static`). If you
/// use closure, don't forget to put `move` in front of the closure.
///
/// The handler must also be thread-safe (`Send` and `Sync`).
/// For example this handler isn't thread-safe:
///
/// ```ignore
/// let mut requests_counter = 0;
///
/// rouille::start_server("localhost:80", move |request| {
///     requests_counter += 1;
///
///     // rest of the handler
/// })
/// ```
///
/// Multiple requests can be processed simultaneously, therefore you can't mutably access
/// variables from the outside.
///
/// Instead you must use a `Mutex`:
///
/// ```no_run
/// use std::sync::Mutex;
/// let requests_counter = Mutex::new(0);
///
/// rouille::start_server("localhost:80", move |request| {
///     *requests_counter.lock().unwrap() += 1;
///
///     // rest of the handler
/// # panic!()
/// })
/// ```
///
/// # Panic handling
///
/// If your request handler panicks, a 500 error will automatically be sent to the client.
///
pub fn start_server<A, F>(addr: A, handler: F) -> !
                          where A: ToSocketAddrs,
                                F: Send + Sync + 'static + Fn(&Request) -> Response
{
    // TODO: unused result?!?
    // TODO: does this block forever or not?
    hyper::server::Server::http(addr).unwrap().handle(Handler(handler));

    struct Handler<H>(H);
    impl<H> hyper::server::Handler for Handler<H>
            where H: Send + Sync + 'static + Fn(&Request) -> Response
    {
        fn handle<'a, 'k>(&'a self, mut hrequest: hyper::server::request::Request<'a, 'k>,
                          mut hresponse: hyper::server::response::Response<'a, hyper::net::Fresh>)
        {
            *hresponse.status_mut() = hyper::status::StatusCode::InternalServerError;

            // TODO: don't read the body in memory immediately
            let mut data = Vec::new();
            hrequest.read_to_end(&mut data);     // TODO: handle error

            // building the `Request` object
            let request = Request {
                url: format!("{}", hrequest.uri),   // TODO: handle this properly?
                method: hrequest.method.as_ref().to_owned(),
                headers: hrequest.headers.iter().map(|h| (h.name().to_owned(), h.value_string()))
                                                .collect(),
                https: false,
                data: data,
                remote_addr: hrequest.remote_addr.clone(),
            };

            // calling the handler ; this most likely takes a lot of time
            let mut response = (self.0)(&request);

            // writing the status code
            *hresponse.status_mut() = hyper::status::StatusCode::from_u16(response.status_code);

            // writing headers
            for (key, value) in response.headers {
                // FIXME: multiple headers with the same key
                hresponse.headers_mut().set_raw(key, vec![value.into_bytes()]);
            }

            if let Some(len) = response.data.data_length {
                hresponse.headers_mut().set(hyper::header::ContentLength(len as u64));
            }

            // sending status code and headers
            let mut hresponse = match hresponse.start() {
                Err(_) => return,
                Ok(r) => r
            };

            let _ = io::copy(response.data.data.by_ref(), &mut hresponse);
            let _ = hresponse.end();
        }
    }

    unreachable!()      // TODO: ?!?
}

/// Represents a request that your handler must answer to.
///
/// This can be either a real request (received by the HTTP server) or a mock object created with
/// one of the `fake_*` constructors.
pub struct Request {
    method: String,
    url: String,
    headers: Vec<(String, String)>,
    https: bool,
    data: Vec<u8>,
    remote_addr: SocketAddr,
}

impl Request {
    /// Builds a fake HTTP request to be used during tests.
    ///
    /// The remote address of the client will be `127.0.0.1:12345`. Use `fake_http_from` to
    /// specify what the client's address should be.
    pub fn fake_http<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
                           -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: false,
            data: data,
            headers: headers,
            remote_addr: "127.0.0.1:12345".parse().unwrap(),
        }
    }

    /// Builds a fake HTTP request to be used during tests.
    pub fn fake_http_from<U, M>(from: SocketAddr, method: M, url: U,
                                headers: Vec<(String, String)>, data: Vec<u8>)
                                -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: false,
            data: data,
            headers: headers,
            remote_addr: from,
        }
    }

    /// Builds a fake HTTPS request to be used during tests.
    ///
    /// The remote address of the client will be `127.0.0.1:12345`. Use `fake_https_from` to
    /// specify what the client's address should be.
    pub fn fake_https<U, M>(method: M, url: U, headers: Vec<(String, String)>, data: Vec<u8>)
                            -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: true,
            data: data,
            headers: headers,
            remote_addr: "127.0.0.1:12345".parse().unwrap(),
        }
    }

    /// Builds a fake HTTPS request to be used during tests.
    pub fn fake_https_from<U, M>(from: SocketAddr, method: M, url: U,
                                 headers: Vec<(String, String)>, data: Vec<u8>)
                                 -> Request where U: Into<String>, M: Into<String>
    {
        Request {
            url: url.into(),
            method: method.into(),
            https: true,
            data: data,
            headers: headers,
            remote_addr: from,
        }
    }

    /// Returns `true` if the request uses HTTPS instead of HTTP.
    #[inline]
    pub fn secure(&self) -> bool {
        self.https
    }

    /// Returns the method of the request (`GET`, `POST`, etc.).
    #[inline]
    pub fn method(&self) -> &str {
        &self.method
    }

    /// Returns the URL requested by the client. It is not decoded and thus can contain strings
    /// such as `%20`.
    ///
    /// See also `url()`.
    #[inline]
    pub fn raw_url(&self) -> &str {
        &self.url
    }

    /// Returns the URL requested by the client.
    ///
    /// Contrary to `raw_url`, special characters have been decoded.
    /// If there is any non-unicode character in the URL, it will be replaced with `U+FFFD`.
    pub fn url(&self) -> String {
        url::percent_encoding::lossy_utf8_percent_decode(self.url.as_bytes())
    }

    /// Returns the value of a header of the request.
    ///
    /// Returns `None` if no such header could be found.
    #[inline]
    pub fn header(&self, key: &str) -> Option<String> {
        self.headers.iter().find(|&&(ref k, _)| k == key).map(|&(_, ref v)| v.clone())
    }

    /// UNSTABLE. Returns the body of the request.
    ///
    /// Will eventually return an object that implements `Read` instead of a `Vec<u8>`.
    pub fn data(&self) -> Vec<u8> {
        self.data.clone()
    }

    /// Returns the address of the client that made this request.
    #[inline]
    pub fn remote_addr(&self) -> &SocketAddr {
        &self.remote_addr
    }
}

/// Contains a prototype of a response.
/// The response is only sent when you call `Request::respond`.
pub struct Response {
    /// The status code to return to the user.
    pub status_code: u16,

    /// List of headers to be returned in the response.
    ///
    /// Note that important headers such as `Connection` or `Content-Length` will be ignored
    /// from this list.
    // TODO: document precisely which headers
    pub headers: Vec<(String, String)>,

    /// An opaque type that contains the body of the response.
    pub data: ResponseBody,
}

impl Response {
    /// UNSTABLE. Builds a default response to handle the given route error.
    ///
    /// Important: don't use this in a real website. This function is just a convenience when
    /// prototyping.
    ///
    /// For authentication-related errors, you are strongly encouraged to handle them yourself.
    #[inline]
    pub fn from_error(err: &RouteError) -> Response {
        match err {
            &RouteError::NoRouteFound => Response {
                status_code: 404, headers: vec![], data: ResponseBody::empty()
            },
            &RouteError::WrongInput => Response {
                status_code: 400, headers: vec![], data: ResponseBody::empty()
            },
            &RouteError::LoginRequired => Response {
                status_code: 401, headers: vec![], data: ResponseBody::empty()
            },     // TODO: www-auth header?
            &RouteError::WrongLoginPassword => Response {
                status_code: 401, headers: vec![], data: ResponseBody::empty()
            },     // TODO: www-auth header?
            &RouteError::NotAuthorized => Response {
                status_code: 403, headers: vec![], data: ResponseBody::empty()
            },
        }
    }

    /// Builds a `Response` that redirects the user to another URL.
    #[inline]
    pub fn redirect(target: &str) -> Response {
        Response {
            status_code: 303,
            headers: vec![("Location".to_owned(), target.to_owned())],
            data: ResponseBody::empty(),
        }
    }

    /// Builds a `Response` that outputs HTML.
    #[inline]
    pub fn html<D>(content: D) -> Response where D: Into<Vec<u8>> {
        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "text/html; charset=utf8".to_owned())],
            data: ResponseBody::from_data(content),
        }
    }

    /// Builds a `Response` that outputs plain text.
    #[inline]
    pub fn text<S>(text: S) -> Response where S: Into<String> {
        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "text/plain; charset=utf8".to_owned())],
            data: ResponseBody::from_string(text),
        }
    }

    /// Builds a `Response` that outputs JSON.
    #[inline]
    pub fn json<T>(content: &T) -> Response where T: rustc_serialize::Encodable {
        let data = rustc_serialize::json::encode(content).unwrap();

        Response {
            status_code: 200,
            headers: vec![("Content-Type".to_owned(), "application/json".to_owned())],
            data: ResponseBody::from_data(data),
        }
    }

    /// Builds a `Response` that returns a `401 Not Authorized` status
    /// and a `WWW-Authenticate` header.
    #[inline]
    pub fn basic_http_auth_login_required(realm: &str) -> Response {
        // TODO: escape the realm
        Response {
            status_code: 401,
            headers: vec![("WWW-Authenticate".to_owned(), format!("Basic realm=\"{}\"", realm))],
            data: ResponseBody::empty(),
        }
    }
}

/// An opaque type that represents the body of a response.
pub struct ResponseBody {
    data: Box<Read + Send>,
    data_length: Option<usize>,
}

impl ResponseBody {
    /// Builds a `ResponseBody` that doesn't return any data.
    #[inline]
    pub fn empty() -> ResponseBody {
        ResponseBody {
            data: Box::new(io::empty()),
            data_length: Some(0),
        }
    }

    /// Builds a new `ResponseBody` that will read the data from a `Read`.
    ///
    /// Note that this is suboptimal compared to other constructors because the length
    /// isn't known in advance.
    #[inline]
    pub fn from_reader<R>(data: R) -> ResponseBody where R: Read + Send + 'static {
        ResponseBody {
            data: Box::new(data),
            data_length: None,
        }
    }

    /// Builds a new `ResponseBody` that returns the given data.
    #[inline]
    pub fn from_data<D>(data: D) -> ResponseBody where D: Into<Vec<u8>> {
        let data = data.into();
        let len = data.len();

        ResponseBody {
            data: Box::new(Cursor::new(data)),
            data_length: Some(len),
        }
    }

    /// Builds a new `ResponseBody` that returns the content of the given file.
    #[inline]
    pub fn from_file(file: File) -> ResponseBody {
        let len = file.metadata().map(|metadata| metadata.len() as usize).ok();

        ResponseBody {
            data: Box::new(file),
            data_length: len,
        }
    }

    /// Builds a new `ResponseBody` that returns an UTF-8 string.
    #[inline]
    pub fn from_string<S>(data: S) -> ResponseBody where S: Into<String> {
        ResponseBody::from_data(data.into().into_bytes())
    }
}
<|endoftext|>