<commit_before>use crate::direction::Direction;
use crate::event::{AnyCb, Event, EventResult};
use crate::rect::Rect;
use crate::vec::Vec2;
use crate::view::{Selector, View};
use crate::Printer;
use crate::With;

/// A blank view that forwards calls to closures.
///
/// You can use this view to easily draw your own interface.
pub struct Canvas<T> {
    state: T,

    draw: Box<dyn Fn(&T, &Printer)>,
    on_event: Box<dyn FnMut(&mut T, Event) -> EventResult>,
    required_size: Box<dyn FnMut(&mut T, Vec2) -> Vec2>,
    layout: Box<dyn FnMut(&mut T, Vec2)>,
    take_focus: Box<dyn FnMut(&mut T, Direction) -> bool>,
    needs_relayout: Box<dyn Fn(&T) -> bool>,
    focus_view: Box<dyn FnMut(&mut T, &Selector) -> Result<(), ()>>,
    call_on_any: Box<dyn for<'a> FnMut(&mut T, &Selector, AnyCb<'a>)>,
    important_area: Box<dyn Fn(&T, Vec2) -> Rect>,
}

impl<T: 'static + View> Canvas<T> {
    /// Creates a new Canvas around the given view.
    ///
    /// By default, forwards all calls to the inner view.
    pub fn wrap(view: T) -> Self {
        Canvas::new(view)
            .with_draw(T::draw)
            .with_on_event(T::on_event)
            .with_required_size(T::required_size)
            .with_layout(T::layout)
            .with_take_focus(T::take_focus)
            .with_needs_relayout(T::needs_relayout)
            .with_focus_view(T::focus_view)
            .with_call_on_any(T::call_on_any)
            .with_important_area(T::important_area)
    }
}

impl<T> Canvas<T> {
    /// Creates a new, empty Canvas.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cursive::views::Canvas;
    /// let canvas = Canvas::new(())
    ///                     .with_draw(|printer, _| {
    ///                         // Print the view
    ///                     });
    /// ```
    pub fn new(state: T) -> Self {
        Canvas {
            state,
            draw: Box::new(|_, _| ()),
            on_event: Box::new(|_, _| EventResult::Ignored),
            required_size: Box::new(|_, _| Vec2::new(1, 1)),
            layout: Box::new(|_, _| ()),
            take_focus: Box::new(|_, _| false),
            needs_relayout: Box::new(|_| true),
            focus_view: Box::new(|_, _| Err(())),
            call_on_any: Box::new(|_, _, _| ()),
            important_area: Box::new(|_, size| {
                Rect::from_corners((0, 0), size)
            }),
        }
    }

    /// Gets a mutable reference to the inner state.
    pub fn state_mut(&mut self) -> &mut T {
        &mut self.state
    }

    /// Sets the closure for `draw(&Printer)`.
    pub fn set_draw<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T, &Printer<'_, '_>),
    {
        self.draw = Box::new(f);
    }

    /// Sets the closure for `draw(&Printer)`.
    ///
    /// Chainable variant.
    pub fn with_draw<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T, &Printer<'_, '_>),
    {
        self.with(|s| s.set_draw(f))
    }

    /// Sets the closure for `on_event(Event)`.
    pub fn set_on_event<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Event) -> EventResult,
    {
        self.on_event = Box::new(f);
    }

    /// Sets the closure for `on_event(Event)`.
    ///
    /// Chainable variant.
    pub fn with_on_event<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Event) -> EventResult,
    {
        self.with(|s| s.set_on_event(f))
    }

    /// Sets the closure for `required_size(Vec2)`.
    pub fn set_required_size<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Vec2) -> Vec2,
    {
        self.required_size = Box::new(f);
    }

    /// Sets the closure for `required_size(Vec2)`.
    ///
    /// Chainable variant.
    pub fn with_required_size<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Vec2) -> Vec2,
    {
        self.with(|s| s.set_required_size(f))
    }

    /// Sets the closure for `layout(Vec2)`.
    pub fn set_layout<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Vec2),
    {
        self.layout = Box::new(f);
    }

    /// Sets the closure for `layout(Vec2)`.
    ///
    /// Chainable variant.
    pub fn with_layout<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Vec2),
    {
        self.with(|s| s.set_layout(f))
    }

    /// Sets the closure for `take_focus(Direction)`.
    pub fn set_take_focus<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Direction) -> bool,
    {
        self.take_focus = Box::new(f);
    }

    /// Sets the closure for `take_focus(Direction)`.
    ///
    /// Chainable variant.
    pub fn with_take_focus<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Direction) -> bool,
    {
        self.with(|s| s.set_take_focus(f))
    }

    /// Sets the closure for `needs_relayout()`.
    pub fn set_needs_relayout<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T) -> bool,
    {
        self.needs_relayout = Box::new(f);
    }

    /// Sets the closure for `needs_relayout()`.
    ///
    /// Chainable variant.
    pub fn with_needs_relayout<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T) -> bool,
    {
        self.with(|s| s.set_needs_relayout(f))
    }

    /// Sets the closure for `call_on_any()`.
    pub fn set_call_on_any<F>(&mut self, f: F)
    where
        F: 'static + for<'a> FnMut(&mut T, &Selector<'_>, AnyCb<'a>),
    {
        self.call_on_any = Box::new(f);
    }

    /// Sets the closure for `call_on_any()`.
    ///
    /// Chainable variant.
    pub fn with_call_on_any<F>(self, f: F) -> Self
    where
        F: 'static + for<'a> FnMut(&mut T, &Selector<'_>, AnyCb<'a>),
    {
        self.with(|s| s.set_call_on_any(f))
    }

    /// Sets the closure for `important_area()`.
    pub fn set_important_area<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T, Vec2) -> Rect,
    {
        self.important_area = Box::new(f);
    }

    /// Sets the closure for `important_area()`.
    ///
    /// Chainable variant.
    pub fn with_important_area<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T, Vec2) -> Rect,
    {
        self.with(|s| s.set_important_area(f))
    }

    /// Sets the closure for `focus_view()`.
    pub fn set_focus_view<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
    {
        self.focus_view = Box::new(f);
    }

    /// Sets the closure for `focus_view()`.
    ///
    /// Chainable variant.
    pub fn with_focus_view<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
    {
        self.with(|s| s.set_focus_view(f))
    }
}

impl<T: 'static> View for Canvas<T> {
    fn draw(&self, printer: &Printer<'_, '_>) {
        (self.draw)(&self.state, printer);
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        (self.on_event)(&mut self.state, event)
    }

    fn required_size(&mut self, constraint: Vec2) -> Vec2 {
        (self.required_size)(&mut self.state, constraint)
    }

    fn layout(&mut self, size: Vec2) {
        (self.layout)(&mut self.state, size);
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        (self.take_focus)(&mut self.state, source)
    }

    fn needs_relayout(&self) -> bool {
        (self.needs_relayout)(&self.state)
    }

    fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
        (self.focus_view)(&mut self.state, selector)
    }

    fn important_area(&self, view_size: Vec2) -> Rect {
        (self.important_area)(&self.state, view_size)
    }

    fn call_on_any<'a>(&mut self, selector: &Selector<'_>, cb: AnyCb<'a>) {
        (self.call_on_any)(&mut self.state, selector, cb);
    }
}
<commit_msg>Fix clippy warning<commit_after>use crate::direction::Direction;
use crate::event::{AnyCb, Event, EventResult};
use crate::rect::Rect;
use crate::vec::Vec2;
use crate::view::{Selector, View};
use crate::Printer;
use crate::With;

// Define this type separately to appease the Clippy god
type CallOnAny<T> = Box<dyn for<'a> FnMut(&mut T, &Selector, AnyCb<'a>)>;

/// A blank view that forwards calls to closures.
///
/// You can use this view to easily draw your own interface.
pub struct Canvas<T> {
    state: T,

    draw: Box<dyn Fn(&T, &Printer)>,
    on_event: Box<dyn FnMut(&mut T, Event) -> EventResult>,
    required_size: Box<dyn FnMut(&mut T, Vec2) -> Vec2>,
    layout: Box<dyn FnMut(&mut T, Vec2)>,
    take_focus: Box<dyn FnMut(&mut T, Direction) -> bool>,
    needs_relayout: Box<dyn Fn(&T) -> bool>,
    focus_view: Box<dyn FnMut(&mut T, &Selector) -> Result<(), ()>>,
    call_on_any: CallOnAny<T>,
    important_area: Box<dyn Fn(&T, Vec2) -> Rect>,
}

