<commit_before>use std::collections::HashMap;
use std::io;
use std::rc::Rc;

use futures::{future, Future};
use recognizer::{Match, Router};
use tokio::{Service, NewService};

use endpoint;
use environment::PreparedEnv;
use http;

pub struct Route {
    pub method: http::Method,
    pub kind: Kind,
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Kind {
    Resource,
    Collection,
    Relationship,
}

#[derive(Clone)]
pub struct RoutingTable {
    table: Rc<HashMap<http::Method, Router<Handler>>>,
    env: PreparedEnv,
}

impl Service for RoutingTable {
    type Request = http::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Future = http::BoxFuture;

    fn call(&self, req: Self::Request) -> Self::Future {
        match self.recognize(&req) {
            Some(handle)    => {
                let id = handle.params.find("id").map(|s| s.to_owned());
                let req = endpoint::Request { req, env: self.env.new(), id };
                handle.handler.call(req)
            }
            None            => not_found()
        }
    }
}

impl NewService for RoutingTable {
    type Request = http::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Instance = Self;
    type Future = future::FutureResult<Self, io::Error>;

    fn new_service(&self) -> Self::Future {
        future::ok(self.clone())
    }
}

impl RoutingTable {
    fn recognize(&self, req: &http::Request) -> Option<Match<&Handler>> {
        self.table.get(req.method()).and_then(|router| {
            router.recognize(req.path()).ok()
        })
    }
}

#[derive(Default)]
pub struct RouteBuilder {
    table: HashMap<http::Method, Router<Handler>>,
}

impl RouteBuilder {
    pub fn add(&mut self, method: http::Method, path: String, handler: Handler) {
        self.table.entry(method).or_insert(Router::new()).add(&path, handler);
    }

    pub fn build(self, env: PreparedEnv) -> RoutingTable {
        RoutingTable { table: Rc::new(self.table), env }
    }
}

pub type Handler = Box<Service<Request = endpoint::Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>>;

pub fn not_found() -> http::BoxFuture {
    future::ok(http::Response::new().with_status(http::StatusCode::NotFound)).boxed()
}

pub fn resource_path(endpoint: &'static str) -> String {
    format!("{}/$id", endpoint)
}

pub fn path(kind: Kind, endpoint: &'static str, rel: Option<&'static str>) -> String {
    match kind {
        Kind::Collection    => endpoint.to_owned(),
        Kind::Resource      => format!("{}/$id", endpoint),
        Kind::Relationship  => format!("{}/$id/{}", endpoint, rel.unwrap())
    }
}

pub fn default_asset_handler(asset: &'static [u8], _: endpoint::Request) -> http::BoxFuture {
    Box::new(future::ok(http::Response::new()
                            .with_status(http::StatusCode::Ok)
                            .with_header(http::headers::ContentLength(asset.len() as u64))
                            .with_body(asset)))
}

pub struct AssetHandler<F> {
    pub handler: F,
    pub data: &'static [u8]
}

impl<F> Service for AssetHandler<F>
where
    F: Fn(&'static [u8], endpoint::Request) -> http::BoxFuture
{
    type Request = endpoint::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Future = http::BoxFuture;

    fn call(&self, req: Self::Request) -> Self::Future {
        (self.handler)(self.data, req)
    }
}
<commit_msg>Make routes work properly.<commit_after>use std::collections::HashMap;
use std::io;
use std::rc::Rc;

use futures::{future, Future};
use recognizer::{Match, Router};
use tokio::{Service, NewService};

use endpoint;
use environment::PreparedEnv;
use http;

pub struct Route {
    pub method: http::Method,
    pub kind: Kind,
}

#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Kind {
    Resource,
    Collection,
    Relationship,
}

#[derive(Clone)]
pub struct RoutingTable {
    table: Rc<HashMap<http::Method, Router<Handler>>>,
    env: PreparedEnv,
}

impl Service for RoutingTable {
    type Request = http::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Future = http::BoxFuture;

    fn call(&self, req: Self::Request) -> Self::Future {
        match self.recognize(&req) {
            Some(handle)    => {
                let id = handle.params.find("id").map(|s| s.to_owned());
                let req = endpoint::Request { req, env: self.env.new(), id };
                handle.handler.call(req)
            }
            None            => not_found()
        }
    }
}

impl NewService for RoutingTable {
    type Request = http::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Instance = Self;
    type Future = future::FutureResult<Self, io::Error>;

    fn new_service(&self) -> Self::Future {
        future::ok(self.clone())
    }
}

impl RoutingTable {
    fn recognize(&self, req: &http::Request) -> Option<Match<&Handler>> {
        self.table.get(req.method()).and_then(|router| {
            router.recognize(req.path()).ok()
        })
    }
}

#[derive(Default)]
pub struct RouteBuilder {
    table: HashMap<http::Method, Router<Handler>>,
}

impl RouteBuilder {
    pub fn add(&mut self, method: http::Method, path: String, handler: Handler) {
        self.table.entry(method).or_insert(Router::new()).add(&path, handler);
    }

    pub fn build(self, env: PreparedEnv) -> RoutingTable {
        RoutingTable { table: Rc::new(self.table), env }
    }
}

pub type Handler = Box<Service<Request = endpoint::Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>>;

pub fn not_found() -> http::BoxFuture {
    future::ok(http::Response::new().with_status(http::StatusCode::NotFound)).boxed()
}

pub fn resource_path(endpoint: &'static str) -> String {
    format!("{}/$id", endpoint)
}

pub fn path(kind: Kind, endpoint: &'static str, rel: Option<&'static str>) -> String {
    match kind {
        Kind::Collection    => endpoint.to_owned(),
        Kind::Resource      => format!("{}/:id", endpoint),
        Kind::Relationship  => format!("{}/:id/{}", endpoint, rel.unwrap())
    }
}

pub fn default_asset_handler(asset: &'static [u8], _: endpoint::Request) -> http::BoxFuture {
    Box::new(future::ok(http::Response::new()
                            .with_status(http::StatusCode::Ok)
                            .with_header(http::headers::ContentLength(asset.len() as u64))
                            .with_body(asset)))
}

pub struct AssetHandler<F> {
    pub handler: F,
    pub data: &'static [u8]
}

impl<F> Service for AssetHandler<F>
where
    F: Fn(&'static [u8], endpoint::Request) -> http::BoxFuture
{
    type Request = endpoint::Request;
    type Response = http::Response;
    type Error = http::Error;
    type Future = http::BoxFuture;

    fn call(&self, req: Self::Request) -> Self::Future {
        (self.handler)(self.data, req)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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 graphics;
use piston_window::*;

use geometry::{Point, Vector};
use turtle::{Turtle, TurtleProgram, TurtleCollectToNextForwardIterator};

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub trait WindowHandler<'a> {
    /// When the window is resized, we may need to plan to re-render.
    fn window_resized(&mut self);

    /// Render a frame.
    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32);
}

/// Renders a TurtleProgram in a PistonWindow.
pub fn run(program: &TurtleProgram, animate: u64) {

    let opengl = OpenGL::V3_2;
    let window: PistonWindow = WindowSettings::new("Fractal", [800, 600])
                                   .opengl(opengl)
                                   .exit_on_esc(true)
                                   .build()
                                   .unwrap_or_else(|e| panic!("Failed to build Window: {}", e));

    let mut window_handler: Box<WindowHandler> = match animate {
        0 => Box::new(DoubleBufferedWindowHandler::new()),
        _ => Box::new(DoubleBufferedAnimatedWindowHandler::new(animate)),
    };

    let mut frame_num: u32 = 0;
    let mut old_size: Size = Size {
        width: 0,
        height: 0,
    };
    for e in window {
        e.draw_2d(|context, gfx| {
            let size = e.size();
            // Size doesn't implement PartialEq, so we have to check ourselves.
            if size.width != old_size.width || size.height != old_size.height {
                println!("resized");
                old_size = size;
                window_handler.window_resized();
            }
            frame_num += 1;
            println!("Render frame {}, window: {:?}", frame_num, size);
            window_handler.render_frame(size, context, gfx, program, frame_num);
        });
        //     // Some(Event::Input(i)) => {
        //     //     match i {
        //     //         Input::Press(Button::Keyboard(k)) => {
        //     //             match k {
        //     //                 Key::Up => {}
        //     //                 Key::Down => {}
        //     //                 _ => {}
        //     //             }
        //     //         }
        //     //         _ => {}
        //     //     }
        //     // }
        //     _ => {}
        // }
    }
}

/// WindowHandler that renders an entire turtle program per-frame, and optimizes re-renders
/// by only rendering twice (once for each buffer).
#[derive(Debug)]
struct DoubleBufferedWindowHandler {
    /// Whether we need to re-render for double-buffered frames.
    redraw: [bool; 2],
}

impl DoubleBufferedWindowHandler {
    pub fn new() -> DoubleBufferedWindowHandler {
        DoubleBufferedWindowHandler { redraw: [true; 2] }
    }

    fn turtledraw(program: &TurtleProgram, turtle: &mut Turtle) {
        let init_turtle_steps = program.init_turtle();

        for action in init_turtle_steps {
            turtle.perform(action)
        }

        for action in program.turtle_program_iter() {
            turtle.perform(action)
        }
        turtle.up();
    }
}

impl<'a> WindowHandler<'a> for DoubleBufferedWindowHandler {
    fn window_resized(&mut self) {
        self.redraw[0] = true;
        self.redraw[1] = true;
    }

    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32) {
        let redraw = self.redraw[(frame_num % 2) as usize];
        if redraw {
            println!("Redrawing frame {}", frame_num % 2);
            clear(WHITE, gfx);

            let mut state = GlTurtleState::new();
            let mut turtle = GlTurtle::new(&mut state, gfx, window_size, context);
            DoubleBufferedWindowHandler::turtledraw(program, &mut turtle);

            println!("Done redrawing frame");
            self.redraw[(frame_num % 2) as usize] = false;
        }
    }
}

/// Internal state of the turtle.
#[derive(Clone, Debug)]
pub struct GlTurtleState {
    position: Point,
    angle: f64,
    down: bool,
}

impl GlTurtleState {
    pub fn new() -> GlTurtleState {
        GlTurtleState {
            position: Point { x: 0.0, y: 0.0 },
            angle: 0.0,
            down: true,
        }
    }
}

/// An implementation of a Turtle within an OpenGL (rather, a gfx) context.
pub struct GlTurtle<'a, G>
    where G: Graphics + 'a
{
    gfx: &'a mut G,
    window_size: Size,
    context: graphics::context::Context,

    state: &'a mut GlTurtleState,
}

impl<'a, G> GlTurtle<'a, G> where G: Graphics + 'a
{
    pub fn new(state: &'a mut GlTurtleState,
               gfx: &'a mut G,
               window_size: Size,
               context: graphics::context::Context)
               -> GlTurtle<'a, G> {
        GlTurtle {
            gfx: gfx,
            window_size: window_size,
            context: context,
            state: state,
        }
    }
}

