<commit_before>use std::f64::consts::PI;
use std::cmp::Ordering;
use cgmath::prelude::*;
use cgmath::Point3;
use point::{Point, SinCosCache};
use events::{Events, EventKind, Circle};
use beach::{Beach, Arc};
use diagram::{Diagram, Kind, Vertex, Edge, Face};

pub trait Position : From<Point> {
    fn point(&self) -> &Point;

    fn position(&self) -> &Point3<f64> {
        &self.point().position
    }
}

fn in_range(phi: f64, phi_start: f64, phi_end: f64) -> Ordering {
    if phi_start <= phi_end {
        if phi < phi_start {
            Ordering::Less
        } else if phi > phi_end {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    } else {
        if phi < phi_end || phi > phi_start {
            Ordering::Equal
        } else if phi >= phi_end {
            Ordering::Greater
        } else {
            Ordering::Less
        }
    }
}

fn are_clockwise(n: Point3<f64>, p0: Point3<f64>, p1: Point3<f64>) -> bool {
    (p0 - n).cross(p1 - n).dot(n.to_vec()) < 0.0
}

fn wrap(phi: f64) -> f64 {
    if phi > PI {
        phi - 2.0 * PI
    } else if phi < -PI {
        phi + 2.0 * PI
    } else {
        phi
    }
}

struct Builder<K: Kind> where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    events: Events<K>,
    beach: Beach<K>,
    diagram: Diagram<K>,
    scan_theta: SinCosCache,
}

impl<K: Kind> Builder<K> where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    fn new(points: &[Point]) -> Result<Self, Error> {
        if points.len() < 2 {
            return Err(Error::FewPoints);
        }
        let mut builder = Builder {
            events: Events::default(),
            beach: Beach::default(),
            diagram: Diagram::default(),
            scan_theta: 0.0.into(),
        };
        for &point in points {
            let face = builder.diagram.add_face(point.into());
            builder.events.add_site(face, point);
        }
        Ok(builder)
    }

    fn build(mut self) -> Result<Diagram<K>, Error> {
        while let Some(event) = self.events.pop() {
            self.scan_theta = event.point.theta;
            match event.kind {
                EventKind::Site(face) => self.site_event(face, event.point),
                EventKind::Circle(event) => self.circle_event(event),
            }
        }
        self.cleanup_vertices();
        self.finish_faces();
        Ok(self.diagram)
    }

    fn arc_point(&self, arc: Arc<K>) -> &Point {
        &self.diagram.face_data(self.beach.face(arc)).point()
    }

    fn create_vertex(&mut self, point: Point, faces: &[Face<K>]) -> Vertex<K> {
        let vertex = self.diagram.add_vertex(point.into());
        for &face in faces {
            self.diagram.add_vertex_face(vertex, face);
        }
        vertex
    }

    fn create_edge(&mut self, vertex0: Vertex<K>, vertex1: Vertex<K>) -> Edge<K> {
        self.diagram.add_edge(Default::default(), vertex0, vertex1)
    }

    fn site_event(&mut self, face: Face<K>, point: Point) {
        if let Some(mut arc) = self.beach.root() {
            if self.beach.len() == 1 {
                self.beach.insert_after(Some(arc), face);
                let arc0 = self.beach.first();
                let arc1 = self.beach.last();
                let point = self.phi_to_point(point.phi, self.arc_point(arc0));
                let faces = [face, self.beach.face(arc0)];
                let vertex = self.create_vertex(point, &faces);
                self.beach.set_start(arc0, Some(vertex));
                self.beach.set_start(arc1, Some(vertex));
                return;
            }
            let mut use_tree = true;
            loop {
                let prev_arc = self.beach.prev(arc);
                let next_arc = self.beach.next(arc);
                let phi_start = self.arcs_intersection(prev_arc, arc);
                let phi_end = self.arcs_intersection(arc, next_arc);
                match in_range(point.phi(), phi_start, phi_end) {
                    Ordering::Less => {
                        if use_tree {
                            if let Some(left) = self.beach.left(arc) {
                                arc = left;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.last();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.prev(arc);
                        }
                    },
                    Ordering::Greater => {
                        if use_tree {
                            if let Some(right) = self.beach.right(arc) {
                                arc = right;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.first();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.next(arc);
                        }
                    },
                    Ordering::Equal => {
                        self.try_remove_circle(arc);
                        let arc2 = {
                            let face = self.beach.face(arc);
                            let a = if prev_arc == self.beach.last() {
                                None
                            } else {
                                Some(prev_arc)
                            };
                            self.beach.insert_after(a, face)
                        };
                        let new_arc = self.beach.insert_after(Some(arc2), face);
                        let point = self.phi_to_point(point.phi, self.arc_point(arc));
                        let faces = [face, self.beach.face(arc)];
                        let vertex = self.create_vertex(point, &faces);
                        self.beach.set_start(arc2, Some(vertex));
                        self.beach.set_start(new_arc, Some(vertex));
                        self.try_add_circle(prev_arc, arc2, new_arc, point.theta());
                        self.try_add_circle(new_arc, arc, next_arc, point.theta());
                        if self.try_remove_circle(prev_arc) {
                            let prev_prev = self.beach.prev(prev_arc);
                            self.try_add_circle(prev_prev, prev_arc, arc2, -2.0 * PI);
                        }
                        break;
                    }
                }
            }
        } else {
            self.beach.insert_after(None, face);
        }
    }

    fn merge_arcs(&mut self, arc0: Arc<K>, arc1: Arc<K>, arc2: Arc<K>, vertex: Option<Vertex<K>>) {
        let (face0, face1, face2) = (self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2));
        if face0 != face1 && face1 != face2 && face2 != face0 {
            let theta = self.scan_theta.value;
            if self.try_add_circle(arc0, arc1, arc2, theta) {
                if vertex.is_some() {
                    self.beach.set_start(arc1, vertex);
                }
            }
        }
    }

    fn edge_from_arc(&mut self, arc: Arc<K>, vertex: Vertex<K>) {
        if let Some(start) = self.beach.start(arc) {
            self.create_edge(start, vertex);
        }
    }

    fn circle_event(&mut self, event: Circle<K>) {
        if self.events.is_invalid(event) {
            return;
        }
        let (arc0, arc1, arc2) = self.events.arcs(event);
        assert_eq!(self.beach.circle(arc1), Some(event));
        self.beach.set_circle(arc1, None);
        self.try_remove_circle(arc0);
        self.try_remove_circle(arc2);
        let faces = [self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2)];
        let point = self.events.center(event);
        let vertex = self.create_vertex(point, &faces);
        self.edge_from_arc(arc0, vertex);
        self.edge_from_arc(arc1, vertex);
        self.beach.remove(arc1);
        if self.beach.prev(arc0) == arc2 {
            self.edge_from_arc(arc2, vertex);
            self.beach.remove(arc0);
            self.beach.remove(arc2);
        } else {
            let prev = self.beach.prev(arc0);
            let next = self.beach.next(arc2);
            self.merge_arcs(prev, arc0, arc2, Some(vertex));
            self.merge_arcs(arc0, arc2, next, None);
        }
    }

    fn arcs_intersection(&mut self, arc0: Arc<K>, arc1: Arc<K>) -> f64 {
        let point0 = self.arc_point(arc0);
        let point1 = self.arc_point(arc1);
        let theta0 = point0.theta;
        let phi0 = point0.phi;
        let theta1 = point1.theta;
        let phi1 = point1.phi;
        if theta0.value >= self.scan_theta.value {
            point0.phi.value
        } else if theta1.value >= self.scan_theta.value {
            point1.phi.value
        } else {
            let u1 = (self.scan_theta.cos - theta1.cos) * theta0.sin;
            let u2 = (self.scan_theta.cos - theta0.cos) * theta1.sin;
            let a1 = u1 * phi0.cos;
            let a2 = u2 * phi1.cos;
            let a = a1 - a2;
            let b1 = u1 * phi0.sin;
            let b2 = u2 * phi1.sin;
            let b = b1 - b2;
            let c = (theta0.cos - theta1.cos) * self.scan_theta.sin;
            let length = (a * a + b * b).sqrt();
            if a.abs() > length || c.abs() > length {
                unreachable!()
            } else {
                let gamma = a.atan2(b);
                let phi_int_plus_gamma1 = (c / length).asin();
                wrap(phi_int_plus_gamma1 - gamma)
            }
        }
    }

    fn phi_to_point(&self, phi: SinCosCache, point: &Point) -> Point {
        let mut phi = phi;
        phi.value = wrap(phi.value);
        if point.theta() >= self.scan_theta.value {
            Point::from_cache(self.scan_theta, phi) // could be any point on the line segment
        } else {
            let a = self.scan_theta.sin - point.theta.sin * (phi.value - point.phi()).cos();
            let b = point.theta.cos - self.scan_theta.cos;
            let theta = SinCosCache::from(b.atan2(a));
            Point::from_cache(theta, phi)
        }
    }

    fn try_add_circle(&mut self, arc0: Arc<K>, arc1: Arc<K>, arc2: Arc<K>, theta: f64) -> bool {
        let p01 = self.arc_point(arc0).position - self.arc_point(arc1).position;
        let p21 = self.arc_point(arc2).position - self.arc_point(arc1).position;
        let cross = p01.cross(p21);
        let center = Point::from_cartesian(cross.x, cross.y, cross.z);
        let radius = center.distance(&self.arc_point(arc0));
        let point = Point::from_spherical(center.theta() + radius, center.phi());
        if point.theta() >= theta {
            let circle = self.events.add_circle((arc0, arc1, arc2), center, radius, point);
            self.beach.set_circle(arc1, Some(circle));
            true
        } else {
            false
        }
    }

    fn try_remove_circle(&mut self, arc: Arc<K>) -> bool {
        if let Some(event) = self.beach.circle(arc) {
            self.events.set_invalid(event, true);
            self.beach.set_circle(arc, None);
            true
        } else {
            false
        }
    }

    fn cleanup_vertices(&mut self) {
        let mut bad_vertices = Vec::new();
        for vertex in self.diagram.vertices() {
            if self.diagram.vertex_faces(vertex).len() == 2 {
                let (edge0, edge1) = {
                    let edges = self.diagram.vertex_edges(vertex);
                    assert_eq!(edges.len(), 2);
                    (edges[0], edges[1])
                };
                let vertex0 = self.diagram.other_edge_vertex(edge0, vertex).unwrap();
                let vertex1 = self.diagram.other_edge_vertex(edge1, vertex).unwrap();
                self.diagram.add_edge(Default::default(), vertex0, vertex1);
                bad_vertices.push(vertex);
            }
        }
        self.diagram.remove_vertices(&bad_vertices);
    }

    fn finish_faces(&mut self) {
        for edge in self.diagram.edges() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.diagram.edge_vertices(edge);
            for face0 in self.diagram.vertex_faces(vertex0) {
                for face1 in self.diagram.vertex_faces(vertex1) {
                    if face0 == face1 {
                        common.push(*face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.diagram.add_face_edge(common[0], edge);
            self.diagram.add_face_edge(common[1], edge);
            self.diagram.set_edge_faces(edge, common[0], common[1]);
        }
        for face in self.diagram.faces() {
            let n = *self.diagram.face_data(face).position();
            let mut edge = self.diagram.face_edges(face)[0];
            let (v0, v1) = self.diagram.edge_vertices(edge);
            let (prev, v) = if are_clockwise(n, *self.diagram.vertex_data(v0).position(), *self.diagram.vertex_data(v1).position()) {
                (v0, v1)
            } else {
                (v1, v0)
            };
            self.diagram.add_face_vertex(face, prev);
            let mut vertex = v;
            for _ in 0..self.diagram.face_edges(face).len() - 1 {
                self.diagram.add_face_vertex(face, vertex);
                for &e in self.diagram.face_edges(face) {
                    if e != edge {
                        if let Some(v) = self.diagram.other_edge_vertex(e, vertex) {
                            vertex = v;
                            edge = e;
                            break;
                        }
                    }
                }
            }
        }
    }
}

#[derive(PartialEq)]
pub enum Error {
    FewPoints,
}

pub fn build<K: Kind>(points: &[Point]) -> Result<Diagram<K>, Error>
    where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    let builder = try!(Builder::new(points));
    builder.build()
}

pub fn build_relaxed<K: Kind>(points: &[Point], relaxations: usize) -> Result<Diagram<K>, Error>
    where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    let mut diagram = try!(build(points));
    for _ in 0..relaxations {
        let new_points: Vec<_> = diagram.faces().
            map(|face| {
                let face_points: Vec<_> = diagram.
                    face_vertices(face).
                    iter().
                    map(|&vertex| {
                        let data: &K::Vertex = diagram.vertex_data(vertex);
                        *data.position()
                    }).collect();
                let p = Point3::centroid(&face_points);
                Point::from_cartesian(p.x, p.y, p.z)
            }).
            collect();
        diagram = try!(build(&new_points));
    }
    Ok(diagram)
}
<commit_msg>Index & IndexMut<commit_after>use std::f64::consts::PI;
use std::cmp::Ordering;
use cgmath::prelude::*;
use cgmath::Point3;
use point::{Point, SinCosCache};
use events::{Events, EventKind, Circle};
use beach::{Beach, Arc};
use diagram::{Diagram, Kind, Vertex, Edge, Face};