impl<T: 'static + View> Canvas<T> {
    /// Creates a new Canvas around the given view.
    ///
    /// By default, forwards all calls to the inner view.
    pub fn wrap(view: T) -> Self {
        Canvas::new(view)
            .with_draw(T::draw)
            .with_on_event(T::on_event)
            .with_required_size(T::required_size)
            .with_layout(T::layout)
            .with_take_focus(T::take_focus)
            .with_needs_relayout(T::needs_relayout)
            .with_focus_view(T::focus_view)
            .with_call_on_any(T::call_on_any)
            .with_important_area(T::important_area)
    }
}

impl<T> Canvas<T> {
    /// Creates a new, empty Canvas.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use cursive::views::Canvas;
    /// let canvas = Canvas::new(())
    ///                     .with_draw(|printer, _| {
    ///                         // Print the view
    ///                     });
    /// ```
    pub fn new(state: T) -> Self {
        Canvas {
            state,
            draw: Box::new(|_, _| ()),
            on_event: Box::new(|_, _| EventResult::Ignored),
            required_size: Box::new(|_, _| Vec2::new(1, 1)),
            layout: Box::new(|_, _| ()),
            take_focus: Box::new(|_, _| false),
            needs_relayout: Box::new(|_| true),
            focus_view: Box::new(|_, _| Err(())),
            call_on_any: Box::new(|_, _, _| ()),
            important_area: Box::new(|_, size| {
                Rect::from_corners((0, 0), size)
            }),
        }
    }

    /// Gets a mutable reference to the inner state.
    pub fn state_mut(&mut self) -> &mut T {
        &mut self.state
    }

    /// Sets the closure for `draw(&Printer)`.
    pub fn set_draw<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T, &Printer<'_, '_>),
    {
        self.draw = Box::new(f);
    }

    /// Sets the closure for `draw(&Printer)`.
    ///
    /// Chainable variant.
    pub fn with_draw<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T, &Printer<'_, '_>),
    {
        self.with(|s| s.set_draw(f))
    }

    /// Sets the closure for `on_event(Event)`.
    pub fn set_on_event<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Event) -> EventResult,
    {
        self.on_event = Box::new(f);
    }

    /// Sets the closure for `on_event(Event)`.
    ///
    /// Chainable variant.
    pub fn with_on_event<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Event) -> EventResult,
    {
        self.with(|s| s.set_on_event(f))
    }

    /// Sets the closure for `required_size(Vec2)`.
    pub fn set_required_size<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Vec2) -> Vec2,
    {
        self.required_size = Box::new(f);
    }

    /// Sets the closure for `required_size(Vec2)`.
    ///
    /// Chainable variant.
    pub fn with_required_size<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Vec2) -> Vec2,
    {
        self.with(|s| s.set_required_size(f))
    }

    /// Sets the closure for `layout(Vec2)`.
    pub fn set_layout<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Vec2),
    {
        self.layout = Box::new(f);
    }

    /// Sets the closure for `layout(Vec2)`.
    ///
    /// Chainable variant.
    pub fn with_layout<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Vec2),
    {
        self.with(|s| s.set_layout(f))
    }

    /// Sets the closure for `take_focus(Direction)`.
    pub fn set_take_focus<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, Direction) -> bool,
    {
        self.take_focus = Box::new(f);
    }

    /// Sets the closure for `take_focus(Direction)`.
    ///
    /// Chainable variant.
    pub fn with_take_focus<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, Direction) -> bool,
    {
        self.with(|s| s.set_take_focus(f))
    }

    /// Sets the closure for `needs_relayout()`.
    pub fn set_needs_relayout<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T) -> bool,
    {
        self.needs_relayout = Box::new(f);
    }

    /// Sets the closure for `needs_relayout()`.
    ///
    /// Chainable variant.
    pub fn with_needs_relayout<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T) -> bool,
    {
        self.with(|s| s.set_needs_relayout(f))
    }

    /// Sets the closure for `call_on_any()`.
    pub fn set_call_on_any<F>(&mut self, f: F)
    where
        F: 'static + for<'a> FnMut(&mut T, &Selector<'_>, AnyCb<'a>),
    {
        self.call_on_any = Box::new(f);
    }

    /// Sets the closure for `call_on_any()`.
    ///
    /// Chainable variant.
    pub fn with_call_on_any<F>(self, f: F) -> Self
    where
        F: 'static + for<'a> FnMut(&mut T, &Selector<'_>, AnyCb<'a>),
    {
        self.with(|s| s.set_call_on_any(f))
    }

    /// Sets the closure for `important_area()`.
    pub fn set_important_area<F>(&mut self, f: F)
    where
        F: 'static + Fn(&T, Vec2) -> Rect,
    {
        self.important_area = Box::new(f);
    }

    /// Sets the closure for `important_area()`.
    ///
    /// Chainable variant.
    pub fn with_important_area<F>(self, f: F) -> Self
    where
        F: 'static + Fn(&T, Vec2) -> Rect,
    {
        self.with(|s| s.set_important_area(f))
    }

    /// Sets the closure for `focus_view()`.
    pub fn set_focus_view<F>(&mut self, f: F)
    where
        F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
    {
        self.focus_view = Box::new(f);
    }

    /// Sets the closure for `focus_view()`.
    ///
    /// Chainable variant.
    pub fn with_focus_view<F>(self, f: F) -> Self
    where
        F: 'static + FnMut(&mut T, &Selector<'_>) -> Result<(), ()>,
    {
        self.with(|s| s.set_focus_view(f))
    }
}

impl<T: 'static> View for Canvas<T> {
    fn draw(&self, printer: &Printer<'_, '_>) {
        (self.draw)(&self.state, printer);
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        (self.on_event)(&mut self.state, event)
    }

    fn required_size(&mut self, constraint: Vec2) -> Vec2 {
        (self.required_size)(&mut self.state, constraint)
    }

    fn layout(&mut self, size: Vec2) {
        (self.layout)(&mut self.state, size);
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        (self.take_focus)(&mut self.state, source)
    }

    fn needs_relayout(&self) -> bool {
        (self.needs_relayout)(&self.state)
    }

    fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
        (self.focus_view)(&mut self.state, selector)
    }

    fn important_area(&self, view_size: Vec2) -> Rect {
        (self.important_area)(&self.state, view_size)
    }

    fn call_on_any<'a>(&mut self, selector: &Selector<'_>, cb: AnyCb<'a>) {
        (self.call_on_any)(&mut self.state, selector, cb);
    }
}
<|endoftext|>


<commit_before>use std::net::{ IpAddr, Ipv4Addr, SocketAddr };
use super::agent::Agent;
use super::config::ServerConfig;
use super::state::*;
use std::sync::{Arc, RwLock};

use tokio::io;
use tokio::net::TcpListener;
use tokio::prelude::*;
use futures::channel::mpsc::{ channel, Sender, Receiver };
use futures::future;
use futures::{ IntoFuture, SinkExt };

pub struct Server<'c> {
    state: Arc<RwLock<State>>,
    config: &'c ServerConfig
}

enum Event {
    NOP
}

pub struct SyncTask {
    tx: Sender<Event>
}

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

    fn poll(&mut self) -> Result<Async<()>, ()> {
        Err(())
    }
}

impl<'c> Server<'c> {
    pub fn new(config: &'c ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Server { state, config }
    }

    pub fn start(&mut self) {
        let addr = "0.0.0.0:7979".parse().unwrap();
        let listener = TcpListener::bind(&addr).unwrap();

        let (tx, rx) = channel(65536);

        let server = listener.incoming().for_each(move |socket| {
            println!("accepted socket; addr={:?}", socket.peer_addr().unwrap());

            let connection = io::write_all(socket, "Hello guy\n")
            .then(|res| {
                println!("Greeting sent, success={:?}", res);
                Ok(())
            });

            ::tokio::spawn(connection);

            let task = SyncTask { tx: tx.clone() };

            ::tokio::spawn(task);

            //let sync = future::result(tx.send(Event::NOP)).into_future();

            //let s: String = tx.send(Event::NOP);

            //::tokio::spawn(sync);

            Ok(())
        }).map_err(|err| println!("accept error = {:?}", err));

        ::tokio::run(server);

        if let Ok(mut state) = self.state.write() {
            let agents: &mut Vec<Agent> = &mut (*state).registered_agents;

            let a = Ipv4Addr::new(127, 0, 0, 1);
            let b = IpAddr::V4(a);
            let c = SocketAddr::new(b, 8080);
            agents.push(Agent::new(c));
        }
    }
}
<commit_msg>Very very basic message sending is working already<commit_after>use std::net::{ IpAddr, Ipv4Addr, SocketAddr };
use super::agent::Agent;
use super::config::ServerConfig;
use super::state::*;
use std::sync::{Arc, RwLock};

