<commit_before>use std::rand;
use std::mem;

use cgmath::point::{Point2};
use cgmath::vector::{Vec2};
use cgmath::aabb::{Aabb, Aabb2};
use color::rgb::consts::*;

use calx::app::App;
use calx::app;
use calx::renderer::Renderer;
use calx::renderer;

use area::{Location, Area, uphill, DijkstraMap};
use area;
use areaview;
use fov::Fov;
use fov;
use mapgen::MapGen;
use mob;
use mob::Mob;
use transform::Transform;
use sprite;

// XXX: Indiscriminate blob of stuff ahoy
pub struct Game {
    area: ~Area,
    pos: Location,
    seen: ~Fov,
    remembered: ~Fov,
    mobs: ~[Mob],
    player_dijkstra: Option<DijkstraMap>,
    rng: rand::StdRng,
    stop: bool,
}

impl Game {
    pub fn new() -> Game {
        let mut ret = Game {
            area: ~Area::new(area::Rock),
            pos: Location(Point2::new(0i8, 0i8)),
            seen: ~Fov::new(),
            remembered: ~Fov::new(),
            mobs: ~[],
            player_dijkstra: None,
            rng: rand::rng(),
            stop: true,
        };
        ret.mobs.push(Mob::new(mob::Player, Location(Point2::new(0i8, 0i8))));
        ret.mobs.push(Mob::new(mob::Morlock, Location(Point2::new(4i8, 4i8))));
        ret.next_level();
        ret
    }

    pub fn player<'a>(&'a mut self) -> &'a mut Mob {
        for i in self.mobs.mut_iter() {
            if i.t == mob::Player {
                return i;
            }
        }
        fail!("No player mob");
    }

    pub fn has_player(&self) -> bool {
        for i in self.mobs.iter() {
            if i.t == mob::Player {
                return true;
            }
        }
        false
    }

    pub fn mob_at<'a>(&'a mut self, loc: Location) -> Option<&'a mut Mob> {
        for i in self.mobs.mut_iter() {
            if i.loc == loc {
                return Some(i);
            }
        }
        None
    }

    pub fn next_level(&mut self) {
        self.area = ~Area::new(area::Rock);
        self.area.gen_cave(&mut self.rng);

        self.pos = Location(Point2::new(0i8, 0i8));

        self.seen = ~Fov::new();
        self.remembered = ~Fov::new();
    }

    pub fn step(&mut self, d: &Vec2<int>) -> bool {
        let new_loc = self.player().loc + *d;
        if self.area.is_walkable(new_loc) {
            self.player().loc = new_loc;
        } else {
            return false;
        }

        if self.area.get(new_loc) == area::Downstairs {
            self.next_level();
        }

        true
    }

    pub fn update(&mut self) {
        // TODO: Run all mobs' AI
    }

    pub fn draw<R: Renderer>(&mut self, app: &mut App<R>) {
        if self.has_player() {
            self.pos = self.player().loc;
        }

        let mouse = app.r.get_mouse();
        let xf = Transform::new(self.pos);
        let cursor_chart_loc = xf.to_chart(&mouse.pos);

        let mut tmp_seen = ~fov::fov(self.area, self.pos, 12);
        mem::swap(self.seen, tmp_seen);
        // Move old fov to map memory.
        self.remembered.add(tmp_seen);

        if app.screen_area().contains(&mouse.pos) {
            if mouse.left {
                self.area.dig(cursor_chart_loc);
            }

            if mouse.right {
                self.area.fill(cursor_chart_loc);
            }
        }

        areaview::draw_area(self, app);
        app.r.draw_tile(areaview::CURSOR_BOTTOM, &xf.to_screen(cursor_chart_loc), sprite::FLOOR_Z, &FIREBRICK, renderer::ColorKeyDraw);
        app.r.draw_tile(areaview::CURSOR_TOP, &xf.to_screen(cursor_chart_loc), sprite::BLOCK_Z, &FIREBRICK, renderer::ColorKeyDraw);

        let text_zone = Aabb2::new(Point2::new(0.0f32, 200.0f32), Point2::new(240.0f32, 360.0f32));
        app.set_color(&LIGHTSLATEGRAY);
        app.print_words(&text_zone, app::Left, "Hello, player. This is a friendly status message.");

        app.set_color(&CORNFLOWERBLUE);
        app.print_words(&Aabb2::new(Point2::new(260.0f32, 0.0f32), Point2::new(380.0f32, 16.0f32)),
            app::Center, format!("cell {} {}", cursor_chart_loc.p().x, cursor_chart_loc.p().y));

        app.set_color(&LIGHTSLATEGRAY);
        app.print_words(&Aabb2::new(Point2::new(560.0f32, 0.0f32), Point2::new(640.0f32, 16.0f32)),
            app::Right, "Area Name");

        if !self.stop {
            if !self.area.fully_explored(self.remembered) {
                let map = self.area.explore_map(self.remembered);
                match uphill(&map, self.pos) {
                    Some(p) => { if self.area.is_walkable(p) { self.pos = p; } },
                    None => (),
                }
            }
        }

        if self.area.get(self.pos) == area::Downstairs {
            self.next_level();
        }
    }
}
<commit_msg>Area and object name UI work right<commit_after>use std::rand;
use std::mem;

use cgmath::point::{Point2};
use cgmath::vector::{Vec2};
use cgmath::aabb::{Aabb, Aabb2};
use color::rgb::consts::*;

use calx::app::App;
use calx::app;
use calx::renderer::Renderer;
use calx::renderer;

use area::{Location, Area, uphill, DijkstraMap};
use area;
use areaview;
use fov::Fov;
use fov;
use mapgen::MapGen;
use mob;
use mob::Mob;
use transform::Transform;
use sprite;

// XXX: Indiscriminate blob of stuff ahoy
pub struct Game {
    area: ~Area,
    pos: Location,
    seen: ~Fov,
    remembered: ~Fov,
    mobs: ~[Mob],
    player_dijkstra: Option<DijkstraMap>,
    rng: rand::StdRng,
    stop: bool,
    depth: uint,
}

impl Game {
    pub fn new() -> Game {
        let mut ret = Game {
            area: ~Area::new(area::Rock),
            pos: Location(Point2::new(0i8, 0i8)),
            seen: ~Fov::new(),
            remembered: ~Fov::new(),
            mobs: ~[],
            player_dijkstra: None,
            rng: rand::rng(),
            stop: true,
            depth: 0,
        };
        ret.mobs.push(Mob::new(mob::Player, Location(Point2::new(0i8, 0i8))));
        ret.mobs.push(Mob::new(mob::Morlock, Location(Point2::new(4i8, 4i8))));
        ret.next_level();
        ret
    }

    pub fn player<'a>(&'a mut self) -> &'a mut Mob {
        for i in self.mobs.mut_iter() {
            if i.t == mob::Player {
                return i;
            }
        }
        fail!("No player mob");
    }

    pub fn has_player(&self) -> bool {
        for i in self.mobs.iter() {
            if i.t == mob::Player {
                return true;
            }
        }
        false
    }

    // TODO: Should have an immutable version.
    pub fn mob_at<'a>(&'a mut self, loc: Location) -> Option<&'a mut Mob> {
        for i in self.mobs.mut_iter() {
            if i.loc == loc {
                return Some(i);
            }
        }
        None
    }

    pub fn next_level(&mut self) {
        self.area = ~Area::new(area::Rock);
        self.area.gen_cave(&mut self.rng);

        self.player().loc = Location(Point2::new(0i8, 0i8));

        self.seen = ~Fov::new();
        self.remembered = ~Fov::new();
        self.depth += 1;
    }

    pub fn area_name(&self) -> ~str {
        format!("Floor {}", self.depth)
    }

    pub fn object_name(&mut self, loc: Location) -> ~str {
        match self.mob_at(loc) {
            Some(mob) => mob.data().name,
            None => ~"",
        }
    }

    pub fn step(&mut self, d: &Vec2<int>) -> bool {
        let new_loc = self.player().loc + *d;
        if self.area.is_walkable(new_loc) {
            self.player().loc = new_loc;
        } else {
            return false;
        }

        if self.area.get(new_loc) == area::Downstairs {
            self.next_level();
        }

        true
    }

    pub fn update(&mut self) {
        // TODO: Run all mobs' AI
    }

    pub fn draw<R: Renderer>(&mut self, app: &mut App<R>) {
        if self.has_player() {
            self.pos = self.player().loc;
        }

        let mouse = app.r.get_mouse();
        let xf = Transform::new(self.pos);
        let cursor_chart_loc = xf.to_chart(&mouse.pos);

        let mut tmp_seen = ~fov::fov(self.area, self.pos, 12);
        mem::swap(self.seen, tmp_seen);
        // Move old fov to map memory.
        self.remembered.add(tmp_seen);

        if app.screen_area().contains(&mouse.pos) {
            if mouse.left {
                self.area.dig(cursor_chart_loc);
            }

            if mouse.right {
                self.area.fill(cursor_chart_loc);
            }
        }

        areaview::draw_area(self, app);
        app.r.draw_tile(areaview::CURSOR_BOTTOM, &xf.to_screen(cursor_chart_loc), sprite::FLOOR_Z, &FIREBRICK, renderer::ColorKeyDraw);
        app.r.draw_tile(areaview::CURSOR_TOP, &xf.to_screen(cursor_chart_loc), sprite::BLOCK_Z, &FIREBRICK, renderer::ColorKeyDraw);

        let text_zone = Aabb2::new(Point2::new(0.0f32, 200.0f32), Point2::new(240.0f32, 360.0f32));
        app.set_color(&LIGHTSLATEGRAY);
        app.print_words(&text_zone, app::Left, "Hello, player. This is a friendly status message.");

        app.set_color(&CORNFLOWERBLUE);
        app.print_words(&Aabb2::new(Point2::new(260.0f32, 0.0f32), Point2::new(380.0f32, 16.0f32)),
            app::Center, self.object_name(cursor_chart_loc));

        app.set_color(&LIGHTSLATEGRAY);
        app.print_words(&Aabb2::new(Point2::new(560.0f32, 0.0f32), Point2::new(640.0f32, 16.0f32)),
            app::Right, self.area_name());

        if !self.stop {
            if !self.area.fully_explored(self.remembered) {
                let map = self.area.explore_map(self.remembered);
                match uphill(&map, self.pos) {
                    Some(p) => { if self.area.is_walkable(p) { self.pos = p; } },
                    None => (),
                }
            }
        }

        if self.area.get(self.pos) == area::Downstairs {
            self.next_level();
        }
    }
}
<|endoftext|>