pub trait Position : From<Point> {
    fn point(&self) -> &Point;

    fn position(&self) -> &Point3<f64> {
        &self.point().position
    }
}

fn in_range(phi: f64, phi_start: f64, phi_end: f64) -> Ordering {
    if phi_start <= phi_end {
        if phi < phi_start {
            Ordering::Less
        } else if phi > phi_end {
            Ordering::Greater
        } else {
            Ordering::Equal
        }
    } else {
        if phi < phi_end || phi > phi_start {
            Ordering::Equal
        } else if phi >= phi_end {
            Ordering::Greater
        } else {
            Ordering::Less
        }
    }
}

fn are_clockwise(n: Point3<f64>, p0: Point3<f64>, p1: Point3<f64>) -> bool {
    (p0 - n).cross(p1 - n).dot(n.to_vec()) < 0.0
}

fn wrap(phi: f64) -> f64 {
    if phi > PI {
        phi - 2.0 * PI
    } else if phi < -PI {
        phi + 2.0 * PI
    } else {
        phi
    }
}

struct Builder<K: Kind> where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    events: Events<K>,
    beach: Beach<K>,
    diagram: Diagram<K>,
    scan_theta: SinCosCache,
}

impl<K: Kind> Builder<K> where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    fn new(points: &[Point]) -> Result<Self, Error> {
        if points.len() < 2 {
            return Err(Error::FewPoints);
        }
        let mut builder = Builder {
            events: Events::default(),
            beach: Beach::default(),
            diagram: Diagram::default(),
            scan_theta: 0.0.into(),
        };
        for &point in points {
            let face = builder.diagram.add_face(point.into());
            builder.events.add_site(face, point);
        }
        Ok(builder)
    }

    fn build(mut self) -> Result<Diagram<K>, Error> {
        while let Some(event) = self.events.pop() {
            self.scan_theta = event.point.theta;
            match event.kind {
                EventKind::Site(face) => self.site_event(face, event.point),
                EventKind::Circle(event) => self.circle_event(event),
            }
        }
        self.cleanup_vertices();
        self.finish_faces();
        Ok(self.diagram)
    }

    fn arc_point(&self, arc: Arc<K>) -> &Point {
        &self.diagram.face_data(self.beach.face(arc)).point()
    }

    fn create_vertex(&mut self, point: Point, faces: &[Face<K>]) -> Vertex<K> {
        let vertex = self.diagram.add_vertex(point.into());
        for &face in faces {
            self.diagram.add_vertex_face(vertex, face);
        }
        vertex
    }

    fn create_edge(&mut self, vertex0: Vertex<K>, vertex1: Vertex<K>) -> Edge<K> {
        self.diagram.add_edge(Default::default(), vertex0, vertex1)
    }

    fn site_event(&mut self, face: Face<K>, point: Point) {
        if let Some(mut arc) = self.beach.root() {
            if self.beach.len() == 1 {
                self.beach.insert_after(Some(arc), face);
                let arc0 = self.beach.first();
                let arc1 = self.beach.last();
                let point = self.phi_to_point(point.phi, self.arc_point(arc0));
                let faces = [face, self.beach.face(arc0)];
                let vertex = self.create_vertex(point, &faces);
                self.beach.set_start(arc0, Some(vertex));
                self.beach.set_start(arc1, Some(vertex));
                return;
            }
            let mut use_tree = true;
            loop {
                let prev_arc = self.beach.prev(arc);
                let next_arc = self.beach.next(arc);
                let phi_start = self.arcs_intersection(prev_arc, arc);
                let phi_end = self.arcs_intersection(arc, next_arc);
                match in_range(point.phi(), phi_start, phi_end) {
                    Ordering::Less => {
                        if use_tree {
                            if let Some(left) = self.beach.left(arc) {
                                arc = left;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.last();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.prev(arc);
                        }
                    },
                    Ordering::Greater => {
                        if use_tree {
                            if let Some(right) = self.beach.right(arc) {
                                arc = right;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.first();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.next(arc);
                        }
                    },
                    Ordering::Equal => {
                        self.try_remove_circle(arc);
                        let arc2 = {
                            let face = self.beach.face(arc);
                            let a = if prev_arc == self.beach.last() {
                                None
                            } else {
                                Some(prev_arc)
                            };
                            self.beach.insert_after(a, face)
                        };
                        let new_arc = self.beach.insert_after(Some(arc2), face);
                        let point = self.phi_to_point(point.phi, self.arc_point(arc));
                        let faces = [face, self.beach.face(arc)];
                        let vertex = self.create_vertex(point, &faces);
                        self.beach.set_start(arc2, Some(vertex));
                        self.beach.set_start(new_arc, Some(vertex));
                        self.try_add_circle(prev_arc, arc2, new_arc, point.theta());
                        self.try_add_circle(new_arc, arc, next_arc, point.theta());
                        if self.try_remove_circle(prev_arc) {
                            let prev_prev = self.beach.prev(prev_arc);
                            self.try_add_circle(prev_prev, prev_arc, arc2, -2.0 * PI);
                        }
                        break;
                    }
                }
            }
        } else {
            self.beach.insert_after(None, face);
        }
    }

    fn merge_arcs(&mut self, arc0: Arc<K>, arc1: Arc<K>, arc2: Arc<K>, vertex: Option<Vertex<K>>) {
        let (face0, face1, face2) = (self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2));
        if face0 != face1 && face1 != face2 && face2 != face0 {
            let theta = self.scan_theta.value;
            if self.try_add_circle(arc0, arc1, arc2, theta) {
                if vertex.is_some() {
                    self.beach.set_start(arc1, vertex);
                }
            }
        }
    }

    fn edge_from_arc(&mut self, arc: Arc<K>, vertex: Vertex<K>) {
        if let Some(start) = self.beach.start(arc) {
            self.create_edge(start, vertex);
        }
    }

    fn circle_event(&mut self, event: Circle<K>) {
        if self.events.is_invalid(event) {
            return;
        }
        let (arc0, arc1, arc2) = self.events.arcs(event);
        assert_eq!(self.beach.circle(arc1), Some(event));
        self.beach.set_circle(arc1, None);
        self.try_remove_circle(arc0);
        self.try_remove_circle(arc2);
        let faces = [self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2)];
        let point = self.events.center(event);
        let vertex = self.create_vertex(point, &faces);
        self.edge_from_arc(arc0, vertex);
        self.edge_from_arc(arc1, vertex);
        self.beach.remove(arc1);
        if self.beach.prev(arc0) == arc2 {
            self.edge_from_arc(arc2, vertex);
            self.beach.remove(arc0);
            self.beach.remove(arc2);
        } else {
            let prev = self.beach.prev(arc0);
            let next = self.beach.next(arc2);
            self.merge_arcs(prev, arc0, arc2, Some(vertex));
            self.merge_arcs(arc0, arc2, next, None);
        }
    }

    fn arcs_intersection(&mut self, arc0: Arc<K>, arc1: Arc<K>) -> f64 {
        let point0 = self.arc_point(arc0);
        let point1 = self.arc_point(arc1);
        let theta0 = point0.theta;
        let phi0 = point0.phi;
        let theta1 = point1.theta;
        let phi1 = point1.phi;
        if theta0.value >= self.scan_theta.value {
            point0.phi.value
        } else if theta1.value >= self.scan_theta.value {
            point1.phi.value
        } else {
            let u1 = (self.scan_theta.cos - theta1.cos) * theta0.sin;
            let u2 = (self.scan_theta.cos - theta0.cos) * theta1.sin;
            let a1 = u1 * phi0.cos;
            let a2 = u2 * phi1.cos;
            let a = a1 - a2;
            let b1 = u1 * phi0.sin;
            let b2 = u2 * phi1.sin;
            let b = b1 - b2;
            let c = (theta0.cos - theta1.cos) * self.scan_theta.sin;
            let length = (a * a + b * b).sqrt();
            if a.abs() > length || c.abs() > length {
                unreachable!()
            } else {
                let gamma = a.atan2(b);
                let phi_int_plus_gamma1 = (c / length).asin();
                wrap(phi_int_plus_gamma1 - gamma)
            }
        }
    }

    fn phi_to_point(&self, phi: SinCosCache, point: &Point) -> Point {
        let mut phi = phi;
        phi.value = wrap(phi.value);
        if point.theta() >= self.scan_theta.value {
            Point::from_cache(self.scan_theta, phi) // could be any point on the line segment
        } else {
            let a = self.scan_theta.sin - point.theta.sin * (phi.value - point.phi()).cos();
            let b = point.theta.cos - self.scan_theta.cos;
            let theta = SinCosCache::from(b.atan2(a));
            Point::from_cache(theta, phi)
        }
    }

    fn try_add_circle(&mut self, arc0: Arc<K>, arc1: Arc<K>, arc2: Arc<K>, theta: f64) -> bool {
        let p01 = self.arc_point(arc0).position - self.arc_point(arc1).position;
        let p21 = self.arc_point(arc2).position - self.arc_point(arc1).position;
        let cross = p01.cross(p21);
        let center = Point::from_cartesian(cross.x, cross.y, cross.z);
        let radius = center.distance(&self.arc_point(arc0));
        let point = Point::from_spherical(center.theta() + radius, center.phi());
        if point.theta() >= theta {
            let circle = self.events.add_circle((arc0, arc1, arc2), center, radius, point);
            self.beach.set_circle(arc1, Some(circle));
            true
        } else {
            false
        }
    }

    fn try_remove_circle(&mut self, arc: Arc<K>) -> bool {
        if let Some(event) = self.beach.circle(arc) {
            self.events.set_invalid(event, true);
            self.beach.set_circle(arc, None);
            true
        } else {
            false
        }
    }

    fn cleanup_vertices(&mut self) {
        let mut bad_vertices = Vec::new();
        for vertex in self.diagram.vertices() {
            if self.diagram.vertex_faces(vertex).len() == 2 {
                let (edge0, edge1) = {
                    let edges = self.diagram.vertex_edges(vertex);
                    assert_eq!(edges.len(), 2);
                    (edges[0], edges[1])
                };
                let vertex0 = self.diagram.other_edge_vertex(edge0, vertex).unwrap();
                let vertex1 = self.diagram.other_edge_vertex(edge1, vertex).unwrap();
                self.diagram.add_edge(Default::default(), vertex0, vertex1);
                bad_vertices.push(vertex);
            }
        }
        self.diagram.remove_vertices(&bad_vertices);
    }

    fn finish_faces(&mut self) {
        for edge in self.diagram.edges() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.diagram.edge_vertices(edge);
            for face0 in self.diagram.vertex_faces(vertex0) {
                for face1 in self.diagram.vertex_faces(vertex1) {
                    if face0 == face1 {
                        common.push(*face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.diagram.add_face_edge(common[0], edge);
            self.diagram.add_face_edge(common[1], edge);
            self.diagram.set_edge_faces(edge, common[0], common[1]);
        }
        for face in self.diagram.faces() {
            let n = *self.diagram.face_data(face).position();
            let mut edge = self.diagram.face_edges(face)[0];
            let (v0, v1) = self.diagram.edge_vertices(edge);
            let (prev, v) = if are_clockwise(n, *self.diagram[v0].position(), *self.diagram[v1].position()) {
                (v0, v1)
            } else {
                (v1, v0)
            };
            self.diagram.add_face_vertex(face, prev);
            let mut vertex = v;
            for _ in 0..self.diagram.face_edges(face).len() - 1 {
                self.diagram.add_face_vertex(face, vertex);
                for &e in self.diagram.face_edges(face) {
                    if e != edge {
                        if let Some(v) = self.diagram.other_edge_vertex(e, vertex) {
                            vertex = v;
                            edge = e;
                            break;
                        }
                    }
                }
            }
        }
    }
}

#[derive(PartialEq)]
pub enum Error {
    FewPoints,
}

pub fn build<K: Kind>(points: &[Point]) -> Result<Diagram<K>, Error>
    where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    let builder = try!(Builder::new(points));
    builder.build()
}

pub fn build_relaxed<K: Kind>(points: &[Point], relaxations: usize) -> Result<Diagram<K>, Error>
    where K::Vertex: Position, K::Edge: Default, K::Face: Position {
    let mut diagram = try!(build(points));
    for _ in 0..relaxations {
        let new_points: Vec<_> = diagram.faces().
            map(|face| {
                let face_points: Vec<_> = diagram.
                    face_vertices(face).
                    iter().
                    map(|&vertex| {
                        let data: &K::Vertex = &diagram[vertex];
                        *data.position()
                    }).collect();
                let p = Point3::centroid(&face_points);
                Point::from_cartesian(p.x, p.y, p.z)
            }).
            collect();
        diagram = try!(build(&new_points));
    }
    Ok(diagram)
}
<|endoftext|>


<commit_before>//! Windows-specific types for signal handling.
//!
//! This module is only defined on Windows and contains the primary `Event` type
//! for receiving notifications of events. These events are listened for via the
//! `SetConsoleCtrlHandler` function which receives events of the type
//! `CTRL_C_EVENT` and `CTRL_BREAK_EVENT`

#![cfg(windows)]

extern crate mio;
extern crate winapi;

use std::cell::RefCell;
use std::io;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Once, ONCE_INIT};