use tokio::io;
use tokio::net::TcpListener;
use tokio::prelude::*;
use futures::channel::mpsc::{ channel, Sender, Receiver };
use futures::future;
use futures::{ IntoFuture, SinkExt };
use std::thread;

pub struct Server<'c> {
    state: Arc<RwLock<State>>,
    config: &'c ServerConfig
}

#[derive(Debug)]
enum Event {
    NOP
}

pub struct SyncTask {
    tx: Sender<Event>
}

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

    fn poll(&mut self) -> Result<Async<()>, ()> {
        self.tx.try_send(Event::NOP);//.unwrap();
        Err(())
    }
}

impl<'c> Server<'c> {
    pub fn new(config: &'c ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Server { state, config }
    }

    pub fn start(&mut self) {
        let addr = "0.0.0.0:7979".parse().unwrap();
        let listener = TcpListener::bind(&addr).unwrap();

        let (tx, mut rx) = channel(65536);

        let server = listener.incoming().for_each(move |socket| {
            println!("accepted socket; addr={:?}", socket.peer_addr().unwrap());

            let connection = io::write_all(socket, "Hello guy\n")
            .then(|res| {
                println!("Greeting sent, success={:?}", res);
                Ok(())
            });

            ::tokio::spawn(connection);

            let task = SyncTask { tx: tx.clone() };

            ::tokio::spawn(task);

            //let sync = future::result(tx.send(Event::NOP)).into_future();

            //let s: String = tx.send(Event::NOP);

            //::tokio::spawn(sync);

            Ok(())
        }).map_err(|err| println!("accept error = {:?}", err));

        let handle = thread::spawn(move || {
            loop {
                if let Ok(msg) = rx.try_next() {
                    println!("Got message: {:?}", msg);
                }
            }
        });

        ::tokio::run(server);

        handle.join().unwrap();

        if let Ok(mut state) = self.state.write() {
            let agents: &mut Vec<Agent> = &mut (*state).registered_agents;

            let a = Ipv4Addr::new(127, 0, 0, 1);
            let b = IpAddr::V4(a);
            let c = SocketAddr::new(b, 8080);
            agents.push(Agent::new(c));
        }
    }
}
<|endoftext|>


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

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>rollup merge of #19832: japaric/no-nocopy<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v[mut read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8, ..4] = [0u8, ..4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8, ..8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(&mut v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>use sys::joystick as ll;

use JoystickSubsystem;
use get_error;
use clear_error;
use sys::event::{SDL_QUERY, SDL_ENABLE};
use std::ffi::{CString, CStr, NulError};
use std::fmt::{Display, Formatter, Error};
use libc::c_char;
use common::{validate_int, IntegerOrSdlError};

impl JoystickSubsystem {
    /// Retreive the total number of attached joysticks *and* controllers identified by SDL.
    pub fn num_joysticks(&self) -> Result<u32, String> {
        let result = unsafe { ll::SDL_NumJoysticks() };

        if result >= 0 {
            Ok(result as u32)
        } else {
            Err(get_error())
        }
    }

    /// Attempt to open the joystick at number `id` and return it.
    pub fn open(&self, joystick_index: u32)
            -> Result<Joystick, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let joystick = unsafe { ll::SDL_JoystickOpen(joystick_index) };

        if joystick.is_null() {
            Err(SdlError(get_error()))
        } else {
            Ok(Joystick {
                subsystem: self.clone(),
                raw: joystick
            })
        }
    }

    /// Return the name of the joystick at index `id`
    pub fn name_for_index(&self, joystick_index: u32) -> Result<String, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let c_str = unsafe { ll::SDL_JoystickNameForIndex(joystick_index) };

        if c_str.is_null() {
            Err(SdlError(get_error()))
        } else {
            Ok(unsafe {
                CStr::from_ptr(c_str as *const _).to_str().unwrap().to_string()
            })
        }
    }

    /// Get the GUID for the joystick number `id`
    pub fn device_guid(&self, joystick_index: u32) -> Result<Guid, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let raw = unsafe { ll::SDL_JoystickGetDeviceGUID(joystick_index) };

        let guid = Guid { raw: raw };

        if guid.is_zero() {
            Err(SdlError(get_error()))
        } else {
            Ok(guid)
        }
    }

    /// If state is `true` joystick events are processed, otherwise
    /// they're ignored.
    pub fn set_event_state(&self, state: bool) {
        unsafe { ll::SDL_JoystickEventState(state as i32) };
    }

    /// Return `true` if joystick events are processed.
    pub fn event_state(&self) -> bool {
        unsafe { ll::SDL_JoystickEventState(SDL_QUERY as i32)
                 == SDL_ENABLE as i32 }
    }

    /// Force joystick update when not using the event loop
    #[inline]
    pub fn update(&self) {
        unsafe { ll::SDL_JoystickUpdate() };
    }

}

/// Wrapper around the SDL_Joystick object
pub struct Joystick {
    subsystem: JoystickSubsystem,
    raw: *mut ll::SDL_Joystick
}

impl Joystick {
    #[inline]
    pub fn subsystem(&self) -> &JoystickSubsystem { &self.subsystem }

    /// Return the name of the joystick or an empty string if no name
    /// is found.
    pub fn name(&self) -> String {
        let name = unsafe { ll::SDL_JoystickName(self.raw) };

        c_str_to_string(name)
    }

    /// Return true if the joystick has been opened and currently
    /// connected.
    pub fn attached(&self) -> bool {
        unsafe { ll::SDL_JoystickGetAttached(self.raw) != 0 }
    }