<commit_before>use http::{HeaderMap, Uri};
use http::header::HeaderValue;
use http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE};
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
use hyper::rt::{Future, Stream};
use pact_matching::models::{OptionalBody, Request, Response, HttpPart};
use pact_matching::models::parse_query_string;
use std::collections::HashMap;

fn extract_query_string(uri: &Uri) -> Option<HashMap<String, Vec<String>>> {
    match uri.query() {
        Some(q) => parse_query_string(&s!(q)),
        None => None
    }
}

fn extract_headers(headers: &HeaderMap<HeaderValue>) -> Option<HashMap<String, String>> {
    if headers.len() > 0 {
        Some(headers.iter().map(|(h, v)| (h.as_str().into(), v.to_str().unwrap_or("").to_string())).collect())
    } else {
        None
    }
}

fn extract_body(req: &mut Body) -> OptionalBody {
    match req.by_ref().concat2().wait() {
        Ok(chunk) => if chunk.is_empty() {
            OptionalBody::Empty
        } else {
            OptionalBody::Present(chunk.iter().cloned().collect())
        },
        Err(err) => {
            warn!("Failed to read request body: {}", err);
            OptionalBody::Empty
        }
    }
}

pub fn hyper_request_to_pact_request(req: &mut HyperRequest<Body>) -> Request {
    Request {
        method: req.method().to_string(),
        path: req.uri().path().to_string(),
        query: extract_query_string(req.uri()),
        headers: extract_headers(req.headers()),
        body: extract_body(req.body_mut()),
        .. Request::default_request()
    }
}

pub fn pact_response_to_hyper_response(response: &Response) -> HyperResponse<Body> {
    info!("<=== Sending response {:?}", response);
    info!("     body '{}'\n\n", response.body.str_value());
    let mut res = HyperResponse::builder();
    {
        res
            .status(response.status)
            .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*");

        match response.headers {
            Some(ref headers) => {
                for (k, v) in headers.clone() {
                    res.header(k.as_str(), v);
                }
            },
            None => ()
        }

        match response.body {
            OptionalBody::Present(ref body) => {
                if !response.has_header(&CONTENT_TYPE.as_str().into()) {
                    res.header(CONTENT_TYPE, response.content_type());
                }
                res.body(Body::from(body.clone()))
            },
            _ => res.body(Body::empty())
        }.unwrap()
    }
}
<commit_msg>fix: add some tests around content type header #14<commit_after>use http::{HeaderMap, Uri};
use http::header::HeaderValue;
use http::header::{ACCESS_CONTROL_ALLOW_ORIGIN, CONTENT_TYPE};
use hyper::{Body, Request as HyperRequest, Response as HyperResponse};
use hyper::rt::{Future, Stream};
use pact_matching::models::{OptionalBody, Request, Response, HttpPart};
use pact_matching::models::parse_query_string;
use std::collections::HashMap;

fn extract_query_string(uri: &Uri) -> Option<HashMap<String, Vec<String>>> {
    match uri.query() {
        Some(q) => parse_query_string(&s!(q)),
        None => None
    }
}

fn extract_headers(headers: &HeaderMap<HeaderValue>) -> Option<HashMap<String, String>> {
    if headers.len() > 0 {
        Some(headers.iter().map(|(h, v)| (h.as_str().into(), v.to_str().unwrap_or("").to_string())).collect())
    } else {
        None
    }
}

fn extract_body(req: &mut Body) -> OptionalBody {
    match req.by_ref().concat2().wait() {
        Ok(chunk) => if chunk.is_empty() {
            OptionalBody::Empty
        } else {
            OptionalBody::Present(chunk.iter().cloned().collect())
        },
        Err(err) => {
            warn!("Failed to read request body: {}", err);
            OptionalBody::Empty
        }
    }
}

pub fn hyper_request_to_pact_request(req: &mut HyperRequest<Body>) -> Request {
    Request {
        method: req.method().to_string(),
        path: req.uri().path().to_string(),
        query: extract_query_string(req.uri()),
        headers: extract_headers(req.headers()),
        body: extract_body(req.body_mut()),
        .. Request::default_request()
    }
}

pub fn pact_response_to_hyper_response(response: &Response) -> HyperResponse<Body> {
    info!("<=== Sending response {:?}", response);
    info!("     body '{}'\n\n", response.body.str_value());
    let mut res = HyperResponse::builder();
    {
        res
            .status(response.status)
            .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*");

        match response.headers {
            Some(ref headers) => {
                for (k, v) in headers.clone() {
                    res.header(k.as_str(), v);
                }
            },
            None => ()
        }

        match response.body {
            OptionalBody::Present(ref body) => {
                if !response.has_header(&CONTENT_TYPE.as_str().into()) {
                    res.header(CONTENT_TYPE, response.content_type());
                }
                res.body(Body::from(body.clone()))
            },
            _ => res.body(Body::empty())
        }.unwrap()
    }
}

#[cfg(test)]
mod test {

    use expectest::prelude::*;
    use super::*;
    use pact_matching::models::{OptionalBody, Response};
    use http::status::StatusCode;
    use http::header::HeaderValue;

    #[test]
    fn test_response() {
        let response = Response {
            status: 201,
            headers: Some(hashmap! {  }),
            .. Response::default_response()
        };
        let hyper_response = pact_response_to_hyper_response(&response);

        expect!(hyper_response.status()).to(be_equal_to(StatusCode::CREATED));
        expect!(hyper_response.headers().len()).to(be_equal_to(1));
    }

    #[test]
    fn test_response_with_content_type() {
        let response = Response {
            status: 201,
            headers: Some(hashmap! { s!("Content-Type") => s!("text/dizzy") }),
            body: OptionalBody::Present("{\"a\": 1, \"b\": 4, \"c\": 6}".as_bytes().into()),
            .. Response::default_response()
        };
        let hyper_response = pact_response_to_hyper_response(&response);

        expect!(hyper_response.status()).to(be_equal_to(StatusCode::CREATED));
        expect!(hyper_response.headers().is_empty()).to(be_false());
        expect!(hyper_response.headers().get("content-type")).to(be_some().value(HeaderValue::from_static("text/dizzy")));
    }

    #[test]
    fn adds_a_content_type_if_there_is_not_one_and_there_is_a_body() {
        let response = Response {
            body: OptionalBody::Present("{\"a\": 1, \"b\": 4, \"c\": 6}".as_bytes().into()),
            .. Response::default_response()
        };
        let hyper_response = pact_response_to_hyper_response(&response);

        expect!(hyper_response.headers().is_empty()).to(be_false());
        expect!(hyper_response.headers().get("content-type")).to(be_some().value(HeaderValue::from_static("application/json")));
    }

}
<|endoftext|>


<commit_before>//! A simple macro library for creating phantom enums. Just simple sugar.
//!
//! See the `phantom_enum!` macro for all the details.

/// Create a phantom type enum.
///
/// A phantom type enum is an enum-like arrangement where the enum is a module
/// and trait and the variants are (uninstantiable) types.
///
/// This is very good for the static representation of state machines in which
/// *nothing* can go wrong.
///
///     #[macro_use] #[no_link]
///     extern crate phantom_enum;
///
///     phantom_enum! {
///         #[doc = "Put things here, of course"]
///         pub enum TableItem {
///             #[doc = "A bottle with a paper label reading “DRINK ME”."]
///             Potion,
///             #[doc = "A cake with the words “EAT ME” marked in currants."]
///             Cake
///         }
///     }
///
///     struct Person<T> {
///         name: &'static str,
///     }
///
///     // Note how this restricts the methods to only meaningful types.
///     // (I look forward to generic bounds in struct definitions!)
///     impl<T: TableItem::Impl> Person<T> {
///         fn new(name: &'static str) -> Person<T> {
///             Person {
///                 name: name,
///             }
///         }
///     }
///
///     impl Person<TableItem::Potion> {
///         fn drink_it(self) -> Person<TableItem::Cake> {
///             println!("Shrinking! Oh look, there’s a box down here!");
///             Person {
///                 name: self.name,
///             }
///         }
///     }
///
///     impl Person<TableItem::Cake> {
///         fn eat_it(self) -> () {
///             println!("Growing! OK, that’s enough of the story.");
///             // Who can remember what comes next, anyway?
///         }
///     }
///
///     fn main() {
///         let person = Person::new("Alice");
///         let person = person.drink_it();
///         person.eat_it();
///     }
///
/// As you will observe with this example, if you have a `Person<Potion>`, you
/// simply cannot call `.eat_it()`; for that, you must have a `Person<Cake>`.
/// Similarly, once you have drunk that potion, you can’t drink it again.
#[macro_export]
macro_rules! phantom_enum {
    (
        #[$enum_attr:meta]
        pub enum $name:ident {
            $(
                #[$variant_attr:meta]
                $variant:ident
             ),*
        }
    ) => {
        #[$enum_attr]
        #[allow(non_snake_case)]
        mod $name {
            /// Implemented exclusively by members of this phantom type enum.
            /// This is for use as a generic bound.
            pub trait Impl { }

            $(
                #[$variant_attr]
                #[derive(Copy)]
                pub enum $variant { }
                impl Impl for $variant { }
            )*
        }
    }
}
<commit_msg>Have both private and public phantom enums.<commit_after>//! A simple macro library for creating phantom enums. Just simple sugar.
//!
//! See the `phantom_enum!` macro for all the details.