use futures::future;
use futures::stream::Fuse;
use futures::sync::mpsc;
use futures::sync::oneshot;
use futures::{Async, Future, IntoFuture, Poll, Stream};
use tokio_reactor::{Handle, PollEvented};
use mio::Ready;
use self::winapi::shared::minwindef::*;
use self::winapi::um::wincon::*;

use IoFuture;

extern "system" {
    fn SetConsoleCtrlHandler(HandlerRoutine: usize, Add: BOOL) -> BOOL;
}

static INIT: Once = ONCE_INIT;
static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _;

/// Stream of events discovered via `SetConsoleCtrlHandler`.
///
/// This structure can be used to listen for events of the type `CTRL_C_EVENT`
/// and `CTRL_BREAK_EVENT`. The `Stream` trait is implemented for this struct
/// and will resolve for each notification received by the process. Note that
/// there are few limitations with this as well:
///
/// * A notification to this process notifies *all* `Event` streams for that
///   event type.
/// * Notifications to an `Event` stream **are coalesced** if they aren't
///   processed quickly enough. This means that if two notifications are
///   received back-to-back, then the stream may only receive one item about the
///   two notifications.
pub struct Event {
    reg: PollEvented<MyRegistration>,
    _finished: oneshot::Sender<()>,
}

struct GlobalState {
    ready: mio::SetReadiness,
    tx: mpsc::UnboundedSender<Message>,
    ctrl_c: GlobalEventState,
    ctrl_break: GlobalEventState,
}

struct GlobalEventState {
    ready: AtomicBool,
}

enum Message {
    NewEvent(DWORD, oneshot::Sender<io::Result<Event>>),
}