impl<'a, G> Turtle for GlTurtle<'a, G> where G: Graphics + 'a
{
    fn forward(&mut self, distance: f64) {
        let old_pos = self.state.position;
        let new_pos = self.state.position.point_at(Vector {
            direction: self.state.angle,
            magnitude: distance,
        });

        if self.state.down {
            let screen_width = self.window_size.width;
            let screen_height = self.window_size.height;

            let startx = (screen_width / 4) as f64;
            let starty = (screen_height / 2) as f64;
            let endx = (3 * screen_width / 4) as f64;
            // let endy = (screen_height / 2) as f64;

            let linesize = (startx - endx).abs() as f64;

            let transform = self.context
                                .transform
                                .trans(startx, starty)
                                .zoom(linesize)
                                .flip_v()
                                .trans(0.0, 0.0);

            Line::new(BLACK, 0.5 / linesize).draw([old_pos.x, old_pos.y, new_pos.x, new_pos.y],
                                                  default_draw_state(),
                                                  transform,
                                                  self.gfx);
        }

        self.state.position = new_pos;
    }

    fn set_pos(&mut self, new_pos: Point) {
        self.state.position = new_pos;
    }

    fn set_rad(&mut self, new_rad: f64) {
        self.state.angle = new_rad;
    }

    fn turn_rad(&mut self, radians: f64) {
        use std::f64::consts::PI;
        self.state.angle = (self.state.angle + radians) % (2.0 * PI);
    }

    fn down(&mut self) {
        self.state.down = true;
    }

    fn up(&mut self) {
        self.state.down = false;
    }
}

/// WindowHandler that animates the rendering of the curve.
struct DoubleBufferedAnimatedWindowHandler<'a> {
    /// stored turtle state for each turtle. double-buffered means we need to animate the curve
    /// "twice".
    turtles: [GlTurtleState; 2],
    /// Two iterators.
    iters: [TurtleCollectToNextForwardIterator<'a>; 2],
    forwards_per_frame: u64,
    /// Whether we need to re-render for double-buffered frames.
    first_draw: [bool; 2],
    frame_is_first: bool,
    frame_is_second: bool,
}

use std::fmt;
impl<'a> fmt::Debug for DoubleBufferedAnimatedWindowHandler<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "DoubleBufferedAnimatedWindowHandler(turtles:{:?}, iters:<iters>, first_draw:{:?}, \
                frame_is_first:{}, frame_is_second:{})",
               self.turtles,
               self.first_draw,
               self.frame_is_first,
               self.frame_is_second)
    }
}

impl<'a> DoubleBufferedAnimatedWindowHandler<'a> {
    pub fn new(animate: u64) -> DoubleBufferedAnimatedWindowHandler<'a> {
        DoubleBufferedAnimatedWindowHandler {
            turtles: [GlTurtleState::new(), GlTurtleState::new()],
            iters: [TurtleCollectToNextForwardIterator::new_null_iter(),
                    TurtleCollectToNextForwardIterator::new_null_iter()],
            forwards_per_frame: animate,
            first_draw: [true, true],
            frame_is_first: true,
            frame_is_second: false,
        }
    }
}

impl<'a> WindowHandler<'a> for DoubleBufferedAnimatedWindowHandler<'a> {
    fn window_resized(&mut self) {
        self.first_draw[0] = true;
        self.first_draw[1] = true;
        self.frame_is_first = true;
        self.turtles[0] = GlTurtleState::new();
        self.turtles[1] = GlTurtleState::new();
    }

    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32) {
        let bufnum = (frame_num % 2) as usize;
        if self.first_draw[bufnum] {
            // If we are starting the animation, then we need to:
            // * clear the frame buffer
            // * initialize the turtle
            // * construct and store a program iterator for this buffer
            // * add an extra move to the second frame (to offset it's moves from the first
            //   frame)
            clear(WHITE, gfx);
            let mut turtle = GlTurtle::new(&mut self.turtles[bufnum], gfx, window_size, context);
            for action in program.init_turtle() {
                turtle.perform(action)
            }
            self.iters[bufnum] = program.turtle_program_iter().collect_to_next_forward();
            if self.frame_is_second {
                // if we are the second frame, then we need to stagger our buffer from
                // the first buffer.
                let one_move = self.iters[bufnum].next();
                if !one_move.is_none() {
                    for action in one_move.unwrap() {
                        turtle.perform(action)
                    }
                }
                self.frame_is_second = false;
            }
            self.first_draw[bufnum] = false;
        }

        let mut turtle = GlTurtle::new(&mut self.turtles[bufnum], gfx, window_size, context);
        for _ in 0..self.forwards_per_frame {
            // Make 2 moves per frame since we are double buffered.
            DoubleBufferedAnimatedWindowHandler::draw_one_move(&mut turtle,
                                                               &mut self.iters[bufnum]);
            DoubleBufferedAnimatedWindowHandler::draw_one_move(&mut turtle,
                                                               &mut self.iters[bufnum]);
        }

        if self.frame_is_first {
            self.frame_is_first = false;
            self.frame_is_second = true;
        }
    }
}

impl<'a> DoubleBufferedAnimatedWindowHandler<'a> {
    fn draw_one_move<G>(turtle: &mut GlTurtle<G>,
                        program_iter: &mut TurtleCollectToNextForwardIterator)
        where G: Graphics
    {
        let one_move = program_iter.next();
        if !one_move.is_none() {
            for action in one_move.unwrap() {
                turtle.perform(action)
            }
        }
    }
}
<commit_msg>Refactoring DoubleBufferedAnimatedWindowHandler::render_frame().<commit_after>// Copyright (c) 2015-2016 William (B.J.) Snow Orvis
//
// 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 graphics;
use piston_window::*;
use std::fmt;

use geometry::{Point, Vector};
use turtle::{Turtle, TurtleProgram, TurtleCollectToNextForwardIterator};

const WHITE: [f32; 4] = [1.0, 1.0, 1.0, 1.0];
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

pub trait WindowHandler<'a> {
    /// When the window is resized, we may need to plan to re-render.
    fn window_resized(&mut self);

    /// Render a frame.
    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32);
}

/// Renders a TurtleProgram in a PistonWindow.
pub fn run(program: &TurtleProgram, animate: u64) {

    let opengl = OpenGL::V3_2;
    let window: PistonWindow = WindowSettings::new("Fractal", [800, 600])
                                   .opengl(opengl)
                                   .exit_on_esc(true)
                                   .build()
                                   .unwrap_or_else(|e| panic!("Failed to build Window: {}", e));

    let mut window_handler: Box<WindowHandler> = match animate {
        0 => Box::new(DoubleBufferedWindowHandler::new()),
        _ => Box::new(DoubleBufferedAnimatedWindowHandler::new(animate)),
    };

    let mut frame_num: u32 = 0;
    let mut old_size: Size = Size {
        width: 0,
        height: 0,
    };
    for e in window {
        e.draw_2d(|context, gfx| {
            let size = e.size();
            // Size doesn't implement PartialEq, so we have to check ourselves.
            if size.width != old_size.width || size.height != old_size.height {
                println!("resized");
                old_size = size;
                window_handler.window_resized();
            }
            frame_num += 1;
            println!("Render frame {}, window: {:?}", frame_num, size);
            window_handler.render_frame(size, context, gfx, program, frame_num);
        });
        //     // Some(Event::Input(i)) => {
        //     //     match i {
        //     //         Input::Press(Button::Keyboard(k)) => {
        //     //             match k {
        //     //                 Key::Up => {}
        //     //                 Key::Down => {}
        //     //                 _ => {}
        //     //             }
        //     //         }
        //     //         _ => {}
        //     //     }
        //     // }
        //     _ => {}
        // }
    }
}

/// WindowHandler that renders an entire turtle program per-frame, and optimizes re-renders
/// by only rendering twice (once for each buffer).
#[derive(Debug)]
struct DoubleBufferedWindowHandler {
    /// Whether we need to re-render for double-buffered frames.
    redraw: [bool; 2],
}