/// Create a phantom type enum.
///
/// A phantom type enum is an enum-like arrangement where the enum is a module
/// and trait and the variants are (uninstantiable) types.
///
/// This is very good for the static representation of state machines in which
/// *nothing* can go wrong.
///
///     #[macro_use] #[no_link]
///     extern crate phantom_enum;
///
///     phantom_enum! {
///         #[doc = "Put things here, of course"]
///         pub enum TableItem {
///             #[doc = "A bottle with a paper label reading “DRINK ME”."]
///             Potion,
///             #[doc = "A cake with the words “EAT ME” marked in currants."]
///             Cake
///         }
///     }
///
///     struct Person<T> {
///         name: &'static str,
///     }
///
///     // Note how this restricts the methods to only meaningful types.
///     // (I look forward to generic bounds in struct definitions!)
///     impl<T: TableItem::Impl> Person<T> {
///         fn new(name: &'static str) -> Person<T> {
///             Person {
///                 name: name,
///             }
///         }
///     }
///
///     impl Person<TableItem::Potion> {
///         fn drink_it(self) -> Person<TableItem::Cake> {
///             println!("Shrinking! Oh look, there’s a box down here!");
///             Person {
///                 name: self.name,
///             }
///         }
///     }
///
///     impl Person<TableItem::Cake> {
///         fn eat_it(self) -> () {
///             println!("Growing! OK, that’s enough of the story.");
///             // Who can remember what comes next, anyway?
///         }
///     }
///
///     fn main() {
///         let person = Person::new("Alice");
///         let person = person.drink_it();
///         person.eat_it();
///     }
///
/// As you will observe with this example, if you have a `Person<Potion>`, you
/// simply cannot call `.eat_it()`; for that, you must have a `Person<Cake>`.
/// Similarly, once you have drunk that potion, you can’t drink it again.
#[macro_export]
macro_rules! phantom_enum {
    (
        #[$enum_attr:meta]
        pub enum $name:ident {
            $(
                #[$variant_attr:meta]
                $variant:ident
             ),*
        }
    ) => {
        #[$enum_attr]
        #[allow(non_snake_case)]
        pub mod $name {
            /// Implemented exclusively by members of this phantom type enum.
            /// This is for use as a generic bound.
            pub trait Impl { }

            $(
                #[$variant_attr]
                #[derive(Copy)]
                pub enum $variant { }
                impl Impl for $variant { }
            )*
        }
    };

    (
        #[$enum_attr:meta]
        enum $name:ident {
            $(
                #[$variant_attr:meta]
                $variant:ident
             ),*
        }
    ) => {
        #[$enum_attr]
        #[allow(non_snake_case)]
        mod $name {
            /// Implemented exclusively by members of this phantom type enum.
            /// This is for use as a generic bound.
            pub trait Impl { }

            $(
                #[$variant_attr]
                #[derive(Copy)]
                pub enum $variant { }
                impl Impl for $variant { }
            )*
        }
    }
}
<|endoftext|>


<commit_before>use cgmath::{Vector2, Vector3};

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AABB2 {
    pub min: Vector2<f32>,
    pub max: Vector2<f32>,
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AABB3 {
    pub min: Vector3<f32>,
    pub max: Vector3<f32>,
}

impl AABB2 {
    pub fn new(minx: f32, miny: f32, maxx: f32, maxy: f32) -> AABB2 {
        AABB2 {
            min: Vector2 { x: minx, y: miny },
            max: Vector2 { x: maxx, y: maxy },
        }
    }

    pub fn intersects(&self, other: AABB2) -> bool {
        if self.max.x < other.min.x || self.min.x > other.max.x {
            return false;
        }
        if self.max.y < other.min.y || self.min.y > other.max.y {
            return false;
        }
        true
    }

    pub fn slide<'a, T>(&mut self, mov: Vector2<f32>, others: T)
        where T: Iterator<Item = &'a AABB2> + Clone
    {
        if mov.x == 0f32 && mov.y == 0f32 {
            return;
        }

        let mut res = mov; // Copy
        let mut aabb = self; // Copy

        // Y movement

        if mov.y < 0f32 {
            for other in others.clone() {
                if aabb.max.x > other.min.x && aabb.min.x < other.max.x &&
                   other.max.y <= aabb.min.y {
                    let min = other.max.y - aabb.min.y;
                    if min > res.y {
                        res.y = min;
                    }
                }
            }
        }

        if mov.y > 0f32 {
            for other in others.clone() {
                if aabb.max.x > other.min.x && aabb.min.x < other.max.x &&
                   other.min.y >= aabb.max.y {
                    let max = other.min.y - aabb.max.y;
                    if max < res.y {
                        res.y = max;
                    }
                }
            }
        }

        aabb.min.y += res.y;
        aabb.max.y += res.y;

        // X movement

        if mov.x < 0f32 {
            for other in others.clone() {
                if aabb.max.y > other.min.y && aabb.min.y < other.max.y &&
                   other.max.x <= aabb.min.x {
                    let min = other.max.x - aabb.min.x;
                    if min > res.x {
                        res.x = min;
                    }
                }
            }
        }

        if mov.x > 0f32 {
            for other in others.clone() {
                if aabb.max.y > other.min.y && aabb.min.y < other.max.y &&
                   other.min.x >= aabb.max.x {
                    let max = other.min.x - aabb.max.x;
                    if max < res.x {
                        res.x = max;
                    }
                }
            }
        }

        aabb.min.x += res.x;
        aabb.max.x += res.x;
    }
}

impl AABB3 {
    pub fn intersects(&self, other: AABB3) -> bool {
        if self.max.x < other.min.x || self.min.x > other.max.x {
            return false;
        }
        if self.max.y < other.min.y || self.min.y > other.max.y {
            return false;
        }
        if self.max.z < other.min.z || self.min.z > other.max.z {
            return false;
        }
        true
    }
}

mod tests {
    use super::*;
    use test::*;

    #[test]
    fn aabb2_slide_test() {
        let v = vec![AABB2::new(2f32, 0f32, 3f32, 1f32), AABB2::new(0f32, 1f32, 1f32, 2f32)];
        let mut aabb = AABB2::new(0f32, 0f32, 1f32, 1f32);

        {
            let mot = Vector2::new(2f32, 0f32);
            aabb.slide(mot, v.iter());
            assert_eq!(aabb, AABB2::new(1f32, 0f32, 2f32, 1f32));
        }

        {
            let mot = Vector2::new(-4f32, 1f32);
            aabb.slide(mot, v.iter());
            assert_eq!(aabb, AABB2::new(1f32, 1f32, 2f32, 2f32));
        }
    }

    fn data() -> Vec<AABB2> {
        vec![AABB2::new(2f32, 0f32, 3f32, 1f32),
             AABB2::new(0f32, 1f32, 1f32, 2f32),
             AABB2::new(3f32, 1f32, 4f32, 2f32),
             AABB2::new(1f32, 2f32, 2f32, 3f32),

             AABB2::new(2f32, 0f32, 3f32, 1f32),
             AABB2::new(0f32, 1f32, 1f32, 2f32),
             AABB2::new(3f32, 1f32, 4f32, 2f32),
             AABB2::new(1f32, 2f32, 2f32, 3f32)]
    }

    #[bench]
    fn bench_test(b: &mut Bencher) {
        let v = data();
        b.iter(|| {
            let mut aabb = AABB2::new(0f32, 0f32, 1f32, 1f32);

            {
                let mot = black_box(Vector2::new(2f32, 0f32));
                aabb.slide(mot, v.iter());
            }

            {
                let mot = black_box(Vector2::new(-4f32, 1f32));
                aabb.slide(mot, v.iter());
            }
        });
    }
}<commit_msg>Hide warnings in the aabb::tests<commit_after>use cgmath::{Vector2, Vector3};

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AABB2 {
    pub min: Vector2<f32>,
    pub max: Vector2<f32>,
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub struct AABB3 {
    pub min: Vector3<f32>,
    pub max: Vector3<f32>,
}

impl AABB2 {
    pub fn new(minx: f32, miny: f32, maxx: f32, maxy: f32) -> AABB2 {
        AABB2 {
            min: Vector2 { x: minx, y: miny },
            max: Vector2 { x: maxx, y: maxy },
        }
    }

    pub fn intersects(&self, other: AABB2) -> bool {
        if self.max.x < other.min.x || self.min.x > other.max.x {
            return false;
        }
        if self.max.y < other.min.y || self.min.y > other.max.y {
            return false;
        }
        true
    }

    pub fn slide<'a, T>(&mut self, mov: Vector2<f32>, others: T)
        where T: Iterator<Item = &'a AABB2> + Clone
    {
        if mov.x == 0f32 && mov.y == 0f32 {
            return;
        }

        let mut res = mov; // Copy
        let mut aabb = self; // Copycc

        // Y movement

        if mov.y < 0f32 {
            for other in others.clone() {
                if aabb.max.x > other.min.x && aabb.min.x < other.max.x &&
                   other.max.y <= aabb.min.y {
                    let min = other.max.y - aabb.min.y;
                    if min > res.y {
                        res.y = min;
                    }
                }
            }
        }

        if mov.y > 0f32 {
            for other in others.clone() {
                if aabb.max.x > other.min.x && aabb.min.x < other.max.x &&
                   other.min.y >= aabb.max.y {
                    let max = other.min.y - aabb.max.y;
                    if max < res.y {
                        res.y = max;
                    }
                }
            }
        }

        aabb.min.y += res.y;
        aabb.max.y += res.y;

        // X movement

        if mov.x < 0f32 {
            for other in others.clone() {
                if aabb.max.y > other.min.y && aabb.min.y < other.max.y &&
                   other.max.x <= aabb.min.x {
                    let min = other.max.x - aabb.min.x;
                    if min > res.x {
                        res.x = min;
                    }
                }
            }
        }

        if mov.x > 0f32 {
            for other in others.clone() {
                if aabb.max.y > other.min.y && aabb.min.y < other.max.y &&
                   other.min.x >= aabb.max.x {
                    let max = other.min.x - aabb.max.x;
                    if max < res.x {
                        res.x = max;
                    }
                }
            }
        }

        aabb.min.x += res.x;
        aabb.max.x += res.x;
    }
}

impl AABB3 {
    pub fn intersects(&self, other: AABB3) -> bool {
        if self.max.x < other.min.x || self.min.x > other.max.x {
            return false;
        }
        if self.max.y < other.min.y || self.min.y > other.max.y {
            return false;
        }
        if self.max.z < other.min.z || self.min.z > other.max.z {
            return false;
        }
        true
    }
}

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

    #[test]
    fn aabb2_slide_test() {
        let v = vec![AABB2::new(2f32, 0f32, 3f32, 1f32), AABB2::new(0f32, 1f32, 1f32, 2f32)];
        let mut aabb = AABB2::new(0f32, 0f32, 1f32, 1f32);

        {
            let mot = Vector2::new(2f32, 0f32);
            aabb.slide(mot, v.iter());
            assert_eq!(aabb, AABB2::new(1f32, 0f32, 2f32, 1f32));
        }

        {
            let mot = Vector2::new(-4f32, 1f32);
            aabb.slide(mot, v.iter());
            assert_eq!(aabb, AABB2::new(1f32, 1f32, 2f32, 2f32));
        }
    }

    #[bench]
    fn bench_test(b: &mut Bencher) {
        let v = vec![
            AABB2::new(2f32, 0f32, 3f32, 1f32),
            AABB2::new(0f32, 1f32, 1f32, 2f32),
            AABB2::new(3f32, 1f32, 4f32, 2f32),
            AABB2::new(1f32, 2f32, 2f32, 3f32),

            AABB2::new(2f32, 0f32, 3f32, 1f32),
            AABB2::new(0f32, 1f32, 1f32, 2f32),
            AABB2::new(3f32, 1f32, 4f32, 2f32),
            AABB2::new(1f32, 2f32, 2f32, 3f32),
        ];
        b.iter(|| {
            let mut aabb = AABB2::new(0f32, 0f32, 1f32, 1f32);

            {
                let mot = black_box(Vector2::new(2f32, 0f32));
                aabb.slide(mot, v.iter());
            }

            {
                let mot = black_box(Vector2::new(-4f32, 1f32));
                aabb.slide(mot, v.iter());
            }
        });
    }
}<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(PartialEq)]
enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