struct DriverTask {
    handle: Handle,
    reg: PollEvented<MyRegistration>,
    rx: Fuse<mpsc::UnboundedReceiver<Message>>,
    ctrl_c: EventState,
    ctrl_break: EventState,
}

struct EventState {
    tasks: Vec<(RefCell<oneshot::Receiver<()>>, mio::SetReadiness)>,
}

impl Event {
    /// Creates a new stream listening for the `CTRL_C_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_c() -> IoFuture<Event> {
        Event::ctrl_c_handle(&Handle::current())
    }

    /// Creates a new stream listening for the `CTRL_C_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_c_handle(handle: &Handle) -> IoFuture<Event> {
        Event::new(CTRL_C_EVENT, handle)
    }

    /// Creates a new stream listening for the `CTRL_BREAK_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_break() -> IoFuture<Event> {
        Event::ctrl_break_handle(&Handle::current())
    }

    /// Creates a new stream listening for the `CTRL_BREAK_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_break_handle(handle: &Handle) -> IoFuture<Event> {
        Event::new(CTRL_BREAK_EVENT, handle)
    }

    fn new(signum: DWORD, handle: &Handle) -> IoFuture<Event> {
        let mut init = None;
        INIT.call_once(|| {
            init = Some(global_init(handle));
        });
        let new_signal = future::lazy(move || {
            let (tx, rx) = oneshot::channel();
            let msg = Message::NewEvent(signum, tx);
            let res = unsafe { (*GLOBAL_STATE).tx.clone().unbounded_send(msg) };
            res.expect(
                "failed to request a new signal stream, did the \
                 first event loop go away?",
            );
            rx.then(|r| r.unwrap())
        });
        match init {
            Some(init) => Box::new(init.into_future().and_then(|()| new_signal)),
            None => Box::new(new_signal),
        }
    }
}

impl Stream for Event {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        if !self.reg.poll_read_ready(Ready::readable())?.is_ready() {
            return Ok(Async::NotReady);
        }
        self.reg.clear_read_ready(Ready::readable())?;
        self.reg
            .get_ref()
            .inner
            .borrow()
            .as_ref()
            .unwrap()
            .1
            .set_readiness(mio::Ready::empty())
            .expect("failed to set readiness");
        Ok(Async::Ready(Some(())))
    }
}

fn global_init(handle: &Handle) -> io::Result<()> {
    let (tx, rx) = mpsc::unbounded();
    let reg = MyRegistration {
        inner: RefCell::new(None),
    };
    let reg = try!(PollEvented::new_with_handle(reg, handle));
    let ready = reg.get_ref().inner.borrow().as_ref().unwrap().1.clone();
    unsafe {
        let state = Box::new(GlobalState {
            ready: ready,
            ctrl_c: GlobalEventState {
                ready: AtomicBool::new(false),
            },
            ctrl_break: GlobalEventState {
                ready: AtomicBool::new(false),
            },
            tx: tx,
        });
        GLOBAL_STATE = Box::into_raw(state);

        let rc = SetConsoleCtrlHandler(handler as usize, TRUE);
        if rc == 0 {
            Box::from_raw(GLOBAL_STATE);
            GLOBAL_STATE = 0 as *mut _;
            return Err(io::Error::last_os_error());
        }

        ::tokio_executor::spawn(Box::new(DriverTask {
            handle: handle.clone(),
            rx: rx.fuse(),
            reg: reg,
            ctrl_c: EventState { tasks: Vec::new() },
            ctrl_break: EventState { tasks: Vec::new() },
        }));

        Ok(())
    }
}

impl Future for DriverTask {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        self.check_event_drops();
        self.check_messages();
        self.check_events().unwrap();

        // TODO: when to finish this task?
        Ok(Async::NotReady)
    }
}

impl DriverTask {
    fn check_event_drops(&mut self) {
        self.ctrl_c
            .tasks
            .retain(|task| !task.0.borrow_mut().poll().is_err());
        self.ctrl_break
            .tasks
            .retain(|task| !task.0.borrow_mut().poll().is_err());
    }

    fn check_messages(&mut self) {
        loop {
            // Acquire the next message
            let message = match self.rx.poll().unwrap() {
                Async::Ready(Some(e)) => e,
                Async::Ready(None) | Async::NotReady => break,
            };
            let (sig, complete) = match message {
                Message::NewEvent(sig, complete) => (sig, complete),
            };

            let event = if sig == CTRL_C_EVENT {
                &mut self.ctrl_c
            } else {
                &mut self.ctrl_break
            };

            // Acquire the (registration, set_readiness) pair by... assuming
            // we're on the event loop (true because of the spawn above).
            let reg = MyRegistration {
                inner: RefCell::new(None),
            };
            let reg = match PollEvented::new_with_handle(reg, &self.handle) {
                Ok(reg) => reg,
                Err(e) => {
                    drop(complete.send(Err(e)));
                    continue;
                }
            };

            // Create the `Event` to pass back and then also keep a handle to
            // the `SetReadiness` for ourselves internally.
            let (tx, rx) = oneshot::channel();
            let ready = reg.get_ref().inner.borrow_mut().as_mut().unwrap().1.clone();
            drop(complete.send(Ok(Event {
                reg: reg,
                _finished: tx,
            })));
            event.tasks.push((RefCell::new(rx), ready));
        }
    }

    fn check_events(&mut self) -> io::Result<()> {
        if self.reg.poll_read_ready(Ready::readable())?.is_not_ready() {
            return Ok(());
        }
        self.reg.clear_read_ready(Ready::readable())?;
        self.reg
            .get_ref()
            .inner
            .borrow()
            .as_ref()
            .unwrap()
            .1
            .set_readiness(mio::Ready::empty())
            .unwrap();

        if unsafe { (*GLOBAL_STATE).ctrl_c.ready.swap(false, Ordering::SeqCst) } {
            for task in self.ctrl_c.tasks.iter() {
                task.1.set_readiness(mio::Ready::readable()).unwrap();
            }
        }
        if unsafe {
            (*GLOBAL_STATE)
                .ctrl_break
                .ready
                .swap(false, Ordering::SeqCst)
        } {
            for task in self.ctrl_break.tasks.iter() {
                task.1.set_readiness(mio::Ready::readable()).unwrap();
            }
        }
        Ok(())
    }
}

unsafe extern "system" fn handler(ty: DWORD) -> BOOL {
    let event = match ty {
        CTRL_C_EVENT => &(*GLOBAL_STATE).ctrl_c,
        CTRL_BREAK_EVENT => &(*GLOBAL_STATE).ctrl_break,
        _ => return FALSE,
    };
    if event.ready.swap(true, Ordering::SeqCst) {
        FALSE
    } else {
        drop((*GLOBAL_STATE).ready.set_readiness(mio::Ready::readable()));
        // TODO: this will report that we handled a CTRL_BREAK_EVENT when in
        //       fact we may not have any streams actually created for that
        //       event.
        TRUE
    }
}

struct MyRegistration {
    inner: RefCell<Option<(mio::Registration, mio::SetReadiness)>>,
}

impl mio::Evented for MyRegistration {
    fn register(
        &self,
        poll: &mio::Poll,
        token: mio::Token,
        events: mio::Ready,
        opts: mio::PollOpt,
    ) -> io::Result<()> {
        let reg = mio::Registration::new(poll, token, events, opts);
        *self.inner.borrow_mut() = Some(reg);
        Ok(())
    }

    fn reregister(
        &self,
        _poll: &mio::Poll,
        _token: mio::Token,
        _events: mio::Ready,
        _opts: mio::PollOpt,
    ) -> io::Result<()> {
        Ok(())
    }

    fn deregister(&self, _poll: &mio::Poll) -> io::Result<()> {
        Ok(())
    }
}
<commit_msg>signal: Don't use the depreceated new method of Registration<commit_after>//! Windows-specific types for signal handling.
//!
//! This module is only defined on Windows and contains the primary `Event` type
//! for receiving notifications of events. These events are listened for via the
//! `SetConsoleCtrlHandler` function which receives events of the type
//! `CTRL_C_EVENT` and `CTRL_BREAK_EVENT`

#![cfg(windows)]

extern crate mio;
extern crate winapi;

use std::cell::RefCell;
use std::io;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Once, ONCE_INIT};

use futures::future;
use futures::stream::Fuse;
use futures::sync::mpsc;
use futures::sync::oneshot;
use futures::{Async, Future, IntoFuture, Poll, Stream};
use tokio_reactor::{Handle, PollEvented};
use mio::Ready;
use self::winapi::shared::minwindef::*;
use self::winapi::um::wincon::*;

use IoFuture;

extern "system" {
    fn SetConsoleCtrlHandler(HandlerRoutine: usize, Add: BOOL) -> BOOL;
}

static INIT: Once = ONCE_INIT;
static mut GLOBAL_STATE: *mut GlobalState = 0 as *mut _;

/// Stream of events discovered via `SetConsoleCtrlHandler`.
///
/// This structure can be used to listen for events of the type `CTRL_C_EVENT`
/// and `CTRL_BREAK_EVENT`. The `Stream` trait is implemented for this struct
/// and will resolve for each notification received by the process. Note that
/// there are few limitations with this as well:
///
/// * A notification to this process notifies *all* `Event` streams for that
///   event type.
/// * Notifications to an `Event` stream **are coalesced** if they aren't
///   processed quickly enough. This means that if two notifications are
///   received back-to-back, then the stream may only receive one item about the
///   two notifications.
pub struct Event {
    reg: PollEvented<MyRegistration>,
    _finished: oneshot::Sender<()>,
}