impl DoubleBufferedWindowHandler {
    pub fn new() -> DoubleBufferedWindowHandler {
        DoubleBufferedWindowHandler { redraw: [true; 2] }
    }

    fn turtledraw(program: &TurtleProgram, turtle: &mut Turtle) {
        let init_turtle_steps = program.init_turtle();

        for action in init_turtle_steps {
            turtle.perform(action)
        }

        for action in program.turtle_program_iter() {
            turtle.perform(action)
        }
        turtle.up();
    }
}

impl<'a> WindowHandler<'a> for DoubleBufferedWindowHandler {
    fn window_resized(&mut self) {
        self.redraw[0] = true;
        self.redraw[1] = true;
    }

    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32) {
        let redraw = self.redraw[(frame_num % 2) as usize];
        if redraw {
            println!("Redrawing frame {}", frame_num % 2);
            clear(WHITE, gfx);

            let mut state = GlTurtleState::new();
            let mut turtle = GlTurtle::new(&mut state, gfx, window_size, context);
            DoubleBufferedWindowHandler::turtledraw(program, &mut turtle);

            println!("Done redrawing frame");
            self.redraw[(frame_num % 2) as usize] = false;
        }
    }
}

/// Internal state of the turtle.
#[derive(Clone, Debug)]
pub struct GlTurtleState {
    position: Point,
    angle: f64,
    down: bool,
}

impl GlTurtleState {
    pub fn new() -> GlTurtleState {
        GlTurtleState {
            position: Point { x: 0.0, y: 0.0 },
            angle: 0.0,
            down: true,
        }
    }
}

/// An implementation of a Turtle within an OpenGL (rather, a gfx) context.
pub struct GlTurtle<'a, G>
    where G: Graphics + 'a
{
    gfx: &'a mut G,
    window_size: Size,
    context: graphics::context::Context,

    state: &'a mut GlTurtleState,
}

impl<'a, G> GlTurtle<'a, G> where G: Graphics + 'a
{
    pub fn new(state: &'a mut GlTurtleState,
               gfx: &'a mut G,
               window_size: Size,
               context: graphics::context::Context)
               -> GlTurtle<'a, G> {
        GlTurtle {
            gfx: gfx,
            window_size: window_size,
            context: context,
            state: state,
        }
    }
}

impl<'a, G> Turtle for GlTurtle<'a, G> where G: Graphics + 'a
{
    fn forward(&mut self, distance: f64) {
        let old_pos = self.state.position;
        let new_pos = self.state.position.point_at(Vector {
            direction: self.state.angle,
            magnitude: distance,
        });

        if self.state.down {
            let screen_width = self.window_size.width;
            let screen_height = self.window_size.height;

            let startx = (screen_width / 4) as f64;
            let starty = (screen_height / 2) as f64;
            let endx = (3 * screen_width / 4) as f64;
            // let endy = (screen_height / 2) as f64;

            let linesize = (startx - endx).abs() as f64;

            let transform = self.context
                                .transform
                                .trans(startx, starty)
                                .zoom(linesize)
                                .flip_v()
                                .trans(0.0, 0.0);

            Line::new(BLACK, 0.5 / linesize).draw([old_pos.x, old_pos.y, new_pos.x, new_pos.y],
                                                  default_draw_state(),
                                                  transform,
                                                  self.gfx);
        }

        self.state.position = new_pos;
    }

    fn set_pos(&mut self, new_pos: Point) {
        self.state.position = new_pos;
    }

    fn set_rad(&mut self, new_rad: f64) {
        self.state.angle = new_rad;
    }

    fn turn_rad(&mut self, radians: f64) {
        use std::f64::consts::PI;
        self.state.angle = (self.state.angle + radians) % (2.0 * PI);
    }

    fn down(&mut self) {
        self.state.down = true;
    }

    fn up(&mut self) {
        self.state.down = false;
    }
}

#[derive(Debug,PartialEq)]
enum WhichFrame {
    FirstFrame,
    SecondFrame,
    AllOtherFrames,
}

/// WindowHandler that animates the rendering of the curve.
struct DoubleBufferedAnimatedWindowHandler<'a> {
    /// stored turtle state for each turtle. double-buffered means we need to animate the curve
    /// "twice".
    turtles: [GlTurtleState; 2],
    /// Two iterators.
    iters: [TurtleCollectToNextForwardIterator<'a>; 2],
    forwards_per_frame: u64,
    /// Whether we need to re-render for double-buffered frames.
    first_draw: [bool; 2],
    /// Which frame we are rendering. We need to perform the initial steps for the first frame, and
    /// we need perform the initial steps and do one extra move forward for the second frame (to
    /// stagger the double buffer). The rest of the frames then just move forward.
    which_frame: WhichFrame,
}

impl<'a> fmt::Debug for DoubleBufferedAnimatedWindowHandler<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "DoubleBufferedAnimatedWindowHandler(turtles:{:?}, iters:<iters>, first_draw:{:?}, \
                which_frame:{:?})",
               self.turtles,
               self.first_draw,
               self.which_frame)
    }
}

impl<'a> DoubleBufferedAnimatedWindowHandler<'a> {
    pub fn new(animate: u64) -> DoubleBufferedAnimatedWindowHandler<'a> {
        DoubleBufferedAnimatedWindowHandler {
            turtles: [GlTurtleState::new(), GlTurtleState::new()],
            iters: [TurtleCollectToNextForwardIterator::new_null_iter(),
                    TurtleCollectToNextForwardIterator::new_null_iter()],
            forwards_per_frame: animate,
            first_draw: [true, true],
            which_frame: WhichFrame::FirstFrame,
        }
    }
}

impl<'a> WindowHandler<'a> for DoubleBufferedAnimatedWindowHandler<'a> {
    fn window_resized(&mut self) {
        self.first_draw[0] = true;
        self.first_draw[1] = true;
        self.which_frame = WhichFrame::FirstFrame;
        self.turtles[0] = GlTurtleState::new();
        self.turtles[1] = GlTurtleState::new();
    }

    fn render_frame(&mut self,
                    window_size: Size,
                    context: graphics::context::Context,
                    gfx: &mut G2d,
                    program: &'a TurtleProgram,
                    frame_num: u32) {
        let bufnum = (frame_num % 2) as usize;

        match self.which_frame {
            WhichFrame::FirstFrame => {
                // gfx can only be &mut borrowed by one thing at a time. If we loan it to the
                // turtle and also use it elsewhere, this would trigger the static analysis.
                // This could be worked around by placing gfx into a RefCell.
                clear(WHITE, gfx);
                let mut turtle = GlTurtle::new(&mut self.turtles[bufnum],
                                               gfx,
                                               window_size,
                                               context);
                for action in program.init_turtle() {
                    turtle.perform(action)
                }
                self.iters[bufnum] = program.turtle_program_iter().collect_to_next_forward();
                self.which_frame = WhichFrame::SecondFrame;
            }
            WhichFrame::SecondFrame => {
                clear(WHITE, gfx);
                let mut turtle = GlTurtle::new(&mut self.turtles[bufnum],
                                               gfx,
                                               window_size,
                                               context);
                for action in program.init_turtle() {
                    turtle.perform(action)
                }
                self.iters[bufnum] = program.turtle_program_iter().collect_to_next_forward();
                // if we are the second frame, then we need to stagger our buffer from
                // the first buffer.
                let one_move = self.iters[bufnum].next();
                if !one_move.is_none() {
                    for action in one_move.unwrap() {
                        turtle.perform(action)
                    }
                }
                self.which_frame = WhichFrame::AllOtherFrames;
            }
            _ => {
                let mut turtle = GlTurtle::new(&mut self.turtles[bufnum],
                                               gfx,
                                               window_size,
                                               context);
                for _ in 0..self.forwards_per_frame {
                    // Make 2 moves per frame since we are double buffered.
                    DoubleBufferedAnimatedWindowHandler::draw_one_move(&mut turtle,
                                                                       &mut self.iters[bufnum]);
                    DoubleBufferedAnimatedWindowHandler::draw_one_move(&mut turtle,
                                                                       &mut self.iters[bufnum]);
                }
            }
        }
    }
}