struct Feature {
    level: Status,
    since: String,
    has_gate_test: bool,
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs"));
    assert!(!features.is_empty());
    let mut lib_features = HashMap::<String, Feature>::new();

    let mut contents = String::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => {
                    err("malformed stability attribute");
                    continue;
                }
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err("malformed stability attribute");
                    continue;
                }
                None => "None",
            };

            if features.contains_key(feature_name) {
                err("duplicating a lang feature");
            }
            if let Some(ref s) = lib_features.get(feature_name) {
                if s.level != level {
                    err("different stability level than before");
                }
                if s.since != since {
                    err("different `since` than before");
                }
                continue;
            }
            lib_features.insert(feature_name.to_owned(),
                                Feature {
                                    level: level,
                                    since: since.to_owned(),
                                    has_gate_test: false,
                                });
        }
    });

    super::walk(&path.join("test/compile-fail"),
                &mut |path| super::filter_dirs(path),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            let found_feature = features.get_mut(feature_name)
                                        .map(|v| { v.has_gate_test = true; () })
                                        .is_some();

            let found_lib_feature = features.get_mut(feature_name)
                                            .map(|v| { v.has_gate_test = true; () })
                                            .is_some();

            if !(found_feature || found_lib_feature) {
                err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                             feature_name));
            }
        }
    });

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .count();

    // FIXME get this number down to zero.
    let gate_untested_expected = 94;

    if gate_untested != gate_untested_expected {
        print!("Expected {} gate untested features, but found {}. ",
                gate_untested_expected, gate_untested);
        if gate_untested < gate_untested_expected {
            println!("Did you forget to reduce the expected number?");
        } else {
            println!("Did you forget to add a gate test for your new feature?");
        }
        *bad = true;
    }

    if *bad {
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str,
                   features: &mut HashMap<String, Feature>) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            Some((name.to_owned(),
                Feature {
                    level: level,
                    since: since.to_owned(),
                    has_gate_test: false,
                }))
        })
        .collect()
}
<commit_msg>Use a whitelist and print nice hints<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to ensure that unstable features are all in order
//!
//! This check will ensure properties like:
//!
//! * All stability attributes look reasonably well formed
//! * The set of library features is disjoint from the set of language features
//! * Library features have at most one stability level
//! * Library features have at most one `since` value
//! * All unstable lang features have tests to ensure they are actually unstable

use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

#[derive(PartialEq)]
enum Status {
    Stable,
    Removed,
    Unstable,
}

impl fmt::Display for Status {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let as_str = match *self {
            Status::Stable => "stable",
            Status::Unstable => "unstable",
            Status::Removed => "removed",
        };
        fmt::Display::fmt(as_str, f)
    }
}

struct Feature {
    level: Status,
    since: String,
    has_gate_test: bool,
}

pub fn check(path: &Path, bad: &mut bool) {
    let mut features = collect_lang_features(&path.join("libsyntax/feature_gate.rs"));
    assert!(!features.is_empty());
    let mut lib_features = HashMap::<String, Feature>::new();

    let mut contents = String::new();
    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/test"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };
            let level = if line.contains("[unstable(") {
                Status::Unstable
            } else if line.contains("[stable(") {
                Status::Stable
            } else {
                continue;
            };
            let feature_name = match find_attr_val(line, "feature") {
                Some(name) => name,
                None => {
                    err("malformed stability attribute");
                    continue;
                }
            };
            let since = match find_attr_val(line, "since") {
                Some(name) => name,
                None if level == Status::Stable => {
                    err("malformed stability attribute");
                    continue;
                }
                None => "None",
            };

            if features.contains_key(feature_name) {
                err("duplicating a lang feature");
            }
            if let Some(ref s) = lib_features.get(feature_name) {
                if s.level != level {
                    err("different stability level than before");
                }
                if s.since != since {
                    err("different `since` than before");
                }
                continue;
            }
            lib_features.insert(feature_name.to_owned(),
                                Feature {
                                    level: level,
                                    since: since.to_owned(),
                                    has_gate_test: false,
                                });
        }
    });

    super::walk(&path.join("test/compile-fail"),
                &mut |path| super::filter_dirs(path),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        if !filename.ends_with(".rs") || filename == "features.rs" ||
           filename == "diagnostic_list.rs" {
            return;
        }

        let filen_underscore = filename.replace("-","_").replace(".rs","");
        test_filen_gate(&filen_underscore, &mut features);

        contents.truncate(0);
        t!(t!(File::open(&file), &file).read_to_string(&mut contents));

        for (i, line) in contents.lines().enumerate() {
            let mut err = |msg: &str| {
                println!("{}:{}: {}", file.display(), i + 1, msg);
                *bad = true;
            };

            let gate_test_str = "gate-test-";

            if !line.contains(gate_test_str) {
                continue;
            }

            let feature_name = match line.find(gate_test_str) {
                Some(i) => {
                    &line[i+gate_test_str.len()..line[i+1..].find(' ').unwrap_or(line.len())]
                },
                None => continue,
            };
            let found_feature = features.get_mut(feature_name)
                                        .map(|v| { v.has_gate_test = true; () })
                                        .is_some();

            let found_lib_feature = features.get_mut(feature_name)
                                            .map(|v| { v.has_gate_test = true; () })
                                            .is_some();

            if !(found_feature || found_lib_feature) {
                err(&format!("gate-test test found referencing a nonexistent feature '{}'",
                             feature_name));
            }
        }
    });

    // FIXME get this whitelist empty.
    let whitelist = vec![
        "abi_ptx", "simd", "safe_suggestion", "macro_reexport",
        "more_struct_aliases", "static_recursion", "reflect",
        "quote", "cfg_target_has_atomic", "custom_attribute",
        "default_type_parameter_fallback", "pushpop_unsafe",
        "use_extern_macros", "staged_api", "const_indexing",
        "unboxed_closures", "stmt_expr_attributes",
        "cfg_target_thread_local", "unwind_attributes",
        "inclusive_range_syntax"
    ];

    // Only check the number of lang features.
    // Obligatory testing for library features is dumb.
    let gate_untested = features.iter()
                                .filter(|&(_, f)| f.level == Status::Unstable)
                                .filter(|&(_, f)| !f.has_gate_test)
                                .filter(|&(n, _)| !whitelist.contains(&n.as_str()))
                                .collect::<Vec<_>>();

    for &(name, _) in gate_untested.iter() {
        println!("Expected a gate test for the feature '{}'.", name);
        println!("Hint: create a file named 'feature-gate-{}.rs' in the compile-fail\
                \n      test suite, with its failures due to missing usage of\
                \n      #![feature({})].", name, name);
        println!("Hint: If you already have such a test and don't want to rename it,\
                \n      you can also add a // gate-test-{} line to the test file.",
                 name);
    }

    if gate_untested.len() > 0 {
        println!("Found {} features without a gate test.", gate_untested.len());
        *bad = true;
    }

    if *bad {
        return;
    }

    let mut lines = Vec::new();
    for (name, feature) in features.iter() {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lang",
                           feature.level,
                           feature.since));
    }
    for (name, feature) in lib_features {
        lines.push(format!("{:<32} {:<8} {:<12} {:<8}",
                           name,
                           "lib",
                           feature.level,
                           feature.since));
    }

    lines.sort();
    for line in lines {
        println!("* {}", line);
    }
}