struct GlobalState {
    ready: mio::SetReadiness,
    tx: mpsc::UnboundedSender<Message>,
    ctrl_c: GlobalEventState,
    ctrl_break: GlobalEventState,
}

struct GlobalEventState {
    ready: AtomicBool,
}

enum Message {
    NewEvent(DWORD, oneshot::Sender<io::Result<Event>>),
}

struct DriverTask {
    handle: Handle,
    reg: PollEvented<MyRegistration>,
    rx: Fuse<mpsc::UnboundedReceiver<Message>>,
    ctrl_c: EventState,
    ctrl_break: EventState,
}

struct EventState {
    tasks: Vec<(RefCell<oneshot::Receiver<()>>, mio::SetReadiness)>,
}

impl Event {
    /// Creates a new stream listening for the `CTRL_C_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_c() -> IoFuture<Event> {
        Event::ctrl_c_handle(&Handle::current())
    }

    /// Creates a new stream listening for the `CTRL_C_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_c_handle(handle: &Handle) -> IoFuture<Event> {
        Event::new(CTRL_C_EVENT, handle)
    }

    /// Creates a new stream listening for the `CTRL_BREAK_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_break() -> IoFuture<Event> {
        Event::ctrl_break_handle(&Handle::current())
    }

    /// Creates a new stream listening for the `CTRL_BREAK_EVENT` events.
    ///
    /// This function will register a handler via `SetConsoleCtrlHandler` and
    /// deliver notifications to the returned stream.
    pub fn ctrl_break_handle(handle: &Handle) -> IoFuture<Event> {
        Event::new(CTRL_BREAK_EVENT, handle)
    }

    fn new(signum: DWORD, handle: &Handle) -> IoFuture<Event> {
        let mut init = None;
        INIT.call_once(|| {
            init = Some(global_init(handle));
        });
        let new_signal = future::lazy(move || {
            let (tx, rx) = oneshot::channel();
            let msg = Message::NewEvent(signum, tx);
            let res = unsafe { (*GLOBAL_STATE).tx.clone().unbounded_send(msg) };
            res.expect(
                "failed to request a new signal stream, did the \
                 first event loop go away?",
            );
            rx.then(|r| r.unwrap())
        });
        match init {
            Some(init) => Box::new(init.into_future().and_then(|()| new_signal)),
            None => Box::new(new_signal),
        }
    }
}

impl Stream for Event {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<()>, io::Error> {
        if !self.reg.poll_read_ready(Ready::readable())?.is_ready() {
            return Ok(Async::NotReady);
        }
        self.reg.clear_read_ready(Ready::readable())?;
        self.reg
            .get_ref()
            .inner
            .borrow()
            .as_ref()
            .unwrap()
            .1
            .set_readiness(mio::Ready::empty())
            .expect("failed to set readiness");
        Ok(Async::Ready(Some(())))
    }
}

fn global_init(handle: &Handle) -> io::Result<()> {
    let (tx, rx) = mpsc::unbounded();
    let reg = MyRegistration {
        inner: RefCell::new(None),
    };
    let reg = try!(PollEvented::new_with_handle(reg, handle));
    let ready = reg.get_ref().inner.borrow().as_ref().unwrap().1.clone();
    unsafe {
        let state = Box::new(GlobalState {
            ready: ready,
            ctrl_c: GlobalEventState {
                ready: AtomicBool::new(false),
            },
            ctrl_break: GlobalEventState {
                ready: AtomicBool::new(false),
            },
            tx: tx,
        });
        GLOBAL_STATE = Box::into_raw(state);

        let rc = SetConsoleCtrlHandler(handler as usize, TRUE);
        if rc == 0 {
            Box::from_raw(GLOBAL_STATE);
            GLOBAL_STATE = 0 as *mut _;
            return Err(io::Error::last_os_error());
        }

        ::tokio_executor::spawn(Box::new(DriverTask {
            handle: handle.clone(),
            rx: rx.fuse(),
            reg: reg,
            ctrl_c: EventState { tasks: Vec::new() },
            ctrl_break: EventState { tasks: Vec::new() },
        }));

        Ok(())
    }
}

impl Future for DriverTask {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        self.check_event_drops();
        self.check_messages();
        self.check_events().unwrap();

        // TODO: when to finish this task?
        Ok(Async::NotReady)
    }
}

impl DriverTask {
    fn check_event_drops(&mut self) {
        self.ctrl_c
            .tasks
            .retain(|task| !task.0.borrow_mut().poll().is_err());
        self.ctrl_break
            .tasks
            .retain(|task| !task.0.borrow_mut().poll().is_err());
    }

    fn check_messages(&mut self) {
        loop {
            // Acquire the next message
            let message = match self.rx.poll().unwrap() {
                Async::Ready(Some(e)) => e,
                Async::Ready(None) | Async::NotReady => break,
            };
            let (sig, complete) = match message {
                Message::NewEvent(sig, complete) => (sig, complete),
            };

            let event = if sig == CTRL_C_EVENT {
                &mut self.ctrl_c
            } else {
                &mut self.ctrl_break
            };

            // Acquire the (registration, set_readiness) pair by... assuming
            // we're on the event loop (true because of the spawn above).
            let reg = MyRegistration {
                inner: RefCell::new(None),
            };
            let reg = match PollEvented::new_with_handle(reg, &self.handle) {
                Ok(reg) => reg,
                Err(e) => {
                    drop(complete.send(Err(e)));
                    continue;
                }
            };

            // Create the `Event` to pass back and then also keep a handle to
            // the `SetReadiness` for ourselves internally.
            let (tx, rx) = oneshot::channel();
            let ready = reg.get_ref().inner.borrow_mut().as_mut().unwrap().1.clone();
            drop(complete.send(Ok(Event {
                reg: reg,
                _finished: tx,
            })));
            event.tasks.push((RefCell::new(rx), ready));
        }
    }

    fn check_events(&mut self) -> io::Result<()> {
        if self.reg.poll_read_ready(Ready::readable())?.is_not_ready() {
            return Ok(());
        }
        self.reg.clear_read_ready(Ready::readable())?;
        self.reg
            .get_ref()
            .inner
            .borrow()
            .as_ref()
            .unwrap()
            .1
            .set_readiness(mio::Ready::empty())
            .unwrap();

        if unsafe { (*GLOBAL_STATE).ctrl_c.ready.swap(false, Ordering::SeqCst) } {
            for task in self.ctrl_c.tasks.iter() {
                task.1.set_readiness(mio::Ready::readable()).unwrap();
            }
        }
        if unsafe {
            (*GLOBAL_STATE)
                .ctrl_break
                .ready
                .swap(false, Ordering::SeqCst)
        } {
            for task in self.ctrl_break.tasks.iter() {
                task.1.set_readiness(mio::Ready::readable()).unwrap();
            }
        }
        Ok(())
    }
}

unsafe extern "system" fn handler(ty: DWORD) -> BOOL {
    let event = match ty {
        CTRL_C_EVENT => &(*GLOBAL_STATE).ctrl_c,
        CTRL_BREAK_EVENT => &(*GLOBAL_STATE).ctrl_break,
        _ => return FALSE,
    };
    if event.ready.swap(true, Ordering::SeqCst) {
        FALSE
    } else {
        drop((*GLOBAL_STATE).ready.set_readiness(mio::Ready::readable()));
        // TODO: this will report that we handled a CTRL_BREAK_EVENT when in
        //       fact we may not have any streams actually created for that
        //       event.
        TRUE
    }
}

struct MyRegistration {
    inner: RefCell<Option<(mio::Registration, mio::SetReadiness)>>,
}

impl mio::Evented for MyRegistration {
    fn register(
        &self,
        poll: &mio::Poll,
        token: mio::Token,
        events: mio::Ready,
        opts: mio::PollOpt,
    ) -> io::Result<()> {
        let reg = mio::Registration::new2();
        reg.0.register(poll, token, events, opts)?;
        *self.inner.borrow_mut() = Some(reg);
        Ok(())
    }

    fn reregister(
        &self,
        _poll: &mio::Poll,
        _token: mio::Token,
        _events: mio::Ready,
        _opts: mio::PollOpt,
    ) -> io::Result<()> {
        Ok(())
    }

