<commit_before>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box can be moved around as an atomic unit.
#![feature(macro_rules, globs)]

#[macro_export]
macro_rules! viewbox(
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new(data: $d, f: <'a>|&'a mut $d| -> $v<'a>) -> $name {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E>(data: $d,
                                 f: <'a>|&'a mut $d|
                                    -> ::std::result::Result<$v<'a>,E>)
                                 -> ::std::result::Result<$name,($d,E)> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn unwrap(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn mut_view<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[deriving(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving(Show $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Show for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
)

#[cfg(test)]
mod test {
    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.unwrap();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.mut_view().x = 5;
        *v.mut_view().y = "Goodbye".to_string();
        let t = v.unwrap();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }
}
<commit_msg>Fix some warnings and add a new test<commit_after>#![crate_type = "rlib"]

//! Macro to create a "view box", a box containing data plus
//! a "view" struct that can have interior references into the data.
//! The view box can be moved around as an atomic unit.
#![feature(macro_rules, globs)]

#[macro_export]
macro_rules! viewbox(
    (struct $name:ident<$d:ty, $v:ident>;) => (
        pub struct $name {
            view: $v<'static>,
            #[allow(dead_code)]
            data: Box<$d>
        }

        #[allow(dead_code)]
        impl $name {
            pub fn new(data: $d, f: for<'a>|&'a mut $d| -> $v<'a>) -> $name {
                let mut d = box data;
                let v = unsafe { ::std::mem::transmute(f(&mut *d)) };

                $name { data: d, view: v }
            }

            pub fn new_result<E>(data: $d,
                                 f: for<'a>|&'a mut $d|
                                    -> ::std::result::Result<$v<'a>,E>)
                                 -> ::std::result::Result<$name,($d,E)> {
                let mut d = box data;
                match f(&mut *d).map(|v| unsafe { ::std::mem::transmute(v) }) {
                    Ok(v) => Ok($name { data: d, view: v }),
                    Err(e) => Err((*d,e))
                }
            }

            pub fn unwrap(self)-> $d {
                let $name { data: box data, .. } = self;
                data
            }

            pub fn view<'a>(&'a self) -> &'a $v<'a> {
                unsafe { ::std::mem::transmute(&self.view) }
            }

            pub fn mut_view<'a>(&'a mut self) -> &'a mut $v<'a> {
                unsafe { ::std::mem::transmute(&mut self.view) }
            }
        }
    );
    (#[deriving(PartialEq $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::cmp::PartialEq for $name {
            fn eq(&self, other: &$name) -> bool { self.view() == other.view(); }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving(Show $(,$derive:ident)*)] struct $name:ident<$d:ty, $v:ident>;) => (
        impl ::std::fmt::Show for $name {
            fn fmt(&self, fmt: &mut ::std::fmt::Formatter)
                   -> ::std::result::Result<(), ::std::fmt::FormatError> {
                self.view().fmt(fmt)
            }
        }
        viewbox!(struct $name<$d,$v>;)
    );
    (#[deriving()] struct $name:ident<$d:ty, $v:ident>;) => (
        viewbox!(struct $name<$d,$v>;)
    );
)

#[cfg(test)]
mod test {
    extern crate arena;
    use self::arena::TypedArena;

    // Test data structure
    #[deriving(PartialEq,Show)]
    struct TestData {
        foo: i32,
        bar: String
    }

    // View structure that has references into the boxed data
    struct TestView<'a> {
        x: &'a i32,
        y: &'a str
    }

    // Create TestBox which combines TestData and TestView
    viewbox! {
        struct TestBox<TestData,TestView>;
    }

    // Mutable view into TestData
    struct MutView<'a> {
        x: &'a mut i32,
        y: &'a mut String
    }

    // MutBox combines TestData and MutView
    viewbox! {
        struct MutBox<TestData, MutView>;
    }

    #[test]
    fn basic() {
        // Create some data
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        // Move it into box, creating a view with interior references
        let v = TestBox::new(t, |d| TestView { x: &d.foo, y: d.bar.as_slice() });

        // We can access the boxed data via the view
        assert_eq!(v.view().x, &42i32);
        assert_eq!(v.view().y, "Hello");
        // We can unwrap the view to get the data back
        let t = v.unwrap();
        assert_eq!(t.foo, 42i32);
        assert_eq!(t.bar, "Hello".to_string());
    }

    #[test]
    fn mutation() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let mut v = MutBox::new(t, |d| MutView { x: &mut d.foo, y: &mut d.bar });

        *v.mut_view().x = 5;
        *v.mut_view().y = "Goodbye".to_string();
        let t = v.unwrap();
        assert_eq!(t, TestData { foo: 5, bar: "Goodbye".to_string() });
    }

    #[test]
    fn error() {
        let t = TestData { foo: 42, bar: "Hello".to_string() };
        let v = MutBox::new_result(t, |_| Err("Nope")).err().unwrap();
        assert_eq!(v, (TestData { foo: 42, bar: "Hello".to_string() }, "Nope"))
    }

    struct ArenaView<'a> {
        arena: &'a TypedArena<int>,
        vec: Vec<&'a int>
    }

    viewbox! {
        struct ArenaBox<TypedArena<int>, ArenaView>;
    }

    #[test]
    fn arenaview() {
        let mut vb = ArenaBox::new(
            TypedArena::new(),
            |a| ArenaView { arena: a, vec: Vec::new()});

        spawn(proc() {
            let v = vb.mut_view();
            let a = v.arena.alloc(1);
            let b = v.arena.alloc(2);
            let c = v.arena.alloc(3);
            v.vec.push(a);
            v.vec.push(b);
            v.vec.push(c);
        });
    }
}
<|endoftext|>


<commit_before>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
       html_root_url = "https://urschrei.github.io/polylabel-rs/")]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
use std::fmt::Debug;
use std::cmp::Ordering;
use std::collections::BinaryHeap;

extern crate num;
use self::num::{Float, FromPrimitive};

extern crate geo;
use self::geo::{Point, Polygon};
use self::geo::algorithm::boundingbox::BoundingBox;
use self::geo::algorithm::distance::Distance;
use self::geo::algorithm::area::Area;
use self::geo::algorithm::centroid::Centroid;
use self::geo::algorithm::contains::Contains;

mod ffi;
pub use ffi::{polylabel_ffi, Array, WrapperArray, Position};