fn find_attr_val<'a>(line: &'a str, attr: &str) -> Option<&'a str> {
    line.find(attr)
        .and_then(|i| line[i..].find('"').map(|j| i + j + 1))
        .and_then(|i| line[i..].find('"').map(|j| (i, i + j)))
        .map(|(i, j)| &line[i..j])
}

fn test_filen_gate(filen_underscore: &str,
                   features: &mut HashMap<String, Feature>) -> bool {
    if filen_underscore.starts_with("feature_gate") {
        for (n, f) in features.iter_mut() {
            if filen_underscore == format!("feature_gate_{}", n) {
                f.has_gate_test = true;
                return true;
            }
        }
    }
    return false;
}

fn collect_lang_features(path: &Path) -> HashMap<String, Feature> {
    let mut contents = String::new();
    t!(t!(File::open(path)).read_to_string(&mut contents));

    contents.lines()
        .filter_map(|line| {
            let mut parts = line.trim().split(",");
            let level = match parts.next().map(|l| l.trim().trim_left_matches('(')) {
                Some("active") => Status::Unstable,
                Some("removed") => Status::Removed,
                Some("accepted") => Status::Stable,
                _ => return None,
            };
            let name = parts.next().unwrap().trim();
            let since = parts.next().unwrap().trim().trim_matches('"');
            Some((name.to_owned(),
                Feature {
                    level: level,
                    since: since.to_owned(),
                    has_gate_test: false,
                }))
        })
        .collect()
}
<|endoftext|>


<commit_before>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::fmt;
use std::net::{TcpListener, TcpStream, SocketAddr};
use std::sync::{Arc, RwLock, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;

use time::Duration;

use transport::{Result, Transport};
use transport::cipher::Cipher;
use transport::direct::{Balancer, Connection, ConnectionMap, Link, Tracker, ServiceMap};
use transport::direct::tracker::Statistic;

use node::{ID, request};

pub struct Direct {
    join_handle: RwLock<Option<thread::JoinHandle<()>>>,
    running: Arc<AtomicBool>,
    local_address: SocketAddr,
    public_address: SocketAddr,
    cipher: Arc<Box<Cipher>>,
    connections: Arc<ConnectionMap>,
    services: Arc<ServiceMap>,
    tracker: Arc<Tracker>,
}

impl Direct {
    pub fn new(cipher: Box<Cipher>,
               balancer: Box<Balancer>,
               local_address: SocketAddr,
               public_address: Option<SocketAddr>,
               request_timeout: Option<Duration>)
               -> Direct {

        let statistic = Arc::new(Statistic::new());
        balancer.assign_statistic(statistic.clone());

        Direct {
            join_handle: RwLock::new(None),
            running: Arc::new(AtomicBool::new(false)),
            local_address: local_address,
            public_address: public_address.unwrap_or(local_address),
            cipher: Arc::new(cipher),
            connections: Arc::new(ConnectionMap::new()),
            services: Arc::new(ServiceMap::new(balancer)),
            tracker: Arc::new(Tracker::new(statistic.clone(), request_timeout)),
        }
    }

    fn unbind(&mut self) -> Result<()> {
        self.running.store(false, Ordering::SeqCst);
        if let Some(join_handle) = self.join_handle.write().unwrap().take() {
            // connect to local address to enable the thread to escape the accept loop.
            try!(TcpStream::connect(self.local_address));
            join_handle.join().unwrap();
        }
        Ok(())
    }
}

impl Transport for Direct {
    fn bind(&self, node_id: ID) -> Result<()> {
        let tcp_listener = try!(TcpListener::bind(self.local_address));

        let public_address = self.public_address;
        let running_clone = self.running.clone();
        let cipher_clone = self.cipher.clone();
        let connections_clone = self.connections.clone();
        let services_clone = self.services.clone();
        let tracker_clone = self.tracker.clone();
        *self.join_handle.write().unwrap() = Some(thread::spawn(move || {
            running_clone.store(true, Ordering::SeqCst);
            for stream in tcp_listener.incoming() {
                if !running_clone.load(Ordering::SeqCst) {
                    break;
                }

                let stream = stream.unwrap();
                let peers = &connections_clone.id_public_address_pairs();
                let mut connection = Connection::new_inbound(stream,
                                                             cipher_clone.clone(),
                                                             node_id,
                                                             public_address,
                                                             peers)
                                         .unwrap();

                set_up(&mut connection, &services_clone, &tracker_clone);

                connection.send_services(&services_clone.local_service_names())
                          .unwrap();

                info!("{}: inbound {}", node_id, connection);
                connections_clone.add(connection).unwrap();
            }
        }));

        Ok(())
    }

    fn join(&self, address: SocketAddr, node_id: ID) -> Result<()> {
        let (tx, rx) = mpsc::channel();
        let mut pending_peers_count = 1;
        tx.send(vec![(ID::new_random(), address)]).unwrap();

        while pending_peers_count > 0 {
            let peers = rx.recv().unwrap();

            for peer in peers {
                let (peer_node_id, peer_public_address) = peer;
                if self.connections.contains_key(&peer_node_id) {
                    continue;
                }

                pending_peers_count += 1;

                let stream = try!(TcpStream::connect(peer_public_address));
                let (mut connection, peers) = try!(Connection::new_outbound(stream,
                                                                            self.cipher.clone(),
                                                                            node_id,
                                                                            self.public_address));
                tx.send(peers).unwrap();

                set_up(&mut connection, &self.services, &self.tracker);

                try!(connection.send_services(&self.services.local_service_names()));

                info!("{}: outbound {}", node_id, connection);
                self.connections.add(connection).unwrap();
            }

            pending_peers_count -= 1;
        }

        Ok(())
    }

    fn connection_count(&self) -> usize {
        self.connections.len()
    }

    fn register(&self, name: &str, f: Box<request::Handler>) -> Result<()> {
        try!(self.services.insert_local(name, f));

        self.connections.send_services(&self.services.local_service_names()).unwrap();

        Ok(())
    }

    fn deregister(&self, name: &str) -> Result<()> {
        try!(self.services.remove_local(name));
        Ok(())
    }

    fn service_count(&self) -> usize {
        self.services.len()
    }

    fn request(&self, name: &str, data: &[u8]) -> request::Response {
        self.services.select(name,
                             |handler| {
                                 let (request_id, _) = self.tracker
                                                           .begin(name, &Link::Local);
                                 let response = handler(data);
                                 self.tracker.end(request_id, None).unwrap();
                                 response
                             },
                             |peer_node_id| {
                                 let (request_id, repsonse_rx) =
                                     self.tracker
                                         .begin(name, &Link::Remote(peer_node_id));
                                 self.connections
                                     .send_request(&peer_node_id, request_id, name, data)
                                     .unwrap();
                                 repsonse_rx.recv().unwrap()
                             })
    }
}

impl fmt::Display for Direct {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "(Direct transport {} connections {} services)",
               self.connection_count(),
               self.service_count())
    }
}

impl Drop for Direct {
    fn drop(&mut self) {
        self.unbind().unwrap();
    }
}

fn set_up(connection: &mut Connection, services: &Arc<ServiceMap>, tracker: &Arc<Tracker>) {
    let services_clone = services.clone();
    connection.set_on_services(Box::new(move |peer_node_id, services| {
        for service in services {
            services_clone.insert_remote(&service, peer_node_id).unwrap();
        }
    }));

    let services_clone = services.clone();
    connection.set_on_request(Box::new(move |name, data| {
        services_clone.select_local(name, |handler| handler(data))
    }));

    let tracker_clone = tracker.clone();
    connection.set_on_response(Box::new(move |request_id, response| {
        tracker_clone.end(request_id, Some(response)).unwrap();
    }));

    let services_clone = services.clone();
    connection.set_on_drop(Box::new(move |peer_node_id| {
        services_clone.remove_remote(&peer_node_id);
    }));
}
<commit_msg>fixed little bug in tracker<commit_after>// Copyright 2015 The Delix Project Authors. See the AUTHORS file at the top level directory.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