impl<'a> DoubleBufferedAnimatedWindowHandler<'a> {
    fn draw_one_move<G>(turtle: &mut GlTurtle<G>,
                        program_iter: &mut TurtleCollectToNextForwardIterator)
        where G: Graphics
    {
        let one_move = program_iter.next();
        if !one_move.is_none() {
            for action in one_move.unwrap() {
                turtle.perform(action)
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

//! This abstraction lets you register custom protocols, which you then can use via
//! `PlaylistOp::Loadfiles`.

// FIXME: test me pls, cleanup

use libc;

use super::*;
use super::utils::mpv_err;
use super::super::raw::*;

use std::ffi::CString;
use std::mem;
use std::panic;
use std::panic::AssertUnwindSafe;

/// Do any initialization. `*mut T` is undefined heap memory.
/// It is assumed that `*mut T` is initialized to a legal value of `T` after the function exited.
pub type StreamOpen<T, U> = unsafe fn(*mut T, &mut U, &str) -> Result<(), MpvError>;
/// Do any necessary cleanup.
pub type StreamClose<T> = unsafe fn(Box<T>);
/// Seek to the given offset. Return the new offset, or `MpvError::Generic` if seek failed.
pub type StreamSeek<T> = unsafe fn(&mut T, i64) -> i64;
/// Read nbytes into the given buffer.
/// Return either the number of read bytes, `0` on EOF, `-1` on error.
pub type StreamRead<T> = unsafe fn(&mut T, *mut libc::c_char, u64) -> i64;
/// Return the total size of the stream in bytes.
pub type StreamSize<T> = unsafe fn(&mut T) -> i64;

unsafe extern "C" fn open_wrapper<T, U>(user_data: *mut libc::c_void,
                                  uri: *mut libc::c_char,
                                  info: *mut MpvStreamCbInfo)
                                  -> libc::c_int
{
	let data = user_data as *mut ProtocolData<T, U>;

	(*info).cookie = user_data;
	(*info).read_fn = read_wrapper::<T, U> as _;
	(*info).seek_fn = seek_wrapper::<T, U> as _;
	(*info).size_fn = size_wrapper::<T, U> as  _;
	(*info).close_fn = close_wrapper::<T, U> as  _;

	let ret = panic::catch_unwind(AssertUnwindSafe(|| {
		let uri = CString::from_raw(uri);
		let ret = ((*data).open_fn)((*data).cookie,
									  &mut (*data).user_data,
									  uri.to_str().unwrap());
		if ret.is_ok() {
			0
		} else {
		    ret.unwrap_err() as libc::c_int
		}
	}));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Generic as libc::c_int
	}
}

unsafe extern "C" fn read_wrapper<T, U>(cookie: *mut libc::c_void,
                                     buf: *mut libc::c_char,
                                     nbytes: libc::uint64_t) -> libc::int64_t
{
	let data = cookie as *mut ProtocolData<T, U>;

	let ret = panic::catch_unwind((AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		((*data).read_fn)(&mut*(*data).cookie, buf, nbytes)
	})));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		-1
	}
}

unsafe extern "C" fn seek_wrapper<T, U>(cookie: *mut libc::c_void,
                                     	offset: libc::int64_t)
										-> libc::int64_t
{
	let data = cookie as *mut ProtocolData<T, U>;

	if (*data).seek_fn.is_none() {
		return MpvError::Unsupported as libc::int64_t;
	}

	let ret = panic::catch_unwind((AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		(*(*data).seek_fn.as_ref().unwrap())(&mut*(*data).cookie, offset)
	})));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Generic as libc::int64_t
	}
}

unsafe extern "C" fn size_wrapper<T, U>(cookie: *mut libc::c_void)-> libc::int64_t {
	let data = cookie as *mut ProtocolData<T, U>;

	if (*data).size_fn.is_none() {
		return MpvError::Unsupported as libc::int64_t;
	}

	let ret = panic::catch_unwind(AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		(*(*data).size_fn.as_ref().unwrap())(&mut*(*data).cookie)
	}));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Unsupported as libc::int64_t
	}
}

#[allow(unused_must_use)]
unsafe extern "C" fn close_wrapper<T, U>(cookie: *mut libc::c_void) {
	let data = AssertUnwindSafe(cookie as *mut ProtocolData<T, U>);

	panic::catch_unwind((|| {
		debug_assert!(!(**data).cookie.is_null());
		((**data).close_fn)(Box::from_raw((**data).cookie))
	}));
}

struct ProtocolData<T, U> {
	cookie: *mut T,
	user_data: U,

	open_fn: StreamOpen<T, U>,
	close_fn: StreamClose<T>,
	read_fn: StreamRead<T>,
	seek_fn: Option<StreamSeek<T>>,
	size_fn: Option<StreamSize<T>>,
}

/// `Protocol` holds all state used by a custom protocol.
pub struct Protocol<T, U> {
	name: String,
	data: *mut ProtocolData<T, U>,
}

impl<T, U> Protocol<T, U> {
	/// `name` is the prefix of the protocol, e.g. `protocol://path`.
	///
	/// `user_data` is data that will be passed to `StreamOpen`.
	///
	/// # Safety
	///	Do not call libmpv functions in any supplied function.
	///
	/// Panic unwinding is catched and returns an appropriate error.
	pub fn new(name: String,
					  user_data: U,
					  open_fn: StreamOpen<T, U>,
					  close_fn: StreamClose<T>,
					  read_fn: StreamRead<T>,
					  seek_fn: Option<StreamSeek<T>>,
					  size_fn: Option<StreamSize<T>>,)
					  -> Protocol<T, U>
	{
		let data = Box::into_raw(Box::new(ProtocolData {
								cookie: unsafe{ libc::malloc(mem::size_of::<T>()) as *mut T },
								user_data: user_data,

								open_fn: open_fn,
								close_fn: close_fn,
								read_fn: read_fn,
								seek_fn: seek_fn,
								size_fn: size_fn,
							}));

		Protocol {
			name: name,
			data: data,
		}
	}

	pub(crate) fn register(&self, ctx: *mut prototype::MpvHandle) -> Result<(), Error> {
		let name = CString::new(self.name.clone()).unwrap();
		unsafe {
			mpv_err((), mpv_stream_cb_add_ro(ctx,
											 name.as_ptr(),
											 self.data as *mut _,
											 open_wrapper::<T, U> as _))
		}
	}
}

impl<T, U> Drop for Protocol<T, U> {
	fn drop(&mut self) {
		unsafe {
			Box::from_raw(self.data);
			// data.cookie will be consumed by the close callback
		};
	}
}
<commit_msg>[protocol] Remove more unnecessary casts<commit_after>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

//! This abstraction lets you register custom protocols, which you then can use via
//! `PlaylistOp::Loadfiles`.

// FIXME: test me pls, cleanup

use libc;

use super::*;
use super::utils::mpv_err;
use super::super::raw::*;

use std::ffi::CString;
use std::mem;
use std::panic;
use std::panic::AssertUnwindSafe;

/// Do any initialization. `*mut T` is undefined heap memory.
/// It is assumed that `*mut T` is initialized to a legal value of `T` after the function exited.
pub type StreamOpen<T, U> = unsafe fn(*mut T, &mut U, &str) -> Result<(), MpvError>;
/// Do any necessary cleanup.
pub type StreamClose<T> = unsafe fn(Box<T>);
/// Seek to the given offset. Return the new offset, or `MpvError::Generic` if seek failed.
pub type StreamSeek<T> = unsafe fn(&mut T, i64) -> i64;
/// Read nbytes into the given buffer.
/// Return either the number of read bytes, `0` on EOF, `-1` on error.
pub type StreamRead<T> = unsafe fn(&mut T, *mut libc::c_char, u64) -> i64;
/// Return the total size of the stream in bytes.
pub type StreamSize<T> = unsafe fn(&mut T) -> i64;

unsafe extern "C" fn open_wrapper<T, U>(user_data: *mut libc::c_void,
                                  uri: *mut libc::c_char,
                                  info: *mut MpvStreamCbInfo)
                                  -> libc::c_int
{
	let data = user_data as *mut ProtocolData<T, U>;

	(*info).cookie = user_data;
	(*info).read_fn = read_wrapper::<T, U>;
	(*info).seek_fn = seek_wrapper::<T, U>;
	(*info).size_fn = size_wrapper::<T, U>;
	(*info).close_fn = close_wrapper::<T, U>;

	let ret = panic::catch_unwind(AssertUnwindSafe(|| {
		let uri = CString::from_raw(uri);
		let ret = ((*data).open_fn)((*data).cookie,
									  &mut (*data).user_data,
									  uri.to_str().unwrap());
		if ret.is_ok() {
			0
		} else {
		    ret.unwrap_err() as libc::c_int
		}
	}));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Generic as libc::c_int
	}
}

unsafe extern "C" fn read_wrapper<T, U>(cookie: *mut libc::c_void,
                                     buf: *mut libc::c_char,
                                     nbytes: libc::uint64_t) -> libc::int64_t
{
	let data = cookie as *mut ProtocolData<T, U>;

	let ret = panic::catch_unwind((AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		((*data).read_fn)(&mut*(*data).cookie, buf, nbytes)
	})));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		-1
	}
}

unsafe extern "C" fn seek_wrapper<T, U>(cookie: *mut libc::c_void,
                                     	offset: libc::int64_t)
										-> libc::int64_t
{
	let data = cookie as *mut ProtocolData<T, U>;

	if (*data).seek_fn.is_none() {
		return MpvError::Unsupported as libc::int64_t;
	}

	let ret = panic::catch_unwind((AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		(*(*data).seek_fn.as_ref().unwrap())(&mut*(*data).cookie, offset)
	})));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Generic as libc::int64_t
	}
}

unsafe extern "C" fn size_wrapper<T, U>(cookie: *mut libc::c_void)-> libc::int64_t {
	let data = cookie as *mut ProtocolData<T, U>;

	if (*data).size_fn.is_none() {
		return MpvError::Unsupported as libc::int64_t;
	}

	let ret = panic::catch_unwind(AssertUnwindSafe(|| {
		debug_assert!(!(*data).cookie.is_null());
		(*(*data).size_fn.as_ref().unwrap())(&mut*(*data).cookie)
	}));
	if ret.is_ok() {
		ret.unwrap()
	} else {
		MpvError::Unsupported as libc::int64_t
	}
}

#[allow(unused_must_use)]
unsafe extern "C" fn close_wrapper<T, U>(cookie: *mut libc::c_void) {
	let data = AssertUnwindSafe(cookie as *mut ProtocolData<T, U>);

	panic::catch_unwind((|| {
		debug_assert!(!(**data).cookie.is_null());
		((**data).close_fn)(Box::from_raw((**data).cookie))
	}));
}

struct ProtocolData<T, U> {
	cookie: *mut T,
	user_data: U,

	open_fn: StreamOpen<T, U>,
	close_fn: StreamClose<T>,
	read_fn: StreamRead<T>,
	seek_fn: Option<StreamSeek<T>>,
	size_fn: Option<StreamSize<T>>,
}