    fn deregister(&self, _poll: &mio::Poll) -> io::Result<()> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::string::String;
use std::ffi::OsStr;
use std::os::raw::{c_void, c_char};
use std::os::windows::ffi::OsStrExt;

use crypt32::{CertOpenStore, CertCloseStore, CertAddEncodedCertificateToStore,
              CertFreeCertificateContext, CertGetCertificateChain,
              CertFreeCertificateChain, CertVerifyCertificateChainPolicy};
use winapi::minwindef::DWORD;
use winapi::wincrypt::{PCCERT_CHAIN_CONTEXT, CERT_STORE_PROV_MEMORY, HCERTSTORE,
                       CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, PCCERT_CONTEXT,
                       X509_ASN_ENCODING, CERT_STORE_ADD_ALWAYS, CERT_CHAIN_PARA,
                       CERT_CHAIN_POLICY_PARA, CERT_CHAIN_POLICY_STATUS,
                       CERT_CHAIN_POLICY_SSL, szOID_PKIX_KP_SERVER_AUTH,
                       szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE};
use winapi::winnt::LPWSTR;

use ValidationResult;

pub fn validate_cert_chain(encoded_certs: &[&[u8]], hostname: &str) -> ValidationResult {
    let context = try!(build_cert_context(encoded_certs));
    let chain = try!(build_chain(context));
    verify_chain_against_policy(chain, hostname)
}

macro_rules! as_cchar_vec {
    ($e:expr) => {
        {
            let mut bytes = String::from($e).into_bytes();
            bytes.push(0);
            bytes.iter().map(|&b| b as c_char).collect()
        }
    }
}

// Sadly, winapi-rs doesn't yet have a structure we need, so I'll need to build it here.
#[repr(C)]
struct SSL_EXTRA_CERT_CHAIN_POLICY_PARA {
    cbSize: DWORD,
    dwAuthType: DWORD,
    fdwChecks: DWORD,
    pwszServerName: LPWSTR
}

impl Copy for SSL_EXTRA_CERT_CHAIN_POLICY_PARA {}
impl Clone for SSL_EXTRA_CERT_CHAIN_POLICY_PARA { fn clone(&self) -> SSL_EXTRA_CERT_CHAIN_POLICY_PARA {*self} }

// Private implementations. We need to do a lot of work here to make sure things
// behave properly. In particular, we need wrapper types.
struct CertStore(HCERTSTORE);

impl Drop for CertStore {
    fn drop(&mut self) {
        unsafe {
            CertCloseStore(self.0 as *mut _, 0);
        }
    }
}

struct CertContext(PCCERT_CONTEXT);

impl Drop for CertContext {
    fn drop(&mut self) {
        unsafe {
            CertFreeCertificateContext(self.0 as *mut _);
        }
    }
}

struct CertChainContext(PCCERT_CHAIN_CONTEXT);

impl Drop for CertChainContext {
    fn drop(&mut self) {
        unsafe {
            CertFreeCertificateChain(self.0 as *mut _);
        }
    }
}

// Verify that a given certificate chain meets the security policy.
fn verify_chain_against_policy(chain_context: CertChainContext, hostname: &str) -> ValidationResult {
    // To begin, we need to create the policy. The policy is simple: suitable for
    // SSL, suitable for this host. First, we need the hostname as a null-terminated array of wchar_t.
    // This bizarre one-liner does that.
    let mut encoded_host = OsStr::new(hostname).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>();

    // Then we need some structs to tell Windows what policy we want.
    let mut extra_policy = SSL_EXTRA_CERT_CHAIN_POLICY_PARA {
        cbSize: mem::size_of::<SSL_EXTRA_CERT_CHAIN_POLICY_PARA>() as u32,
        dwAuthType: 2,  // AUTHTYPE_SERVER
        fdwChecks: 0,
        pwszServerName: encoded_host.as_mut_ptr(),  // This is safe: the function won't modify the buffer.
    };
    let mut policy = CERT_CHAIN_POLICY_PARA {
        cbSize: mem::size_of::<CERT_CHAIN_POLICY_PARA>() as u32,
        dwFlags: 0,
        pvExtraPolicyPara: &mut extra_policy as *mut _ as *mut c_void,
    };

    // Finally we need a structure where Windows can tell us the result.
    let mut result = CERT_CHAIN_POLICY_STATUS {
        cbSize: mem::size_of::<CERT_CHAIN_POLICY_STATUS>() as u32,
        dwError: 0,
        lChainIndex: 0,
        lElementIndex: 0,
        pvExtraPolicyStatus: ptr::null_mut(),
    };

    // We can now ask Windows to validate.
    unsafe {
        let verified = CertVerifyCertificateChainPolicy(
            CERT_CHAIN_POLICY_SSL as *const i8,
            chain_context.0,
            &mut policy,
            &mut result,
        );

        if verified == 0 {
            return ValidationResult::ErrorDuringValidation;
        }
    }
    // This is probably overbroad: look at the errors in https://msdn.microsoft.com/en-us/library/windows/desktop/aa377188(v=vs.85).aspx
    // and re-evaluate.
    match result.dwError {
        0 => ValidationResult::Trusted,
        _ => ValidationResult::NotTrusted,
    }
}

// Builds a certificate chain context. This tells Windows to build a chain, but
// doesn't validate that it's acceptable for the host in question.
fn build_chain(cert_context: CertContext) -> Result<CertChainContext, ValidationResult> {
    // Define acceptable certificate uses. In this case, we would like to just use SERVER_AUTH, but
    // Chrome uses SERVER_GATED_CRYPTO and SGC_NETSCAPE because...well, who knows, but let's do that
    // anyway.
    //
    // We get mutable pointers to these strings and then a mutable pointer to the array, but only
    // because Windows isn't good enough with saying that things are const. These won't change.
    // Annoyingly, though, we have to convince Rust to do it.
    let mut server_auth: Vec<c_char> = as_cchar_vec!(szOID_PKIX_KP_SERVER_AUTH);
    let mut server_gated_crypto: Vec<c_char> = as_cchar_vec!(szOID_SERVER_GATED_CRYPTO);
    let mut sgc_netscape: Vec<c_char> = as_cchar_vec!(szOID_SGC_NETSCAPE);
    let mut usage = [
        server_auth.as_mut_ptr(),
        server_gated_crypto.as_mut_ptr(),
        sgc_netscape.as_mut_ptr(),
    ];

    let mut chain_parameters: CERT_CHAIN_PARA = unsafe{ mem::zeroed() };
    chain_parameters.RequestedUsage.dwType = 1;  // USAGE_MATCH_TYPE_OR
    chain_parameters.RequestedUsage.Usage.cUsageIdentifier = usage.len() as u32;
    chain_parameters.RequestedUsage.Usage.rgpszUsageIdentifier = usage.as_mut_ptr();
    chain_parameters.cbSize = mem::size_of::<CERT_CHAIN_PARA>() as u32;

    let mut chain_context_ptr = ptr::null();
    unsafe {
        let got_chain = CertGetCertificateChain(
            ptr::null_mut(),  // default engine
            cert_context.0,  // leaf certificate
            ptr::null_mut(),  // use the default system time
            (*(cert_context.0)).hCertStore,  // where to find intermediate certs
            &mut chain_parameters,  // The chain building constraints
            0,  // no flags
            ptr::null_mut(),  // reserved
            &mut chain_context_ptr
        );
        if got_chain == 0 {
            return Err(ValidationResult::NotTrusted);
        }
        if chain_context_ptr.is_null() {
            return Err(ValidationResult::ErrorDuringValidation);
        }
    }
    let context = CertChainContext(chain_context_ptr as PCCERT_CHAIN_CONTEXT);
    Ok(context)
}

// Builds the certificate chain provided into a certificate store.
fn build_cert_context(encoded_certs: &[&[u8]]) -> Result<CertContext, ValidationResult> {
    // Build a backing store, in-memory.
    let store_ptr = unsafe {
        let backing_store = CertOpenStore(
            CERT_STORE_PROV_MEMORY as *const i8,
            0,
            0,
            CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
            ptr::null(),
        );
        if backing_store.is_null() {
            return Err(ValidationResult::ErrorDuringValidation);
        }
        backing_store
    };
    let store = CertStore(store_ptr);
    let mut primary_cert_ptr = ptr::null();

    // Then, add the leaf cert. We want to hold on to a reference to it, because
    // that's what we'll end up returning.
    unsafe {
        let ok = CertAddEncodedCertificateToStore(
            store.0,
            X509_ASN_ENCODING,
            encoded_certs[0].as_ptr(),
            encoded_certs[0].len() as u32,
            CERT_STORE_ADD_ALWAYS,
            &mut primary_cert_ptr,
        );
        if ok == 0 {
            return Err(ValidationResult::MalformedCertificateInChain);
        }
    }
    let primary_cert = CertContext(primary_cert_ptr);

    // Now, for every other cert, add it to the store. Don't bother
    // keeping a reference.
    for cert in &encoded_certs[1..] {
        unsafe {
            let ok = CertAddEncodedCertificateToStore(
                store.0,
                X509_ASN_ENCODING,
                cert.as_ptr(),
                cert.len() as u32,
                CERT_STORE_ADD_ALWAYS,
                ptr::null_mut(),
            );
            if ok == 0 {
                return Err(ValidationResult::MalformedCertificateInChain);
            }
        }
    }

    Ok(primary_cert)
}

#[cfg(test)]
mod test {
    use windows::validate_cert_chain;
    use test::{expired_chain, certifi_chain, self_signed_chain};
    use ValidationResult;

    #[test]
    fn can_validate_good_chain() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(&chain, "certifi.io");
        assert_eq!(valid, ValidationResult::Trusted);
    }

    #[test]
    fn fails_on_bad_hostname() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(&chain, "lukasa.co.uk");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }

    #[test]
    fn fails_on_bad_cert() {
        let mut good_chain = certifi_chain();
        let originals = good_chain.split_first_mut().unwrap();
        let leaf = originals.0;
        let intermediates = originals.1;

        // Deliberately truncate the leaf cert.
        let mut certs = vec![&leaf[1..50]];
        certs.extend(intermediates.iter());
        let valid = validate_cert_chain(&certs, "certifi.io");
        assert_eq!(valid, ValidationResult::MalformedCertificateInChain);
    }

    #[test]
    fn fails_on_expired_cert() {
        let chain = expired_chain();
        let valid = validate_cert_chain(&chain, "expired.badssl.com");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }

    #[test]
    fn test_fails_on_self_signed() {
        let chain = self_signed_chain();
        let valid = validate_cert_chain(&chain, "self-signed.badssl.com");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }
}<commit_msg>try! doesn't work here.<commit_after>use std::mem;
use std::ptr;
use std::string::String;
use std::ffi::OsStr;
use std::os::raw::{c_void, c_char};
use std::os::windows::ffi::OsStrExt;