use std::fmt;
use std::net::{TcpListener, TcpStream, SocketAddr};
use std::sync::{Arc, RwLock, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;

use time::Duration;

use transport::{Result, Transport};
use transport::cipher::Cipher;
use transport::direct::{Balancer, Connection, ConnectionMap, Link, Tracker, ServiceMap};
use transport::direct::tracker::Statistic;

use node::{ID, request};

pub struct Direct {
    join_handle: RwLock<Option<thread::JoinHandle<()>>>,
    running: Arc<AtomicBool>,
    local_address: SocketAddr,
    public_address: SocketAddr,
    cipher: Arc<Box<Cipher>>,
    connections: Arc<ConnectionMap>,
    services: Arc<ServiceMap>,
    tracker: Arc<Tracker>,
}

impl Direct {
    pub fn new(cipher: Box<Cipher>,
               balancer: Box<Balancer>,
               local_address: SocketAddr,
               public_address: Option<SocketAddr>,
               request_timeout: Option<Duration>)
               -> Direct {

        let statistic = Arc::new(Statistic::new());
        balancer.assign_statistic(statistic.clone());

        Direct {
            join_handle: RwLock::new(None),
            running: Arc::new(AtomicBool::new(false)),
            local_address: local_address,
            public_address: public_address.unwrap_or(local_address),
            cipher: Arc::new(cipher),
            connections: Arc::new(ConnectionMap::new()),
            services: Arc::new(ServiceMap::new(balancer)),
            tracker: Arc::new(Tracker::new(statistic.clone(), request_timeout)),
        }
    }

    fn unbind(&mut self) -> Result<()> {
        self.running.store(false, Ordering::SeqCst);
        if let Some(join_handle) = self.join_handle.write().unwrap().take() {
            // connect to local address to enable the thread to escape the accept loop.
            try!(TcpStream::connect(self.local_address));
            join_handle.join().unwrap();
        }
        Ok(())
    }
}

impl Transport for Direct {
    fn bind(&self, node_id: ID) -> Result<()> {
        let tcp_listener = try!(TcpListener::bind(self.local_address));

        let public_address = self.public_address;
        let running_clone = self.running.clone();
        let cipher_clone = self.cipher.clone();
        let connections_clone = self.connections.clone();
        let services_clone = self.services.clone();
        let tracker_clone = self.tracker.clone();
        *self.join_handle.write().unwrap() = Some(thread::spawn(move || {
            running_clone.store(true, Ordering::SeqCst);
            for stream in tcp_listener.incoming() {
                if !running_clone.load(Ordering::SeqCst) {
                    break;
                }

                let stream = stream.unwrap();
                let peers = &connections_clone.id_public_address_pairs();
                let mut connection = Connection::new_inbound(stream,
                                                             cipher_clone.clone(),
                                                             node_id,
                                                             public_address,
                                                             peers)
                                         .unwrap();

                set_up(&mut connection, &services_clone, &tracker_clone);

                connection.send_services(&services_clone.local_service_names())
                          .unwrap();

                info!("{}: inbound {}", node_id, connection);
                connections_clone.add(connection).unwrap();
            }
        }));

        Ok(())
    }

    fn join(&self, address: SocketAddr, node_id: ID) -> Result<()> {
        let (tx, rx) = mpsc::channel();
        let mut pending_peers_count = 1;
        tx.send(vec![(ID::new_random(), address)]).unwrap();

        while pending_peers_count > 0 {
            let peers = rx.recv().unwrap();

            for peer in peers {
                let (peer_node_id, peer_public_address) = peer;
                if self.connections.contains_key(&peer_node_id) {
                    continue;
                }

                pending_peers_count += 1;

                let stream = try!(TcpStream::connect(peer_public_address));
                let (mut connection, peers) = try!(Connection::new_outbound(stream,
                                                                            self.cipher.clone(),
                                                                            node_id,
                                                                            self.public_address));
                tx.send(peers).unwrap();

                set_up(&mut connection, &self.services, &self.tracker);

                try!(connection.send_services(&self.services.local_service_names()));

                info!("{}: outbound {}", node_id, connection);
                self.connections.add(connection).unwrap();
            }

            pending_peers_count -= 1;
        }

        Ok(())
    }

    fn connection_count(&self) -> usize {
        self.connections.len()
    }

    fn register(&self, name: &str, f: Box<request::Handler>) -> Result<()> {
        try!(self.services.insert_local(name, f));

        self.connections.send_services(&self.services.local_service_names()).unwrap();

        Ok(())
    }

    fn deregister(&self, name: &str) -> Result<()> {
        try!(self.services.remove_local(name));
        Ok(())
    }

    fn service_count(&self) -> usize {
        self.services.len()
    }

    fn request(&self, name: &str, data: &[u8]) -> request::Response {
        self.services.select(name,
                             |handler| {
                                 let (request_id, response_rx) = self.tracker
                                                                     .begin(name, &Link::Local);
                                 let response = handler(data);
                                 self.tracker.end(request_id, None).unwrap();
                                 drop(response_rx);
                                 response
                             },
                             |peer_node_id| {
                                 let (request_id, repsonse_rx) =
                                     self.tracker
                                         .begin(name, &Link::Remote(peer_node_id));
                                 self.connections
                                     .send_request(&peer_node_id, request_id, name, data)
                                     .unwrap();
                                 repsonse_rx.recv().unwrap()
                             })
    }
}

impl fmt::Display for Direct {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "(Direct transport {} connections {} services)",
               self.connection_count(),
               self.service_count())
    }
}

impl Drop for Direct {
    fn drop(&mut self) {
        self.unbind().unwrap();
    }
}

fn set_up(connection: &mut Connection, services: &Arc<ServiceMap>, tracker: &Arc<Tracker>) {
    let services_clone = services.clone();
    connection.set_on_services(Box::new(move |peer_node_id, services| {
        for service in services {
            services_clone.insert_remote(&service, peer_node_id).unwrap();
        }
    }));

    let services_clone = services.clone();
    connection.set_on_request(Box::new(move |name, data| {
        services_clone.select_local(name, |handler| handler(data))
    }));

    let tracker_clone = tracker.clone();
    connection.set_on_response(Box::new(move |request_id, response| {
        tracker_clone.end(request_id, Some(response)).unwrap();
    }));

    let services_clone = services.clone();
    connection.set_on_drop(Box::new(move |peer_node_id| {
        services_clone.remove_remote(&peer_node_id);
    }));
}
<|endoftext|>


<commit_before>use DocId;
use Score;
use collector::Collector;
use docset::{DocSet, SkipResult};
use common::BitSet;
use std::ops::DerefMut;
use downcast;

/// Scored set of documents matching a query within a specific segment.
///
/// See [`Query`](./trait.Query.html).
pub trait Scorer: downcast::Any + DocSet + 'static {
    /// Returns the score.
    ///
    /// This method will perform a bit of computation and is not cached.
    fn score(&mut self) -> Score;

    /// Consumes the complete `DocSet` and
    /// push the scored documents to the collector.
    fn collect(&mut self, collector: &mut Collector) {
        while self.advance() {
            collector.collect(self.doc(), self.score());
        }
    }
}

#[allow(missing_docs)]
mod downcast_impl {
    downcast!(super::Scorer);
}

impl Scorer for Box<Scorer> {
    fn score(&mut self) -> Score {
        self.deref_mut().score()
    }

    fn collect(&mut self, collector: &mut Collector) {
        let scorer = self.deref_mut();
        scorer.collect(collector);
    }
}

/// `EmptyScorer` is a dummy `Scorer` in which no document matches.
///
/// It is useful for tests and handling edge cases.
pub struct EmptyScorer;

impl DocSet for EmptyScorer {
    fn advance(&mut self) -> bool {
        false
    }

    fn doc(&self) -> DocId {
        DocId::max_value()
    }

    fn size_hint(&self) -> u32 {
        0
    }
}

impl Scorer for EmptyScorer {
    fn score(&mut self) -> Score {
        0f32
    }
}

/// Wraps a `DocSet` and simply returns a constant `Scorer`.
/// The `ConstScorer` is useful if you have a `DocSet` where
/// you needed a scorer.
///
/// The `ConstScorer`'s constant score can be set
/// by calling `.set_score(...)`.
pub struct ConstScorer<TDocSet: DocSet> {
    docset: TDocSet,
    score: Score,
}

impl<TDocSet: DocSet> ConstScorer<TDocSet> {
    /// Creates a new `ConstScorer`.
    pub fn new(docset: TDocSet) -> ConstScorer<TDocSet> {
        ConstScorer {
            docset,
            score: 1f32,
        }
    }

    /// Sets the constant score to a different value.
    pub fn set_score(&mut self, score: Score) {
        self.score = score;
    }
}

impl<TDocSet: DocSet> DocSet for ConstScorer<TDocSet> {
    fn advance(&mut self) -> bool {
        self.docset.advance()
    }

    fn skip_next(&mut self, target: DocId) -> SkipResult {
        self.docset.skip_next(target)
    }

    fn fill_buffer(&mut self, buffer: &mut [DocId]) -> usize {
        self.docset.fill_buffer(buffer)
    }

    fn doc(&self) -> DocId {
        self.docset.doc()
    }

    fn size_hint(&self) -> u32 {
        self.docset.size_hint()
    }

    fn append_to_bitset(&mut self, bitset: &mut BitSet) {
        self.docset.append_to_bitset(bitset);
    }
}

impl<TDocSet: DocSet + 'static> Scorer for ConstScorer<TDocSet> {
    fn score(&mut self) -> Score {
        1f32
    }
}
<commit_msg>Added unit test<commit_after>use DocId;
use Score;
use collector::Collector;
use docset::{DocSet, SkipResult};
use common::BitSet;
use std::ops::DerefMut;
use downcast;

/// Scored set of documents matching a query within a specific segment.
///
/// See [`Query`](./trait.Query.html).
pub trait Scorer: downcast::Any + DocSet + 'static {
    /// Returns the score.
    ///
    /// This method will perform a bit of computation and is not cached.
    fn score(&mut self) -> Score;

    /// Consumes the complete `DocSet` and
    /// push the scored documents to the collector.
    fn collect(&mut self, collector: &mut Collector) {
        while self.advance() {
            collector.collect(self.doc(), self.score());
        }
    }
}

#[allow(missing_docs)]
mod downcast_impl {
    downcast!(super::Scorer);
}

impl Scorer for Box<Scorer> {
    fn score(&mut self) -> Score {
        self.deref_mut().score()
    }

    fn collect(&mut self, collector: &mut Collector) {
        let scorer = self.deref_mut();
        scorer.collect(collector);
    }
}

/// `EmptyScorer` is a dummy `Scorer` in which no document matches.
///
/// It is useful for tests and handling edge cases.
pub struct EmptyScorer;