/// `Protocol` holds all state used by a custom protocol.
pub struct Protocol<T, U> {
	name: String,
	data: *mut ProtocolData<T, U>,
}

impl<T, U> Protocol<T, U> {
	/// `name` is the prefix of the protocol, e.g. `protocol://path`.
	///
	/// `user_data` is data that will be passed to `StreamOpen`.
	///
	/// # Safety
	///	Do not call libmpv functions in any supplied function.
	///
	/// Panic unwinding is catched and returns an appropriate error.
	pub fn new(name: String,
					  user_data: U,
					  open_fn: StreamOpen<T, U>,
					  close_fn: StreamClose<T>,
					  read_fn: StreamRead<T>,
					  seek_fn: Option<StreamSeek<T>>,
					  size_fn: Option<StreamSize<T>>,)
					  -> Protocol<T, U>
	{
		let data = Box::into_raw(Box::new(ProtocolData {
								cookie: unsafe{ libc::malloc(mem::size_of::<T>()) as *mut T },
								user_data: user_data,

								open_fn: open_fn,
								close_fn: close_fn,
								read_fn: read_fn,
								seek_fn: seek_fn,
								size_fn: size_fn,
							}));

		Protocol {
			name: name,
			data: data,
		}
	}

	pub(crate) fn register(&self, ctx: *mut prototype::MpvHandle) -> Result<(), Error> {
		let name = CString::new(self.name.clone()).unwrap();
		unsafe {
			mpv_err((), mpv_stream_cb_add_ro(ctx,
											 name.as_ptr(),
											 self.data as *mut _,
											 open_wrapper::<T, U> as _))
		}
	}
}

impl<T, U> Drop for Protocol<T, U> {
	fn drop(&mut self) {
		unsafe {
			Box::from_raw(self.data);
			// data.cookie will be consumed by the close callback
		};
	}
}
<|endoftext|>


<commit_before>//! simple model-checking tools for rust.
//!
//! aims to reduce the boiler plate required
//! to write model-based and linearizability tests.
//!
//! it can find linearizability violations in
//! implementations without having any knowledge
//! of their inner-workings, by running sequential
//! operations on different commands and then
//! trying to find a sequential ordering that results
//! in the same return values.
//!
//! model-based testing:
//!
//! ```rust,noexecute
//! #[macro_use]
//! extern crate model;
//! #[macro_use]
//! extern crate proptest;
//!
//! use std::sync::atomic::{AtomicUsize, Ordering};
//!
//!# fn main() {
//! model! {
//!     Model => let m = AtomicUsize::new(0),
//!     Implementation => let mut i: usize = 0,
//!     Add(usize)(v in 0usize..4) => {
//!         let expected = m.fetch_add(v, Ordering::SeqCst) + v;
//!         i += v;
//!         assert_eq!(expected, i);
//!     },
//!     Set(usize)(v in 0usize..4) => {
//!         m.store(v, Ordering::SeqCst);
//!         i = v;
//!     },
//!     Eq(usize)(v in 0usize..4) => {
//!         let expected = m.load(Ordering::SeqCst) == v;
//!         let actual = i == v;
//!         assert_eq!(expected, actual);
//!     },
//!     Cas((usize, usize))((old, new) in (0usize..4, 0usize..4)) => {
//!         let expected =
//!             m.compare_and_swap(old, new, Ordering::SeqCst);
//!         let actual = if i == old {
//!             i = new;
//!             old
//!         } else {
//!             i
//!         };
//!         assert_eq!(expected, actual);
//!     }
//! }
//!# }
//! ```
//!
//! linearizability testing:
//!
//! ```rust,noexecute
//! #[macro_use]
//! extern crate model;
//! #[macro_use]
//! extern crate proptest;
//!
//! use std::sync::atomic::{AtomicUsize, Ordering};
//!
//!# fn main() {
//! linearizable! {
//!     Implementation => let i = model::Shared::new(AtomicUsize::new(0)),
//!     BuggyAdd(usize)(v in 0usize..4) -> usize {
//!         let current = i.load(Ordering::SeqCst);
//!         thread::yield_now();
//!         i.store(current + v, Ordering::SeqCst);
//!         current + v
//!     },
//!     Set(usize)(v in 0usize..4) -> () {
//!         i.store(v, Ordering::SeqCst)
//!     },
//!     BuggyCas((usize, usize))((old, new) in (0usize..4, 0usize..4)) -> usize {
//!         let current = i.load(Ordering::SeqCst);
//!         thread::yield_now();
//!         if current == old {
//!             i.store(new, Ordering::SeqCst);
//!             new
//!         } else {
//!             current
//!         }
//!     }
//! }
//!# }
//! ```
extern crate permutohedron;

use std::ops::Deref;

pub struct Shared<T>(*mut T);

impl<T> Clone for Shared<T> {
    fn clone(&self) -> Shared<T> {
        *self
    }
}

impl<T> Copy for Shared<T> {}

unsafe impl<T> Sync for Shared<T> {}

unsafe impl<T> Send for Shared<T> {}

impl<T> Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.0 }
    }
}

impl<T> Shared<T> {
    pub fn new(inner: T) -> Shared<T> {
        Shared(Box::into_raw(Box::new(inner)))
    }
}

#[macro_export]
macro_rules! model {
    (
        Model => $model:stmt,
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) => $body:expr),*
    ) => {
        model! {
            Config => Config::with_cases(1000).clone_with_source_file(file!()),
            Model => $model,
            Implementation => $implementation,
            $($op ($($type),*) ($parm in $strategy) => $body),*
        }
    };
    (
        Config => $config:expr,
        Model => $model:stmt,
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) => $body:expr),*
    ) => {
        use proptest::collection::vec as prop_vec;
        use proptest::prelude::*;
        use proptest::test_runner::{Config, TestRunner};

        #[derive(Debug)]
        enum Op {
            $(
                $op($($type),*)
            ),*
        }

        fn arb() -> BoxedStrategy<Vec<Op>> {
            prop_vec(
                prop_oneof![
                    $(
                        $strategy.prop_map(Op::$op)
                    ),*
                ],
                0..40,
            ).boxed()
        }

        let config = $config;
        let mut runner = TestRunner::new(config);

        match runner.run(&arb(), |ops| {
            $model;
            $implementation;

            for op in ops {
                match *op {
                    $(Op::$op($parm) => $body),*
                };
            };
            Ok(())
        }) {
            Ok(_) => {}
            Err(e) =>  panic!("{}\n{}", e, runner),
        }
    }
}

#[macro_export]
macro_rules! linearizable {
    (
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) -> $ret:ty $body:block),*
    ) => {
        use std::thread;

        use proptest::collection::vec as prop_vec;
        use proptest::prelude::*;
        use proptest::test_runner::{Config, TestRunner};

        #[derive(Debug, Clone)]
        enum Op {
            $(
                $op($($type),*)
            ),*
        }

        #[derive(Debug, PartialEq)]
        enum Ret {
            $(
                $op($ret)
            ),*
        }

        fn arb() -> BoxedStrategy<(usize, Vec<Op>)> {
            prop_vec(
                prop_oneof![
                    $(
                        $strategy.prop_map(Op::$op)
                    ),*
                ],
                1..4,
            )
                .prop_flat_map(|ops| (0..ops.len(), Just(ops)))
                .boxed()
        }

        let config = Config::with_cases(10000).clone_with_source_file(file!());
        let mut runner = TestRunner::new(config);

        match runner.run(&arb(), |&(split_point, ref ops)| {
            $implementation;

            let ops1 = ops[0..split_point].to_vec();
            let ops2 = ops[split_point..].to_vec();

            let t1 = thread::spawn(move || {
                    let mut ret = vec![];
                    for op in ops1 {
                        ret.push(match op {
                            $(
                                Op::$op($parm) => Ret::$op($body)
                            ),*
                        });
                    }
                    ret
                });

            let t2 = thread::spawn(move || {
                    let mut ret = vec![];
                    for op in ops2 {
                        ret.push(match op {
                            $(
                                Op::$op($parm) => Ret::$op($body)
                            ),*
                        });
                    }
                    ret
                });

            let r1 = t1.join().expect("thread should not panic");
            let r2 = t2.join().expect("thread should not panic");

            // try to find sequential walk through ops
            let o1 = ops[0..split_point].to_vec();
            let o2 = ops[split_point..].to_vec();

            let calls1: Vec<(Op, Ret)> = o1.into_iter().zip(r1.into_iter()).collect();
            let calls2: Vec<(Op, Ret)> = o2.into_iter().zip(r2.into_iter()).collect();
            let mut indexes = vec![0; calls1.len()];
            indexes.resize(calls1.len() + calls2.len(), 1);
            let calls = vec![calls1, calls2];

            let mut linearizable = false;

            let call_permutations = model::permutohedron_heap(&mut indexes);

            'outer: for walk in call_permutations {
                $implementation;

                let mut indexes = vec![0, 0];
                // println!("trying walk {:?}", walk);

                for idx in walk {
                    let (ref op, ref expected) = calls[idx][indexes[idx]];
                    indexes[idx] += 1;

                    match *op {
                        $(
                            Op::$op($parm) => {
                                let ret = Ret::$op($body);
                                if ret != *expected {
                                    continue 'outer;
                                }
                            }
                        ),*
                    }
                }

                linearizable = true;
                break;
            }

            assert!(linearizable, "operations are not linearizable: {:?}", calls);

            Ok(())
        }) {
            Ok(_) => {}
            Err(e) =>  panic!("{}\n{}", e, runner),
        }
    }
}