use crypt32::{CertOpenStore, CertCloseStore, CertAddEncodedCertificateToStore,
              CertFreeCertificateContext, CertGetCertificateChain,
              CertFreeCertificateChain, CertVerifyCertificateChainPolicy};
use winapi::minwindef::DWORD;
use winapi::wincrypt::{PCCERT_CHAIN_CONTEXT, CERT_STORE_PROV_MEMORY, HCERTSTORE,
                       CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, PCCERT_CONTEXT,
                       X509_ASN_ENCODING, CERT_STORE_ADD_ALWAYS, CERT_CHAIN_PARA,
                       CERT_CHAIN_POLICY_PARA, CERT_CHAIN_POLICY_STATUS,
                       CERT_CHAIN_POLICY_SSL, szOID_PKIX_KP_SERVER_AUTH,
                       szOID_SERVER_GATED_CRYPTO, szOID_SGC_NETSCAPE};
use winapi::winnt::LPWSTR;

use ValidationResult;

pub fn validate_cert_chain(encoded_certs: &[&[u8]], hostname: &str) -> ValidationResult {
    let context = match build_cert_context(encoded_certs) {
        Ok(context) => context,
        Err(e) => return e,
    };
    let chain = match build_chain(context) {
        Ok(chain) => chain,
        Err(e) => return e,
    };
    verify_chain_against_policy(chain, hostname)
}

macro_rules! as_cchar_vec {
    ($e:expr) => {
        {
            let mut bytes = String::from($e).into_bytes();
            bytes.push(0);
            bytes.iter().map(|&b| b as c_char).collect()
        }
    }
}

// Sadly, winapi-rs doesn't yet have a structure we need, so I'll need to build it here.
#[repr(C)]
struct SSL_EXTRA_CERT_CHAIN_POLICY_PARA {
    cbSize: DWORD,
    dwAuthType: DWORD,
    fdwChecks: DWORD,
    pwszServerName: LPWSTR
}

impl Copy for SSL_EXTRA_CERT_CHAIN_POLICY_PARA {}
impl Clone for SSL_EXTRA_CERT_CHAIN_POLICY_PARA { fn clone(&self) -> SSL_EXTRA_CERT_CHAIN_POLICY_PARA {*self} }

// Private implementations. We need to do a lot of work here to make sure things
// behave properly. In particular, we need wrapper types.
struct CertStore(HCERTSTORE);

impl Drop for CertStore {
    fn drop(&mut self) {
        unsafe {
            CertCloseStore(self.0 as *mut _, 0);
        }
    }
}

struct CertContext(PCCERT_CONTEXT);

impl Drop for CertContext {
    fn drop(&mut self) {
        unsafe {
            CertFreeCertificateContext(self.0 as *mut _);
        }
    }
}

struct CertChainContext(PCCERT_CHAIN_CONTEXT);

impl Drop for CertChainContext {
    fn drop(&mut self) {
        unsafe {
            CertFreeCertificateChain(self.0 as *mut _);
        }
    }
}

// Verify that a given certificate chain meets the security policy.
fn verify_chain_against_policy(chain_context: CertChainContext, hostname: &str) -> ValidationResult {
    // To begin, we need to create the policy. The policy is simple: suitable for
    // SSL, suitable for this host. First, we need the hostname as a null-terminated array of wchar_t.
    // This bizarre one-liner does that.
    let mut encoded_host = OsStr::new(hostname).encode_wide().chain(Some(0).into_iter()).collect::<Vec<_>>();

    // Then we need some structs to tell Windows what policy we want.
    let mut extra_policy = SSL_EXTRA_CERT_CHAIN_POLICY_PARA {
        cbSize: mem::size_of::<SSL_EXTRA_CERT_CHAIN_POLICY_PARA>() as u32,
        dwAuthType: 2,  // AUTHTYPE_SERVER
        fdwChecks: 0,
        pwszServerName: encoded_host.as_mut_ptr(),  // This is safe: the function won't modify the buffer.
    };
    let mut policy = CERT_CHAIN_POLICY_PARA {
        cbSize: mem::size_of::<CERT_CHAIN_POLICY_PARA>() as u32,
        dwFlags: 0,
        pvExtraPolicyPara: &mut extra_policy as *mut _ as *mut c_void,
    };

    // Finally we need a structure where Windows can tell us the result.
    let mut result = CERT_CHAIN_POLICY_STATUS {
        cbSize: mem::size_of::<CERT_CHAIN_POLICY_STATUS>() as u32,
        dwError: 0,
        lChainIndex: 0,
        lElementIndex: 0,
        pvExtraPolicyStatus: ptr::null_mut(),
    };

    // We can now ask Windows to validate.
    unsafe {
        let verified = CertVerifyCertificateChainPolicy(
            CERT_CHAIN_POLICY_SSL as *const i8,
            chain_context.0,
            &mut policy,
            &mut result,
        );

        if verified == 0 {
            return ValidationResult::ErrorDuringValidation;
        }
    }
    // This is probably overbroad: look at the errors in https://msdn.microsoft.com/en-us/library/windows/desktop/aa377188(v=vs.85).aspx
    // and re-evaluate.
    match result.dwError {
        0 => ValidationResult::Trusted,
        _ => ValidationResult::NotTrusted,
    }
}

// Builds a certificate chain context. This tells Windows to build a chain, but
// doesn't validate that it's acceptable for the host in question.
fn build_chain(cert_context: CertContext) -> Result<CertChainContext, ValidationResult> {
    // Define acceptable certificate uses. In this case, we would like to just use SERVER_AUTH, but
    // Chrome uses SERVER_GATED_CRYPTO and SGC_NETSCAPE because...well, who knows, but let's do that
    // anyway.
    //
    // We get mutable pointers to these strings and then a mutable pointer to the array, but only
    // because Windows isn't good enough with saying that things are const. These won't change.
    // Annoyingly, though, we have to convince Rust to do it.
    let mut server_auth: Vec<c_char> = as_cchar_vec!(szOID_PKIX_KP_SERVER_AUTH);
    let mut server_gated_crypto: Vec<c_char> = as_cchar_vec!(szOID_SERVER_GATED_CRYPTO);
    let mut sgc_netscape: Vec<c_char> = as_cchar_vec!(szOID_SGC_NETSCAPE);
    let mut usage = [
        server_auth.as_mut_ptr(),
        server_gated_crypto.as_mut_ptr(),
        sgc_netscape.as_mut_ptr(),
    ];

    let mut chain_parameters: CERT_CHAIN_PARA = unsafe{ mem::zeroed() };
    chain_parameters.RequestedUsage.dwType = 1;  // USAGE_MATCH_TYPE_OR
    chain_parameters.RequestedUsage.Usage.cUsageIdentifier = usage.len() as u32;
    chain_parameters.RequestedUsage.Usage.rgpszUsageIdentifier = usage.as_mut_ptr();
    chain_parameters.cbSize = mem::size_of::<CERT_CHAIN_PARA>() as u32;

    let mut chain_context_ptr = ptr::null();
    unsafe {
        let got_chain = CertGetCertificateChain(
            ptr::null_mut(),  // default engine
            cert_context.0,  // leaf certificate
            ptr::null_mut(),  // use the default system time
            (*(cert_context.0)).hCertStore,  // where to find intermediate certs
            &mut chain_parameters,  // The chain building constraints
            0,  // no flags
            ptr::null_mut(),  // reserved
            &mut chain_context_ptr
        );
        if got_chain == 0 {
            return Err(ValidationResult::NotTrusted);
        }
        if chain_context_ptr.is_null() {
            return Err(ValidationResult::ErrorDuringValidation);
        }
    }
    let context = CertChainContext(chain_context_ptr as PCCERT_CHAIN_CONTEXT);
    Ok(context)
}

// Builds the certificate chain provided into a certificate store.
fn build_cert_context(encoded_certs: &[&[u8]]) -> Result<CertContext, ValidationResult> {
    // Build a backing store, in-memory.
    let store_ptr = unsafe {
        let backing_store = CertOpenStore(
            CERT_STORE_PROV_MEMORY as *const i8,
            0,
            0,
            CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG,
            ptr::null(),
        );
        if backing_store.is_null() {
            return Err(ValidationResult::ErrorDuringValidation);
        }
        backing_store
    };
    let store = CertStore(store_ptr);
    let mut primary_cert_ptr = ptr::null();

    // Then, add the leaf cert. We want to hold on to a reference to it, because
    // that's what we'll end up returning.
    unsafe {
        let ok = CertAddEncodedCertificateToStore(
            store.0,
            X509_ASN_ENCODING,
            encoded_certs[0].as_ptr(),
            encoded_certs[0].len() as u32,
            CERT_STORE_ADD_ALWAYS,
            &mut primary_cert_ptr,
        );
        if ok == 0 {
            return Err(ValidationResult::MalformedCertificateInChain);
        }
    }
    let primary_cert = CertContext(primary_cert_ptr);

    // Now, for every other cert, add it to the store. Don't bother
    // keeping a reference.
    for cert in &encoded_certs[1..] {
        unsafe {
            let ok = CertAddEncodedCertificateToStore(
                store.0,
                X509_ASN_ENCODING,
                cert.as_ptr(),
                cert.len() as u32,
                CERT_STORE_ADD_ALWAYS,
                ptr::null_mut(),
            );
            if ok == 0 {
                return Err(ValidationResult::MalformedCertificateInChain);
            }
        }
    }

    Ok(primary_cert)
}