impl DocSet for EmptyScorer {
    fn advance(&mut self) -> bool {
        false
    }

    fn doc(&self) -> DocId {
        panic!("You may not call .doc() on a scorer \
        where the last call to advance() did not return true.");
    }

    fn size_hint(&self) -> u32 {
        0
    }
}

impl Scorer for EmptyScorer {
    fn score(&mut self) -> Score {
        0f32
    }
}

/// Wraps a `DocSet` and simply returns a constant `Scorer`.
/// The `ConstScorer` is useful if you have a `DocSet` where
/// you needed a scorer.
///
/// The `ConstScorer`'s constant score can be set
/// by calling `.set_score(...)`.
pub struct ConstScorer<TDocSet: DocSet> {
    docset: TDocSet,
    score: Score,
}

impl<TDocSet: DocSet> ConstScorer<TDocSet> {
    /// Creates a new `ConstScorer`.
    pub fn new(docset: TDocSet) -> ConstScorer<TDocSet> {
        ConstScorer {
            docset,
            score: 1f32,
        }
    }

    /// Sets the constant score to a different value.
    pub fn set_score(&mut self, score: Score) {
        self.score = score;
    }
}

impl<TDocSet: DocSet> DocSet for ConstScorer<TDocSet> {
    fn advance(&mut self) -> bool {
        self.docset.advance()
    }

    fn skip_next(&mut self, target: DocId) -> SkipResult {
        self.docset.skip_next(target)
    }

    fn fill_buffer(&mut self, buffer: &mut [DocId]) -> usize {
        self.docset.fill_buffer(buffer)
    }

    fn doc(&self) -> DocId {
        self.docset.doc()
    }

    fn size_hint(&self) -> u32 {
        self.docset.size_hint()
    }

    fn append_to_bitset(&mut self, bitset: &mut BitSet) {
        self.docset.append_to_bitset(bitset);
    }
}

impl<TDocSet: DocSet + 'static> Scorer for ConstScorer<TDocSet> {
    fn score(&mut self) -> Score {
        1f32
    }
}

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

    #[test]
    fn test_empty_scorer() {
        let mut empty_scorer = EmptyScorer;
        assert!(!empty_scorer.advance());
    }

    #[test]
    #[should_panic]
    fn test_empty_scorer_panic_on_doc_call() {
        EmptyScorer.doc();
    }
}
<|endoftext|>


<commit_before>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;

use hlua::any::AnyLuaValue;
use convert::{ToTable, FromTable, ConverterError};

use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

mod types;
pub use self::types::*; // Export constants too

#[cfg(test)]
mod tests;

pub type RegMap = HashMap<String, RegistryValue>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> =
        RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq, Eq)]
pub enum RegistryError {
    /// The value in the registry could not be parsed
    InvalidLua(ConverterError),
    /// The registry key was not found
    KeyNotFound
}

/// Acquires a read lock on the registry.
pub fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().unwrap()
}

/// Acquires a write lock on the registry.
pub fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().unwrap()
}

/// Gets a Lua object from a registry key
pub fn get_lua<K>(name: &K) -> Option<(AccessFlags, Arc<AnyLuaValue>)>
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("get_lua: {}", *name);
    let reg = read_lock();
    reg.get(name).map(|val| (val.flags(), val.get_lua()))
}

/// Gets an object from the registry, decoding its internal Lua
/// representation.
pub fn get<K, T>(name: &K) -> Result<(AccessFlags, T), RegistryError>
    where T: FromTable, String: Borrow<K>, K: Hash + Eq + Display {
    if let Some(lua_pair) = get_lua(name) {
        let (access, lua_arc) = lua_pair;
        // Ultimately, values must be cloned out of the registry as well
        match T::from_lua_table(lua_arc.deref().clone()) {
            Ok(val) => Ok((access, val)),
            Err(e) => Err(RegistryError::InvalidLua(e))
        }
    }
    else {
        Err(RegistryError::KeyNotFound)
    }
}

/// Set a key in the registry to a particular value
pub fn set<T: ToTable>(key: String, flags: AccessFlags, val: T) {
    trace!("set: {:?} {}", flags, key);
    let regvalue = RegistryValue::new(flags, val);
    let mut write_reg = write_lock();
    write_reg.insert(key, regvalue);
}

/// Whether this map contains a key
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let read_reg = read_lock();
    read_reg.contains_key(key)
}
<commit_msg>I lied, found some more unused methods. Actual last ones (not including lua/ dir)<commit_after>//! way-cooler registry.

use std::ops::Deref;
use std::cmp::Eq;
use std::fmt::Display;
use std::hash::Hash;
use std::borrow::Borrow;

use hlua::any::AnyLuaValue;
use convert::{ToTable, FromTable, ConverterError};

use std::collections::HashMap;
use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard};

mod types;
pub use self::types::*; // Export constants too

#[cfg(test)]
mod tests;

pub type RegMap = HashMap<String, RegistryValue>;

lazy_static! {
    /// Registry variable for the registry
    static ref REGISTRY: RwLock<RegMap> =
        RwLock::new(HashMap::new());
}

/// Error types that can happen
#[derive(Debug, PartialEq, Eq)]
pub enum RegistryError {
    /// The value in the registry could not be parsed
    InvalidLua(ConverterError),
    /// The registry key was not found
    KeyNotFound
}

/// Acquires a read lock on the registry.
pub fn read_lock<'a>() -> RwLockReadGuard<'a, RegMap> {
    REGISTRY.read().unwrap()
}

/// Acquires a write lock on the registry.
pub fn write_lock<'a>() -> RwLockWriteGuard<'a, RegMap> {
    REGISTRY.write().unwrap()
}

/// Gets a Lua object from a registry key
pub fn get_lua<K>(name: &K) -> Option<(AccessFlags, Arc<AnyLuaValue>)>
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("get_lua: {}", *name);
    let reg = read_lock();
    reg.get(name).map(|val| (val.flags(), val.get_lua()))
}

/// Gets an object from the registry, decoding its internal Lua
/// representation.
#[allow(dead_code)]
pub fn get<K, T>(name: &K) -> Result<(AccessFlags, T), RegistryError>
    where T: FromTable, String: Borrow<K>, K: Hash + Eq + Display {
    if let Some(lua_pair) = get_lua(name) {
        let (access, lua_arc) = lua_pair;
        // Ultimately, values must be cloned out of the registry as well
        match T::from_lua_table(lua_arc.deref().clone()) {
            Ok(val) => Ok((access, val)),
            Err(e) => Err(RegistryError::InvalidLua(e))
        }
    }
    else {
        Err(RegistryError::KeyNotFound)
    }
}

/// Set a key in the registry to a particular value
#[allow(dead_code)]
pub fn set<T: ToTable>(key: String, flags: AccessFlags, val: T) {
    trace!("set: {:?} {}", flags, key);
    let regvalue = RegistryValue::new(flags, val);
    let mut write_reg = write_lock();
    write_reg.insert(key, regvalue);
}

/// Whether this map contains a key
#[allow(dead_code)]
pub fn contains_key<K>(key: &K) -> bool
where String: Borrow<K>, K: Hash + Eq + Display {
    trace!("contains_key: {}", *key);
    let read_reg = read_lock();
    read_reg.contains_key(key)
}
<|endoftext|>


<commit_before>pub use self::os::{idtype_t};
pub use self::os::{P_ALL};
pub use self::os::{P_PID};
pub use self::os::{P_PGID};
pub use self::os::{WCONTINUED};
pub use self::os::{WNOHANG};
pub use self::os::{WUNTRACED};
pub use self::os::{WEXITED};
pub use self::os::{WNOWAIT};
pub use self::os::{WSTOPPED};
pub use self::os::{WEXITSTATUS};
pub use self::os::{WIFCONTINUED};
pub use self::os::{WIFEXITED};
pub use self::os::{WIFSIGNALED};
pub use self::os::{WIFSTOPPED};
pub use self::os::{WSTOPSIG};
pub use self::os::{WTERMSIG};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn wait(status: &mut ::int_t) -> ::sys::types::pid_t {
    extern { fn wait(status: *mut ::int_t) -> ::sys::types::pid_t; }
    unsafe { wait(status as *mut _) }
}

pub fn waitpid(pid: ::sys::types::pid_t, stat_loc: &mut ::int_t,
               options: ::int_t) -> ::sys::types::pid_t {
    extern { fn waitpid(pid: ::sys::types::pid_t, stat_loc: *mut ::int_t,
                        options: ::int_t) -> ::sys::types::pid_t; }
    unsafe { waitpid(pid, stat_loc as *mut _, options) }
}

pub fn waitid(idtype: idtype_t, id: ::sys::types::id_t, infop: &mut ::signal::siginfo_t,
              options: ::int_t) -> ::int_t {
    extern { fn waitid(idtype: idtype_t, id: ::sys::types::id_t,
                       infop: *mut ::signal::siginfo_t, options: ::int_t) -> ::int_t; }
    unsafe { waitid(idtype, id, infop as *mut _, options) }
}
<commit_msg>sys/wait.h<commit_after>pub use self::os::{idtype_t};
pub use self::os::{P_ALL};
pub use self::os::{P_PID};
pub use self::os::{P_PGID};
pub use self::os::{WCONTINUED};
pub use self::os::{WNOHANG};
pub use self::os::{WUNTRACED};
pub use self::os::{WEXITED};
pub use self::os::{WNOWAIT};
pub use self::os::{WSTOPPED};
pub use self::os::{WEXITSTATUS};
pub use self::os::{WIFCONTINUED};
pub use self::os::{WIFEXITED};
pub use self::os::{WIFSIGNALED};
pub use self::os::{WIFSTOPPED};
pub use self::os::{WSTOPSIG};
pub use self::os::{WTERMSIG};