pub fn permutohedron_heap<'a, Data, T>(
    orig: &'a mut Data,
) -> permutohedron::Heap<'a, Data, T>
    where Data: 'a + Sized + AsMut<[T]>,
          T: 'a
{
    permutohedron::Heap::new(orig)
}
<commit_msg>`noexecute` is actually called `no_run`.<commit_after>//! simple model-checking tools for rust.
//!
//! aims to reduce the boiler plate required
//! to write model-based and linearizability tests.
//!
//! it can find linearizability violations in
//! implementations without having any knowledge
//! of their inner-workings, by running sequential
//! operations on different commands and then
//! trying to find a sequential ordering that results
//! in the same return values.
//!
//! model-based testing:
//!
//! ```rust,no_run
//! #[macro_use]
//! extern crate model;
//! #[macro_use]
//! extern crate proptest;
//!
//! use std::sync::atomic::{AtomicUsize, Ordering};
//!
//!# fn main() {
//! model! {
//!     Model => let m = AtomicUsize::new(0),
//!     Implementation => let mut i: usize = 0,
//!     Add(usize)(v in 0usize..4) => {
//!         let expected = m.fetch_add(v, Ordering::SeqCst) + v;
//!         i += v;
//!         assert_eq!(expected, i);
//!     },
//!     Set(usize)(v in 0usize..4) => {
//!         m.store(v, Ordering::SeqCst);
//!         i = v;
//!     },
//!     Eq(usize)(v in 0usize..4) => {
//!         let expected = m.load(Ordering::SeqCst) == v;
//!         let actual = i == v;
//!         assert_eq!(expected, actual);
//!     },
//!     Cas((usize, usize))((old, new) in (0usize..4, 0usize..4)) => {
//!         let expected =
//!             m.compare_and_swap(old, new, Ordering::SeqCst);
//!         let actual = if i == old {
//!             i = new;
//!             old
//!         } else {
//!             i
//!         };
//!         assert_eq!(expected, actual);
//!     }
//! }
//!# }
//! ```
//!
//! linearizability testing:
//!
//! ```rust,no_run
//! #[macro_use]
//! extern crate model;
//! #[macro_use]
//! extern crate proptest;
//!
//! use std::sync::atomic::{AtomicUsize, Ordering};
//!
//!# fn main() {
//! linearizable! {
//!     Implementation => let i = model::Shared::new(AtomicUsize::new(0)),
//!     BuggyAdd(usize)(v in 0usize..4) -> usize {
//!         let current = i.load(Ordering::SeqCst);
//!         thread::yield_now();
//!         i.store(current + v, Ordering::SeqCst);
//!         current + v
//!     },
//!     Set(usize)(v in 0usize..4) -> () {
//!         i.store(v, Ordering::SeqCst)
//!     },
//!     BuggyCas((usize, usize))((old, new) in (0usize..4, 0usize..4)) -> usize {
//!         let current = i.load(Ordering::SeqCst);
//!         thread::yield_now();
//!         if current == old {
//!             i.store(new, Ordering::SeqCst);
//!             new
//!         } else {
//!             current
//!         }
//!     }
//! }
//!# }
//! ```
extern crate permutohedron;

use std::ops::Deref;

pub struct Shared<T>(*mut T);

impl<T> Clone for Shared<T> {
    fn clone(&self) -> Shared<T> {
        *self
    }
}

impl<T> Copy for Shared<T> {}

unsafe impl<T> Sync for Shared<T> {}

unsafe impl<T> Send for Shared<T> {}

impl<T> Deref for Shared<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.0 }
    }
}

impl<T> Shared<T> {
    pub fn new(inner: T) -> Shared<T> {
        Shared(Box::into_raw(Box::new(inner)))
    }
}

#[macro_export]
macro_rules! model {
    (
        Model => $model:stmt,
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) => $body:expr),*
    ) => {
        model! {
            Config => Config::with_cases(1000).clone_with_source_file(file!()),
            Model => $model,
            Implementation => $implementation,
            $($op ($($type),*) ($parm in $strategy) => $body),*
        }
    };
    (
        Config => $config:expr,
        Model => $model:stmt,
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) => $body:expr),*
    ) => {
        use proptest::collection::vec as prop_vec;
        use proptest::prelude::*;
        use proptest::test_runner::{Config, TestRunner};

        #[derive(Debug)]
        enum Op {
            $(
                $op($($type),*)
            ),*
        }

        fn arb() -> BoxedStrategy<Vec<Op>> {
            prop_vec(
                prop_oneof![
                    $(
                        $strategy.prop_map(Op::$op)
                    ),*
                ],
                0..40,
            ).boxed()
        }

        let config = $config;
        let mut runner = TestRunner::new(config);

        match runner.run(&arb(), |ops| {
            $model;
            $implementation;

            for op in ops {
                match *op {
                    $(Op::$op($parm) => $body),*
                };
            };
            Ok(())
        }) {
            Ok(_) => {}
            Err(e) =>  panic!("{}\n{}", e, runner),
        }
    }
}

#[macro_export]
macro_rules! linearizable {
    (
        Implementation => $implementation:stmt,
        $($op:ident ($($type:ty),*) ($parm:pat in $strategy:expr) -> $ret:ty $body:block),*
    ) => {
        use std::thread;

        use proptest::collection::vec as prop_vec;
        use proptest::prelude::*;
        use proptest::test_runner::{Config, TestRunner};

        #[derive(Debug, Clone)]
        enum Op {
            $(
                $op($($type),*)
            ),*
        }

        #[derive(Debug, PartialEq)]
        enum Ret {
            $(
                $op($ret)
            ),*
        }

        fn arb() -> BoxedStrategy<(usize, Vec<Op>)> {
            prop_vec(
                prop_oneof![
                    $(
                        $strategy.prop_map(Op::$op)
                    ),*
                ],
                1..4,
            )
                .prop_flat_map(|ops| (0..ops.len(), Just(ops)))
                .boxed()
        }

        let config = Config::with_cases(10000).clone_with_source_file(file!());
        let mut runner = TestRunner::new(config);

        match runner.run(&arb(), |&(split_point, ref ops)| {
            $implementation;

            let ops1 = ops[0..split_point].to_vec();
            let ops2 = ops[split_point..].to_vec();

            let t1 = thread::spawn(move || {
                    let mut ret = vec![];
                    for op in ops1 {
                        ret.push(match op {
                            $(
                                Op::$op($parm) => Ret::$op($body)
                            ),*
                        });
                    }
                    ret
                });

            let t2 = thread::spawn(move || {
                    let mut ret = vec![];
                    for op in ops2 {
                        ret.push(match op {
                            $(
                                Op::$op($parm) => Ret::$op($body)
                            ),*
                        });
                    }
                    ret
                });

            let r1 = t1.join().expect("thread should not panic");
            let r2 = t2.join().expect("thread should not panic");

            // try to find sequential walk through ops
            let o1 = ops[0..split_point].to_vec();
            let o2 = ops[split_point..].to_vec();

            let calls1: Vec<(Op, Ret)> = o1.into_iter().zip(r1.into_iter()).collect();
            let calls2: Vec<(Op, Ret)> = o2.into_iter().zip(r2.into_iter()).collect();
            let mut indexes = vec![0; calls1.len()];
            indexes.resize(calls1.len() + calls2.len(), 1);
            let calls = vec![calls1, calls2];

            let mut linearizable = false;

            let call_permutations = model::permutohedron_heap(&mut indexes);

            'outer: for walk in call_permutations {
                $implementation;

                let mut indexes = vec![0, 0];
                // println!("trying walk {:?}", walk);

                for idx in walk {
                    let (ref op, ref expected) = calls[idx][indexes[idx]];
                    indexes[idx] += 1;

                    match *op {
                        $(
                            Op::$op($parm) => {
                                let ret = Ret::$op($body);
                                if ret != *expected {
                                    continue 'outer;
                                }
                            }
                        ),*
                    }
                }

                linearizable = true;
                break;
            }

            assert!(linearizable, "operations are not linearizable: {:?}", calls);

            Ok(())
        }) {
            Ok(_) => {}
            Err(e) =>  panic!("{}\n{}", e, runner),
        }
    }
}

pub fn permutohedron_heap<'a, Data, T>(
    orig: &'a mut Data,
) -> permutohedron::Heap<'a, Data, T>
    where Data: 'a + Sized + AsMut<[T]>,
          T: 'a
{
    permutohedron::Heap::new(orig)
}
<|endoftext|>


<commit_before>use relation::Change;
use flow::Flow;
use value::{Value};

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    Add,
    Subtract,
}

impl Primitive {
    pub fn eval<'a>(self, arguments: &[&Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (self, arguments) {
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            _ => panic!("Type error while calling: {:?} {:?}", self, &arguments)
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
    ]
}