// A helper struct for `polylabel`
#[derive(Debug)]
struct Cell<T>
    where T: Float
{
    // Centroid coordinates
    x: T,
    y: T,
    // Half the cell size
    h: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Cell<T>
    where T: Float
{
    /// Creates a new Cell
    pub fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Cell<T> {
        Cell {
            x: x,
            y: y,
            h: h,
            distance: distance,
            max_distance: max_distance,
        }
    }
}

impl<T> Ord for Cell<T>
    where T: Float
{
    fn cmp(&self, other: &Cell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Cell<T>
    where T: Float
{
    fn partial_cmp(&self, other: &Cell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Cell<T> where T: Float {}
impl<T> PartialEq for Cell<T>
    where T: Float
{
    fn eq(&self, other: &Cell<T>) -> bool
        where T: Float
    {
        self.max_distance == other.max_distance
    }
}

// Signed distance from a Cell's centroid to a Polygon's outline
// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
    where T: Float
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.distance(&polygon.exterior);
    if inside { distance } else { -distance }
}

// Add a new quadtree node to the minimum priority queue
fn add_quad<T>(mpq: &mut BinaryHeap<Cell<T>>, cell: &Cell<T>, nh: &T, polygon: &Polygon<T>)
    where T: Float
{
    let two = T::one() + T::one();
    // 1
    let mut new_dist = signed_distance(&(cell.x - *nh), &(cell.y - *nh), polygon);
    mpq.push(Cell::new(cell.x - *nh,
                       cell.y - *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 2
    new_dist = signed_distance(&(cell.x + *nh), &(cell.y - *nh), polygon);
    mpq.push(Cell::new(cell.x + *nh,
                       cell.y - *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 3
    new_dist = signed_distance(&(cell.x - *nh), &(cell.y + *nh), polygon);
    mpq.push(Cell::new(cell.x - *nh,
                       cell.y + *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 4
    new_dist = signed_distance(&(cell.x + *nh), &(cell.y + *nh), polygon);
    mpq.push(Cell::new(cell.x + *nh,
                       cell.y + *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
/// let poly = Polygon(ls, vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
    where T: Float + FromPrimitive + Debug
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        // best_cell = Cell {
        //     x: polygon.exterior.0[0].x(),
        //     y: polygon.exterior.0[0].y(),
        //     h: T::zero(),
        //     distance: distance,
        //     max_distance: max_distance
        // };
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bbox().unwrap();
    let width = bbox.xmax - bbox.xmin;
    let height = bbox.ymax - bbox.ymin;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.xmin, bbox.ymin);
    }
    let mut h: T = cell_size / two;
    let distance: T = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance: T = distance + T::zero() * two.sqrt();

    let mut best_cell = Cell {
        x: centroid.x(),
        y: centroid.y(),
        h: T::zero(),
        distance: distance,
        max_distance: max_distance,
    };

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(&(bbox.xmin + width / two),
                                         &(bbox.ymin + height / two),
                                         polygon);
    let bbox_cell = Cell {
        x: bbox.xmin + width / two,
        y: bbox.ymin + height / two,
        h: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Minimum priority queue
    let mut cell_queue: BinaryHeap<Cell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.xmin;
    let mut y;
    while x < bbox.xmax {
        y = bbox.ymin;
        while y < bbox.ymax {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Cell {
                x: x + h,
                y: y + h,
                h: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.x = cell.x;
            best_cell.y = cell.y;
            best_cell.h = cell.h;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.h / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.x, best_cell.y)
}

#[cfg(test)]
mod tests {
    use std::collections::BinaryHeap;
    use super::{polylabel, Cell};
    extern crate libc;
    extern crate geo;
    use geo::{Point, Polygon, LineString};
    use geo::contains::Contains;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 1.0), (1.0, 1.0), (1.0, 4.0), (0.0, 4.0),
                          (0.0, 0.0)];
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_ls = LineString(a_coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let a_poly = Polygon::new(a_ls, vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_ls = LineString(b_coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let b_poly = Polygon::new(b_ls, vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<commit_msg>Fix comment<commit_after>#![doc(html_logo_url = "https://cdn.rawgit.com/urschrei/polylabel-rs/7a07336e85572eb5faaf0657c2383d7de5620cd8/ell.svg",
       html_root_url = "https://urschrei.github.io/polylabel-rs/")]
//! This crate provides a Rust implementation of the [Polylabel](https://github.com/mapbox/polylabel) algorithm
use std::fmt::Debug;
use std::cmp::Ordering;
use std::collections::BinaryHeap;

extern crate num;
use self::num::{Float, FromPrimitive};

extern crate geo;
use self::geo::{Point, Polygon};
use self::geo::algorithm::boundingbox::BoundingBox;
use self::geo::algorithm::distance::Distance;
use self::geo::algorithm::area::Area;
use self::geo::algorithm::centroid::Centroid;
use self::geo::algorithm::contains::Contains;

mod ffi;
pub use ffi::{polylabel_ffi, Array, WrapperArray, Position};

// A helper struct for `polylabel`
#[derive(Debug)]
struct Cell<T>
    where T: Float
{
    // Centroid coordinates
    x: T,
    y: T,
    // Half the cell size
    h: T,
    // Distance from centroid to polygon
    distance: T,
    // Maximum distance to polygon within a cell
    max_distance: T,
}

impl<T> Cell<T>
    where T: Float
{
    /// Creates a new Cell
    pub fn new(x: T, y: T, h: T, distance: T, max_distance: T) -> Cell<T> {
        Cell {
            x: x,
            y: y,
            h: h,
            distance: distance,
            max_distance: max_distance,
        }
    }
}

impl<T> Ord for Cell<T>
    where T: Float
{
    fn cmp(&self, other: &Cell<T>) -> std::cmp::Ordering {
        self.max_distance.partial_cmp(&other.max_distance).unwrap()
    }
}
impl<T> PartialOrd for Cell<T>
    where T: Float
{
    fn partial_cmp(&self, other: &Cell<T>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl<T> Eq for Cell<T> where T: Float {}
impl<T> PartialEq for Cell<T>
    where T: Float
{
    fn eq(&self, other: &Cell<T>) -> bool
        where T: Float
    {
        self.max_distance == other.max_distance
    }
}

// Signed distance from a Cell's centroid to a Polygon's outline
// Returned value is negative if the point is outside the polygon's exterior ring
fn signed_distance<T>(x: &T, y: &T, polygon: &Polygon<T>) -> T
    where T: Float
{
    let point = Point::new(*x, *y);
    let inside = polygon.contains(&point);
    // Use LineString distance, because Polygon distance returns 0.0 for inside
    let distance = point.distance(&polygon.exterior);
    if inside { distance } else { -distance }
}

// Add a new quadtree node to the binary heap
fn add_quad<T>(mpq: &mut BinaryHeap<Cell<T>>, cell: &Cell<T>, nh: &T, polygon: &Polygon<T>)
    where T: Float
{
    let two = T::one() + T::one();
    // 1
    let mut new_dist = signed_distance(&(cell.x - *nh), &(cell.y - *nh), polygon);
    mpq.push(Cell::new(cell.x - *nh,
                       cell.y - *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 2
    new_dist = signed_distance(&(cell.x + *nh), &(cell.y - *nh), polygon);
    mpq.push(Cell::new(cell.x + *nh,
                       cell.y - *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 3
    new_dist = signed_distance(&(cell.x - *nh), &(cell.y + *nh), polygon);
    mpq.push(Cell::new(cell.x - *nh,
                       cell.y + *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
    // 4
    new_dist = signed_distance(&(cell.x + *nh), &(cell.y + *nh), polygon);
    mpq.push(Cell::new(cell.x + *nh,
                       cell.y + *nh,
                       *nh,
                       new_dist,
                       new_dist + *nh * two.sqrt()));
}

/// Calculate a Polygon's ideal label position by calculating its ✨pole of inaccessibility✨
///
/// The calculation uses an [iterative grid-based algorithm](https://github.com/mapbox/polylabel#how-the-algorithm-works).
///
/// # Examples
///
/// ```
/// use polylabel::polylabel;
/// extern crate geo;
/// use self::geo::{Point, LineString, Polygon};
///
/// // An approximate `L` shape
/// let coords = vec![
///    (0.0, 0.0),
///    (4.0, 0.0),
///    (4.0, 1.0),
///    (1.0, 1.0),
///    (1.0, 4.0),
///    (0.0, 4.0),
///    (0.0, 0.0)];
///
/// let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
/// let poly = Polygon(ls, vec![]);
///
/// // Its centroid lies outside the polygon
/// assert_eq!(poly.centroid(), Point::new(1.3571428571428572, 1.3571428571428572));
///
/// let label_position = polylabel(&poly, &1.0);
/// // Optimum label position is inside the polygon
/// assert_eq!(label_position, Point::new(0.5625, 0.5625));
/// ```
///
pub fn polylabel<T>(polygon: &Polygon<T>, tolerance: &T) -> Point<T>
    where T: Float + FromPrimitive + Debug
{
    // special case for degenerate polygons
    if polygon.area() == T::zero() {
        // best_cell = Cell {
        //     x: polygon.exterior.0[0].x(),
        //     y: polygon.exterior.0[0].y(),
        //     h: T::zero(),
        //     distance: distance,
        //     max_distance: max_distance
        // };
        return Point::new(T::zero(), T::zero());
    }
    let two = T::one() + T::one();
    // Initial best cell values
    let centroid = polygon.centroid().unwrap();
    let bbox = polygon.bbox().unwrap();
    let width = bbox.xmax - bbox.xmin;
    let height = bbox.ymax - bbox.ymin;
    let cell_size = width.min(height);
    // Special case for degenerate polygons
    if cell_size == T::zero() {
        return Point::new(bbox.xmin, bbox.ymin);
    }
    let mut h: T = cell_size / two;
    let distance: T = signed_distance(&centroid.x(), &centroid.y(), polygon);
    let max_distance: T = distance + T::zero() * two.sqrt();

    let mut best_cell = Cell {
        x: centroid.x(),
        y: centroid.y(),
        h: T::zero(),
        distance: distance,
        max_distance: max_distance,
    };

    // special case for rectangular polygons
    let bbox_cell_dist = signed_distance(&(bbox.xmin + width / two),
                                         &(bbox.ymin + height / two),
                                         polygon);
    let bbox_cell = Cell {
        x: bbox.xmin + width / two,
        y: bbox.ymin + height / two,
        h: T::zero(),
        distance: bbox_cell_dist,
        max_distance: bbox_cell_dist + T::zero() * two.sqrt(),
    };

    if bbox_cell.distance > best_cell.distance {
        best_cell = bbox_cell;
    }

    // Minimum priority queue
    let mut cell_queue: BinaryHeap<Cell<T>> = BinaryHeap::new();
    // Build an initial quadtree node, which covers the Polygon
    let mut x = bbox.xmin;
    let mut y;
    while x < bbox.xmax {
        y = bbox.ymin;
        while y < bbox.ymax {
            let latest_dist = signed_distance(&(x + h), &(y + h), polygon);
            cell_queue.push(Cell {
                x: x + h,
                y: y + h,
                h: h,
                distance: latest_dist,
                max_distance: latest_dist + h * two.sqrt(),
            });
            y = y + cell_size;
        }
        x = x + cell_size;
    }
    // Now try to find better solutions
    while !cell_queue.is_empty() {
        let cell = cell_queue.pop().unwrap();
        // Update the best cell if we find a cell with greater distance
        if cell.distance > best_cell.distance {
            best_cell.x = cell.x;
            best_cell.y = cell.y;
            best_cell.h = cell.h;
            best_cell.distance = cell.distance;
            best_cell.max_distance = cell.max_distance;
        }
        // Bail out of this iteration if we can't find a better solution
        if cell.max_distance - best_cell.distance <= *tolerance {
            continue;
        }
        // Otherwise, add a new quadtree node and start again
        h = cell.h / two;
        add_quad(&mut cell_queue, &cell, &h, polygon);
    }
    // We've exhausted the queue, so return the best solution we've found
    Point::new(best_cell.x, best_cell.y)
}

#[cfg(test)]
mod tests {
    use std::collections::BinaryHeap;
    use super::{polylabel, Cell};
    extern crate libc;
    extern crate geo;
    use geo::{Point, Polygon, LineString};
    use geo::contains::Contains;
    #[test]
    // polygons are those used in Shapely's tests
    fn test_polylabel() {
        let coords = include!("poly1.rs");
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &10.000);
        assert_eq!(res, Point::new(59.35615556364569, 121.83919629746435));
    }
    #[test]
    // does a concave polygon contain the calculated point?
    // relevant because the centroid lies outside the polygon in this case
    fn test_concave() {
        let coords = include!("poly2.rs");
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &1.0);
        assert!(poly.contains(&res));
    }
    #[test]
    fn polygon_l_test() {
        // an L shape
        let coords = vec![(0.0, 0.0), (4.0, 0.0), (4.0, 1.0), (1.0, 1.0), (1.0, 4.0), (0.0, 4.0),
                          (0.0, 0.0)];
        let ls = LineString(coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let poly = Polygon::new(ls, vec![]);
        let res = polylabel(&poly, &0.10);
        assert_eq!(res, Point::new(0.5625, 0.5625));
    }
    #[test]
    fn degenerate_polygon_test() {
        let a_coords = vec![(0.0, 0.0), (1.0, 0.0), (2.0, 0.0), (0.0, 0.0)];
        let a_ls = LineString(a_coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let a_poly = Polygon::new(a_ls, vec![]);
        let a_res = polylabel(&a_poly, &1.0);
        assert_eq!(a_res, Point::new(0.0, 0.0));
    }
    #[test]
    fn degenerate_polygon_test_2() {
        let b_coords = vec![(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)];
        let b_ls = LineString(b_coords.iter().map(|e| Point::new(e.0, e.1)).collect());
        let b_poly = Polygon::new(b_ls, vec![]);
        let b_res = polylabel(&b_poly, &1.0);
        assert_eq!(b_res, Point::new(0.0, 0.0));
    }
    #[test]
    // Is our priority queue behaving as it should?
    fn test_queue() {
        let a = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 8.0,
        };
        let b = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 7.0,
        };
        let c = Cell {
            x: 1.0,
            y: 2.0,
            h: 3.0,
            distance: 4.0,
            max_distance: 9.0,
        };
        let mut v = vec![];
        v.push(a);
        v.push(b);
        v.push(c);
        let mut q = BinaryHeap::from(v);
        assert_eq!(q.pop().unwrap().max_distance, 9.0);
        assert_eq!(q.pop().unwrap().max_distance, 8.0);
        assert_eq!(q.pop().unwrap().max_distance, 7.0);
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate unicase;

use unicase::UniCase;
use iron::prelude::*;
use iron::method::Method;
use iron::status;
use iron::headers::{Origin,
					ContentType,
                    AccessControlRequestMethod,
                    AccessControlAllowOrigin,
                    AccessControlAllowHeaders,
                    AccessControlAllowMethods};
use iron::middleware::{AroundMiddleware, Handler};

struct CorsMiddleware;
impl AroundMiddleware for CorsMiddleware {

    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(move | req: &mut Request | {
            let allowed_headers: Vec<unicase::UniCase<String>> = vec![
                    // To allow application/json
                    UniCase("Content-Type".to_owned()),
                    // Set by some js libs
                    UniCase("X-Requested-With".to_owned()),
                    ];
            let allowed_methods: Vec<Method> = vec![ Method::Get, Method::Put, Method::Post ];
            if req.method == Method::Options &&
                req.headers.get::<AccessControlRequestMethod>().is_some() {
                // Preflight request
                // 1.If the Origin header is not present terminate this set of steps. The request is
                // outside the scope of this specification.
                let maybe_origin = req.headers.get::<Origin>();
                if maybe_origin.is_none() {
                    let resp = Response::with((status::BadRequest,
                                               "Preflight request without Origin header"));
                    return Ok(resp);
                }
                let origin = maybe_origin.unwrap();
                let mut res = Response::with((status::NoContent));
                //
                // 2.If the value of the Origin header is not a case-sensitive match for any of the
                // values in list of origins do not set any additional headers and terminate this
                // set of steps.
                //
                // Note: Always matching is acceptable since the list of origins can be unbounded.
                //
                // Note: The Origin header can only contain a single origin as the user agent
                //       will not follow redirects.
                //
                // 3. Let method be the value as result of parsing the Access-Control-Request-Method
                // header.
                //
                // If there is no Access-Control-Request-Method header or if parsing failed, do not
                // set any additional headers and terminate this set of steps. The request is
                // outside the scope of this specification.
                //
                // 4. Let header field-names be the values as result of parsing the
                // Access-Control-Request-Headers headers.
                //
                // If there are no Access-Control-Request-Headers headers let header field-names be
                // the empty list.
                //
                // If parsing failed do not set any additional headers and terminate this set of
                // steps. The request is outside the scope of this specification.
                //
                // 5.If method is not a case-sensitive match for any of the values in list of
                //   methods do not set any additional headers and terminate this set of steps.
                //
                // Always matching is acceptable since the list of methods can be unbounded.
                //
                // 6. If any of the header field-names is not a ASCII case-insensitive match for any
                // of the values in list of headers do not set any additional headers and terminate
                // this set of steps.
                //
                // Always matching is acceptable since the list of headers can be unbounded.
                //
                // 7. If the resource supports credentials add a single Access-Control-Allow-Origin
                // header, with the value of the Origin header as value, and add a single
                // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
                // value.
                //
                // Otherwise, add a single Access-Control-Allow-Origin header, with either the
                // value of the Origin header or the string "*" as value.
                res.headers.set(AccessControlAllowOrigin::Value(format!("{}", origin)));
                //
                // The string "*" cannot be used for a resource that supports credentials.
                //
                // 8. Optionally add a single Access-Control-Max-Age header with as value the amount
                // of seconds the user agent is allowed to cache the result of the request.
                //
                // 9. If method is a simple method this step may be skipped.
                //
                // Add one or more Access-Control-Allow-Methods headers consisting of (a subset of)
                // the list of methods.
                res.headers.set(AccessControlAllowMethods(allowed_methods));
                //
                // If a method is a simple method it does not need to be listed, but this is not
                // prohibited.
                //
                // Since the list of methods can be unbounded, simply returning the method
                // indicated by Access-Control-Request-Method (if supported) can be enough.
                //
                // 10.If each of the header field-names is a simple header and none is Content-Type,
                // this step may be skipped.
                //
                // Add one or more Access-Control-Allow-Headers headers consisting of (a subset of)
                // the list of headers.
                res.headers.set(AccessControlAllowHeaders(allowed_headers));
                //
                // If a header field name is a simple header and is not Content-Type, it is not
                // required to be listed. Content-Type is to be listed as only a subset of its
                // values makes it qualify as simple header.
                //
                // Since the list of headers can be unbounded, simply returning supported headers
                // from Access-Control-Allow-Headers can be enough.
                Ok(res)

            } else {
                // Normal request
                // 1.If the Origin header is not present terminate this set of steps. The request is
                // outside the scope of this specification.
                //
                // 2.If the value of the Origin header is not a case-sensitive match for any of the
                // values in list of origins, do not set any additional headers and terminate this
                // set of steps.
                //
                // Note: Always matching is acceptable since the list of origins can be unbounded.
                //
                // 3. If the resource supports credentials add a single Access-Control-Allow-Origin
                // header, with the value of the Origin header as value, and add a single
                // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
                // value.
                //
                // Otherwise, add a single Access-Control-Allow-Origin header, with either the
                // value of the Origin header or the string "*" as value.
                //
                // Note: The string "*" cannot be used for a resource that supports credentials.
                //
                // 4. If the list of exposed headers is not empty add one or more
                // Access-Control-Expose-Headers headers, with as values the header field names
                // given in the list of exposed headers.
                let result = handler.handle(req);
                match result {
                    Ok(mut resp) => {
                        // And set CORS headers
                        resp.headers.set(AccessControlAllowOrigin::Value("*".to_string()));
                        Ok(resp)
                    }
                    _ => result
                }
            }
        })
    }
}

#[cfg(test)]
mod tests {
	extern crate router;
	extern crate hyper;
	use iron::Listening;
	use self::router::Router;
	use iron::prelude::*;
	use iron::status;
	use self::hyper::Client;
	use self::hyper::header::Headers;
	use std::io::Read;
    use iron::headers::{Origin,
					ContentType,
                    AccessControlRequestMethod,
                    AccessControlAllowOrigin,
                    AccessControlAllowHeaders,
                    AccessControlAllowMethods};
    use iron::middleware::{AroundMiddleware, Handler};
    use iron::method::Method;
    use super::CorsMiddleware;
    use std::str::FromStr;

	struct AutoServer {
		listening: Listening,
		port: u16
	}

	impl AutoServer {
		pub fn new() -> AutoServer {
			let mut router = Router::new();
			router.get("/a",
               |_: &mut Request| Ok(Response::with((status::ImATeapot, ""))),
               "get_a");
            let mut chain = Chain::new(router);
            chain.link_around(CorsMiddleware);
    		let l = Iron::new(chain).http(format!("localhost:0")).unwrap();
			let p = l.socket.port();
			AutoServer { listening: l, port: p }
		}
	}

	impl Drop for AutoServer {
		fn drop(&mut self) {
			// Workaround for https://github.com/hyperium/hyper/issues/338
			self.listening.close().unwrap();
		}
	}

    #[test]
    fn normal_request_possible() {
		let server = AutoServer::new();
		let client = Client::new();
		let res = client.get(&format!("http://127.0.0.1:{}/a", server.port)).send().unwrap();
		assert_eq!(res.status, status::ImATeapot);
	}

    #[test]
    fn preflight_without_origin_is_bad_request() {
		let server = AutoServer::new();
		let client = Client::new();
		let mut headers = Headers::new();
		headers.set(AccessControlRequestMethod(Method::Get));
		let mut res = client
				.request(Method::Options, &format!("http://127.0.0.1:{}/a", server.port))
				.headers(headers)
				.send().unwrap();
		assert_eq!(res.status, status::BadRequest);
        let mut payload = String::new();
        res.read_to_string(&mut payload).unwrap();
        assert_eq!(payload, "Preflight request without Origin header");
	}

    #[test]
    fn preflight_with_origin_accepts_same_origin() {
		let server = AutoServer::new();
		let client = Client::new();
		let mut headers = Headers::new();
		headers.set(AccessControlRequestMethod(Method::Get));
		headers.set(Origin::from_str("http://www.a.com:8080").unwrap());
		let mut res = client
				.request(Method::Options, &format!("http://127.0.0.1:{}/a", server.port))
				.headers(headers)
				.send().unwrap();
		assert_eq!(res.status, status::NoContent);
        let allow_origin = res.headers.get::<AccessControlAllowOrigin>().unwrap();
        assert_eq!(format!("{}", allow_origin) , "http://www.a.com:8080");
        let allow_headers = res.headers.get::<AccessControlAllowHeaders>().unwrap();
        assert_eq!(format!("{}", allow_headers) , "Content-Type, X-Requested-With");
        let allow_methods = res.headers.get::<AccessControlAllowMethods>().unwrap();
        assert_eq!(format!("{}", allow_methods) , "GET, PUT, POST");
	}
}
<commit_msg>max-age, borrowing problem<commit_after>extern crate iron;
extern crate unicase;

use unicase::UniCase;
use iron::prelude::*;
use iron::method::Method;
use iron::status;
use iron::headers::{Origin,
					ContentType,
                    AccessControlRequestMethod,
                    AccessControlAllowOrigin,
                    AccessControlAllowHeaders,
                    AccessControlMaxAge,
                    AccessControlAllowMethods};
use iron::middleware::{AroundMiddleware, Handler};

struct CorsMiddleware;
impl AroundMiddleware for CorsMiddleware {

    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(move | req: &mut Request | {
            let allowed_headers: Vec<unicase::UniCase<String>> = vec![
                    // To allow application/json
                    UniCase("Content-Type".to_owned()),
                    // Set by some js libs
                    UniCase("X-Requested-With".to_owned()),
                    ];
            let allowed_methods: Vec<Method> = vec![ Method::Get, Method::Put, Method::Post ];
            if req.method == Method::Options &&
                req.headers.get::<AccessControlRequestMethod>().is_some() {
                // Preflight request
                // 1.If the Origin header is not present terminate this set of steps. The request is
                // outside the scope of this specification.
                let maybe_origin = req.headers.get::<Origin>();
                if maybe_origin.is_none() {
                    let resp = Response::with((status::BadRequest,
                                               "Preflight request without Origin header"));
                    return Ok(resp);
                }
                let origin = maybe_origin.unwrap();
                let mut res = Response::with((status::NoContent));
                //
                // 2.If the value of the Origin header is not a case-sensitive match for any of the
                // values in list of origins do not set any additional headers and terminate this
                // set of steps.
                //
                // Note: Always matching is acceptable since the list of origins can be unbounded.
                //
                // Note: The Origin header can only contain a single origin as the user agent
                //       will not follow redirects.
                //
                // 3. Let method be the value as result of parsing the Access-Control-Request-Method
                // header.
                //
                // If there is no Access-Control-Request-Method header or if parsing failed, do not
                // set any additional headers and terminate this set of steps. The request is
                // outside the scope of this specification.
                //
                // 4. Let header field-names be the values as result of parsing the
                // Access-Control-Request-Headers headers.
                //
                // If there are no Access-Control-Request-Headers headers let header field-names be
                // the empty list.
                //
                // If parsing failed do not set any additional headers and terminate this set of
                // steps. The request is outside the scope of this specification.
                //
                // 5.If method is not a case-sensitive match for any of the values in list of
                //   methods do not set any additional headers and terminate this set of steps.
                //
                // Always matching is acceptable since the list of methods can be unbounded.
                //
                // 6. If any of the header field-names is not a ASCII case-insensitive match for any
                // of the values in list of headers do not set any additional headers and terminate
                // this set of steps.
                //
                // Always matching is acceptable since the list of headers can be unbounded.
                //
                // 7. If the resource supports credentials add a single Access-Control-Allow-Origin
                // header, with the value of the Origin header as value, and add a single
                // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
                // value.
                //
                // Otherwise, add a single Access-Control-Allow-Origin header, with either the
                // value of the Origin header or the string "*" as value.
                res.headers.set(AccessControlAllowOrigin::Value(format!("{}", origin)));
                //
                // The string "*" cannot be used for a resource that supports credentials.
                //
                // 8. Optionally add a single Access-Control-Max-Age header with as value the amount
                // of seconds the user agent is allowed to cache the result of the request.
                res.headers.set(AccessControlMaxAge(60*60));
                //
                // 9. If method is a simple method this step may be skipped.
                //
                // Add one or more Access-Control-Allow-Methods headers consisting of (a subset of)
                // the list of methods.
                res.headers.set(AccessControlAllowMethods(allowed_methods));
                //
                // If a method is a simple method it does not need to be listed, but this is not
                // prohibited.
                //
                // Since the list of methods can be unbounded, simply returning the method
                // indicated by Access-Control-Request-Method (if supported) can be enough.
                //
                // 10.If each of the header field-names is a simple header and none is Content-Type,
                // this step may be skipped.
                //
                // Add one or more Access-Control-Allow-Headers headers consisting of (a subset of)
                // the list of headers.
                res.headers.set(AccessControlAllowHeaders(allowed_headers));
                //
                // If a header field name is a simple header and is not Content-Type, it is not
                // required to be listed. Content-Type is to be listed as only a subset of its
                // values makes it qualify as simple header.
                //
                // Since the list of headers can be unbounded, simply returning supported headers
                // from Access-Control-Allow-Headers can be enough.
                Ok(res)
            } else {
                // Normal request
                // 1.If the Origin header is not present terminate this set of steps. The request is
                // outside the scope of this specification.
                let maybe_origin = req.headers.get::<Origin>();
                if maybe_origin.is_none() {
                    return handler.handle(req);
                }
                let origin = maybe_origin.unwrap();
                //
                // 2.If the value of the Origin header is not a case-sensitive match for any of the
                // values in list of origins, do not set any additional headers and terminate this
                // set of steps.
                //
                // Note: Always matching is acceptable since the list of origins can be unbounded.
                //
                // 3. If the resource supports credentials add a single Access-Control-Allow-Origin
                // header, with the value of the Origin header as value, and add a single
                // Access-Control-Allow-Credentials header with the case-sensitive string "true" as
                // value.
                //
                // Otherwise, add a single Access-Control-Allow-Origin header, with either the
                // value of the Origin header or the string "*" as value.
                //
                // Note: The string "*" cannot be used for a resource that supports credentials.
                //
                // 4. If the list of exposed headers is not empty add one or more
                // Access-Control-Expose-Headers headers, with as values the header field names
                // given in the list of exposed headers.
                let result = handler.handle(req);
                match result {
                    Ok(mut res) => {
                        // And set CORS headers
                        res.headers.set(AccessControlAllowOrigin::Value(format!("{}", origin)));
                        Ok(res)
                    }
                    _ => result
                }
            }
        })
    }
}

#[cfg(test)]
mod tests {
	extern crate router;
	extern crate hyper;
	use iron::Listening;
	use self::router::Router;
	use iron::prelude::*;
	use iron::status;
	use self::hyper::Client;
	use self::hyper::header::Headers;
	use std::io::Read;
    use iron::headers::{Origin,
					ContentType,
                    AccessControlRequestMethod,
                    AccessControlAllowOrigin,
                    AccessControlAllowHeaders,
                    AccessControlMaxAge,
                    AccessControlAllowMethods};
    use iron::middleware::{AroundMiddleware, Handler};
    use iron::method::Method;
    use super::CorsMiddleware;
    use std::str::FromStr;

	struct AutoServer {
		listening: Listening,
		port: u16
	}

	impl AutoServer {
		pub fn new() -> AutoServer {
			let mut router = Router::new();
			router.get("/a",
               |_: &mut Request| Ok(Response::with((status::ImATeapot, ""))),
               "get_a");
            let mut chain = Chain::new(router);
            chain.link_around(CorsMiddleware);
    		let l = Iron::new(chain).http(format!("localhost:0")).unwrap();
			let p = l.socket.port();
			AutoServer { listening: l, port: p }
		}
	}

	impl Drop for AutoServer {
		fn drop(&mut self) {
			// Workaround for https://github.com/hyperium/hyper/issues/338
			self.listening.close().unwrap();
		}
	}

    #[test]
    fn normal_request_possible() {
		let server = AutoServer::new();
		let client = Client::new();
		let res = client.get(&format!("http://127.0.0.1:{}/a", server.port)).send().unwrap();
		assert_eq!(res.status, status::ImATeapot);
	}

    #[test]
    fn preflight_without_origin_is_bad_request() {
		let server = AutoServer::new();
		let client = Client::new();
		let mut headers = Headers::new();
		headers.set(AccessControlRequestMethod(Method::Get));
		let mut res = client
				.request(Method::Options, &format!("http://127.0.0.1:{}/a", server.port))
				.headers(headers)
				.send().unwrap();
		assert_eq!(res.status, status::BadRequest);
        let mut payload = String::new();
        res.read_to_string(&mut payload).unwrap();
        assert_eq!(payload, "Preflight request without Origin header");
	}

    #[test]
    fn preflight_with_origin_accepts_same_origin() {
		let server = AutoServer::new();
		let client = Client::new();
		let mut headers = Headers::new();
		headers.set(AccessControlRequestMethod(Method::Get));
		headers.set(Origin::from_str("http://www.a.com:8080").unwrap());
		let mut res = client
				.request(Method::Options, &format!("http://127.0.0.1:{}/a", server.port))
				.headers(headers)
				.send().unwrap();
		assert_eq!(res.status, status::NoContent);
        let allow_origin = res.headers.get::<AccessControlAllowOrigin>().unwrap();
        assert_eq!(format!("{}", allow_origin) , "http://www.a.com:8080");
        let allow_headers = res.headers.get::<AccessControlAllowHeaders>().unwrap();
        assert_eq!(format!("{}", allow_headers) , "Content-Type, X-Requested-With");
        let allow_methods = res.headers.get::<AccessControlAllowMethods>().unwrap();
        assert_eq!(format!("{}", allow_methods) , "GET, PUT, POST");
        let max_age = res.headers.get::<AccessControlMaxAge>().unwrap();
        assert_eq!(max_age.0, 60*60u32);
	}
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate num;

#[allow(non_camel_case_types, non_snake_case, raw_pointer_derive, dead_code)]
extern crate libhdf5_sys as ffi;

#[macro_use]
extern crate lazy_static;

#[cfg(test)]
extern crate tempdir;

#[cfg(test)]
extern crate regex;

#[macro_use]
pub mod macros;

pub mod container;
pub mod error;
pub mod file;
pub mod globals;
pub mod group;
pub mod location;
pub mod object;
pub mod plist;
pub mod sync;
pub mod util;

#[cfg(test)]
pub mod test;
<commit_msg>Make "object" module private<commit_after>extern crate libc;
extern crate num;

#[allow(non_camel_case_types, non_snake_case, raw_pointer_derive, dead_code)]
extern crate libhdf5_sys as ffi;

#[macro_use]
extern crate lazy_static;

#[cfg(test)]
extern crate tempdir;

#[cfg(test)]
extern crate regex;

#[macro_use]
pub mod macros;

mod object;

pub mod container;
pub mod error;
pub mod file;
pub mod globals;
pub mod group;
pub mod location;
pub mod plist;
pub mod sync;
pub mod util;

#[cfg(test)]
pub mod test;
<|endoftext|>


<commit_before>/*!
# nalgebra

[![Build Status](https://travis-ci.org/sebcrozet/nalgebra.png?branch=master)](https://travis-ci.org/sebcrozet/nalgebra)

**nalgebra** is a linear algebra library written for Rust targeting:

* general-purpose linear algebra (still misses a lot of features…).
* real time computer graphics.
* real time computer physics.

An on-line version of this documentation is available [here](http://crozet.re/nalgebra/doc/nalgebra/index.html).

## Using **nalgebra**
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
This module re-exports everything and includes free functions for all traits methods doing
out-of-place modifications.

* You can import the whole prelude using:

```.rust
use nalgebra::na::*;
```

The preferred way to use **nalgebra** is to import types and traits explicitly, and call
free-functions using the `na::` prefix:

```.rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Rot3, Rotation};
use nalgebra::na;

fn main() {
    let     a = Vec3::new(1.0f64, 1.0, 1.0);
    let mut b = Rot3::new(na::zero());

    b.append_rotation(&a);

    assert!(na::approx_eq(&na::rotation(&b), &a));
}
```

## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
and keeps an optimized set of tools for computational graphics and physics. Those features include:

* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`.
* A few methods for data analysis: `Cov`, `Mean`.
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
  [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
  For example, the following works:

```rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Mat3};
use nalgebra::na;

fn main() {
    let v: Vec3<f64> = na::zero();
    let m: Mat3<f64> = na::one();

    let _ = m * v;   // matrix-vector multiplication.
    let _ = v * m;   // vector-matrix multiplication.
    let _ = m * m;   // matrix-matrix multiplication.
    let _ = v * 2.0; // vector-scalar multiplication.
}
```

## Compilation
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.

    git clone git://github.com/sebcrozet/nalgebra.git
    cd nalgebra
    make

You can build the documentation on the `doc` folder using:

```.rust
make doc
```

## **nalgebra** in use
Here are some projects using **nalgebra**.
Feel free to add your project to this list if you happen to use **nalgebra**!

* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
*/

#[crate_id = "nalgebra#0.1"];
#[crate_type = "lib"];
#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[warn(missing_doc)];
#[feature(macro_rules)];

extern mod std;
extern mod extra;

pub mod na;
mod structs;
mod traits;

// mod lower_triangular;
// mod chol;

#[cfg(test)]
mod tests {
    mod vec;
    mod mat;
}

#[cfg(test)]
mod bench {
    mod vec;
    mod mat;
}
<commit_msg>Add the `html_doc_url` attribute.<commit_after>/*!
# nalgebra

[![Build Status](https://travis-ci.org/sebcrozet/nalgebra.png?branch=master)](https://travis-ci.org/sebcrozet/nalgebra)

**nalgebra** is a linear algebra library written for Rust targeting:

* general-purpose linear algebra (still misses a lot of features…).
* real time computer graphics.
* real time computer physics.

An on-line version of this documentation is available [here](http://crozet.re/nalgebra/doc/nalgebra/index.html).

## Using **nalgebra**
All the functionalities of **nalgebra** are grouped in one place: the `na` module.
This module re-exports everything and includes free functions for all traits methods doing
out-of-place modifications.

* You can import the whole prelude using:

```.rust
use nalgebra::na::*;
```

The preferred way to use **nalgebra** is to import types and traits explicitly, and call
free-functions using the `na::` prefix:

```.rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Rot3, Rotation};
use nalgebra::na;

fn main() {
    let     a = Vec3::new(1.0f64, 1.0, 1.0);
    let mut b = Rot3::new(na::zero());

    b.append_rotation(&a);

    assert!(na::approx_eq(&na::rotation(&b), &a));
}
```

## Features
**nalgebra** is meant to be a general-purpose linear algebra library (but is very far from that…),
and keeps an optimized set of tools for computational graphics and physics. Those features include:

* Vectors with static sizes: `Vec0`, `Vec1`, `Vec2`, `Vec3`, `Vec4`, `Vec5`, `Vec6`.
* Square matrices with static sizes: `Mat1`, `Mat2`, `Mat3`, `Mat4`, `Mat5`, `Mat6 `.
* Rotation matrices: `Rot2`, `Rot3`, `Rot4`.
* Isometries: `Iso2`, `Iso3`, `Iso4`.
* Dynamically sized vector: `DVec`.
* Dynamically sized (square or rectangular) matrix: `DMat`.
* A few methods for data analysis: `Cov`, `Mean`.
* Almost one trait per functionality: useful for generic programming.
* Operator overloading using the double trait dispatch
  [trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
  For example, the following works:

```rust
extern mod nalgebra;
use nalgebra::na::{Vec3, Mat3};
use nalgebra::na;

fn main() {
    let v: Vec3<f64> = na::zero();
    let m: Mat3<f64> = na::one();

    let _ = m * v;   // matrix-vector multiplication.
    let _ = v * m;   // vector-matrix multiplication.
    let _ = m * m;   // matrix-matrix multiplication.
    let _ = v * 2.0; // vector-scalar multiplication.
}
```

## Compilation
You will need the last rust compiler from the master branch.
If you encounter problems, make sure you have the last version before creating an issue.

    git clone git://github.com/sebcrozet/nalgebra.git
    cd nalgebra
    make

You can build the documentation on the `doc` folder using:

```.rust
make doc
```

## **nalgebra** in use
Here are some projects using **nalgebra**.
Feel free to add your project to this list if you happen to use **nalgebra**!

* [nphysics](https://github.com/sebcrozet/nphysics): a real-time physics engine.
* [ncollide](https://github.com/sebcrozet/ncollide): a collision detection library.
* [kiss3d](https://github.com/sebcrozet/kiss3d): a minimalistic graphics engine.
* [frog](https://github.com/natal/frog): a machine learning library.
*/

#[crate_id = "nalgebra#0.1"];
#[crate_type = "lib"];
#[deny(non_camel_case_types)];
#[deny(non_uppercase_statics)];
#[deny(unnecessary_qualification)];
#[warn(missing_doc)];
#[feature(macro_rules)];
#[doc(html_root_url = "http://crozet.re/nalgebra/doc")];

extern mod std;
extern mod extra;

pub mod na;
mod structs;
mod traits;

// mod lower_triangular;
// mod chol;

#[cfg(test)]
mod tests {
    mod vec;
    mod mat;
}

#[cfg(test)]
mod bench {
    mod vec;
    mod mat;
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
extern crate libc;
use self::libc::{c_char, size_t, uint8_t, uint16_t, uint32_t, uint64_t};

pub type SkBool = ::libc::c_uint;

/* ATA SMART test type (ATA8 7.52.5.2) */
#[repr(C)]
#[derive(Debug)]
pub enum SkSmartSelfTest {
    SK_SMART_SELF_TEST_SHORT = 1,
    SK_SMART_SELF_TEST_EXTENDED = 2,
    SK_SMART_SELF_TEST_CONVEYANCE = 3,
    SK_SMART_SELF_TEST_ABORT = 127
}

#[repr(C)]
pub struct SkIdentifyParsedData {
    pub serial: [c_char; 21],
    pub firmware: [c_char; 9],
    pub model: [c_char; 41],
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartOfflineDataCollectionStatus {
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_NEVER,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_SUCCESS,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_INPROGRESS,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_SUSPENDED,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_ABORTED,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_FATAL,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_UNKNOWN,
    _SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_MAX
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartSelfTestExecutionStatus {
    SK_SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER = 0,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ABORTED = 1,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED = 2,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_FATAL = 3,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN = 4,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL = 5,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO = 6,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ = 7,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING = 8,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS = 15,
    _SK_SMART_SELF_TEST_EXECUTION_STATUS_MAX
}

#[repr(C)]
#[derive(Debug)]
pub struct SkSmartParsedData {
    /* Volatile data */
    pub offline_data_collection_status: SkSmartOfflineDataCollectionStatus ,
    pub total_offline_data_collection_seconds: uint32_t,
    pub self_test_execution_status: SkSmartSelfTestExecutionStatus,
    pub self_test_execution_percent_remaining: uint32_t,

    /* Fixed data */
    pub short_and_extended_test_available: SkBool,
    pub conveyance_test_available: SkBool,
    pub start_test_available: SkBool,
    pub abort_test_available: SkBool,

    pub short_test_polling_minutes: uint32_t,
    pub extended_test_polling_minutes: uint32_t,
    pub conveyance_test_polling_minutes: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartAttributeUnit {
    SK_SMART_ATTRIBUTE_UNIT_UNKNOWN,
    SK_SMART_ATTRIBUTE_UNIT_NONE,
    SK_SMART_ATTRIBUTE_UNIT_MSECONDS,      /* milliseconds */
    SK_SMART_ATTRIBUTE_UNIT_SECTORS,
    SK_SMART_ATTRIBUTE_UNIT_MKELVIN,       /* millikelvin */
    SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, /* percentage with 3 decimal points */
    SK_SMART_ATTRIBUTE_UNIT_PERCENT,       /* integer percentage */
    SK_SMART_ATTRIBUTE_UNIT_MB,
    _SK_SMART_ATTRIBUTE_UNIT_MAX

}

#[repr(C)]
#[derive(Debug)]
pub struct SkSmartAttributeParsedData {
    pub id: uint8_t,
    pub name: *const ::libc::c_char,
    pub pretty_unit: SkSmartAttributeUnit,
    pub flags: uint16_t ,
    pub threshold: uint8_t,
    pub threshold_valid: SkBool,
    pub online: SkBool,
    pub prefailure: SkBool,
    pub good_now: SkBool,
    pub good_now_valid: SkBool,
    pub good_in_the_past: SkBool,
    pub good_in_the_past_valid: SkBool,
    pub current_value_valid: SkBool,
    pub worst_value_valid: SkBool,
    pub warn: SkBool,
    pub current_value: uint8_t,
    pub worst_value: uint8_t,
    pub pretty_value: uint64_t,
    pub raw: uint8_t,
}

pub enum SkDisk{

}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartOverall  {
    SK_SMART_OVERALL_GOOD,
    SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST,  /* At least one pre-fail attribute exceeded its threshold in the past */
    SK_SMART_OVERALL_BAD_SECTOR,                 /* At least one bad sector */
    SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW,          /* At least one pre-fail attribute is exceeding its threshold now */
    SK_SMART_OVERALL_BAD_SECTOR_MANY,            /* Many bad sectors */
    SK_SMART_OVERALL_BAD_STATUS,                 /* Smart Self Assessment negative */
    SK_SMART_OVERALL_MAX
}

#[link(name = "atasmart")]
extern "C" {
    pub fn sk_smart_self_test_execution_status_to_string(status: SkSmartSelfTestExecutionStatus) -> *const ::libc::c_char;
    pub fn sk_smart_offline_data_collection_status_to_string(status: SkSmartOfflineDataCollectionStatus) -> *const ::libc::c_char;
    pub fn sk_smart_self_test_to_string(test: SkSmartSelfTest) -> *const ::libc::c_char;
    pub fn sk_smart_self_test_available(d: *const SkSmartParsedData, test: SkSmartSelfTest) -> SkBool;
    pub fn sk_smart_self_test_polling_minutes(d: *const SkSmartParsedData, test: SkSmartSelfTest) -> uint32_t;
    pub fn sk_smart_attribute_unit_to_string(unit: SkSmartAttributeUnit) -> *const ::libc::c_char;
    pub fn sk_smart_overall_to_string(overall: SkSmartOverall) -> *const ::libc::c_char;
    pub fn sk_disk_open(name: *const ::libc::c_char, d: *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_get_size(d: *mut SkDisk, bytes: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_check_sleep_mode(d: *mut SkDisk, awake: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_identify_is_available(d: *mut SkDisk, available: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_identify_parse(d: *mut SkDisk, data: *const SkIdentifyParsedData) -> ::libc::c_int;
    pub fn sk_disk_smart_is_available(d: *mut SkDisk, available: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_smart_status(d: *mut SkDisk, good: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_smart_read_data(d: *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_get_blob(d: *mut SkDisk, blob: *const ::libc::c_void, size: *mut size_t) -> ::libc::c_int;
    pub fn sk_disk_set_blob(d: *mut SkDisk, blob: *const ::libc::c_void, size: size_t) -> ::libc::c_int;
    pub fn sk_disk_smart_parse(d: *mut SkDisk, data: *const SkSmartParsedData) -> ::libc::c_int;
    //pub fn sk_disk_smart_parse_attributes(d: *mut SkDisk, cb: SkSmartAttributeParseCallback, userdata: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn sk_disk_smart_self_test(d: *mut SkDisk, test: SkSmartSelfTest) -> ::libc::c_int;
    pub fn sk_disk_smart_get_power_on(d: *mut SkDisk, mseconds: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_power_cycle(d: *mut SkDisk, count: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_bad(d: *mut SkDisk, sectors: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_temperature(d: *mut SkDisk, mkelvin: *mut uint64_t ) -> ::libc::c_int;
    pub fn sk_disk_smart_get_overall(d: *mut SkDisk, overall: *mut SkSmartOverall) -> ::libc::c_int;
    pub fn sk_disk_dump(d: *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_free(d: *mut SkDisk) -> ::libc::c_void;
}
<commit_msg>Messed up a few double pointer bindings<commit_after>#![allow(non_camel_case_types)]
extern crate libc;
use self::libc::{c_char, size_t, uint8_t, uint16_t, uint32_t, uint64_t};

pub type SkBool = ::libc::c_uint;

/* ATA SMART test type (ATA8 7.52.5.2) */
#[repr(C)]
#[derive(Debug)]
pub enum SkSmartSelfTest {
    SK_SMART_SELF_TEST_SHORT = 1,
    SK_SMART_SELF_TEST_EXTENDED = 2,
    SK_SMART_SELF_TEST_CONVEYANCE = 3,
    SK_SMART_SELF_TEST_ABORT = 127
}

#[repr(C)]
pub struct SkIdentifyParsedData {
    pub serial: [c_char; 21],
    pub firmware: [c_char; 9],
    pub model: [c_char; 41],
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartOfflineDataCollectionStatus {
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_NEVER,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_SUCCESS,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_INPROGRESS,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_SUSPENDED,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_ABORTED,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_FATAL,
    SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_UNKNOWN,
    _SK_SMART_OFFLINE_DATA_COLLECTION_STATUS_MAX
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartSelfTestExecutionStatus {
    SK_SMART_SELF_TEST_EXECUTION_STATUS_SUCCESS_OR_NEVER = 0,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ABORTED = 1,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_INTERRUPTED = 2,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_FATAL = 3,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_UNKNOWN = 4,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_ELECTRICAL = 5,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_SERVO = 6,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_READ = 7,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_ERROR_HANDLING = 8,
    SK_SMART_SELF_TEST_EXECUTION_STATUS_INPROGRESS = 15,
    _SK_SMART_SELF_TEST_EXECUTION_STATUS_MAX
}

#[repr(C)]
#[derive(Debug)]
pub struct SkSmartParsedData {
    /* Volatile data */
    pub offline_data_collection_status: SkSmartOfflineDataCollectionStatus ,
    pub total_offline_data_collection_seconds: uint32_t,
    pub self_test_execution_status: SkSmartSelfTestExecutionStatus,
    pub self_test_execution_percent_remaining: uint32_t,

    /* Fixed data */
    pub short_and_extended_test_available: SkBool,
    pub conveyance_test_available: SkBool,
    pub start_test_available: SkBool,
    pub abort_test_available: SkBool,

    pub short_test_polling_minutes: uint32_t,
    pub extended_test_polling_minutes: uint32_t,
    pub conveyance_test_polling_minutes: uint32_t,
}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartAttributeUnit {
    SK_SMART_ATTRIBUTE_UNIT_UNKNOWN,
    SK_SMART_ATTRIBUTE_UNIT_NONE,
    SK_SMART_ATTRIBUTE_UNIT_MSECONDS,      /* milliseconds */
    SK_SMART_ATTRIBUTE_UNIT_SECTORS,
    SK_SMART_ATTRIBUTE_UNIT_MKELVIN,       /* millikelvin */
    SK_SMART_ATTRIBUTE_UNIT_SMALL_PERCENT, /* percentage with 3 decimal points */
    SK_SMART_ATTRIBUTE_UNIT_PERCENT,       /* integer percentage */
    SK_SMART_ATTRIBUTE_UNIT_MB,
    _SK_SMART_ATTRIBUTE_UNIT_MAX

}

#[repr(C)]
#[derive(Debug)]
pub struct SkSmartAttributeParsedData {
    pub id: uint8_t,
    pub name: *const ::libc::c_char,
    pub pretty_unit: SkSmartAttributeUnit,
    pub flags: uint16_t ,
    pub threshold: uint8_t,
    pub threshold_valid: SkBool,
    pub online: SkBool,
    pub prefailure: SkBool,
    pub good_now: SkBool,
    pub good_now_valid: SkBool,
    pub good_in_the_past: SkBool,
    pub good_in_the_past_valid: SkBool,
    pub current_value_valid: SkBool,
    pub worst_value_valid: SkBool,
    pub warn: SkBool,
    pub current_value: uint8_t,
    pub worst_value: uint8_t,
    pub pretty_value: uint64_t,
    pub raw: uint8_t,
}

pub enum SkDisk{

}

#[repr(C)]
#[derive(Debug)]
pub enum SkSmartOverall  {
    SK_SMART_OVERALL_GOOD,
    SK_SMART_OVERALL_BAD_ATTRIBUTE_IN_THE_PAST,  /* At least one pre-fail attribute exceeded its threshold in the past */
    SK_SMART_OVERALL_BAD_SECTOR,                 /* At least one bad sector */
    SK_SMART_OVERALL_BAD_ATTRIBUTE_NOW,          /* At least one pre-fail attribute is exceeding its threshold now */
    SK_SMART_OVERALL_BAD_SECTOR_MANY,            /* Many bad sectors */
    SK_SMART_OVERALL_BAD_STATUS,                 /* Smart Self Assessment negative */
    SK_SMART_OVERALL_MAX
}

#[link(name = "atasmart")]
extern "C" {
    pub fn sk_smart_self_test_execution_status_to_string(status: SkSmartSelfTestExecutionStatus) -> *const ::libc::c_char;
    pub fn sk_smart_offline_data_collection_status_to_string(status: SkSmartOfflineDataCollectionStatus) -> *const ::libc::c_char;
    pub fn sk_smart_self_test_to_string(test: SkSmartSelfTest) -> *const ::libc::c_char;
    pub fn sk_smart_self_test_available(d: *const SkSmartParsedData, test: SkSmartSelfTest) -> SkBool;
    pub fn sk_smart_self_test_polling_minutes(d: *const SkSmartParsedData, test: SkSmartSelfTest) -> uint32_t;
    pub fn sk_smart_attribute_unit_to_string(unit: SkSmartAttributeUnit) -> *const ::libc::c_char;
    pub fn sk_smart_overall_to_string(overall: SkSmartOverall) -> *const ::libc::c_char;
    pub fn sk_disk_open(name: *const ::libc::c_char, d: *mut *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_get_size(d: *mut SkDisk, bytes: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_check_sleep_mode(d: *mut SkDisk, awake: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_identify_is_available(d: *mut SkDisk, available: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_identify_parse(d: *mut *mut SkDisk, data: *const SkIdentifyParsedData) -> ::libc::c_int;
    pub fn sk_disk_smart_is_available(d: *mut SkDisk, available: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_smart_status(d: *mut SkDisk, good: *mut SkBool) -> ::libc::c_int;
    pub fn sk_disk_smart_read_data(d: *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_get_blob(d: *mut *mut SkDisk, blob: *const ::libc::c_void, size: *mut size_t) -> ::libc::c_int;
    pub fn sk_disk_set_blob(d: *mut SkDisk, blob: *const ::libc::c_void, size: size_t) -> ::libc::c_int;
    pub fn sk_disk_smart_parse(d: *mut *mut SkDisk, data: *const SkSmartParsedData) -> ::libc::c_int;
    //pub fn sk_disk_smart_parse_attributes(d: *mut SkDisk, cb: SkSmartAttributeParseCallback, userdata: *mut ::libc::c_void) -> ::libc::c_int;
    pub fn sk_disk_smart_self_test(d: *mut SkDisk, test: SkSmartSelfTest) -> ::libc::c_int;
    pub fn sk_disk_smart_get_power_on(d: *mut SkDisk, mseconds: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_power_cycle(d: *mut SkDisk, count: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_bad(d: *mut SkDisk, sectors: *mut uint64_t) -> ::libc::c_int;
    pub fn sk_disk_smart_get_temperature(d: *mut SkDisk, mkelvin: *mut uint64_t ) -> ::libc::c_int;
    pub fn sk_disk_smart_get_overall(d: *mut SkDisk, overall: *mut SkSmartOverall) -> ::libc::c_int;
    pub fn sk_disk_dump(d: *mut SkDisk) -> ::libc::c_int;
    pub fn sk_disk_free(d: *mut SkDisk) -> ::libc::c_void;
}
<|endoftext|>


<commit_before>#![feature(drop_types_in_const)]

mod gameboy;
pub mod debugger;
pub use gameboy::joypad::Key;

pub const WIDTH: usize = 160;
pub const HEIGHT: usize = 144;

///Global gameboy object
static mut GAMEBOY: Option<Box<gameboy::GBC>> = None;

#[no_mangle]
///Create a new gameboy object (and store it as a global variable)
pub fn rustboy_init(rom: Box<[u8]>, ram: Box<[u8]>) {
	unsafe {
		GAMEBOY = Some(Box::new(gameboy::GBC::new(rom, ram)));
	}
}

#[no_mangle]
///Create a new gameboy object from a path to a rom (and store it as a global variable)
pub fn rustboy_init_from_path(rom_path: String, ram_path: String) {
	unsafe {
		GAMEBOY = Some(Box::new(gameboy::GBC::from_path(rom_path, ram_path)));
	}
}

#[no_mangle]
///Step to the next frame
pub fn rustboy_step_frame() {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.step_frame(),
			None => panic!("rustboy not initialized")
		}
	}
}

#[no_mangle]
///Get a pointer to the current front framebuffer
pub fn rustboy_get_framebuffer() -> *mut u32 {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.ppu.get_framebuffer_mut().as_mut_ptr(),
			None => panic!("rustboy not initialized"),	//return null?
		}
	}
}

#[no_mangle]
///Pass a keydown event to the gameboy
pub fn rustboy_keydown(key: Key) {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.keydown(key),
			None => panic!("rustboy not initialized")
		};
	}
}

#[no_mangle]
///Pass a keyup event to the gameboy
pub fn rustboy_keyup(key: Key) {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.keyup(key),
			None => panic!("rustboy not initialized")
		};
	}
}
<commit_msg>First attempt at taking in c arrays for the c api.<commit_after>#![feature(drop_types_in_const)]

use std::slice;

pub mod gameboy;
pub mod debugger;
pub use gameboy::joypad::Key;

pub const WIDTH: usize = 160;
pub const HEIGHT: usize = 144;

///Global gameboy object
static mut GAMEBOY: Option<Box<gameboy::GBC>> = None;

#[no_mangle]
///Create a new gameboy object (and store it as a global variable)
pub fn rustboy_init(rom_ptr: *const u8, rom_size: u32, ram_ptr: *const u8, ram_size: u32) {
	unsafe {
		/* Copy into a boxed array */
		let rom_slice: &[u8] = slice::from_raw_parts(rom_ptr, rom_size as usize);
		let ram_slice: &[u8] = slice::from_raw_parts(ram_ptr, ram_size as usize);

		let mut rom: Vec<u8> = Vec::with_capacity(rom_size as usize);
		let mut ram: Vec<u8> = Vec::with_capacity(ram_size as usize);

		rom.extend_from_slice(rom_slice);
		ram.extend_from_slice(ram_slice);

		GAMEBOY = Some(Box::new(gameboy::GBC::new(rom.into_boxed_slice(), ram.into_boxed_slice())));
	}
}

#[no_mangle]
///Create a new gameboy object from a path to a rom (and store it as a global variable)
pub fn rustboy_init_from_path(rom_path: String, ram_path: String) {
	unsafe {
		GAMEBOY = Some(Box::new(gameboy::GBC::from_path(rom_path, ram_path)));
	}
}

#[no_mangle]
///Step to the next frame
pub fn rustboy_step_frame() {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.step_frame(),
			None => panic!("rustboy not initialized")
		}
	}
}

#[no_mangle]
///Get a pointer to the current front framebuffer
pub fn rustboy_get_framebuffer() -> *mut u32 {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.ppu.get_framebuffer_mut().as_mut_ptr(),
			None => panic!("rustboy not initialized"),	//return null?
		}
	}
}

#[no_mangle]
///Pass a keydown event to the gameboy
pub fn rustboy_keydown(key: Key) {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.keydown(key),
			None => panic!("rustboy not initialized")
		};
	}
}

#[no_mangle]
///Pass a keyup event to the gameboy
pub fn rustboy_keyup(key: Key) {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.keyup(key),
			None => panic!("rustboy not initialized")
		};
	}
}
<|endoftext|>


<commit_before>//! Derive a builder for a struct
//!
//! This crate implements the _non-consuming_ [builder pattern].
//! When applied to a struct, it will derive **setter-methods** for all struct fields.
//!
//! **Please note**:
//!
//! * There are slightly different ways to implement the builder pattern in rust.
//!   The preferred way to do it, is the so called _non-consuming_ variant.
//!   That means: all generated setter-methods take and return `&mut self`.
//! * To complete the builder pattern you only have to implement at least one method
//!   which actually builds something based on the struct.
//!   These custom build methods of yours should also take `&mut self` to take advantage of the
//!   non-consuming pattern.
//! * **Don't worry at all** if you have to `clone` or `copy` data in your build methods,
//!   because luckily the Compiler is smart enough to optimize them away in release builds
//!   for your every-day use cases. Thats quite a safe bet - we checked this for you. ;-)
//!   Switching to consuming signatures (=`self`) would not give you any performance
//!   gain, but only restrict your API for every-day use cases
//!
//! [builder pattern]: https://aturon.github.io/ownership/builders.html
//!
//! # Examples
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Debug, PartialEq, Default, Clone, Builder)]
//! struct Lorem {
//!     ipsum: String,
//!     dolor: i32,
//! }
//!
//! fn main() {
//!     let x = Lorem::default().ipsum("sit").dolor(42).clone();
//!     assert_eq!(x, Lorem { ipsum: "sit".into(), dolor: 42 });
//! }
//! ```
//!
//! In `main()`: The final call of `clone()` represents the act of **building a new struct**
//! when our builder is ready. For the sake of brevity we chose clone and pretend we get
//! something brand new. As already mentioned, the compiler will optimize this away in release
//! mode.
//!
//! ## Generic structs
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Debug, PartialEq, Default, Clone, Builder)]
//! struct GenLorem<T> {
//!     ipsum: String,
//!     dolor: T,
//! }
//!
//! fn main() {
//!     let x = GenLorem::default().ipsum("sit").dolor(42).clone();
//!     assert_eq!(x, GenLorem { ipsum: "sit".into(), dolor: 42 });
//! }
//! ```
//!
//! ## Doc-Comments and Attributes
//!
//! `#[derive(Builder)]` copies doc-comments and attributes `#[...]` from your fields
//! to the according setter-method, if it is one of the following:
//!
//! * `/// ...`
//! * `#[doc = ...]`
//! * `#[cfg(...)]`
//! * `#[allow(...)]`
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Builder)]
//! struct Lorem {
//!     /// `ipsum` may be any `String` (be creative).
//!     ipsum: String,
//!     #[doc = r"`dolor` is the estimated amount of work."]
//!     dolor: i32,
//!     // `#[derive(Builder)]` understands conditional compilation via cfg-attributes,
//!     // i.e. => "no field = no setter".
//!     #[cfg(target_os = "macos")]
//!     #[allow(non_snake_case)]
//!     Im_a_Mac: bool,
//! }
//! # fn main() {}
//! ```
//!
//! ## Gotchas
//!
//! - Tuple structs and unit structs are not supported as they have no field
//!   names.
//! - When defining a generic struct, you cannot use `VALUE` as a generic
//!   parameter as this is what all setters are using.

#![crate_type = "proc-macro"]
#![feature(proc_macro, proc_macro_lib)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
    let input: String = input.to_string();

    let ast = syn::parse_macro_input(&input).expect("Couldn't parse item");

    let result = builder_for_struct(ast);

    format!("{}\n{}", input, result).parse().expect("couldn't parse string to tokens")
}

fn builder_for_struct(ast: syn::MacroInput) -> quote::Tokens {
    let fields = match ast.body {
        syn::Body::Struct(syn::VariantData::Struct(ref fields)) => fields,
        _ => panic!("#[derive(new)] can only be used with braced structs"),
    };

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let funcs = fields.iter().map(|f| {
        let f_name = &f.ident;
        let ty = &f.ty;
        quote!(pub fn #f_name<VALUE: Into<#ty>>(&mut self, value: VALUE) -> &mut Self {
            self.#f_name = value.into();
            self
        })
    });

    quote! {
        impl #impl_generics #name #ty_generics #where_clause {
            #(#funcs)*
        }
    }
}
<commit_msg>allow attributes on fields<commit_after>//! Derive a builder for a struct
//!
//! This crate implements the _non-consuming_ [builder pattern].
//! When applied to a struct, it will derive **setter-methods** for all struct fields.
//!
//! **Please note**:
//!
//! * There are slightly different ways to implement the builder pattern in rust.
//!   The preferred way to do it, is the so called _non-consuming_ variant.
//!   That means: all generated setter-methods take and return `&mut self`.
//! * To complete the builder pattern you only have to implement at least one method
//!   which actually builds something based on the struct.
//!   These custom build methods of yours should also take `&mut self` to take advantage of the
//!   non-consuming pattern.
//! * **Don't worry at all** if you have to `clone` or `copy` data in your build methods,
//!   because luckily the Compiler is smart enough to optimize them away in release builds
//!   for your every-day use cases. Thats quite a safe bet - we checked this for you. ;-)
//!   Switching to consuming signatures (=`self`) would not give you any performance
//!   gain, but only restrict your API for every-day use cases
//!
//! [builder pattern]: https://aturon.github.io/ownership/builders.html
//!
//! # Examples
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Debug, PartialEq, Default, Clone, Builder)]
//! struct Lorem {
//!     ipsum: String,
//!     dolor: i32,
//! }
//!
//! fn main() {
//!     let x = Lorem::default().ipsum("sit").dolor(42).clone();
//!     assert_eq!(x, Lorem { ipsum: "sit".into(), dolor: 42 });
//! }
//! ```
//!
//! In `main()`: The final call of `clone()` represents the act of **building a new struct**
//! when our builder is ready. For the sake of brevity we chose clone and pretend we get
//! something brand new. As already mentioned, the compiler will optimize this away in release
//! mode.
//!
//! ## Generic structs
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Debug, PartialEq, Default, Clone, Builder)]
//! struct GenLorem<T> {
//!     ipsum: String,
//!     dolor: T,
//! }
//!
//! fn main() {
//!     let x = GenLorem::default().ipsum("sit").dolor(42).clone();
//!     assert_eq!(x, GenLorem { ipsum: "sit".into(), dolor: 42 });
//! }
//! ```
//!
//! ## Doc-Comments and Attributes
//!
//! `#[derive(Builder)]` copies doc-comments and attributes `#[...]` from your fields
//! to the according setter-method, if it is one of the following:
//!
//! * `/// ...`
//! * `#[doc = ...]`
//! * `#[cfg(...)]`
//! * `#[allow(...)]`
//!
//! ```rust
//! #[macro_use] extern crate derive_builder;
//!
//! #[derive(Builder)]
//! struct Lorem {
//!     /// `ipsum` may be any `String` (be creative).
//!     ipsum: String,
//!     #[doc = r"`dolor` is the estimated amount of work."]
//!     dolor: i32,
//!     // `#[derive(Builder)]` understands conditional compilation via cfg-attributes,
//!     // i.e. => "no field = no setter".
//!     #[cfg(target_os = "macos")]
//!     #[allow(non_snake_case)]
//!     Im_a_Mac: bool,
//! }
//! # fn main() {}
//! ```
//!
//! ## Gotchas
//!
//! - Tuple structs and unit structs are not supported as they have no field
//!   names.
//! - When defining a generic struct, you cannot use `VALUE` as a generic
//!   parameter as this is what all setters are using.

#![crate_type = "proc-macro"]
#![feature(proc_macro, proc_macro_lib)]

extern crate proc_macro;
extern crate syn;
#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

#[proc_macro_derive(Builder)]
pub fn derive(input: TokenStream) -> TokenStream {
    let input: String = input.to_string();

    let ast = syn::parse_macro_input(&input).expect("Couldn't parse item");

    let result = builder_for_struct(ast);

    format!("{}\n{}", input, result).parse().expect("Couldn't parse string to tokens")
}

fn filter_attr(attr: &&syn::Attribute) -> bool {
    if attr.style != syn::AttrStyle::Outer {
        return false
    }

    if attr.is_sugared_doc == true {
        if let syn::MetaItem::NameValue(ref ident, _) = attr.value {
            // example:
            // Attribute { style: Outer, value: NameValue(Ident("doc"), Str("/// This is a doc comment for a field", Cooked)), is_sugared_doc: true }
            if ident == "doc" {
                return true
            }
        }
    } else {
        if let syn::MetaItem::List(ref ident, _) = attr.value {
            // example:
            // Attribute { style: Outer, value: List(Ident("allow"), [MetaItem(Word(Ident("non_snake_case")))]), is_sugared_doc: false }
            return match ident.as_ref() {
                "cfg" => true,
                "allow" => true,
                _ => false,
            }
        }
    }
    false
}

fn builder_for_struct(ast: syn::MacroInput) -> quote::Tokens {
    let fields = match ast.body {
        syn::Body::Struct(syn::VariantData::Struct(ref fields)) => fields,
        _ => panic!("#[derive(Builder)] can only be used with braced structs"),
    };

    let name = &ast.ident;
    let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
    let funcs = fields.iter().map(|f| {
        let f_name = &f.ident;
        let ty = &f.ty;

        let attrs = f.attrs.iter()
            .filter(filter_attr);

        quote!(
            #(#attrs)*
            pub fn #f_name<VALUE: Into<#ty>>(&mut self, value: VALUE) -> &mut Self {
            self.#f_name = value.into();
            self
        })
    });

    quote! {
        #[allow(dead_code)]
        impl #impl_generics #name #ty_generics #where_clause {
            #(#funcs)*
        }
    }
}
<|endoftext|>