use {int_t};
use sys::types::{pid_t, id_t};
use signal::{siginfo_t};

#[cfg(target_os = "linux")]
#[path = "linux/mod.rs"]
mod os;

pub fn wait(status: &mut int_t) -> pid_t {
    extern { fn wait(status: *mut int_t) -> pid_t; }
    unsafe { wait(status as *mut _) }
}

pub fn waitpid(pid: pid_t, stat_loc: &mut int_t, options: int_t) -> pid_t {
    extern { fn waitpid(pid: pid_t, stat_loc: *mut int_t,
                        options: int_t) -> pid_t; }
    unsafe { waitpid(pid, stat_loc as *mut _, options) }
}

pub fn waitid(idtype: idtype_t, id: id_t, infop: &mut siginfo_t,
              options: int_t) -> int_t {
    extern { fn waitid(idtype: idtype_t, id: id_t,
                       infop: *mut siginfo_t, options: int_t) -> int_t; }
    unsafe { waitid(idtype, id, infop as *mut _, options) }
}
<|endoftext|>


<commit_before>
use CreationError;
use GlAttributes;
use GlProfile;
use GlRequest;
use PixelFormatRequirements;
use ReleaseBehavior;
use cocoa::appkit::*;
use cocoa::base::nil;

pub fn get_gl_profile<T>(
    opengl: &GlAttributes<&T>
) -> Result<NSOpenGLPFAOpenGLProfiles, CreationError> {
    let version = opengl.version.to_gl_version();
    // first, compatibility profile support is strict
    if opengl.profile == Some(GlProfile::Compatibility) {
        // Note: we are not using ranges because of a rust bug that should be fixed here:
        // https://github.com/rust-lang/rust/pull/27050
        if version.unwrap_or((2, 1)) < (3, 2) {
            Ok(NSOpenGLProfileVersionLegacy)
        } else {
            Err(CreationError::OpenGlVersionNotSupported)
        }
    } else if let Some(v) = version {
        // second, process exact requested version, if any
        if v < (3, 2) {
            Err(CreationError::OpenGlVersionNotSupported)
        } else if v == (3, 2) {
            Ok(NSOpenGLProfileVersion3_2Core)
        } else {
            Ok(NSOpenGLProfileVersion4_1Core)
        }
    } else if let GlRequest::Latest = opengl.version {
        // now, find the latest supported version automatically
        let mut attributes = vec![
            // Note: we assume here that non-accelerated contexts don't care
            NSOpenGLPFAAccelerated as u32,
            NSOpenGLPFAOpenGLProfile as u32,
            0, // this is where we put the test profile
            0,
        ];
        for &profile in &[NSOpenGLProfileVersion4_1Core, NSOpenGLProfileVersion3_2Core] {
            attributes[2] = profile as u32;
            let id = unsafe {
                NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes)
            };
            if id != nil {
                unsafe { msg_send![id, release] }
                return Ok(profile);
            }
        }
        // nothing else to do
        Ok(NSOpenGLProfileVersionLegacy)
    } else {
        Err(CreationError::OpenGlVersionNotSupported)
    }
}

pub fn build_nsattributes(
    pf_reqs: &PixelFormatRequirements, profile: NSOpenGLPFAOpenGLProfiles
) -> Result<Vec<u32>, CreationError> {
    // NOTE: OS X no longer has the concept of setting individual
    // color component's bit size. Instead we can only specify the
    // full color size and hope for the best. Another hiccup is that
    // `NSOpenGLPFAColorSize` also includes `NSOpenGLPFAAlphaSize`,
    // so we have to account for that as well.
    let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8);
    let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth;

    let mut attributes = vec![
        NSOpenGLPFAOpenGLProfile as u32, profile as u32,
        NSOpenGLPFAClosestPolicy as u32,
        NSOpenGLPFAColorSize as u32, color_depth as u32,
        NSOpenGLPFAAlphaSize as u32, alpha_depth as u32,
        NSOpenGLPFADepthSize as u32, pf_reqs.depth_bits.unwrap_or(24) as u32,
        NSOpenGLPFAStencilSize as u32, pf_reqs.stencil_bits.unwrap_or(8) as u32,
        NSOpenGLPFAAllowOfflineRenderers as u32,
    ];

    if let Some(true) = pf_reqs.hardware_accelerated {
        attributes.push(NSOpenGLPFAAccelerated as u32);
    }

    if let Some(true) = pf_reqs.double_buffer {
        attributes.push(NSOpenGLPFADoubleBuffer as u32);
    }

    if pf_reqs.release_behavior != ReleaseBehavior::Flush {
        return Err(CreationError::NoAvailablePixelFormat);
    }

    if pf_reqs.stereoscopy {
        unimplemented!();   // TODO:
    }

    if pf_reqs.float_color_buffer {
        attributes.push(NSOpenGLPFAColorFloat as u32);
    }

    if let Some(samples) = pf_reqs.multisampling {
        attributes.push(NSOpenGLPFAMultisample as u32);
        attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1);
        attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32);
    }

    // attribute list must be null terminated.
    attributes.push(0);

    Ok(attributes)
}
<commit_msg>[osx] default PF attribs to use double buffering (#971)<commit_after>
use CreationError;
use GlAttributes;
use GlProfile;
use GlRequest;
use PixelFormatRequirements;
use ReleaseBehavior;
use cocoa::appkit::*;
use cocoa::base::nil;

pub fn get_gl_profile<T>(
    opengl: &GlAttributes<&T>
) -> Result<NSOpenGLPFAOpenGLProfiles, CreationError> {
    let version = opengl.version.to_gl_version();
    // first, compatibility profile support is strict
    if opengl.profile == Some(GlProfile::Compatibility) {
        // Note: we are not using ranges because of a rust bug that should be fixed here:
        // https://github.com/rust-lang/rust/pull/27050
        if version.unwrap_or((2, 1)) < (3, 2) {
            Ok(NSOpenGLProfileVersionLegacy)
        } else {
            Err(CreationError::OpenGlVersionNotSupported)
        }
    } else if let Some(v) = version {
        // second, process exact requested version, if any
        if v < (3, 2) {
            Err(CreationError::OpenGlVersionNotSupported)
        } else if v == (3, 2) {
            Ok(NSOpenGLProfileVersion3_2Core)
        } else {
            Ok(NSOpenGLProfileVersion4_1Core)
        }
    } else if let GlRequest::Latest = opengl.version {
        // now, find the latest supported version automatically
        let mut attributes = vec![
            // Note: we assume here that non-accelerated contexts don't care
            NSOpenGLPFAAccelerated as u32,
            NSOpenGLPFAOpenGLProfile as u32,
            0, // this is where we put the test profile
            0,
        ];
        for &profile in &[NSOpenGLProfileVersion4_1Core, NSOpenGLProfileVersion3_2Core] {
            attributes[2] = profile as u32;
            let id = unsafe {
                NSOpenGLPixelFormat::alloc(nil).initWithAttributes_(&attributes)
            };
            if id != nil {
                unsafe { msg_send![id, release] }
                return Ok(profile);
            }
        }
        // nothing else to do
        Ok(NSOpenGLProfileVersionLegacy)
    } else {
        Err(CreationError::OpenGlVersionNotSupported)
    }
}

pub fn build_nsattributes(
    pf_reqs: &PixelFormatRequirements, profile: NSOpenGLPFAOpenGLProfiles
) -> Result<Vec<u32>, CreationError> {
    // NOTE: OS X no longer has the concept of setting individual
    // color component's bit size. Instead we can only specify the
    // full color size and hope for the best. Another hiccup is that
    // `NSOpenGLPFAColorSize` also includes `NSOpenGLPFAAlphaSize`,
    // so we have to account for that as well.
    let alpha_depth = pf_reqs.alpha_bits.unwrap_or(8);
    let color_depth = pf_reqs.color_bits.unwrap_or(24) + alpha_depth;

    let mut attributes = vec![
        NSOpenGLPFAOpenGLProfile as u32, profile as u32,
        NSOpenGLPFAClosestPolicy as u32,
        NSOpenGLPFAColorSize as u32, color_depth as u32,
        NSOpenGLPFAAlphaSize as u32, alpha_depth as u32,
        NSOpenGLPFADepthSize as u32, pf_reqs.depth_bits.unwrap_or(24) as u32,
        NSOpenGLPFAStencilSize as u32, pf_reqs.stencil_bits.unwrap_or(8) as u32,
        NSOpenGLPFAAllowOfflineRenderers as u32,
    ];

    if let Some(true) = pf_reqs.hardware_accelerated {
        attributes.push(NSOpenGLPFAAccelerated as u32);
    }

    // Note: according to Apple docs, not specifying `NSOpenGLPFADoubleBuffer`
    // equals to requesting a single front buffer, in which case most of the GL
    // renderers will show nothing, since they draw to GL_BACK.
    if pf_reqs.double_buffer != Some(false) {
        attributes.push(NSOpenGLPFADoubleBuffer as u32);
    }

    if pf_reqs.release_behavior != ReleaseBehavior::Flush {
        return Err(CreationError::NoAvailablePixelFormat);
    }

    if pf_reqs.stereoscopy {
        unimplemented!();   // TODO:
    }

    if pf_reqs.float_color_buffer {
        attributes.push(NSOpenGLPFAColorFloat as u32);
    }

    if let Some(samples) = pf_reqs.multisampling {
        attributes.push(NSOpenGLPFAMultisample as u32);
        attributes.push(NSOpenGLPFASampleBuffers as u32); attributes.push(1);
        attributes.push(NSOpenGLPFASamples as u32); attributes.push(samples as u32);
    }

    // attribute list must be null terminated.
    attributes.push(0);

    Ok(attributes)
}
<|endoftext|>