    pub fn instance_id(&self) -> i32 {
        let result = unsafe { ll::SDL_JoystickInstanceID(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result
        }
    }

    /// Retreive the joystick's GUID
    pub fn guid(&self) -> Guid {
        let raw = unsafe { ll::SDL_JoystickGetGUID(self.raw) };

        let guid = Guid { raw: raw };

        if guid.is_zero() {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            guid
        }
    }

    /// Retreive the number of axes for this joystick
    pub fn num_axes(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumAxes(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Gets the position of the given `axis`.
    ///
    /// The function will fail if the joystick doesn't have the provided axis.
    pub fn axis(&self, axis: u32) -> Result<i16, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // This interface is a bit messed up: 0 is a valid position
        // but can also mean that an error occured. As far as I can
        // tell the only way to know if an error happened is to see if
        // get_error() returns a non-empty string.
        clear_error();

        let axis = try!(validate_int(axis, "axis"));
        let pos = unsafe { ll::SDL_JoystickGetAxis(self.raw, axis) };

        if pos != 0 {
            Ok(pos)
        } else {
            let err = get_error();

            if err.is_empty() {
                Ok(pos)
            } else {
                Err(SdlError(err))
            }
        }
    }

    /// Retreive the number of buttons for this joystick
    pub fn num_buttons(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumButtons(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return `Ok(true)` if `button` is pressed.
    ///
    /// The function will fail if the joystick doesn't have the provided button.
    pub fn button(&self, button: u32) -> Result<bool, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // Same deal as axis, 0 can mean both unpressed or
        // error...
        clear_error();

        let button = try!(validate_int(button, "button"));
        let pressed = unsafe { ll::SDL_JoystickGetButton(self.raw, button) };

        match pressed {
            1 => Ok(true),
            0 => {
                let err = get_error();

                if err.is_empty() {
                    // Button is not pressed
                    Ok(false)
                } else {
                    Err(SdlError(err))
                }
            }
            // Should be unreachable
            _ => unreachable!(),
        }
    }

    /// Retreive the number of balls for this joystick
    pub fn num_balls(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumBalls(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return a pair `(dx, dy)` containing the difference in axis
    /// position since the last poll
    pub fn ball(&self, ball: u32) -> Result<(i32, i32), IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let mut dx = 0;
        let mut dy = 0;

        let ball = try!(validate_int(ball, "ball"));
        let result = unsafe { ll::SDL_JoystickGetBall(self.raw, ball, &mut dx, &mut dy) };

        if result == 0 {
            Ok((dx, dy))
        } else {
            Err(SdlError(get_error()))
        }
    }

    /// Retreive the number of balls for this joystick
    pub fn num_hats(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumHats(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return the position of `hat` for this joystick
    pub fn hat(&self, hat: u32) -> Result<HatState, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // Guess what? This function as well uses 0 to report an error
        // but 0 is also a valid value (HatState::Centered). So we
        // have to use the same hack as `axis`...
        clear_error();

        let hat = try!(validate_int(hat, "hat"));
        let result = unsafe { ll::SDL_JoystickGetHat(self.raw, hat) };

        let state = HatState::from_raw(result as u8);

        if result != 0 {
            Ok(state)
        } else {
            let err = get_error();

            if err.is_empty() {
                Ok(state)
            } else {
                Err(SdlError(err))
            }
        }
    }
}

impl Drop for Joystick {
    fn drop(&mut self) {
        if self.attached() {
            unsafe { ll::SDL_JoystickClose(self.raw) }
        }
    }
}

/// Wrapper around a SDL_JoystickGUID, a globally unique identifier
/// for a joystick.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Guid {
    raw: ll::SDL_JoystickGUID,
}

impl Guid {
    /// Create a GUID from a string representation.
    pub fn from_string(guid: &str) -> Result<Guid, NulError> {
        let guid = try!(CString::new(guid));

        let raw = unsafe { ll::SDL_JoystickGetGUIDFromString(guid.as_ptr() as *const c_char) };

        Ok(Guid { raw: raw })
    }

    /// Return `true` if GUID is full 0s
    pub fn is_zero(&self) -> bool {
        for &i in self.raw.data.iter() {
            if i != 0 {
                return false;
            }
        }

        return true;
    }

    /// Return a String representation of GUID
    pub fn string(&self) -> String {
        // Doc says "buf should supply at least 33bytes". I took that
        // to mean that 33bytes should be enough in all cases, but
        // maybe I'm wrong?
        let mut buf = [0; 33];

        let len   = buf.len() as i32;
        let c_str = buf.as_mut_ptr();

        unsafe {
            ll::SDL_JoystickGetGUIDString(self.raw, c_str, len);
        }

        // The buffer should always be NUL terminated (the
        // documentation doesn't explicitely say it but I checked the
        // code)
        if c_str.is_null() {
            String::new()
        } else {
            unsafe {
                CStr::from_ptr(c_str as *const _).to_str().unwrap().to_string()
            }
        }
    }

    /// Return a copy of the internal SDL_JoystickGUID
    pub fn raw(self) -> ll::SDL_JoystickGUID {
        self.raw
    }
}

impl Display for Guid {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.string())
    }
}

/// This is represented in SDL2 as a bitfield but obviously not all
/// combinations make sense: 5 for instance would mean up and down at
/// the same time... To simplify things I turn it into an enum which
/// is how the SDL2 docs present it anyway (using macros).
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum HatState {
    Centered  = 0,
    Up        = 0x01,
    Right     = 0x02,
    Down      = 0x04,
    Left      = 0x08,
    RightUp   = 0x02 | 0x01,
    RightDown = 0x02 | 0x04,
    LeftUp    = 0x08 | 0x01,
    Leftdown  = 0x08 | 0x04,
}

impl HatState {
    pub fn from_raw(raw: u8) -> HatState {
        match raw {
            0  => HatState::Centered,
            1  => HatState::Up,
            2  => HatState::Right,
            4  => HatState::Down,
            8  => HatState::Left,
            3  => HatState::RightUp,
            6  => HatState::RightDown,
            9  => HatState::LeftUp,
            12 => HatState::Leftdown,
            _  => panic!("Unexpected hat position: {}", raw),
        }
    }

    pub fn to_raw(&self) -> u8 {
        match *self {
            HatState::Centered => 0,
            HatState::Up => 1,
            HatState::Right => 2,
            HatState::Down => 4,
            HatState::Left => 8,
            HatState::RightUp => 3,
            HatState::RightDown => 6,
            HatState::LeftUp => 9,
            HatState::Leftdown => 12,
        }

    }
}

/// Convert C string `c_str` to a String. Return an empty string if
/// c_str is NULL.
fn c_str_to_string(c_str: *const c_char) -> String {
    if c_str.is_null() {
        String::new()
    } else {
        let bytes = unsafe { CStr::from_ptr(c_str as *const _).to_bytes() };

        String::from_utf8_lossy(bytes).to_string()
    }
}
<commit_msg>Fix HatState::Leftdown casing into HatState::LeftDown<commit_after>use sys::joystick as ll;

use JoystickSubsystem;
use get_error;
use clear_error;
use sys::event::{SDL_QUERY, SDL_ENABLE};
use std::ffi::{CString, CStr, NulError};
use std::fmt::{Display, Formatter, Error};
use libc::c_char;
use common::{validate_int, IntegerOrSdlError};

impl JoystickSubsystem {
    /// Retreive the total number of attached joysticks *and* controllers identified by SDL.
    pub fn num_joysticks(&self) -> Result<u32, String> {
        let result = unsafe { ll::SDL_NumJoysticks() };

        if result >= 0 {
            Ok(result as u32)
        } else {
            Err(get_error())
        }
    }

    /// Attempt to open the joystick at number `id` and return it.
    pub fn open(&self, joystick_index: u32)
            -> Result<Joystick, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let joystick = unsafe { ll::SDL_JoystickOpen(joystick_index) };

        if joystick.is_null() {
            Err(SdlError(get_error()))
        } else {
            Ok(Joystick {
                subsystem: self.clone(),
                raw: joystick
            })
        }
    }

    /// Return the name of the joystick at index `id`
    pub fn name_for_index(&self, joystick_index: u32) -> Result<String, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let c_str = unsafe { ll::SDL_JoystickNameForIndex(joystick_index) };

        if c_str.is_null() {
            Err(SdlError(get_error()))
        } else {
            Ok(unsafe {
                CStr::from_ptr(c_str as *const _).to_str().unwrap().to_string()
            })
        }
    }

    /// Get the GUID for the joystick number `id`
    pub fn device_guid(&self, joystick_index: u32) -> Result<Guid, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let joystick_index = try!(validate_int(joystick_index, "joystick_index"));

        let raw = unsafe { ll::SDL_JoystickGetDeviceGUID(joystick_index) };

        let guid = Guid { raw: raw };

        if guid.is_zero() {
            Err(SdlError(get_error()))
        } else {
            Ok(guid)
        }
    }

    /// If state is `true` joystick events are processed, otherwise
    /// they're ignored.
    pub fn set_event_state(&self, state: bool) {
        unsafe { ll::SDL_JoystickEventState(state as i32) };
    }

    /// Return `true` if joystick events are processed.
    pub fn event_state(&self) -> bool {
        unsafe { ll::SDL_JoystickEventState(SDL_QUERY as i32)
                 == SDL_ENABLE as i32 }
    }

    /// Force joystick update when not using the event loop
    #[inline]
    pub fn update(&self) {
        unsafe { ll::SDL_JoystickUpdate() };
    }

}

/// Wrapper around the SDL_Joystick object
pub struct Joystick {
    subsystem: JoystickSubsystem,
    raw: *mut ll::SDL_Joystick
}

impl Joystick {
    #[inline]
    pub fn subsystem(&self) -> &JoystickSubsystem { &self.subsystem }

    /// Return the name of the joystick or an empty string if no name
    /// is found.
    pub fn name(&self) -> String {
        let name = unsafe { ll::SDL_JoystickName(self.raw) };

        c_str_to_string(name)
    }

    /// Return true if the joystick has been opened and currently
    /// connected.
    pub fn attached(&self) -> bool {
        unsafe { ll::SDL_JoystickGetAttached(self.raw) != 0 }
    }