pub fn install(flow: &mut Flow) {
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut display_name_values = Vec::new();
    for (name, scalar_inputs, vector_inputs, outputs) in primitives().into_iter() {
        view_values.push(vec![string!("{}", name), string!("primitive")]);
        display_name_values.push(vec![string!("{}", name), string!("{}", name)]);
        for field in scalar_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("scalar input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in vector_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("vector input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in outputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
    }
    flow.get_output_mut("view").change(Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("display name").change(Change{
        fields: vec!["display name: id".to_owned(), "display name: name".to_owned()],
        insert: display_name_values,
        remove: Vec::new(),
    });
}<commit_msg>Add a vector primitive<commit_after>use relation::Change;
use flow::Flow;
use value::{Value};

#[derive(Clone, Debug, Copy)]
pub enum Primitive {
    Add,
    Subtract,
    Count,
}

impl Primitive {
    pub fn eval<'a>(self, arguments: &[&Value]) -> Vec<Vec<Value>> {
        use primitive::Primitive::*;
        use value::Value::*;
        match (self, arguments) {
            (Add, [&Float(a), &Float(b)]) => vec![vec![Float(a+b)]],
            (Subtract, [&Float(a), &Float(b)]) => vec![vec![Float(a-b)]],
            (Count, _) => unimplemented!(), // what would the interface even be...  eval_scalar vs eval_vector?
            _ => panic!("Type error while calling: {:?} {:?}", self, &arguments)
        }
    }

    pub fn from_str(string: &str) -> Self {
        match string {
            "add" => Primitive::Add,
            "subtract" => Primitive::Subtract,
            "count" => Primitive::Count,
            _ => panic!("Unknown primitive: {:?}", string),
        }
    }
}

pub fn primitives() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>, Vec<&'static str>)> {
    vec![
        ("add", vec!["in A", "in B"], vec![], vec!["out"]),
        ("subtract", vec!["in A", "in B"], vec![], vec!["out"]),
        ("count", vec![], vec!["in"], vec!["out"]),
    ]
}

pub fn install(flow: &mut Flow) {
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut display_name_values = Vec::new();
    for (name, scalar_inputs, vector_inputs, outputs) in primitives().into_iter() {
        view_values.push(vec![string!("{}", name), string!("primitive")]);
        display_name_values.push(vec![string!("{}", name), string!("{}", name)]);
        for field in scalar_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("scalar input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in vector_inputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("vector input")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
        for field in outputs.into_iter() {
            field_values.push(vec![string!("{}: {}", name, field), string!("{}", name), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", name, field), string!("{}", field)]);
        }
    }
    flow.get_output_mut("view").change(Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("display name").change(Change{
        fields: vec!["display name: id".to_owned(), "display name: name".to_owned()],
        insert: display_name_values,
        remove: Vec::new(),
    });
}<|endoftext|>


<commit_before>use std::net::Ipv4Addr;
use Ipv4Network;
use Ipv6Network;
use helpers;
use extprim::u128::u128;

#[cfg(target_pointer_width = "16")]
const POINTER_WIDTH: u32 = 16;
#[cfg(target_pointer_width = "32")]
const POINTER_WIDTH: u32 = 32;
#[cfg(target_pointer_width = "64")]
const POINTER_WIDTH: u32 = 64;
#[cfg(target_pointer_width = "128")]
const POINTER_WIDTH: u32 = 128;

/// IPv4 range iterator
pub struct Ipv4RangeIterator {
    current: u32,
    to: u32,
    is_done: bool,
}

impl Ipv4RangeIterator {
    /// Constructs new `Ipv4RangeIterator`, both `from` and `to` address are inclusive.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ip_network::iterator::Ipv4RangeIterator;
    ///
    /// let mut iterator = Ipv4RangeIterator::new(
    ///     Ipv4Addr::new(192, 168, 2, 0),
    ///     Ipv4Addr::new(192, 168, 2, 255)
    /// );
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
    /// assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    /// ```
    pub fn new(from: Ipv4Addr, to: Ipv4Addr) -> Self {
        let current = u32::from(from);
        let to = u32::from(to);
        assert!(to >= current);
        Self { current, to, is_done: false }
    }
}

impl Iterator for Ipv4RangeIterator {
    type Item = Ipv4Addr;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(1) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(output))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = (self.to - self.current + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4RangeIterator {}

/// Iterates over new created IPv4 network from given network
pub struct Ipv4NetworkIterator {
    current: u32,
    to: u32,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv4NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv4Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 32);

        let current = u32::from(network.get_network_address());
        let mask = !helpers::get_bite_mask(32 - (new_netmask - network.get_netmask())) << (32 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u32 {
        1 << (32 - self.new_netmask)
    }
}

impl Iterator for Ipv4NetworkIterator {
    type Item = Ipv4Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv4Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = ((self.to - self.current) / self.step() + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4NetworkIterator {}

/// Iterates over new created IPv6 network from given network
pub struct Ipv6NetworkIterator {
    current: u128,
    to: u128,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv6NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv6Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 128);

        let current = helpers::ipv6addr_to_u128(network.get_network_address());
        let mask = !helpers::get_bite_mask_u128(128 - (new_netmask - network.get_netmask())) << (128 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u128 {
        u128::new(1) << (128 - self.new_netmask)
    }

    pub fn real_len(&self) -> u128 {
        if self.is_done {
            return u128::new(0);
        }

        (self.to - self.current) / self.step() + u128::new(1)
    }
}

impl Iterator for Ipv6NetworkIterator {
    type Item = Ipv6Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(helpers::u128_to_ipv6addr(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.real_len();

        if 128 - remaining.leading_zeros() > POINTER_WIDTH {
            (::std::usize::MAX, None)
        } else {
            (remaining.low64() as usize, Some(remaining.low64() as usize))
        }
    }
}

impl ExactSizeIterator for Ipv6NetworkIterator {}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};
    use super::{Ipv4NetworkIterator, Ipv4RangeIterator, Ipv6NetworkIterator};

    #[test]
    fn test_ipv4_range_iterator() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
        assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    }

    #[test]
    fn test_ipv4_range_iterator_length() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.len(), 256);
        iterator.next().unwrap();
        assert_eq!(iterator.len(), 255);
        assert_eq!(iterator.collect::<Vec<_>>().len(), 255);
    }

    #[test]
    fn test_ipv4_range_iterator_same_values() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(255, 255, 255, 255),
            Ipv4Addr::new(255, 255, 255, 255)
        );
        assert_eq!(iterator.len(), 1);
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(255, 255, 255, 255));
        assert!(iterator.next().is_none());
        assert_eq!(iterator.len(), 0);
    }

    #[test]
    fn test_ipv4_network_iterator() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let mut iterator = Ipv4NetworkIterator::new(network, 16);

        assert_eq!(iterator.len(), 256);
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 1, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 2, 0, 0), 16).unwrap());
        assert_eq!(iterator.last().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 255, 0, 0), 16).unwrap());
    }

    #[test]
    fn test_ipv4_network_iterator_len() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let iterator = Ipv4NetworkIterator::new(network, 16);
        assert_eq!(256, iterator.len());
    }

    #[test]
    fn test_ipv6_network_iterator() {
        let ip = Ipv6Addr::new(0x2001, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 16).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 17);

        assert_eq!(2, iterator.len());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(ip, 17).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0x2001, 0x8000, 0, 0, 0, 0, 0, 0), 17).unwrap());
        assert!(iterator.next().is_none());
    }
}
<commit_msg>Added tests for Ipv6NetworkIterator<commit_after>use std::net::Ipv4Addr;
use Ipv4Network;
use Ipv6Network;
use helpers;
use extprim::u128::u128;

#[cfg(target_pointer_width = "16")]
const POINTER_WIDTH: u32 = 16;
#[cfg(target_pointer_width = "32")]
const POINTER_WIDTH: u32 = 32;
#[cfg(target_pointer_width = "64")]
const POINTER_WIDTH: u32 = 64;
#[cfg(target_pointer_width = "128")]
const POINTER_WIDTH: u32 = 128;

/// IPv4 range iterator
pub struct Ipv4RangeIterator {
    current: u32,
    to: u32,
    is_done: bool,
}

impl Ipv4RangeIterator {
    /// Constructs new `Ipv4RangeIterator`, both `from` and `to` address are inclusive.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::net::Ipv4Addr;
    /// use ip_network::iterator::Ipv4RangeIterator;
    ///
    /// let mut iterator = Ipv4RangeIterator::new(
    ///     Ipv4Addr::new(192, 168, 2, 0),
    ///     Ipv4Addr::new(192, 168, 2, 255)
    /// );
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
    /// assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
    /// assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    /// ```
    pub fn new(from: Ipv4Addr, to: Ipv4Addr) -> Self {
        let current = u32::from(from);
        let to = u32::from(to);
        assert!(to >= current);
        Self { current, to, is_done: false }
    }
}