#[cfg(test)]
mod test {
    use windows::validate_cert_chain;
    use test::{expired_chain, certifi_chain, self_signed_chain};
    use ValidationResult;

    #[test]
    fn can_validate_good_chain() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(&chain, "certifi.io");
        assert_eq!(valid, ValidationResult::Trusted);
    }

    #[test]
    fn fails_on_bad_hostname() {
        let chain = certifi_chain();
        let valid = validate_cert_chain(&chain, "lukasa.co.uk");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }

    #[test]
    fn fails_on_bad_cert() {
        let mut good_chain = certifi_chain();
        let originals = good_chain.split_first_mut().unwrap();
        let leaf = originals.0;
        let intermediates = originals.1;

        // Deliberately truncate the leaf cert.
        let mut certs = vec![&leaf[1..50]];
        certs.extend(intermediates.iter());
        let valid = validate_cert_chain(&certs, "certifi.io");
        assert_eq!(valid, ValidationResult::MalformedCertificateInChain);
    }

    #[test]
    fn fails_on_expired_cert() {
        let chain = expired_chain();
        let valid = validate_cert_chain(&chain, "expired.badssl.com");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }

    #[test]
    fn test_fails_on_self_signed() {
        let chain = self_signed_chain();
        let valid = validate_cert_chain(&chain, "self-signed.badssl.com");
        assert_eq!(valid, ValidationResult::NotTrusted);
    }
}<|endoftext|>


<commit_before>use super::paths;
use pulldown_cmark::{html, Options, Parser};

pub fn clean() {
    // Removes any previously generated output
    paths::remove_dir(&paths::public());
}

pub fn build() {
    // Generates a static HTML bundle from markdown notes
    paths::create_dir(&paths::public());
    let markdown_input = "EmptySome **example** testing from trevordmiller.com";
    let parser = Parser::new_ext(markdown_input, Options::empty());
    let mut html_output = String::new();
    html::push_html(&mut html_output, parser);
    let html_output_in_document = format!(
        "
        <!DOCTYPE html>

                <meta charset=\"utf-8\">
                <meta name=\"author\" content=\"Trevor D. Miller\">
                <meta name=\"description\" content=\"Personal website.\">
                <title>trevordmiller.com</title>

Header

                        {}

Footer

    ",
        &html_output
    );
    paths::create_file(
        &paths::public().join("index.html"),
        &html_output_in_document,
    );
}

pub fn configure() {
    // Adds a CNAME file for the host (GitHub Pages) and registrar (Hover) to use my custom domain name (trevordmiller.com)
    paths::create_file(&paths::cname(), "trevordmiller.com");
}

pub fn deploy() {
    // Pushes output to my GitHub Pages repo (https://github.com/trevordmiller/trevordmiller.github.io)
}
<commit_msg>Break out markdown to html logic<commit_after>use super::paths;
use pulldown_cmark::{html, Options, Parser};

// Removes any previously generated output
pub fn clean() {
    paths::remove_dir(&paths::public());
}

// Generates a static HTML bundle from markdown notes
pub fn build() {
    paths::create_dir(&paths::public());
    paths::create_file(
        &paths::public().join("index.html"),
        &markdown_to_html("Some **markdown** testing from trevordmiller.com"),
    );
}

// Adds a CNAME file for the host (GitHub Pages) and registrar (Hover) to use my custom domain name (trevordmiller.com)
pub fn configure() {
    paths::create_file(&paths::cname(), "trevordmiller.com");
}

// Pushes output to my GitHub Pages repo (https://github.com/trevordmiller/trevordmiller.github.io)
pub fn deploy() {}

fn markdown_to_html(markdown: &str) -> std::string::String {
    let parser = Parser::new_ext(markdown, Options::empty());
    let mut html = String::new();
    html::push_html(&mut html, parser);
    format!(
        "
        <!DOCTYPE html>

                <meta charset=\"utf-8\">
                <meta name=\"author\" content=\"Trevor D. Miller\">
                <meta name=\"description\" content=\"Personal website.\">
                <title>trevordmiller.com</title>

Header

                        {}

Footer

    ",
        &html
    )
}
<|endoftext|>


<commit_before>use clap::{app_from_crate, arg};

fn main() {
    let matches = app_from_crate!()
        .arg(
            arg!(<PORT>)
                .help("Network port to use")
                .validator(|s| s.parse::<usize>()),
        )
        .get_matches();

    // Note, it's safe to call unwrap() because the arg is required
    let port: usize = matches
        .value_of_t("PORT")
        .expect("'MODE' is required and parsing will fail if its missing");
    println!("PORT = {}", port);
}
<commit_msg>docs: Fix copy paste error in example<commit_after>use clap::{app_from_crate, arg};

fn main() {
    let matches = app_from_crate!()
        .arg(
            arg!(<PORT>)
                .help("Network port to use")
                .validator(|s| s.parse::<usize>()),
        )
        .get_matches();

    // Note, it's safe to call unwrap() because the arg is required
    let port: usize = matches
        .value_of_t("PORT")
        .expect("'PORT' is required and parsing will fail if its missing");
    println!("PORT = {}", port);
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate find_folder;

use piston_window::Transformed;

use piston_window as pw;

mod object;
use object::Object;

struct Game {
    player: Object,
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Game {
    fn new(sprite: piston_window::Texture<gfx_device_gl::Resources>) -> Game {
        Game { player: Object::new(sprite), up: false, down: false, left: false, right: false }
    }

    fn on_update(&mut self, args: &pw::UpdateArgs) {
        if self.up   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.down { self.player.mov(0.0, 150.0 * args.dt); }
        if self.left { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.right { self.player.mov(150.0 * args.dt, 0.0); }
    }

    fn on_draw(&mut self, args: &pw::RenderArgs, window: &pw::PistonWindow) {
        window.draw_2d(|context, graphics| {
            pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    fn on_input(&mut self, input: &pw::Input) {
        use piston_window::{Input, Button, Key};

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn main() {
    use piston_window::Event;

    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join("skeleton.png");
    let sprite = pw::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, pw::Flip::None, &pw::TextureSettings::new()).unwrap();
    let mut game = Game::new(sprite);

    for w in window {
        match w.event {
            Some(Event::Update(args)) => { game.on_update(&args); }
            Some(Event::Render(args)) => { game.on_draw(&args, &w); }
            Some(Event::Input(input)) => { game.on_input(&input); }
            _ => {}
        }
    }
}
<commit_msg>load_sprite function<commit_after>extern crate piston_window;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate find_folder;

use piston_window::Transformed;

use piston_window as pw;

mod object;
use object::Object;

struct Game {
    player: Object,
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Game {
    fn new(sprite: piston_window::Texture<gfx_device_gl::Resources>) -> Game {
        Game { player: Object::new(sprite), up: false, down: false, left: false, right: false }
    }

    fn on_update(&mut self, args: &pw::UpdateArgs) {
        if self.up   { self.player.mov(0.0, -150.0 * args.dt); }
        if self.down { self.player.mov(0.0, 150.0 * args.dt); }
        if self.left { self.player.mov(-150.0 * args.dt, 0.0); }
        if self.right { self.player.mov(150.0 * args.dt, 0.0); }
    }

    fn on_draw(&mut self, args: &pw::RenderArgs, window: &pw::PistonWindow) {
        window.draw_2d(|context, graphics| {
            pw::clear([0.0, 0.0, 0.0, 1.0], graphics);

            let center = context.transform.trans((args.width / 2) as f64, (args.height / 2) as f64);
            self.player.render(graphics, &center);
        });
    }

    fn on_input(&mut self, input: &pw::Input) {
        use piston_window::{Input, Button, Key};

        match input {
            &Input::Press(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = true; }
                    Button::Keyboard(Key::Down) => { self.down = true; }
                    Button::Keyboard(Key::Left) => { self.left = true; }
                    Button::Keyboard(Key::Right) => { self.right = true; }
                    _ => {}
                }
            }
            &Input::Release(button) => {
                match button {
                    Button::Keyboard(Key::Up) => { self.up = false; }
                    Button::Keyboard(Key::Down) => { self.down = false; }
                    Button::Keyboard(Key::Left) => { self.left = false; }
                    Button::Keyboard(Key::Right) => { self.right = false; }
                    _ => {}
                }
            }
            _ => {}
        }
    }
}

fn load_sprite(window: &pw::PistonWindow, name: &str) -> piston_window::Texture<gfx_device_gl::Resources> {
    let assets = find_folder::Search::ParentsThenKids(3, 3).for_folder("assets").unwrap();
    let sprite = assets.join(name);
    pw::Texture::from_path(&mut *window.factory.borrow_mut(), &sprite, pw::Flip::None, &pw::TextureSettings::new()).unwrap()
}

fn main() {
    use piston_window::Event;

    let window: pw::PistonWindow = pw::WindowSettings::new("rrthozopsi", [600, 600])
        .exit_on_esc(true)
        .build()
        .unwrap();

    let mut game = Game::new(load_sprite(&window, "skeleton.png"));

    for w in window {
        match w.event {
            Some(Event::Update(args)) => { game.on_update(&args); }
            Some(Event::Render(args)) => { game.on_draw(&args, &w); }
            Some(Event::Input(input)) => { game.on_input(&input); }
            _ => {}
        }
    }
}
<|endoftext|>