    pub fn instance_id(&self) -> i32 {
        let result = unsafe { ll::SDL_JoystickInstanceID(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result
        }
    }

    /// Retreive the joystick's GUID
    pub fn guid(&self) -> Guid {
        let raw = unsafe { ll::SDL_JoystickGetGUID(self.raw) };

        let guid = Guid { raw: raw };

        if guid.is_zero() {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            guid
        }
    }

    /// Retreive the number of axes for this joystick
    pub fn num_axes(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumAxes(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Gets the position of the given `axis`.
    ///
    /// The function will fail if the joystick doesn't have the provided axis.
    pub fn axis(&self, axis: u32) -> Result<i16, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // This interface is a bit messed up: 0 is a valid position
        // but can also mean that an error occured. As far as I can
        // tell the only way to know if an error happened is to see if
        // get_error() returns a non-empty string.
        clear_error();

        let axis = try!(validate_int(axis, "axis"));
        let pos = unsafe { ll::SDL_JoystickGetAxis(self.raw, axis) };

        if pos != 0 {
            Ok(pos)
        } else {
            let err = get_error();

            if err.is_empty() {
                Ok(pos)
            } else {
                Err(SdlError(err))
            }
        }
    }

    /// Retreive the number of buttons for this joystick
    pub fn num_buttons(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumButtons(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return `Ok(true)` if `button` is pressed.
    ///
    /// The function will fail if the joystick doesn't have the provided button.
    pub fn button(&self, button: u32) -> Result<bool, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // Same deal as axis, 0 can mean both unpressed or
        // error...
        clear_error();

        let button = try!(validate_int(button, "button"));
        let pressed = unsafe { ll::SDL_JoystickGetButton(self.raw, button) };

        match pressed {
            1 => Ok(true),
            0 => {
                let err = get_error();

                if err.is_empty() {
                    // Button is not pressed
                    Ok(false)
                } else {
                    Err(SdlError(err))
                }
            }
            // Should be unreachable
            _ => unreachable!(),
        }
    }

    /// Retreive the number of balls for this joystick
    pub fn num_balls(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumBalls(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return a pair `(dx, dy)` containing the difference in axis
    /// position since the last poll
    pub fn ball(&self, ball: u32) -> Result<(i32, i32), IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        let mut dx = 0;
        let mut dy = 0;

        let ball = try!(validate_int(ball, "ball"));
        let result = unsafe { ll::SDL_JoystickGetBall(self.raw, ball, &mut dx, &mut dy) };

        if result == 0 {
            Ok((dx, dy))
        } else {
            Err(SdlError(get_error()))
        }
    }

    /// Retreive the number of balls for this joystick
    pub fn num_hats(&self) -> u32 {
        let result = unsafe { ll::SDL_JoystickNumHats(self.raw) };

        if result < 0 {
            // Should only fail if the joystick is NULL.
            panic!(get_error())
        } else {
            result as u32
        }
    }

    /// Return the position of `hat` for this joystick
    pub fn hat(&self, hat: u32) -> Result<HatState, IntegerOrSdlError> {
        use common::IntegerOrSdlError::*;
        // Guess what? This function as well uses 0 to report an error
        // but 0 is also a valid value (HatState::Centered). So we
        // have to use the same hack as `axis`...
        clear_error();

        let hat = try!(validate_int(hat, "hat"));
        let result = unsafe { ll::SDL_JoystickGetHat(self.raw, hat) };

        let state = HatState::from_raw(result as u8);

        if result != 0 {
            Ok(state)
        } else {
            let err = get_error();

            if err.is_empty() {
                Ok(state)
            } else {
                Err(SdlError(err))
            }
        }
    }
}

impl Drop for Joystick {
    fn drop(&mut self) {
        if self.attached() {
            unsafe { ll::SDL_JoystickClose(self.raw) }
        }
    }
}

/// Wrapper around a SDL_JoystickGUID, a globally unique identifier
/// for a joystick.
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub struct Guid {
    raw: ll::SDL_JoystickGUID,
}

impl Guid {
    /// Create a GUID from a string representation.
    pub fn from_string(guid: &str) -> Result<Guid, NulError> {
        let guid = try!(CString::new(guid));

        let raw = unsafe { ll::SDL_JoystickGetGUIDFromString(guid.as_ptr() as *const c_char) };

        Ok(Guid { raw: raw })
    }

    /// Return `true` if GUID is full 0s
    pub fn is_zero(&self) -> bool {
        for &i in self.raw.data.iter() {
            if i != 0 {
                return false;
            }
        }

        return true;
    }

    /// Return a String representation of GUID
    pub fn string(&self) -> String {
        // Doc says "buf should supply at least 33bytes". I took that
        // to mean that 33bytes should be enough in all cases, but
        // maybe I'm wrong?
        let mut buf = [0; 33];

        let len   = buf.len() as i32;
        let c_str = buf.as_mut_ptr();

        unsafe {
            ll::SDL_JoystickGetGUIDString(self.raw, c_str, len);
        }

        // The buffer should always be NUL terminated (the
        // documentation doesn't explicitely say it but I checked the
        // code)
        if c_str.is_null() {
            String::new()
        } else {
            unsafe {
                CStr::from_ptr(c_str as *const _).to_str().unwrap().to_string()
            }
        }
    }

    /// Return a copy of the internal SDL_JoystickGUID
    pub fn raw(self) -> ll::SDL_JoystickGUID {
        self.raw
    }
}

impl Display for Guid {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f, "{}", self.string())
    }
}

/// This is represented in SDL2 as a bitfield but obviously not all
/// combinations make sense: 5 for instance would mean up and down at
/// the same time... To simplify things I turn it into an enum which
/// is how the SDL2 docs present it anyway (using macros).
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum HatState {
    Centered  = 0,
    Up        = 0x01,
    Right     = 0x02,
    Down      = 0x04,
    Left      = 0x08,
    RightUp   = 0x02 | 0x01,
    RightDown = 0x02 | 0x04,
    LeftUp    = 0x08 | 0x01,
    LeftDown  = 0x08 | 0x04,
}

impl HatState {
    pub fn from_raw(raw: u8) -> HatState {
        match raw {
            0  => HatState::Centered,
            1  => HatState::Up,
            2  => HatState::Right,
            4  => HatState::Down,
            8  => HatState::Left,
            3  => HatState::RightUp,
            6  => HatState::RightDown,
            9  => HatState::LeftUp,
            12 => HatState::Leftdown,
            _  => panic!("Unexpected hat position: {}", raw),
        }
    }

    pub fn to_raw(&self) -> u8 {
        match *self {
            HatState::Centered => 0,
            HatState::Up => 1,
            HatState::Right => 2,
            HatState::Down => 4,
            HatState::Left => 8,
            HatState::RightUp => 3,
            HatState::RightDown => 6,
            HatState::LeftUp => 9,
            HatState::Leftdown => 12,
        }

    }
}

/// Convert C string `c_str` to a String. Return an empty string if
/// c_str is NULL.
fn c_str_to_string(c_str: *const c_char) -> String {
    if c_str.is_null() {
        String::new()
    } else {
        let bytes = unsafe { CStr::from_ptr(c_str as *const _).to_bytes() };

        String::from_utf8_lossy(bytes).to_string()
    }
}
<|endoftext|>


<commit_before>use std::usize;
use std::cmp::min;

use netbuf::MAX_BUF_SIZE;
use rotor::Scope;
use rotor_stream::{Protocol, StreamSocket, Deadline, Expectation as E};
use rotor_stream::{Request, Transport};
use hyper::status::StatusCode::{self, PayloadTooLarge};
use hyper::method::Method::Head;
use hyper::header::Expect;

use super::{MAX_HEADERS_NUM, MAX_HEADERS_SIZE, MAX_CHUNK_HEAD};
use super::{Response};
use super::protocol::{Server, RecvMode};
use super::context::Context;
use super::request::Head;
use super::body::BodyKind;

struct ReadBody<M: Sized> {
    machine: M,
    deadline: Deadline,
    progress: BodyProgress,
}

pub enum BodyProgress {
    /// Buffered fixed-size request (bytes left)
    BufferFixed(usize),
    /// Buffered request till end of input (byte limit)
    BufferEOF(usize),
    /// Buffered request with chunked encoding
    /// (limit, bytes buffered, bytes left for current chunk)
    BufferChunked(usize, usize, usize),
    /// Progressive fixed-size request (size hint, bytes left)
    ProgressiveFixed(usize, u64),
    /// Progressive till end of input (size hint)
    ProgressiveEOF(usize),
    /// Progressive with chunked encoding (hint, bytes left for current chunk)
    // To be able to merge chunks, should add offset here
    ProgressiveChunked(usize, u64),
}

pub enum Parser<M: Sized> {
    Idle,
    ReadHeaders,
    ReadingBody(ReadBody<M>),
    /// Close connection after buffer is flushed. In other cases -> Idle
    DoneResponse,
}

impl<M> Parser<M>
{
    fn flush<C>(scope: &mut Scope<C>) -> Request<Parser<M>>
        where C: Context
    {
        Some((Parser::DoneResponse, E::Flush(0),
              Deadline::now() + scope.byte_timeout()))
    }
}

fn start_headers<C: Context, M: Sized>(scope: &mut Scope<C>)
    -> Request<Parser<M>>
{
    Some((Parser::ReadHeaders,
          E::Delimiter(0, b"\r\n\r\n", MAX_HEADERS_SIZE),
          Deadline::now() + scope.byte_timeout()))
}

fn start_body(mode: RecvMode, body: BodyKind) -> BodyProgress {
    use super::body::BodyKind::*;
    use super::protocol::RecvMode::*;
    use self::BodyProgress::*;

    match (mode, body) {
        // The size of Fixed(x) is checked in parse_headers
        (Buffered(x), Fixed(y)) => BufferFixed(y as usize),
        (Buffered(x), Chunked) => BufferChunked(x, 0, 0),
        (Buffered(x), Eof) => BufferEOF(x),
        (Progressive(x), Fixed(y)) => ProgressiveFixed(x, y),
        (Progressive(x), Chunked) => ProgressiveChunked(x, 0),
        (Progressive(x), Eof) => ProgressiveEOF(x),
        (_, Upgrade) => unimplemented!(),
    }
}

// Parses headers
//
// On error returns bool, which is true if keep-alive connection can be
// carried on.
fn parse_headers<C, M, S>(transport: &mut Transport<S>, end: usize,
    scope: &mut Scope<C>) -> Result<ReadBody<M>, bool>
    where M: Server<C, S>,
          S: StreamSocket,
          C: Context,
{
    use self::Parser::*;
    // Determines if we can keep-alive after error response.
    // We may not be able to keep keep-alive for multiple reasons:
    //
    // 1. When request headers are too wrong
    //    (probably client connects with wrong protocol)
    //
    // 2. When request contains non-empty request body (we don't
    //    want to wait until it is uploaded just to send error)
    //
    // Note we definitely can't keep alive if we can't say
    // whether request method is HEAD
    //
    // All of these are important to avoid cache poisoning attacks
    // on proxy servers.
    let mut can_keep_alive = false;
    // Determines if we can safely send the response body
    let mut is_head = false;

    let status = match Head::parse(&transport.input()[..end+4]) {
        Ok(head) => {
            is_head = head.method == Head;
            match M::headers_received(&head, scope) {
                Ok((_, RecvMode::Buffered(x), _)) if x >= MAX_BUF_SIZE
                => panic!("Can't buffer {} bytes, max {}",
                          x, MAX_BUF_SIZE),
                Ok((m, mode, dline)) => {
                    match BodyKind::parse(&head) {
                        Ok(body) => {
                            // TODO(tailhook)
                            // Probably can handle small
                            // request bodies that are already
                            // in the buffer
                            if body == BodyKind::Fixed(0) {
                                can_keep_alive = true;
                            }
                            match (body, mode) {
                                (BodyKind::Fixed(x), RecvMode::Buffered(y))
                                if x >= y as u64 => {
                                    Err(PayloadTooLarge)
                                }
                                _ => {
                                    Ok((head, body, m, mode, dline))
                                }
                            }
                        }
                        Err(status) => Err(status),
                    }
                }
                Err(status) => Err(status),
            }
        }
        Err(status) => Err(status),
    };
    transport.input().consume(end+4);
    match status {
        Ok((head, body, m, mode, dline)) => {
            if head.headers.get::<Expect>() == Some(&Expect::Continue) {
                // Handler has already approved request, so just push it
                transport.output().extend(
                    format!("{} 100 Continue\r\n\r\n", head.version)
                    .as_bytes());
            }
            Ok(ReadBody {
                machine: m,
                deadline: dline,
                progress: start_body(mode, body)
            })
        }
        Err(status) => {
            let mut resp = Response::new(transport, is_head);
            scope.emit_error_page(status, &mut resp);
            resp.done();
            Err(can_keep_alive)
        }
    }
}

impl<M> Parser<M>
{
    fn request<C>(self, scope: &mut Scope<C>) -> Request<Parser<M>>
        where C: Context
    {
        use rotor_stream::Expectation::*;
        use self::Parser::*;
        use self::BodyProgress::*;
        let (exp, dline) = match *&self {
            Idle => (Bytes(0), None),
            ReadHeaders => (Delimiter(0, b"\r\n\r\n", MAX_HEADERS_SIZE), None),
            ReadingBody(ref b) => {
                let exp = match *&b.progress {
                    BufferFixed(x) => Bytes(x),
                    BufferEOF(x) => Eof(x),
                    BufferChunked(limit, off, 0)
                    => Delimiter(off, b"\r\n", off+MAX_CHUNK_HEAD),
                    BufferChunked(limit, off, y) => Bytes(y),
                    ProgressiveFixed(hint, left)
                    => Bytes(min(hint as u64, left) as usize),
                    ProgressiveEOF(hint) => Eof(hint),
                    ProgressiveChunked(hint, 0)
                    => Delimiter(0, b"\r\n", 0+MAX_CHUNK_HEAD),
                    ProgressiveChunked(hint, left)
                    => Bytes(min(hint as u64, left) as usize)
                };
                (exp, Some(b.deadline))
            }
            DoneResponse => (Flush(0), None),
        };

        let byte_dline = Deadline::now() + scope.byte_timeout();
        let deadline = dline.map_or_else(
            || byte_dline,
            |x| min(byte_dline, x));
        Some((self, exp, deadline))
    }
}

impl<C, M, S> Protocol<C, S> for Parser<M>
    where M: Server<C, S>,
          S: StreamSocket,
          C: Context,
{
    type Seed = ();
    fn create(_seed: (), _sock: &mut S, scope: &mut Scope<C>)
        -> Request<Self>
    {
        Some((Parser::Idle, E::Bytes(1),
            Deadline::now() + scope.byte_timeout()))
    }
    fn bytes_read(self, transport: &mut Transport<S>,
                  end: usize, scope: &mut Scope<C>)
        -> Request<Self>
    {
        use self::Parser::*;
        match self {
            Idle => {
                start_headers(scope)
            }
            ReadHeaders => {
                match parse_headers::<C, M, S>(transport, end, scope) {
                    Ok(body) => {
                        ReadingBody(body).request(scope)
                    }
                    Err(can_keep_alive) => {
                        if can_keep_alive {
                            start_headers(scope)
                        } else {
                            Parser::flush(scope)
                        }
                    }
                }
            }
            me @ ReadingBody(_) => me.request(scope),
            me @ DoneResponse => me.request(scope),
        }
    }
    fn bytes_flushed(self, _transport: &mut Transport<S>,
                     scope: &mut Scope<C>)
        -> Request<Self>
    {
        match self {
            Parser::DoneResponse => None,
            me => me.request(scope),
        }
    }
    fn timeout(self, _transport: &mut Transport<S>,
        _scope: &mut Scope<C>)
        -> Request<Self>
    {
        unimplemented!();
    }
    fn delimiter_not_found(self, _transport: &mut Transport<S>,
        scope: &mut Scope<C>)
        -> Request<Self>
    {
        use self::Parser::*;
        match self {
            Idle => None,
            ReadHeaders => {
                // TODO(tailhook) send RequestHeaderFieldsTooLarge
                Parser::flush(scope)
            }
            _ => unimplemented!(),
        }
    }
    fn wakeup(self, transport: &mut Transport<S>, _scope: &mut Scope<C>)
        -> Request<Self>
    {
        unimplemented!();
    }
}
<commit_msg>WIP: more request parsing refinements<commit_after>use std::usize;
use std::cmp::min;

use netbuf::MAX_BUF_SIZE;
use rotor::Scope;
use rotor_stream::{Protocol, StreamSocket, Deadline, Expectation as E};
use rotor_stream::{Request, Transport};
use hyper::status::StatusCode::{self, PayloadTooLarge};
use hyper::method::Method::Head;
use hyper::header::Expect;

use super::{MAX_HEADERS_NUM, MAX_HEADERS_SIZE, MAX_CHUNK_HEAD};
use super::{Response};
use super::protocol::{Server, RecvMode};
use super::context::Context;
use super::request::Head;
use super::body::BodyKind;

struct ReadBody<M: Sized> {
    machine: M,
    deadline: Deadline,
    progress: BodyProgress,
}

pub enum BodyProgress {
    /// Buffered fixed-size request (bytes left)
    BufferFixed(usize),
    /// Buffered request till end of input (byte limit)
    BufferEOF(usize),
    /// Buffered request with chunked encoding
    /// (limit, bytes buffered, bytes left for current chunk)
    BufferChunked(usize, usize, usize),
    /// Progressive fixed-size request (size hint, bytes left)
    ProgressiveFixed(usize, u64),
    /// Progressive till end of input (size hint)
    ProgressiveEOF(usize),
    /// Progressive with chunked encoding (hint, bytes left for current chunk)
    // To be able to merge chunks, should add offset here
    ProgressiveChunked(usize, u64),
}

pub enum Parser<M: Sized> {
    Idle,
    ReadHeaders,
    ReadingBody(ReadBody<M>),
    /// Close connection after buffer is flushed. In other cases -> Idle
    Processing(M, Deadline),
    DoneResponse,
}

impl<M> Parser<M>
{
    fn flush<C>(scope: &mut Scope<C>) -> Request<Parser<M>>
        where C: Context
    {
        Some((Parser::DoneResponse, E::Flush(0),
              Deadline::now() + scope.byte_timeout()))
    }
}

fn start_headers<C: Context, M: Sized>(scope: &mut Scope<C>)
    -> Request<Parser<M>>
{
    Some((Parser::ReadHeaders,
          E::Delimiter(0, b"\r\n\r\n", MAX_HEADERS_SIZE),
          Deadline::now() + scope.byte_timeout()))
}

fn start_body(mode: RecvMode, body: BodyKind) -> BodyProgress {
    use super::body::BodyKind::*;
    use super::protocol::RecvMode::*;
    use self::BodyProgress::*;

    match (mode, body) {
        // The size of Fixed(x) is checked in parse_headers
        (Buffered(x), Fixed(y)) => BufferFixed(y as usize),
        (Buffered(x), Chunked) => BufferChunked(x, 0, 0),
        (Buffered(x), Eof) => BufferEOF(x),
        (Progressive(x), Fixed(y)) => ProgressiveFixed(x, y),
        (Progressive(x), Chunked) => ProgressiveChunked(x, 0),
        (Progressive(x), Eof) => ProgressiveEOF(x),
        (_, Upgrade) => unimplemented!(),
    }
}

// Parses headers
//
// On error returns bool, which is true if keep-alive connection can be
// carried on.
fn parse_headers<C, M, S>(transport: &mut Transport<S>, end: usize,
    scope: &mut Scope<C>) -> Result<ReadBody<M>, bool>
    where M: Server<C, S>,
          S: StreamSocket,
          C: Context,
{
    use self::Parser::*;
    // Determines if we can keep-alive after error response.
    // We may not be able to keep keep-alive for multiple reasons:
    //
    // 1. When request headers are too wrong
    //    (probably client connects with wrong protocol)
    //
    // 2. When request contains non-empty request body (we don't
    //    want to wait until it is uploaded just to send error)
    //
    // Note we definitely can't keep alive if we can't say
    // whether request method is HEAD
    //
    // All of these are important to avoid cache poisoning attacks
    // on proxy servers.
    let mut can_keep_alive = false;
    // Determines if we can safely send the response body
    let mut is_head = false;

    let status = match Head::parse(&transport.input()[..end+4]) {
        Ok(head) => {
            is_head = head.method == Head;
            match M::headers_received(&head, scope) {
                Ok((_, RecvMode::Buffered(x), _)) if x >= MAX_BUF_SIZE
                => panic!("Can't buffer {} bytes, max {}",
                          x, MAX_BUF_SIZE),
                Ok((m, mode, dline)) => {
                    match BodyKind::parse(&head) {
                        Ok(body) => {
                            // TODO(tailhook)
                            // Probably can handle small
                            // request bodies that are already
                            // in the buffer
                            if body == BodyKind::Fixed(0) {
                                can_keep_alive = true;
                            }
                            match (body, mode) {
                                (BodyKind::Fixed(x), RecvMode::Buffered(y))
                                if x >= y as u64 => {
                                    Err(PayloadTooLarge)
                                }
                                _ => {
                                    Ok((head, body, m, mode, dline))
                                }
                            }
                        }
                        Err(status) => Err(status),
                    }
                }
                Err(status) => Err(status),
            }
        }
        Err(status) => Err(status),
    };
    transport.input().consume(end+4);
    match status {
        Ok((head, body, m, mode, dline)) => {
            if head.headers.get::<Expect>() == Some(&Expect::Continue) {
                // Handler has already approved request, so just push it
                transport.output().extend(
                    format!("{} 100 Continue\r\n\r\n", head.version)
                    .as_bytes());
            }
            Ok(ReadBody {
                machine: m,
                deadline: dline,
                progress: start_body(mode, body)
            })
        }
        Err(status) => {
            let mut resp = Response::new(transport, is_head);
            scope.emit_error_page(status, &mut resp);
            resp.done();
            Err(can_keep_alive)
        }
    }
}

impl<M> Parser<M>
{
    fn request<C>(self, scope: &mut Scope<C>) -> Request<Parser<M>>
        where C: Context
    {
        use rotor_stream::Expectation::*;
        use self::Parser::*;
        use self::BodyProgress::*;
        let (exp, dline) = match *&self {
            Idle => (Bytes(0), None),
            ReadHeaders => (Delimiter(0, b"\r\n\r\n", MAX_HEADERS_SIZE), None),
            ReadingBody(ref b) => {
                let exp = match *&b.progress {
                    BufferFixed(x) => Bytes(x),
                    BufferEOF(x) => Eof(x),
                    BufferChunked(limit, off, 0)
                    => Delimiter(off, b"\r\n", off+MAX_CHUNK_HEAD),
                    BufferChunked(limit, off, y) => Bytes(y),
                    ProgressiveFixed(hint, left)
                    => Bytes(min(hint as u64, left) as usize),
                    ProgressiveEOF(hint) => Eof(hint),
                    ProgressiveChunked(hint, 0)
                    => Delimiter(0, b"\r\n", 0+MAX_CHUNK_HEAD),
                    ProgressiveChunked(hint, left)
                    => Bytes(min(hint as u64, left) as usize)
                };
                (exp, Some(b.deadline))
            }
            Processing(..) => unreachable!(),
            /// TODO(tailhook) fix output timeout
            DoneResponse => (Flush(0), None),
        };

        let byte_dline = Deadline::now() + scope.byte_timeout();
        let deadline = dline.map_or_else(
            || byte_dline,
            |x| min(byte_dline, x));
        Some((self, exp, deadline))
    }
}

impl<C, M, S> Protocol<C, S> for Parser<M>
    where M: Server<C, S>,
          S: StreamSocket,
          C: Context,
{
    type Seed = ();
    fn create(_seed: (), _sock: &mut S, scope: &mut Scope<C>)
        -> Request<Self>
    {
        Some((Parser::Idle, E::Bytes(1),
            Deadline::now() + scope.byte_timeout()))
    }
    fn bytes_read(self, transport: &mut Transport<S>,
                  end: usize, scope: &mut Scope<C>)
        -> Request<Self>
    {
        use self::Parser::*;
        match self {
            Idle => {
                start_headers(scope)
            }
            ReadHeaders => {
                match parse_headers::<C, M, S>(transport, end, scope) {
                    Ok(body) => {
                        unimplemented!();
                        ReadingBody(body).request(scope)
                    }
                    Err(can_keep_alive) => {
                        if can_keep_alive {
                            Idle.request(scope)
                        } else {
                            Parser::flush(scope)
                        }
                    }
                }
            }
            me @ ReadingBody(_) => {
                unimplemented!();
            }
            // Spurious event?
            me @ DoneResponse => me.request(scope),
            Processing(m, dline) => Some((Processing(m, dline),
                                         E::Sleep, dline)),
        }
    }
    fn bytes_flushed(self, _transport: &mut Transport<S>,
                     scope: &mut Scope<C>)
        -> Request<Self>
    {
        match self {
            Parser::DoneResponse => None,
            me => me.request(scope),
        }
    }
    fn timeout(self, _transport: &mut Transport<S>,
        _scope: &mut Scope<C>)
        -> Request<Self>
    {
        unimplemented!();
    }
    fn delimiter_not_found(self, _transport: &mut Transport<S>,
        scope: &mut Scope<C>)
        -> Request<Self>
    {
        use self::Parser::*;
        use self::BodyProgress::*;
        // We may just flush and exit in every state. But:
        // 1. The match asserts that we know which state parser may be in
        // 2. We may send more specific response, so that browser will not
        //    retry ugly request multiple times
        match self {
            ReadHeaders
                // TODO(tailhook) send RequestHeaderFieldsTooLarge
            | ReadingBody( ReadBody { progress: ProgressiveChunked(_, 0), ..})
            | ReadingBody( ReadBody { progress: BufferChunked(_, _, 0), ..})
                // TODO(tailhook) send BadRequest ?
            => {
                // Should we flush or just close?
                // Probably closing is useful because previous responses might
                // be absolutely valid, and we've got invalid pipelined
                // request
                Parser::flush(scope)
            }
            // TODO(tailhook) Any other weird cases?
            _ => unreachable!(),
        }
    }
    fn wakeup(self, transport: &mut Transport<S>, scope: &mut Scope<C>)
        -> Request<Self>
    {
        use self::Parser::*;
        match self {
            me@Idle | me@ReadHeaders | me@DoneResponse => me.request(scope),
            ReadingBody(reader) => {
                unimplemented!();
            }
            Processing(_, _) => {
                unimplemented!();
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Kyle Mayes
//
// 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.

#[macro_use]
extern crate queuecheck;
extern crate npnc;

use std::env;

const WARMUP: usize = 1_000_000;
const MEASUREMENT: usize = 100_000_000;

fn thousands(ops: f64) -> String {
    let mut string = format!("{:.2}", ops);
    let mut index = string.find('.').unwrap();
    while index > 3 {
        index -= 3;
        string.insert(index, '_');
    }
    string
}

macro_rules! bench {
    ([$($path:tt)*], $producers:expr, $consumers:expr) => ({
        queuecheck_bench_throughput!(
            (WARMUP, MEASUREMENT),
            $producers,
            $consumers,
            |p: &npnc::$($path)*::Producer<i32>, i: i32| p.produce(i).unwrap(),
            |c: &npnc::$($path)*::Consumer<i32>| c.consume().ok()
        )
    });
}

macro_rules! bench_spsc {
    ([$($path:tt)*]$(, $size:expr)*) => ({
        let (producer, consumer) = npnc::$($path)*::channel($($size)*);
        bench!([$($path)*], vec![producer], vec![consumer])
    });
}

macro_rules! run {
    ($filter:expr, $name:expr, $runs:expr, $bench:expr) => ({
        if $filter.as_ref().map_or(true, |f| $name.contains(f)) {
            println!("bench {} ...", $name);
            let mut runs = (0..$runs).map(|_| $bench).collect::<Vec<_>>();
            runs.sort_by(|a, b| a.partial_cmp(b).unwrap());
            println!("  {} operation/second", thousands(runs[$runs / 2]));
        }
    });
}

fn main() {
    let filter = env::args().nth(1).and_then(|f| if f == "--bench" { None } else { Some(f) });
    run!(filter, "bounded_spsc", 25, bench_spsc!([bounded::spsc], 2 << 24));
    run!(filter, "unbounded_spsc", 5, bench_spsc!([unbounded::spsc]));
    run!(filter, "bounded_mpmc", 5, bench_spsc!([bounded::mpmc], 2 << 24));
    run!(filter, "unbounded_mpmc", 3, bench_spsc!([unbounded::mpmc], 0));
}
<commit_msg>Add latency benchmarks<commit_after>// Copyright 2017 Kyle Mayes
//
// 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.

#[macro_use]
extern crate queuecheck;
extern crate npnc;

use std::env;

const WARMUP: usize = 1_000_000;
const MEASUREMENT: usize = 100_000_000;

fn thousands(ops: f64) -> String {
    let mut string = format!("{:.2}", ops);
    let mut index = string.find('.').unwrap();
    while index > 3 {
        index -= 3;
        string.insert(index, '_');
    }
    string
}

macro_rules! bench_throughput {
    ([$($path:tt)*], $producers:expr, $consumers:expr) => ({
        queuecheck_bench_throughput!(
            (WARMUP, MEASUREMENT),
            $producers,
            $consumers,
            |p: &npnc::$($path)*::Producer<i32>, i: i32| p.produce(i).unwrap(),
            |c: &npnc::$($path)*::Consumer<i32>| c.consume().ok()
        )
    });
}

macro_rules! bench_throughput_spsc {
    ([$($path:tt)*]$(, $size:expr)*) => ({
        let (producer, consumer) = npnc::$($path)*::channel($($size)*);
        bench_throughput!([$($path)*], vec![producer], vec![consumer])
    });
}

macro_rules! run_throughput {
    ($filter:expr, $name:expr, $runs:expr, $bench:expr) => ({
        let name = format!("throughput_{}", $name);
        if $filter.as_ref().map_or(true, |f| name.contains(f)) {
            println!("bench {} ...", name);
            let mut runs = (0..$runs).map(|_| $bench).collect::<Vec<_>>();
            runs.sort_by(|a, b| a.partial_cmp(b).unwrap());
            println!("  {} operation/second", thousands(runs[$runs / 2]));
        }
    });
}

macro_rules! bench_latency {
    ([$($path:tt)*], $producers:expr, $consumers:expr) => ({
        queuecheck_bench_latency!(
            (WARMUP, MEASUREMENT),
            $producers,
            $consumers,
            |p: &npnc::$($path)*::Producer<i32>, i: i32| p.produce(i).unwrap(),
            |c: &npnc::$($path)*::Consumer<i32>| c.consume().ok()
        )
    });
}

macro_rules! bench_latency_spsc {
    ([$($path:tt)*]$(, $size:expr)*) => ({
        let (producer, consumer) = npnc::$($path)*::channel($($size)*);
        bench_latency!([$($path)*], vec![producer], vec![consumer])
    });
}

macro_rules! run_latency {
    ($filter:expr, $name:expr, $bench:expr) => ({
        let name = format!("latency_{}", $name);
        if $filter.as_ref().map_or(true, |f| name.contains(f)) {
            println!("bench {} ...", name);
            let latency = $bench;
            println!("  consume");
            println!("    50.0%: {}ns", thousands(latency.consume.percentile(50.0)));
            println!("    70.0%: {}ns", thousands(latency.consume.percentile(70.0)));
            println!("    90.0%: {}ns", thousands(latency.consume.percentile(90.0)));
            println!("    95.0%: {}ns", thousands(latency.consume.percentile(95.0)));
            println!("    99.0%: {}ns", thousands(latency.consume.percentile(99.0)));
            println!("    99.9%: {}ns", thousands(latency.consume.percentile(99.9)));
            println!("  produce");
            println!("    50.0%: {}ns", thousands(latency.produce.percentile(50.0)));
            println!("    70.0%: {}ns", thousands(latency.produce.percentile(70.0)));
            println!("    90.0%: {}ns", thousands(latency.produce.percentile(90.0)));
            println!("    95.0%: {}ns", thousands(latency.produce.percentile(95.0)));
            println!("    99.0%: {}ns", thousands(latency.produce.percentile(99.0)));
            println!("    99.9%: {}ns", thousands(latency.produce.percentile(99.9)));
        }
    });
}

fn main() {
    let filter = env::args().nth(1).and_then(|f| if f == "--bench" { None } else { Some(f) });
    run_throughput!(filter, "bounded_spsc", 25, bench_throughput_spsc!([bounded::spsc], 2 << 24));
    run_throughput!(filter, "unbounded_spsc", 5, bench_throughput_spsc!([unbounded::spsc]));
    run_throughput!(filter, "bounded_mpmc", 5, bench_throughput_spsc!([bounded::mpmc], 2 << 24));
    run_throughput!(filter, "unbounded_mpmc", 3, bench_throughput_spsc!([unbounded::mpmc], 0));
    run_latency!(filter, "bounded_spsc", bench_latency_spsc!([bounded::spsc], 2 << 24));
    run_latency!(filter, "unbounded_spsc", bench_latency_spsc!([unbounded::spsc]));
    run_latency!(filter, "bounded_mpmc", bench_latency_spsc!([bounded::mpmc], 2 << 24));
    run_latency!(filter, "unbounded_mpmc", bench_latency_spsc!([unbounded::mpmc], 0));
}
<|endoftext|>