impl Iterator for Ipv4RangeIterator {
    type Item = Ipv4Addr;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(1) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(output))
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = (self.to - self.current + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4RangeIterator {}

/// Iterates over new created IPv4 network from given network
pub struct Ipv4NetworkIterator {
    current: u32,
    to: u32,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv4NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv4Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 32);

        let current = u32::from(network.get_network_address());
        let mask = !helpers::get_bite_mask(32 - (new_netmask - network.get_netmask())) << (32 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u32 {
        1 << (32 - self.new_netmask)
    }
}

impl Iterator for Ipv4NetworkIterator {
    type Item = Ipv4Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(Ipv4Addr::from(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_done {
            return (0, Some(0))
        }

        let remaining = ((self.to - self.current) / self.step() + 1) as usize;
        (remaining, Some(remaining))
    }
}

impl ExactSizeIterator for Ipv4NetworkIterator {}

/// Iterates over new created IPv6 network from given network
pub struct Ipv6NetworkIterator {
    current: u128,
    to: u128,
    new_netmask: u8,
    is_done: bool,
}

impl Ipv6NetworkIterator {
    // TODO: Change assert to error?
    pub fn new(network: Ipv6Network, new_netmask: u8) -> Self {
        assert!(network.get_netmask() < new_netmask);
        assert!(new_netmask <= 128);

        let current = helpers::ipv6addr_to_u128(network.get_network_address());
        let mask = !helpers::get_bite_mask_u128(128 - (new_netmask - network.get_netmask())) << (128 - new_netmask);
        let to = current | mask;

        Self {
            current,
            to,
            new_netmask,
            is_done: false,
        }
    }

    #[inline]
    fn step(&self) -> u128 {
        u128::new(1) << (128 - self.new_netmask)
    }

    pub fn real_len(&self) -> u128 {
        if self.is_done {
            return u128::new(0);
        }

        ((self.to - self.current) / self.step()).saturating_add(u128::new(1))
    }
}

impl Iterator for Ipv6NetworkIterator {
    type Item = Ipv6Network;

    fn next(&mut self) -> Option<Self::Item> {
        if self.current <= self.to && !self.is_done {
            let output = self.current;

            match self.current.checked_add(self.step()) {
                Some(x) => self.current = x,
                None => self.is_done = true,
            };

            Some(Self::Item::from(helpers::u128_to_ipv6addr(output), self.new_netmask).unwrap())
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let remaining = self.real_len();

        if 128 - remaining.leading_zeros() > POINTER_WIDTH {
            (::std::usize::MAX, None)
        } else {
            (remaining.low64() as usize, Some(remaining.low64() as usize))
        }
    }
}

impl ExactSizeIterator for Ipv6NetworkIterator {}

#[cfg(test)]
mod tests {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use {Ipv4Network, Ipv6Network};
    use super::{Ipv4NetworkIterator, Ipv4RangeIterator, Ipv6NetworkIterator};
    use extprim::u128::u128;

    #[test]
    fn test_ipv4_range_iterator() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 0));
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(192, 168, 2, 1));
        assert_eq!(iterator.last().unwrap(), Ipv4Addr::new(192, 168, 2, 255));
    }

    #[test]
    fn test_ipv4_range_iterator_length() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(192, 168, 2, 0),
            Ipv4Addr::new(192, 168, 2, 255)
        );
        assert_eq!(iterator.len(), 256);
        iterator.next().unwrap();
        assert_eq!(iterator.len(), 255);
        assert_eq!(iterator.collect::<Vec<_>>().len(), 255);
    }

    #[test]
    fn test_ipv4_range_iterator_same_values() {
        let mut iterator = Ipv4RangeIterator::new(
            Ipv4Addr::new(255, 255, 255, 255),
            Ipv4Addr::new(255, 255, 255, 255)
        );
        assert_eq!(iterator.len(), 1);
        assert_eq!(iterator.next().unwrap(), Ipv4Addr::new(255, 255, 255, 255));
        assert!(iterator.next().is_none());
        assert_eq!(iterator.len(), 0);
    }

    #[test]
    fn test_ipv4_network_iterator() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let mut iterator = Ipv4NetworkIterator::new(network, 16);

        assert_eq!(iterator.len(), 256);
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 1, 0, 0), 16).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 2, 0, 0), 16).unwrap());
        assert_eq!(iterator.last().unwrap(), Ipv4Network::from(Ipv4Addr::new(127, 255, 0, 0), 16).unwrap());
    }

    #[test]
    fn test_ipv4_network_iterator_len() {
        let network = Ipv4Network::from(Ipv4Addr::new(127, 0, 0, 0), 8).unwrap();
        let iterator = Ipv4NetworkIterator::new(network, 16);
        assert_eq!(256, iterator.len());
    }

    #[test]
    fn test_ipv6_network_iterator() {
        let ip = Ipv6Addr::new(0x2001, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 16).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 17);

        assert_eq!(2, iterator.len());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(ip, 17).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0x2001, 0x8000, 0, 0, 0, 0, 0, 0), 17).unwrap());
        assert!(iterator.next().is_none());
    }

    #[test]
    #[should_panic] // because range is bigger than `usize` on 64bit machine
    fn test_ipv6_network_iterator_whole_range_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        iterator.len();
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range_real_len() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.real_len(), u128::max_value());
    }

    #[test]
    fn test_ipv6_network_iterator_whole_range() {
        let ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0);
        let network = Ipv6Network::from(ip, 0).unwrap();
        let mut iterator = Ipv6NetworkIterator::new(network, 128);

        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0), 128).unwrap());
        assert_eq!(iterator.next().unwrap(), Ipv6Network::from(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 128).unwrap());
    }
}
<|endoftext|>


<commit_before>#![crate_id = "js.rs"]
#![comment = "Javascript parsing and execution command line tool"]
#![license = "MIT"]
#![crate_type = "bin"]
#![doc(
	html_favicon_url = "http://tombebbington.github.io/favicon.png",
	html_root_url = "http://tombebbington.github.io/js.rs/"
)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, non_camel_case_types, unused_must_use)]
#![feature(phase)]
//! A Javascript execution command line tool

extern crate js;
extern crate syntax = "js_syntax";
extern crate getopts;
extern crate collections;
#[phase(plugin, link)]
extern crate log;
/// Interactive mode
pub use interactive::Interactive;
/// Unit test mode
pub use tests::Tests;
/// Script runner mode
pub use runner::Runner;
mod interactive;
mod tests;
mod runner;
/// The main function
pub fn main() {
	let opts = [
		getopts::optflag("h", "help", "Show this message"),
		getopts::optflag("t", "tests", "Run tests"),
		getopts::optflag("i", "interactive", "Run in interactive mode"),
		getopts::optopt("s", "source-code", "Run some Javascript code", "The path to the source code")
	];
	let m = getopts::getopts(std::os::args().as_slice(), opts).unwrap();
	match m.opt_str("s") {
		Some(path) => {
			Runner::new(path).run()
		},
		None if m.opt_present("h") => {
			println!("{}", getopts::usage("Usage: js.rs [OPTIONS] [INPUT]", opts));
		},
		None if m.opt_present("t") || (m.free.len() >= 2 && m.free.get(1).as_slice() == "test") => {
			Tests::new().run();
		},
		None if m.opt_present("i") || (m.free.len() >= 2 && m.free.get(1).as_slice() == "interactive") => {
			Interactive::new().run();
		},
		None if m.free.len() >= 2 => {
			Runner::new(m.free.get(1).clone()).run();
		},
		None => {
			println!("{}", getopts::short_usage("Usage: js.rs [OPTIONS] [INPUT]", opts));
		}
	}
}<commit_msg>Use specific error message when parsing arguments in frontend<commit_after>#![crate_id = "js.rs"]
#![comment = "Javascript parsing and execution command line tool"]
#![license = "MIT"]
#![crate_type = "bin"]
#![doc(
	html_favicon_url = "http://tombebbington.github.io/favicon.png",
	html_root_url = "http://tombebbington.github.io/js.rs/"
)]
#![deny(non_uppercase_statics, missing_doc, unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, non_camel_case_types, unused_must_use)]
#![feature(phase)]
//! A Javascript execution command line tool

extern crate js;
extern crate syntax = "js_syntax";
extern crate getopts;
extern crate collections;
#[phase(plugin, link)]
extern crate log;
/// Interactive mode
pub use interactive::Interactive;
/// Unit test mode
pub use tests::Tests;
/// Script runner mode
pub use runner::Runner;
mod interactive;
mod tests;
mod runner;
/// The main function
pub fn main() {
	let opts = [
		getopts::optflag("h", "help", "Show this message"),
		getopts::optflag("t", "tests", "Run tests"),
		getopts::optflag("i", "interactive", "Run in interactive mode"),
		getopts::optopt("s", "source-code", "Run some Javascript code", "The path to the source code")
	];
	let m = getopts::getopts(std::os::args().as_slice(), opts).ok().expect("Could not parse arguments");
	match m.opt_str("s") {
		Some(path) => {
			Runner::new(path).run()
		},
		None if m.opt_present("h") => {
			println!("{}", getopts::usage("Usage: js.rs [OPTIONS] [INPUT]", opts));
		},
		None if m.opt_present("t") || (m.free.len() >= 2 && m.free.get(1).as_slice() == "test") => {
			Tests::new().run();
		},
		None if m.opt_present("i") || (m.free.len() >= 2 && m.free.get(1).as_slice() == "interactive") => {
			Interactive::new().run();
		},
		None if m.free.len() >= 2 => {
			Runner::new(m.free.get(1).clone()).run();
		},
		None => {
			println!("{}", getopts::short_usage("Usage: js.rs [OPTIONS] [INPUT]", opts));
		}
	}
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate rustuv;

extern crate "plugins" as servo_plugins;
extern crate servo;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate opengles;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate green;
extern crate native;
extern crate libc;
extern crate "url" as std_url;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

pub mod browser;
pub mod command_line;
pub mod core;
pub mod eutil;
#[cfg(target_os="linux")] #[cfg(target_os="macos")]
pub mod mem;
pub mod request;
pub mod string;
pub mod string_list;
pub mod task;
pub mod types;
pub mod urlrequest;

<commit_msg>Make some warnings errors in the cef port.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]
#![deny(unused_imports, unused_variable, unused_mut)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate rustuv;

extern crate "plugins" as servo_plugins;
extern crate servo;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate opengles;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate green;
extern crate native;
extern crate libc;
extern crate "url" as std_url;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

pub mod browser;
pub mod command_line;
pub mod core;
pub mod eutil;
#[cfg(target_os="linux")] #[cfg(target_os="macos")]
pub mod mem;
pub mod request;
pub mod string;
pub mod string_list;
pub mod task;
pub mod types;
pub mod urlrequest;

<|endoftext|>