<commit_before>#![deny(missing_docs)]

//! The official Piston window wrapper for the Piston game engine
//!
//! Sets up [Gfx](https://github.com/gfx-rs/gfx) with an OpenGL back-end.
//! Uses [gfx_graphics](https://github.com/pistondevelopers/gfx_graphics)
//! for 2D rendering.
//! Uses [glutin_window](https://github.com/pistondevelopers/glutin_window)
//! as default window back-end, but this can be swapped.
//!
//! sRGB is turned on because it is required by gfx_graphics.
//!
//! ### Example
//!
//! ```ignore
//! extern crate piston_window;
//!
//! use piston_window::*;
//!
//! fn main() {
//!     let window: PistonWindow =
//!         WindowSettings::new("Hello World!", [512; 2])
//!             .build().unwrap();
//!     for e in window {
//!         e.draw_2d(|c, g| {
//!             clear([0.5, 0.5, 0.5, 1.0], g);
//!             rectangle([1.0, 0.0, 0.0, 1.0], // red
//!                       [0.0, 0.0, 100.0, 100.0], // rectangle
//!                       c.transform, g);
//!         });
//!     }
//! }
//! ```
//!
//! ### Swap to another window back-end
//!
//! Change the second generic parameter to the window back-end you want to use.
//!
//! ```ignore
//! let window: PistonWindow<(), Sdl2Window> =
//!     WindowSettings::new("title", [512; 2])
//!         .build().unwrap();
//! ```
//!
//! ### Do not depend on this library
//!
//! This library is not meant to be depended on by other libraries.
//! Instead, libraries should depend on the lower abstractions,
//! such as the [Piston core](https://github.com/pistondevelopers/piston).
//! The only purpose of this library is to provide a convenient way to get started.

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;
extern crate shader_version;
extern crate glutin_window;

use glutin_window::GlutinWindow;
pub use shader_version::OpenGL;
pub use graphics::*;
pub use piston::window::*;
pub use piston::input::*;
pub use piston::event_loop::*;
pub use gfx_graphics::{ GlyphError, Texture, TextureSettings, Flip };

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };

/// Actual gfx::Stream implementation carried by the window.
pub type GfxEncoder = gfx::Encoder<gfx_device_gl::Resources,
    gfx_device_gl::command::CommandBuffer>;
/// Glyph cache.
pub type Glyphs = gfx_graphics::GlyphCache<gfx_device_gl::Resources,
    gfx_device_gl::Factory>;
/// 2D graphics.
pub type G2d<'a> = GfxGraphics<'a,
    gfx_device_gl::Resources,
    gfx_device_gl::command::CommandBuffer>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<T = (), W: Window = GlutinWindow> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX encoder.
    pub encoder: Rc<RefCell<GfxEncoder>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Output frame buffer.
    pub output_color: Rc<gfx::handle::RenderTargetView<
        gfx_device_gl::Resources, gfx::format::Srgb8>>,
    /// Output stencil buffer.
    pub output_stencil: Rc<gfx::handle::DepthStencilView<
        gfx_device_gl::Resources, gfx::format::DepthStencil>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<WindowEvents>>,
    /// The event.
    pub event: Option<Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
    /// The factory that was created along with the device.
    pub factory: Rc<RefCell<gfx_device_gl::Factory>>,
}

impl<W> BuildFromWindowSettings for PistonWindow<(), W>
    where W: Window + OpenGLWindow + BuildFromWindowSettings,
          W::Event: GenericEvent
{
    fn build_from_window_settings(mut settings: WindowSettings)
    -> Result<PistonWindow<(), W>, String> {
        // Turn on sRGB.
        settings = settings.srgb(true);

        // Use OpenGL 3.2 by default, because this is what window backends
        // usually do.
        let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
        let samples = settings.get_samples();

        Ok(PistonWindow::new(opengl, samples,
            Rc::new(RefCell::new(try!(settings.build()))), empty_app()))
    }
}

impl<T, W> Clone for PistonWindow<T, W>
    where W: Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            encoder: self.encoder.clone(),
            device: self.device.clone(),
            output_color: self.output_color.clone(),
            output_stencil: self.output_stencil.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
            factory: self.factory.clone(),
        }
    }
}

impl<T, W> PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    /// Creates a new piston window.
    pub fn new(
        opengl: OpenGL,
        samples: u8,
        window: Rc<RefCell<W>>,
        app: Rc<RefCell<T>>
    ) -> Self
        where W: OpenGLWindow
    {
        use piston::event_loop::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (device, mut factory) =
            gfx_device_gl::create(|s|
                window.borrow_mut().get_proc_address(s) as *const _);

        let draw_size = window.borrow().draw_size();
        let aa = samples as gfx::tex::NumSamples;
        let dim = (draw_size.width as u16, draw_size.height as u16,
                   1, aa.into());
        let (output_color, output_stencil) =
            gfx_device_gl::create_main_targets(dim);
        let g2d = Gfx2d::new(opengl, &mut factory);
        let encoder = factory.create_encoder();
        PistonWindow {
            window: window.clone(),
            encoder: Rc::new(RefCell::new(encoder)),
            device: Rc::new(RefCell::new(device)),
            output_color: Rc::new(output_color),
            output_stencil: Rc::new(output_stencil),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.borrow().events())),
            event: None,
            app: app,
            factory: Rc::new(RefCell::new(factory)),
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<U, W> {
        PistonWindow {
            window: self.window,
            encoder: self.encoder,
            device: self.device,
            output_color: self.output_color,
            output_stencil: self.output_stencil,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
            factory: self.factory,
        }
    }

    /// Changes application structure.
    #[inline(always)]
    pub fn app_by_value<U>(self, app: U) -> PistonWindow<U, W> {
        self.app(Rc::new(RefCell::new(app)))
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnOnce(Context, &mut G2d)
    {
        use piston::input::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut encoder = self.encoder.borrow_mut();
                encoder.reset();
                self.g2d.borrow_mut().draw(
                    &mut encoder,
                    &self.output_color,
                    &self.output_stencil,
                    args.viewport(),
                    f
                );
                self.device.borrow_mut().submit(encoder.as_buffer());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, f: F) where
        F: FnOnce(&mut GfxEncoder)
    {
        use piston::input::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut encoder = self.encoder.borrow_mut();
                encoder.reset();
                f(&mut *encoder);
                self.device.borrow_mut().submit(encoder.as_buffer());
            }
        }
    }
}

impl<T, W> Iterator for PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    type Item = PistonWindow<T, W>;

    fn next(&mut self) -> Option<PistonWindow<T, W>> {
        use piston::input::*;
        use gfx::core::factory::Phantom;

        let window = &mut *self.window.borrow_mut();
        if let Some(e) = self.events.borrow_mut().next(window) {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            // Check whether window has resized and update the output.
            let dim = self.output_color.raw().get_dimensions();
            let (w, h) = (dim.0, dim.1);
            let draw_size = window.draw_size();
            let (output_color, output_stencil) =
                if w != draw_size.width as u16 || h != draw_size.height as u16 {
                    let dim = (draw_size.width as u16,
                               draw_size.height as u16,
                               dim.2, dim.3);
                    let (output_color, output_stencil) =
                        gfx_device_gl::create_main_targets(dim);
                    (Rc::new(output_color), Rc::new(output_stencil))
                } else {
                    (self.output_color.clone(), self.output_stencil.clone())
                };

            Some(PistonWindow {
                window: self.window.clone(),
                encoder: self.encoder.clone(),
                device: self.device.clone(),
                output_color: output_color,
                output_stencil: output_stencil,
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
                factory: self.factory.clone(),
            })
        } else { None }
    }
}

impl<T, W> GenericEvent for PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    fn event_id(&self) -> EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(
        event_id: EventId,
        any: &Any,
        old_event: &Self
    ) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        encoder: old_event.encoder.clone(),
                        device: old_event.device.clone(),
                        output_color: old_event.output_color.clone(),
                        output_stencil: old_event.output_stencil.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                        factory: old_event.factory.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<T, W> Window for PistonWindow<T, W>
    where W: Window
{
    type Event = <W as Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn set_should_close(&mut self, value: bool) {
        self.window.borrow_mut().set_should_close(value)
    }
    fn size(&self) -> Size { self.window.borrow().size() }
    fn draw_size(&self) -> Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<T, W> AdvancedWindow for PistonWindow<T, W>
    where W: AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

impl<T, W> EventLoop for PistonWindow<T, W>
    where W: Window
{
    fn set_ups(&mut self, frames: u64) {
        self.events.borrow_mut().set_ups(frames);
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.events.borrow_mut().set_max_fps(frames);
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.events.borrow_mut().set_swap_buffers(enable);
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.events.borrow_mut().set_bench_mode(enable);
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<commit_msg>Expose a G2dTexture type (open to a better name) that is compatible with the exposed G2d type<commit_after>#![deny(missing_docs)]

//! The official Piston window wrapper for the Piston game engine
//!
//! Sets up [Gfx](https://github.com/gfx-rs/gfx) with an OpenGL back-end.
//! Uses [gfx_graphics](https://github.com/pistondevelopers/gfx_graphics)
//! for 2D rendering.
//! Uses [glutin_window](https://github.com/pistondevelopers/glutin_window)
//! as default window back-end, but this can be swapped.
//!
//! sRGB is turned on because it is required by gfx_graphics.
//!
//! ### Example
//!
//! ```ignore
//! extern crate piston_window;
//!
//! use piston_window::*;
//!
//! fn main() {
//!     let window: PistonWindow =
//!         WindowSettings::new("Hello World!", [512; 2])
//!             .build().unwrap();
//!     for e in window {
//!         e.draw_2d(|c, g| {
//!             clear([0.5, 0.5, 0.5, 1.0], g);
//!             rectangle([1.0, 0.0, 0.0, 1.0], // red
//!                       [0.0, 0.0, 100.0, 100.0], // rectangle
//!                       c.transform, g);
//!         });
//!     }
//! }
//! ```
//!
//! ### Swap to another window back-end
//!
//! Change the second generic parameter to the window back-end you want to use.
//!
//! ```ignore
//! let window: PistonWindow<(), Sdl2Window> =
//!     WindowSettings::new("title", [512; 2])
//!         .build().unwrap();
//! ```
//!
//! ### Do not depend on this library
//!
//! This library is not meant to be depended on by other libraries.
//! Instead, libraries should depend on the lower abstractions,
//! such as the [Piston core](https://github.com/pistondevelopers/piston).
//! The only purpose of this library is to provide a convenient way to get started.

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;
extern crate shader_version;
extern crate glutin_window;

use glutin_window::GlutinWindow;
pub use shader_version::OpenGL;
pub use graphics::*;
pub use piston::window::*;
pub use piston::input::*;
pub use piston::event_loop::*;
pub use gfx_graphics::{ GlyphError, Texture, TextureSettings, Flip };

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };

/// Actual gfx::Stream implementation carried by the window.
pub type GfxEncoder = gfx::Encoder<gfx_device_gl::Resources,
    gfx_device_gl::command::CommandBuffer>;
/// Glyph cache.
pub type Glyphs = gfx_graphics::GlyphCache<gfx_device_gl::Resources,
    gfx_device_gl::Factory>;
/// 2D graphics.
pub type G2d<'a> = GfxGraphics<'a,
    gfx_device_gl::Resources,
    gfx_device_gl::command::CommandBuffer>;
/// Texture type compatible with `G2d`.
pub type G2dTexture<'a> = Texture<gfx_device_gl::Resources>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<T = (), W: Window = GlutinWindow> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX encoder.
    pub encoder: Rc<RefCell<GfxEncoder>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Output frame buffer.
    pub output_color: Rc<gfx::handle::RenderTargetView<
        gfx_device_gl::Resources, gfx::format::Srgb8>>,
    /// Output stencil buffer.
    pub output_stencil: Rc<gfx::handle::DepthStencilView<
        gfx_device_gl::Resources, gfx::format::DepthStencil>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<WindowEvents>>,
    /// The event.
    pub event: Option<Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
    /// The factory that was created along with the device.
    pub factory: Rc<RefCell<gfx_device_gl::Factory>>,
}

impl<W> BuildFromWindowSettings for PistonWindow<(), W>
    where W: Window + OpenGLWindow + BuildFromWindowSettings,
          W::Event: GenericEvent
{
    fn build_from_window_settings(mut settings: WindowSettings)
    -> Result<PistonWindow<(), W>, String> {
        // Turn on sRGB.
        settings = settings.srgb(true);

        // Use OpenGL 3.2 by default, because this is what window backends
        // usually do.
        let opengl = settings.get_maybe_opengl().unwrap_or(OpenGL::V3_2);
        let samples = settings.get_samples();

        Ok(PistonWindow::new(opengl, samples,
            Rc::new(RefCell::new(try!(settings.build()))), empty_app()))
    }
}

impl<T, W> Clone for PistonWindow<T, W>
    where W: Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            encoder: self.encoder.clone(),
            device: self.device.clone(),
            output_color: self.output_color.clone(),
            output_stencil: self.output_stencil.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
            factory: self.factory.clone(),
        }
    }
}

impl<T, W> PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    /// Creates a new piston window.
    pub fn new(
        opengl: OpenGL,
        samples: u8,
        window: Rc<RefCell<W>>,
        app: Rc<RefCell<T>>
    ) -> Self
        where W: OpenGLWindow
    {
        use piston::event_loop::Events;
        use piston::window::{ OpenGLWindow, Window };

        let (device, mut factory) =
            gfx_device_gl::create(|s|
                window.borrow_mut().get_proc_address(s) as *const _);

        let draw_size = window.borrow().draw_size();
        let aa = samples as gfx::tex::NumSamples;
        let dim = (draw_size.width as u16, draw_size.height as u16,
                   1, aa.into());
        let (output_color, output_stencil) =
            gfx_device_gl::create_main_targets(dim);
        let g2d = Gfx2d::new(opengl, &mut factory);
        let encoder = factory.create_encoder();
        PistonWindow {
            window: window.clone(),
            encoder: Rc::new(RefCell::new(encoder)),
            device: Rc::new(RefCell::new(device)),
            output_color: Rc::new(output_color),
            output_stencil: Rc::new(output_stencil),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.borrow().events())),
            event: None,
            app: app,
            factory: Rc::new(RefCell::new(factory)),
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<U, W> {
        PistonWindow {
            window: self.window,
            encoder: self.encoder,
            device: self.device,
            output_color: self.output_color,
            output_stencil: self.output_stencil,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
            factory: self.factory,
        }
    }

    /// Changes application structure.
    #[inline(always)]
    pub fn app_by_value<U>(self, app: U) -> PistonWindow<U, W> {
        self.app(Rc::new(RefCell::new(app)))
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnOnce(Context, &mut G2d)
    {
        use piston::input::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut encoder = self.encoder.borrow_mut();
                encoder.reset();
                self.g2d.borrow_mut().draw(
                    &mut encoder,
                    &self.output_color,
                    &self.output_stencil,
                    args.viewport(),
                    f
                );
                self.device.borrow_mut().submit(encoder.as_buffer());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, f: F) where
        F: FnOnce(&mut GfxEncoder)
    {
        use piston::input::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut encoder = self.encoder.borrow_mut();
                encoder.reset();
                f(&mut *encoder);
                self.device.borrow_mut().submit(encoder.as_buffer());
            }
        }
    }
}

impl<T, W> Iterator for PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    type Item = PistonWindow<T, W>;

    fn next(&mut self) -> Option<PistonWindow<T, W>> {
        use piston::input::*;
        use gfx::core::factory::Phantom;

        let window = &mut *self.window.borrow_mut();
        if let Some(e) = self.events.borrow_mut().next(window) {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            // Check whether window has resized and update the output.
            let dim = self.output_color.raw().get_dimensions();
            let (w, h) = (dim.0, dim.1);
            let draw_size = window.draw_size();
            let (output_color, output_stencil) =
                if w != draw_size.width as u16 || h != draw_size.height as u16 {
                    let dim = (draw_size.width as u16,
                               draw_size.height as u16,
                               dim.2, dim.3);
                    let (output_color, output_stencil) =
                        gfx_device_gl::create_main_targets(dim);
                    (Rc::new(output_color), Rc::new(output_stencil))
                } else {
                    (self.output_color.clone(), self.output_stencil.clone())
                };

            Some(PistonWindow {
                window: self.window.clone(),
                encoder: self.encoder.clone(),
                device: self.device.clone(),
                output_color: output_color,
                output_stencil: output_stencil,
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
                factory: self.factory.clone(),
            })
        } else { None }
    }
}

impl<T, W> GenericEvent for PistonWindow<T, W>
    where W: Window, W::Event: GenericEvent
{
    fn event_id(&self) -> EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(
        event_id: EventId,
        any: &Any,
        old_event: &Self
    ) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        encoder: old_event.encoder.clone(),
                        device: old_event.device.clone(),
                        output_color: old_event.output_color.clone(),
                        output_stencil: old_event.output_stencil.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                        factory: old_event.factory.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<T, W> Window for PistonWindow<T, W>
    where W: Window
{
    type Event = <W as Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn set_should_close(&mut self, value: bool) {
        self.window.borrow_mut().set_should_close(value)
    }
    fn size(&self) -> Size { self.window.borrow().size() }
    fn draw_size(&self) -> Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<T, W> AdvancedWindow for PistonWindow<T, W>
    where W: AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

impl<T, W> EventLoop for PistonWindow<T, W>
    where W: Window
{
    fn set_ups(&mut self, frames: u64) {
        self.events.borrow_mut().set_ups(frames);
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.events.borrow_mut().set_max_fps(frames);
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.events.borrow_mut().set_swap_buffers(enable);
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.events.borrow_mut().set_bench_mode(enable);
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<|endoftext|>


<commit_before>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.
use std::sync::{Mutex, Condvar};

///A synchronization primitive that signals when its count reaches zero.
///
///With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
///occurring in other threads by making the other threads interact with the counter as they perform
///their work.
///
///The main limitation of a CountdownEvent is that once its counter reaches zero (even by starting
///there), any attempts to update the counter will return `CountdownError::AlreadySet` until the
///counter is reset by calling `reset` or `reset_to_count`.
///
///# Example
///
///```
/// use synchronoise::CountdownEvent;
/// use std::sync::Arc;
/// use std::thread;
/// use std::time::Duration;
///
/// let counter = Arc::new(CountdownEvent::new(5));
///
/// for i in 0..5 {
///     let signal = counter.clone();
///     thread::spawn(move || {
///         thread::sleep(Duration::from_secs(3));
///         println!("thread {} activated!", i);
///         signal.decrement();
///     });
/// }
///
/// counter.wait();
///
/// println!("all done!");
///```
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = self.counter.lock().unwrap();

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: fn.add.html
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: fn.signal.html
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = self.counter.lock().unwrap();

        while *count > 0 {
            count = self.lock.wait(count).unwrap();
        }
    }
}
<commit_msg>add CountdownEvent::wait_timeout<commit_after>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.

use std::sync::{Mutex, Condvar};
use std::time::Duration;

/// A synchronization primitive that signals when its count reaches zero.
///
/// With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
/// occurring in other threads by making the other threads interact with the counter as they perform
/// their work.
///
/// The main limitation of a CountdownEvent is that once its counter reaches zero (even by starting
/// there), any attempts to update the counter will return `CountdownError::AlreadySet` until the
/// counter is reset by calling `reset` or `reset_to_count`.
///
/// # Example
///
/// ```
/// use synchronoise::CountdownEvent;
/// use std::sync::Arc;
/// use std::thread;
/// use std::time::Duration;
///
/// let counter = Arc::new(CountdownEvent::new(5));
///
/// for i in 0..5 {
///     let signal = counter.clone();
///     thread::spawn(move || {
///         thread::sleep(Duration::from_secs(3));
///         println!("thread {} activated!", i);
///         signal.decrement();
///     });
/// }
///
/// counter.wait();
///
/// println!("all done!");
/// ```
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = self.counter.lock().unwrap();

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = self.counter.lock().unwrap();

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: fn.add.html
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: fn.signal.html
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = self.counter.lock().unwrap();

        while *count > 0 {
            count = self.lock.wait(count).unwrap();
        }
    }

    ///Blocks the current thread until the timer reaches zero, or until the given timeout elapses,
    ///returning the count at the time of wakeup and whether the timeout is known to have elapsed.
    ///
    ///This function will return immediately if the counter was already at zero. Otherwise, it will
    ///block for roughly no longer than `timeout`. Due to limitations in the platform specific
    ///implementation of `std::sync::Condvar`, this method could spuriously wake up both before the timeout
    ///elapsed and without the count being zero.
    pub fn wait_timeout(&self, timeout: Duration) -> (isize, bool) {
        let count = self.counter.lock().unwrap();

        if *count == 0 {
            return (*count, false);
        }

        let (count, status) = self.lock.wait_timeout(count, timeout).unwrap();

        (*count, status.timed_out())
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]

#[cfg(test)] extern crate test;
extern crate xxhash;

use std::default::Default;
use std::hash::{Hasher, Hash};
use std::iter::{FromIterator, Iterator};
use std::borrow::BorrowFrom;
use std::collections::HashMap;
use std::collections::hash_map::{Keys, Iter};
use std::collections::hash_state::{HashState, DefaultState};

use xxhash::XXHasher;

/// Distribution doesn't require a cryptographically secure hash, and by
/// default will not use one.
pub trait Distribution<H = XXHasher> {
  type Key;
  type Quantity;

  fn len(&self) -> usize;
  fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Self::Quantity>
    where Q: Hash<H> + Eq + BorrowFrom<Self::Key>;
  fn clear(&mut self);
  fn insert(&mut self, k: Self::Key);
  fn remove<Q: ?Sized>(&mut self, k: &Q)
    where Q: Hash<H> + Eq + BorrowFrom<Self::Key>;
}

/// Implementation of a Frequency Distribution in Rust. Keeps track of how many
/// times an object appears in a larger context (for example, how many times a
/// token appears in a piece of text). The underlying data structure of the
/// Frequency Distribution is a HashMap, so the object that is being counted
/// must be hashable.
///
/// # Example
///
/// ```rust
/// use freqdist::{Distribution, FrequencyDistribution};
///
/// let mut fdist = FrequencyDistribution::new();
///
/// fdist.insert("hello");
/// fdist.insert("hello");
/// fdist.insert("goodbyte");
///
/// assert_eq!(*fdist.get("hello").unwrap(), 2);
/// ```
pub struct FrequencyDistribution<K, S = DefaultState<XXHasher>> {
  hashmap: HashMap<K, usize, S>,
  sum_counts: usize
}

impl<K> FrequencyDistribution<K>
  where K: Eq + Hash<XXHasher>
{
  /// Creates a new FrequencyDistribution where the size of the
  /// HashMap is unknown.
  #[inline]
  pub fn new() -> FrequencyDistribution<K> {
    FrequencyDistribution::with_hash_state(Default::default())
  }

  /// Creates a new FrequencyDistribution where the size of the HashMap
  /// is known, or a estimate can be made.
  #[inline]
  pub fn with_capacity(
    size: usize
  ) -> FrequencyDistribution<K> {
    FrequencyDistribution::with_capacity_and_hash_state(size, Default::default())
  }
}

impl<K, S, H> FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Creates a new FrequencyDistrbution with a hash state and size, where
  /// the size is known or can be estimated.
  #[inline]
  pub fn with_capacity_and_hash_state(
    size: usize,
    state: S
  ) -> FrequencyDistribution<K, S> {
    FrequencyDistribution {
      hashmap: HashMap::with_capacity_and_hash_state(size, state),
      sum_counts: 0
    }
  }

  /// Creates a new FrequencyDistribution with a hash state and default size.
  #[inline]
  pub fn with_hash_state(state: S) -> FrequencyDistribution<K, S> {
    FrequencyDistribution {
      hashmap: HashMap::with_hash_state(state),
      sum_counts: 0
    }
  }
}

impl<K, S, H> FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Iterator over the keys.
  #[inline]
  #[stable]
  pub fn keys(&self) -> Keys<K, usize> {
    self.hashmap.keys()
  }

  /// Iterator over the key, frequency pairs.
  #[inline]
  #[stable]
  pub fn iter(&self) -> Iter<K, usize> {
    self.hashmap.iter()
  }

  /// Iterator over the non-zero frequency keys.
  #[inline]
  #[stable]
  pub fn iter_non_zero(&self) -> NonZeroKeysIter<K> {
    NonZeroKeysIter { iter: self.iter() }
  }

  /// Iterator over just the keys.
  #[inline]
  #[stable]
  pub fn sum_counts(&self) -> usize {
    self.sum_counts
  }

  /// Inserts a value sizeo the hashmap if it does not exist with a new quantity
  /// specified by the increment. If the value already exists, increments by
  /// the specified amount.
  #[inline]
  fn insert_or_incr_by(&mut self, k: K, incr: usize) {
    if !self.hashmap.contains_key(&k) {
      self.hashmap.insert(k, incr);
    } else {
      *self.hashmap.get_mut(&k).unwrap() += incr;
    }

    self.sum_counts += incr;
  }
}

impl<K> Default for FrequencyDistribution<K>
  where K: Eq + Hash<XXHasher>
{
  /// Creates a default FrequencyDistribution with an XXHasher.
  #[inline]
  #[stable]
  fn default() -> FrequencyDistribution<K> {
    FrequencyDistribution::new()
  }
}

impl<K, S, H> FromIterator<(K, usize)> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher = H> + Default,
        H: Hasher<Output = u64>
{
  /// Iterates through an iterator, and creates a new FrequencyDistribution from
  /// it. The iterator should be an iterator over keys and frequencies. If a
  /// upper bounded `size_hsize` is available, then it is used, otherwise the lower
  /// bounded `size_hsize` is used.
  ///
  /// # Example
  ///
  /// ```rust
  /// #![allow(unstable)]
  /// use std::iter::FromIterator;
  /// use freqdist::{Distribution, FrequencyDistribution};
  ///
  /// let existing = vec![
  ///   ("apples", 3),
  ///   ("oranges", 4),
  ///   ("bannana", 7)
  /// ];
  ///
  /// let fdist: FrequencyDistribution<&str> =
  ///   FromIterator::from_iter(existing.into_iter());
  ///
  /// assert_eq!(*fdist.get("apples").unwrap(), 3);
  /// assert_eq!(*fdist.get("oranges").unwrap(), 4);
  /// assert_eq!(*fdist.get("bannana").unwrap(), 7);
  /// ```
  fn from_iter<T: Iterator<Item = (K, usize)>>(
    iter: T
  ) -> FrequencyDistribution<K, S> {
    let mut fdist = if iter.size_hint().1.is_some() {
      FrequencyDistribution::with_capacity_and_hash_state(
        iter.size_hint().1.unwrap(),
        Default::default())
    } else {
      FrequencyDistribution::with_capacity_and_hash_state(
        iter.size_hint().0,
        Default::default())
    };

    fdist.extend(iter);
    fdist
  }
}

impl<K, S, H> Extend<(K, usize)> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Extends the hashmap by adding the keys or updating the frequencies of the keys.
  #[inline]
  fn extend<T: Iterator<Item = (K, usize)>>(&mut self, mut iter: T) {
    for (k, freq) in iter {
      self.insert_or_incr_by(k, freq);
    }
  }
}

impl<K, S, H> Distribution<H> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  type Key = K;
  type Quantity = usize;

  /// Returns the number of entries in the distribution
  #[inline]
  #[stable]
  fn len(&self) -> usize {
    self.hashmap.len()
  }

  /// Gets the frequency in which the key occurs.
  #[inline]
  #[stable]
  fn get<Q: ?Sized>(&self, k: &Q) -> Option<&usize>
    where Q: Hash<H> + Eq + BorrowFrom<K>
  {
    self.hashmap.get(k)
  }

  /// Clears the counts of all keys and clears all keys from
  /// the distribution.
  #[inline]
  #[stable]
  fn clear(&mut self) {
    self.hashmap.clear()
  }

  /// Updates the frequency of the value found with the key if it
  /// already exists. Otherwise, inserts the key sizeo the hashmap,
  /// and sets its frequency to 1.
  #[inline]
  #[stable]
  fn insert(&mut self, k: K) {
    self.insert_or_incr_by(k, 1);
  }

  /// Removes a Key and its associated value from the Distrbution.
  #[inline]
  #[stable]
  fn remove<Q: ?Sized>(&mut self, k: &Q)
    where Q: Hash<H> + Eq + BorrowFrom<K>
  {
    match self.hashmap.remove(k) {
      Some(count) => self.sum_counts -= count,
      None        => ()
    }
  }
}

/// Iterator over entries with non-zero quantities.
#[stable]
pub struct NonZeroKeysIter<'a, K: 'a> {
  iter: Iter<'a, K, usize>
}

impl<'a, K: 'a> Iterator for NonZeroKeysIter<'a, K> {
  type Item = &'a K;

  #[inline]
  fn next(&mut self) -> Option<&'a K> {
    loop {
      match self.iter.next() {
        Some((k, c)) if *c > 0 => return Some(k),
        None                   => return None,
        _                      => ()
      }
    }
  }

  #[inline]
  fn size_hint(&self) -> (usize, Option<usize>) {
    self.iter.size_hint()
  }
}

#[test]
fn smoke_test_frequency_distribution_insert() {
  let words = vec!("alpha", "beta");
  let mut dist: FrequencyDistribution<&str> = FrequencyDistribution::new();

  dist.insert(words[0]);

  assert_eq!(*dist.get(&words[0]).unwrap(), 1);

  dist.insert(words[1]);

  assert_eq!(*dist.get(&words[1]).unwrap(), 1);

  for _ in range(0, 7us) { dist.insert(words[0]); }

  assert_eq!(*dist.get(&words[0]).unwrap(), 8);
}

#[test]
fn smoke_test_frequency_distribution_iter() {
  let words = vec!(("a", 50us), ("b", 100us), ("c", 75us), ("d", 0us));
  let dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert_eq!(*dist.get(&"a").unwrap(), 50);
  assert_eq!(*dist.get(&"b").unwrap(), 100);
  assert_eq!(*dist.get(&"c").unwrap(), 75);

  let mut iter = dist.iter_non_zero();

  assert!(iter.next().is_some());
  assert!(iter.next().is_some());
  assert!(iter.next().is_some());
  assert!(iter.next().is_none());

  assert_eq!(dist.sum_counts(), 225);
}

#[test]
fn smoke_test_frequency_distribution_remove() {
  let words = vec!(("a", 50us), ("b", 100us), ("c", 25us));
  let mut dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert!(dist.get(&"a").is_some());

  dist.remove(&"a");

  assert!(dist.get(&"a").is_none());
  assert_eq!(dist.sum_counts(), 125);
}

#[test]
fn smoke_test_frequency_sum_counts() {
  let words = vec!(("a", 7us), ("b", 5us), ("c", 8us), ("d", 3us));
  let mut dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert_eq!(dist.sum_counts(), 23);

  dist.insert("e");

  assert_eq!(dist.sum_counts(), 24);
}
<commit_msg>update for rust nightly<commit_after>#![feature(core)]
#![feature(std_misc)]

#[cfg(test)] extern crate test;
extern crate xxhash;

use std::default::Default;
use std::hash::{Hasher, Hash};
use std::iter::{FromIterator, Iterator};
use std::borrow::BorrowFrom;
use std::collections::HashMap;
use std::collections::hash_map::{Keys, Iter};
use std::collections::hash_state::{HashState, DefaultState};

use xxhash::XXHasher;

/// Distribution doesn't require a cryptographically secure hash, and by
/// default will not use one.
pub trait Distribution<H = XXHasher> {
  type Key;
  type Quantity;

  fn len(&self) -> usize;
  fn get<Q: ?Sized>(&self, k: &Q) -> Option<&Self::Quantity>
    where Q: Hash<H> + Eq + BorrowFrom<Self::Key>;
  fn clear(&mut self);
  fn insert(&mut self, k: Self::Key);
  fn remove<Q: ?Sized>(&mut self, k: &Q)
    where Q: Hash<H> + Eq + BorrowFrom<Self::Key>;
}

/// Implementation of a Frequency Distribution in Rust. Keeps track of how many
/// times an object appears in a larger context (for example, how many times a
/// token appears in a piece of text). The underlying data structure of the
/// Frequency Distribution is a HashMap, so the object that is being counted
/// must be hashable.
///
/// # Example
///
/// ```rust
/// use freqdist::{Distribution, FrequencyDistribution};
///
/// let mut fdist = FrequencyDistribution::new();
///
/// fdist.insert("hello");
/// fdist.insert("hello");
/// fdist.insert("goodbyte");
///
/// assert_eq!(*fdist.get("hello").unwrap(), 2);
/// ```
pub struct FrequencyDistribution<K, S = DefaultState<XXHasher>> {
  hashmap: HashMap<K, usize, S>,
  sum_counts: usize
}

impl<K> FrequencyDistribution<K>
  where K: Eq + Hash<XXHasher>
{
  /// Creates a new FrequencyDistribution where the size of the
  /// HashMap is unknown.
  #[inline]
  pub fn new() -> FrequencyDistribution<K> {
    FrequencyDistribution::with_hash_state(Default::default())
  }

  /// Creates a new FrequencyDistribution where the size of the HashMap
  /// is known, or a estimate can be made.
  #[inline]
  pub fn with_capacity(
    size: usize
  ) -> FrequencyDistribution<K> {
    FrequencyDistribution::with_capacity_and_hash_state(size, Default::default())
  }
}

impl<K, S, H> FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Creates a new FrequencyDistrbution with a hash state and size, where
  /// the size is known or can be estimated.
  #[inline]
  pub fn with_capacity_and_hash_state(
    size: usize,
    state: S
  ) -> FrequencyDistribution<K, S> {
    FrequencyDistribution {
      hashmap: HashMap::with_capacity_and_hash_state(size, state),
      sum_counts: 0
    }
  }

  /// Creates a new FrequencyDistribution with a hash state and default size.
  #[inline]
  pub fn with_hash_state(state: S) -> FrequencyDistribution<K, S> {
    FrequencyDistribution {
      hashmap: HashMap::with_hash_state(state),
      sum_counts: 0
    }
  }
}

impl<K, S, H> FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Iterator over the keys.
  #[inline]
  #[stable]
  pub fn keys(&self) -> Keys<K, usize> {
    self.hashmap.keys()
  }

  /// Iterator over the key, frequency pairs.
  #[inline]
  #[stable]
  pub fn iter(&self) -> Iter<K, usize> {
    self.hashmap.iter()
  }

  /// Iterator over the non-zero frequency keys.
  #[inline]
  #[stable]
  pub fn iter_non_zero(&self) -> NonZeroKeysIter<K> {
    NonZeroKeysIter { iter: self.iter() }
  }

  /// Iterator over just the keys.
  #[inline]
  #[stable]
  pub fn sum_counts(&self) -> usize {
    self.sum_counts
  }

  /// Inserts a value sizeo the hashmap if it does not exist with a new quantity
  /// specified by the increment. If the value already exists, increments by
  /// the specified amount.
  #[inline]
  fn insert_or_incr_by(&mut self, k: K, incr: usize) {
    if !self.hashmap.contains_key(&k) {
      self.hashmap.insert(k, incr);
    } else {
      *self.hashmap.get_mut(&k).unwrap() += incr;
    }

    self.sum_counts += incr;
  }
}

impl<K> Default for FrequencyDistribution<K>
  where K: Eq + Hash<XXHasher>
{
  /// Creates a default FrequencyDistribution with an XXHasher.
  #[inline]
  #[stable]
  fn default() -> FrequencyDistribution<K> {
    FrequencyDistribution::new()
  }
}

impl<K, S, H> FromIterator<(K, usize)> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher = H> + Default,
        H: Hasher<Output = u64>
{
  /// Iterates through an iterator, and creates a new FrequencyDistribution from
  /// it. The iterator should be an iterator over keys and frequencies. If a
  /// upper bounded `size_hsize` is available, then it is used, otherwise the lower
  /// bounded `size_hsize` is used.
  ///
  /// # Example
  ///
  /// ```rust
  /// #![allow(unstable)]
  /// use std::iter::FromIterator;
  /// use freqdist::{Distribution, FrequencyDistribution};
  ///
  /// let existing = vec![
  ///   ("apples", 3),
  ///   ("oranges", 4),
  ///   ("bannana", 7)
  /// ];
  ///
  /// let fdist: FrequencyDistribution<&str> =
  ///   FromIterator::from_iter(existing.into_iter());
  ///
  /// assert_eq!(*fdist.get("apples").unwrap(), 3);
  /// assert_eq!(*fdist.get("oranges").unwrap(), 4);
  /// assert_eq!(*fdist.get("bannana").unwrap(), 7);
  /// ```
  fn from_iter<T: Iterator<Item = (K, usize)>>(
    iter: T
  ) -> FrequencyDistribution<K, S> {
    let mut fdist = if iter.size_hint().1.is_some() {
      FrequencyDistribution::with_capacity_and_hash_state(
        iter.size_hint().1.unwrap(),
        Default::default())
    } else {
      FrequencyDistribution::with_capacity_and_hash_state(
        iter.size_hint().0,
        Default::default())
    };

    fdist.extend(iter);
    fdist
  }
}

impl<K, S, H> Extend<(K, usize)> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  /// Extends the hashmap by adding the keys or updating the frequencies of the keys.
  #[inline]
  fn extend<T: Iterator<Item = (K, usize)>>(&mut self, iter: T) {
    for (k, freq) in iter {
      self.insert_or_incr_by(k, freq);
    }
  }
}

impl<K, S, H> Distribution<H> for FrequencyDistribution<K, S>
  where K: Eq + Hash<H>,
        S: HashState<Hasher=H>,
        H: Hasher<Output=u64>
{
  type Key = K;
  type Quantity = usize;

  /// Returns the number of entries in the distribution
  #[inline]
  #[stable]
  fn len(&self) -> usize {
    self.hashmap.len()
  }

  /// Gets the frequency in which the key occurs.
  #[inline]
  #[stable]
  fn get<Q: ?Sized>(&self, k: &Q) -> Option<&usize>
    where Q: Hash<H> + Eq + BorrowFrom<K>
  {
    self.hashmap.get(k)
  }

  /// Clears the counts of all keys and clears all keys from
  /// the distribution.
  #[inline]
  #[stable]
  fn clear(&mut self) {
    self.hashmap.clear()
  }

  /// Updates the frequency of the value found with the key if it
  /// already exists. Otherwise, inserts the key sizeo the hashmap,
  /// and sets its frequency to 1.
  #[inline]
  #[stable]
  fn insert(&mut self, k: K) {
    self.insert_or_incr_by(k, 1);
  }

  /// Removes a Key and its associated value from the Distrbution.
  #[inline]
  #[stable]
  fn remove<Q: ?Sized>(&mut self, k: &Q)
    where Q: Hash<H> + Eq + BorrowFrom<K>
  {
    match self.hashmap.remove(k) {
      Some(count) => self.sum_counts -= count,
      None        => ()
    }
  }
}

/// Iterator over entries with non-zero quantities.
#[stable]
pub struct NonZeroKeysIter<'a, K: 'a> {
  iter: Iter<'a, K, usize>
}

impl<'a, K: 'a> Iterator for NonZeroKeysIter<'a, K> {
  type Item = &'a K;

  #[inline]
  fn next(&mut self) -> Option<&'a K> {
    loop {
      match self.iter.next() {
        Some((k, c)) if *c > 0 => return Some(k),
        None                   => return None,
        _                      => ()
      }
    }
  }

  #[inline]
  fn size_hint(&self) -> (usize, Option<usize>) {
    self.iter.size_hint()
  }
}

#[test]
fn smoke_test_frequency_distribution_insert() {
  let words = vec!("alpha", "beta");
  let mut dist: FrequencyDistribution<&str> = FrequencyDistribution::new();

  dist.insert(words[0]);

  assert_eq!(*dist.get(&words[0]).unwrap(), 1);

  dist.insert(words[1]);

  assert_eq!(*dist.get(&words[1]).unwrap(), 1);

  for _ in range(0, 7us) { dist.insert(words[0]); }

  assert_eq!(*dist.get(&words[0]).unwrap(), 8);
}

#[test]
fn smoke_test_frequency_distribution_iter() {
  let words = vec!(("a", 50us), ("b", 100us), ("c", 75us), ("d", 0us));
  let dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert_eq!(*dist.get(&"a").unwrap(), 50);
  assert_eq!(*dist.get(&"b").unwrap(), 100);
  assert_eq!(*dist.get(&"c").unwrap(), 75);

  let mut iter = dist.iter_non_zero();

  assert!(iter.next().is_some());
  assert!(iter.next().is_some());
  assert!(iter.next().is_some());
  assert!(iter.next().is_none());

  assert_eq!(dist.sum_counts(), 225);
}

#[test]
fn smoke_test_frequency_distribution_remove() {
  let words = vec!(("a", 50us), ("b", 100us), ("c", 25us));
  let mut dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert!(dist.get(&"a").is_some());

  dist.remove(&"a");

  assert!(dist.get(&"a").is_none());
  assert_eq!(dist.sum_counts(), 125);
}

#[test]
fn smoke_test_frequency_sum_counts() {
  let words = vec!(("a", 7us), ("b", 5us), ("c", 8us), ("d", 3us));
  let mut dist: FrequencyDistribution<&str> = FromIterator::from_iter(words.into_iter());

  assert_eq!(dist.sum_counts(), 23);

  dist.insert("e");

  assert_eq!(dist.sum_counts(), 24);
}
<|endoftext|>


<commit_before>pub mod bundle;
pub mod cldr;
pub mod cli;
pub mod m17n_mim;
pub mod xkb;

pub use bundle::*;

pub(crate) mod pad;
pub(crate) mod utils;

use std::{convert::TryFrom, convert::TryInto, path::PathBuf, sync::Arc};

use pahkat_client::{PackageStore, InstallTarget, config::RepoRecord, package_store::prefix::PrefixPackageStore, types::package_key::PackageKeyParams};
use pahkat_client::transaction::{PackageAction, PackageTransaction};
use pahkat_client::types::{repo::RepoUrl, PackageKey};

use futures::stream::StreamExt;

pub fn prefix_dir() -> PathBuf {
    let kbdgen_data = pathos::user::app_data_dir("kbdgen").unwrap();
    kbdgen_data.join("prefix")
}

async fn create_prefix() -> Arc<dyn PackageStore> {
    let prefix_path = prefix_dir();
    let prefix = PrefixPackageStore::open_or_create(prefix_path).await.unwrap();
    let config = prefix.config();

    let mut config = config.write().unwrap();
    let settings = config.settings_mut();
    settings.set_cache_dir(pathos::user::app_cache_dir("kbdgen").unwrap().try_into().unwrap()).unwrap();
    settings.set_tmp_dir(pathos::user::app_temporary_dir("kbdgen").unwrap().try_into().unwrap()).unwrap();

    let repos = config.repos_mut();
    repos.insert("https://pahkat.uit.no/devtools/".parse().unwrap(), RepoRecord { channel: Some("nightly".into()) }).unwrap();

    Arc::new(prefix)
}

async fn install_kbdi() {
    log::info!("Updating 'kbdi' and 'kbdi-legacy'...");

    let store = create_prefix().await;

    let repo_url: RepoUrl = "https://pahkat.uit.no/devtools/".parse().unwrap();

    let pkg_key_kbdi = PackageKey::new_unchecked(repo_url.clone(), "kbdi".to_string(), Some(PackageKeyParams {
        channel: Some("nightly".to_string()),
        ..Default::default()
    }));
    let pkg_key_kbdi_legacy = PackageKey::new_unchecked(repo_url.clone(), "kbdi-legacy".to_string(), Some(PackageKeyParams {
        channel: Some("nightly".to_string()),
        ..Default::default()
    }));

    let actions = vec![
        PackageAction::install(pkg_key_kbdi, InstallTarget::System),
        PackageAction::install(pkg_key_kbdi_legacy, InstallTarget::System)
    ];

    let tx = PackageTransaction::new(Arc::clone(&store as _), actions).unwrap();

    for record in tx.actions().iter() {
        let action = &record.action;
        let mut download = store.download(&action.id);

        use pahkat_client::package_store::DownloadEvent;

        while let Some(event) = download.next().await {
            match event {
                DownloadEvent::Error(e) => {
                    log::error!("{:?}", &e);
                    std::process::exit(1);
                }
                event => {
                    log::debug!("{:?}", &event);
                }
            };
        }
    }

    let (_cancel, mut stream) = tx.process();

    while let Some(value) = stream.next().await {
        println!("{:?}", value);
    }
}

pub fn install_kbdi_blocking() {
    let mut rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(install_kbdi());
}
<commit_msg>Refresh repos after changing config<commit_after>pub mod bundle;
pub mod cldr;
pub mod cli;
pub mod m17n_mim;
pub mod xkb;

pub use bundle::*;

pub(crate) mod pad;
pub(crate) mod utils;

use std::{convert::TryFrom, convert::TryInto, path::PathBuf, sync::Arc};

use pahkat_client::{PackageStore, InstallTarget, config::RepoRecord, package_store::prefix::PrefixPackageStore, types::package_key::PackageKeyParams};
use pahkat_client::transaction::{PackageAction, PackageTransaction};
use pahkat_client::types::{repo::RepoUrl, PackageKey};

use futures::stream::StreamExt;

pub fn prefix_dir() -> PathBuf {
    let kbdgen_data = pathos::user::app_data_dir("kbdgen").unwrap();
    kbdgen_data.join("prefix")
}

async fn create_prefix() -> Arc<dyn PackageStore> {
    let prefix_path = prefix_dir();
    let prefix = PrefixPackageStore::open_or_create(prefix_path).await.unwrap();
    let config = prefix.config();

    let mut config = config.write().unwrap();
    let settings = config.settings_mut();
    settings.set_cache_dir(pathos::user::app_cache_dir("kbdgen").unwrap().try_into().unwrap()).unwrap();
    settings.set_tmp_dir(pathos::user::app_temporary_dir("kbdgen").unwrap().try_into().unwrap()).unwrap();

    let repos = config.repos_mut();
    repos.insert("https://pahkat.uit.no/devtools/".parse().unwrap(), RepoRecord { channel: Some("nightly".into()) }).unwrap();

    let _ = prefix.force_refresh_repos().await;

    Arc::new(prefix)
}

async fn install_kbdi() {
    log::info!("Updating 'kbdi' and 'kbdi-legacy'...");

    let store = create_prefix().await;

    let repo_url: RepoUrl = "https://pahkat.uit.no/devtools/".parse().unwrap();

    let pkg_key_kbdi = PackageKey::new_unchecked(repo_url.clone(), "kbdi".to_string(), Some(PackageKeyParams {
        channel: Some("nightly".to_string()),
        ..Default::default()
    }));
    let pkg_key_kbdi_legacy = PackageKey::new_unchecked(repo_url.clone(), "kbdi-legacy".to_string(), Some(PackageKeyParams {
        channel: Some("nightly".to_string()),
        ..Default::default()
    }));

    let actions = vec![
        PackageAction::install(pkg_key_kbdi, InstallTarget::System),
        PackageAction::install(pkg_key_kbdi_legacy, InstallTarget::System)
    ];

    let tx = PackageTransaction::new(Arc::clone(&store as _), actions).unwrap();

    for record in tx.actions().iter() {
        let action = &record.action;
        let mut download = store.download(&action.id);

        use pahkat_client::package_store::DownloadEvent;

        while let Some(event) = download.next().await {
            match event {
                DownloadEvent::Error(e) => {
                    log::error!("{:?}", &e);
                    std::process::exit(1);
                }
                event => {
                    log::debug!("{:?}", &event);
                }
            };
        }
    }

    let (_cancel, mut stream) = tx.process();

    while let Some(value) = stream.next().await {
        println!("{:?}", value);
    }
}

pub fn install_kbdi_blocking() {
    let mut rt = tokio::runtime::Runtime::new().unwrap();
    rt.block_on(install_kbdi());
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotRouter {
        bots: HashMap::new(),
        output_bins: HashMap::new(),
    };

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                let return_commands = if self.chip1 < self.chip2 {
                    if self.chip1 == Some(17) && self.chip2 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    if self.chip2 == Some(17) && self.chip1 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<commit_msg>Add some printing. I think I'm processing things in the wrong order.<commit_after>use std::collections::HashMap;

pub fn puzzle(input: &str) -> usize {
    let mut br = BotRouter {
        bots: HashMap::new(),
        output_bins: HashMap::new(),
    };

    for line in input.lines() {
        br.exec_command(line);
    }
    0
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BotOrOutput {
    Bot,
    Output,
}

#[derive(PartialEq, Debug)]
pub struct Bot {
    key: usize,
    chip1: Option<usize>,
    chip2: Option<usize>,
    low: Option<usize>,
    low_bot_or_output: Option<BotOrOutput>,
    high: Option<usize>,
    high_bot_or_output: Option<BotOrOutput>,
}

impl Bot {
    pub fn new(key: usize) -> Bot {
        Bot {
            key: key,
            chip1: None, chip2: None,
            low: None, high: None,
            low_bot_or_output: None,
            high_bot_or_output: None,
        }
    }

    pub fn receive_chip(&mut self, chip: usize)
           -> Vec<(usize, BotOrOutput, usize)> {
        if self.chip1.is_none() {
            println!("bot {}, chip1 = {}", self.key, chip);
            self.chip1 = Some(chip);
            vec![]
        } else if self.chip2.is_none() {
            println!("bot {}, chip2 = {}", self.key, chip);
            self.chip2 = Some(chip);
            if let (Some(lo), Some(hi)) = (self.low, self.high) {
                println!("bot {} has 2 chips; low to {:?} {}, high to {:?} {}", self.key, self.low_bot_or_output, lo, self.high_bot_or_output, hi);
                let return_commands = if self.chip1 < self.chip2 {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip1, self.chip2);
                    if self.chip1 == Some(17) && self.chip2 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                    ]
                } else {
                    println!("bot {} finds {:?} < {:?}", self.key, self.chip2, self.chip1);
                    if self.chip2 == Some(17) && self.chip1 == Some(61) {
                        panic!("The bot you are looking for is {}", self.key);
                    }

                    vec![
                        (
                            lo,
                            self.low_bot_or_output.unwrap(),
                            self.chip2.unwrap()
                        ),
                        (
                            hi,
                            self.high_bot_or_output.unwrap(),
                            self.chip1.unwrap()
                        ),
                    ]
                };
                self.chip1 = None;
                self.chip2 = None;
                self.low = None;
                self.high = None;
                self.low_bot_or_output = None;
                self.high_bot_or_output = None;
                return_commands
            } else {
                vec![]
            }
        } else {
            panic!("Cannot hold more than two chips");
        }
    }

    pub fn receive_command(&mut self, low_bot_or_output: &str, low: usize,
                                      high_bot_or_output: &str, high: usize) {
        println!("bot {} storing command low to {} {}, high to {} {}", self.key, low_bot_or_output, low, high_bot_or_output, high);
        self.low = Some(low);
        if low_bot_or_output == "bot" {
            self.low_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.low_bot_or_output = Some(BotOrOutput::Output);
        }
        self.high = Some(high);
        if high_bot_or_output == "bot" {
            self.high_bot_or_output = Some(BotOrOutput::Bot);
        } else {
            self.high_bot_or_output = Some(BotOrOutput::Output);
        }
    }
}

pub struct BotRouter {
    bots: HashMap<usize, Bot>,
    output_bins: HashMap<usize, Vec<usize>>,
}

impl BotRouter {
    pub fn exec_command(&mut self, input: &str) {
        println!("COMMAND: {}", input);
        let pieces: Vec<&str> = input.split_whitespace().collect();

        if pieces[0] == "value" {
            self.value_to_bot(
                pieces[5].parse().expect("can't parse bot key"),
                pieces[1].parse().expect("can't parse chip value")
            );
        } else if pieces[0] == "bot" {
            self.command_to_bot(
                pieces[1].parse().expect("can't parse bot key"),
                pieces[5],
                pieces[6].parse().expect("can't parse low key"),
                pieces[10],
                pieces[11].parse().expect("can't parse high key"),
            );
        }
    }

    pub fn value_to_bot(&mut self, bot_key: usize, value: usize) {
        println!("ROUTER sending value {} to bot {}", value, bot_key);
        let return_commands = self.bots
                                  .entry(bot_key)
                                  .or_insert(Bot::new(bot_key))
                                  .receive_chip(value);
        for &(key, bot_or_output, chip_value) in return_commands.iter() {
            match bot_or_output {
                BotOrOutput::Bot => self.value_to_bot(key, chip_value),
                BotOrOutput::Output => self.value_to_output(key, chip_value),
            }
        }
    }

    pub fn value_to_output(&mut self, output_key: usize, value: usize) {
        println!("ROUTER sending value {} to output {}", value, output_key);
        self.output_bins.entry(output_key).or_insert(Vec::new()).push(value);
    }

    pub fn command_to_bot(&mut self, bot_key: usize,
                          low_bot_or_output: &str, low_key: usize,
                          high_bot_or_output: &str, high_key: usize) {
        let bot = self.bots.entry(bot_key).or_insert(Bot::new(bot_key));
        bot.receive_command(
            low_bot_or_output,
            low_key,
            high_bot_or_output,
            high_key
        );
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::collections::HashMap;

    #[test]
    fn router_can_give_values() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            Some(5)
        );
    }

    #[test]
    fn router_can_give_commands_that_get_stored() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        assert_eq!(
            br.bots.get(&2).unwrap().low,
            Some(1)
        );
        assert_eq!(
            br.bots.get(&2).unwrap().high,
            Some(0)
        );
    }

    #[test]
    fn router_adds_two_values_so_commands_get_executed() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.bots.get(&2).unwrap().chip1,
            None
        );
        assert_eq!(
            br.bots.get(&2).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&1).unwrap().chip1,
            Some(2)
        );
        assert_eq!(
            br.bots.get(&1).unwrap().chip2,
            None
        );

        assert_eq!(
            br.bots.get(&0).unwrap().chip1,
            Some(5)
        );
        assert_eq!(
            br.bots.get(&0).unwrap().chip2,
            None
        );
    }

    #[test]
    fn test_sample() {
        let mut br = BotRouter {
            bots: HashMap::new(),
            output_bins: HashMap::new(),
        };
        br.exec_command("value 5 goes to bot 2");
        br.exec_command("bot 2 gives low to bot 1 and high to bot 0");
        br.exec_command("value 3 goes to bot 1");
        br.exec_command("bot 1 gives low to output 1 and high to bot 0");
        br.exec_command("bot 0 gives low to output 2 and high to output 0");
        br.exec_command("value 2 goes to bot 2");

        assert_eq!(
            br.output_bins.get(&0),
            Some(&vec![5])
        );

        assert_eq!(
            br.output_bins.get(&1),
            Some(&vec![2])
        );

        assert_eq!(
            br.output_bins.get(&2),
            Some(&vec![3])
        )
    }
}
<|endoftext|>


<commit_before>//! A library for interacting with Twitter.
//!
//! Please see [the repository][] and its enclosed examples for tips on working with this library
//! while it's still in progress.
//!
//! [the repository]: https://github.com/QuietMisdreavus/twitter-rs
//!
//! ## Getting Started
//!
//! The very first thing you'll need to do to get access to the Twitter API is to head to
//! [Twitter's Application Manager][twitter-apps] and create an app. Once you've done that, there
//! are two sets of keys immediately available to you. First are the "consumer key" and "consumer
//! secret", that are used to represent you as the application author when signing requests. These
//! keys are given to every single API call regardless of permission level. Related are an "access
//! token" and "access token secret", that can be used to skip the authentication steps if you're
//! only interacting with your own account or with no account in particular. Generally, if you want
//! to read or write to a particular user's stream, you'll need to request authorization and get an
//! access token to work on their behalf.
//!
//! [twitter-apps]: https://apps.twitter.com/
//!
//! The process to get an access token for a specific user (with this library) has three basic
//! steps:
//!
//! 1. Log your request with Twitter by getting a [request token][].
//! 2. Direct the user to grant permission to your application by sending them to an
//!    [authenticate][] or [authorize][] URL, depending on the nature of your app.
//! 3. Convert the verifier given by the permission request into an [access token][].
//!
//! [request token]: fn.request_token.html
//! [authorize]: fn.authorize_url.html
//! [authenticate]: fn.authenticate_url.html
//! [access token]: fn.access_token.html
//!
//! The process changes some smaller details depending on whether your application is web- or
//! mobile-based, as opposed to desktop-based or in another situation where redirecting users to a
//! web browser and back automatically is difficult or impossible. In the former case where URLs
//! can be used to direct the user into and out of your app, give Twitter a "callback URL" when
//! setting up your request token, and redirect the user to an [authenticate][] URL to grant your
//! app permissions. When the user accepts the request, they will be redirected back to this URL to
//! get back to your app, with the original request token and a verifier given to your app to
//! signify their acceptance.
//!
//! On the other hand, if you can't use the callback URL in this fashion, you can instead use the
//! "PIN-based Auth" version of the flow. In this version, give a "callback URL" of "oob" when
//! setting up your request token, and use an [authorize][] URL. When the user grants the
//! permissions request in this fashion, they are given a numeric PIN that can be given back to
//! your app to use as a verifier.
//!
//! Either way, when you have a "verifier" from either of these methods, you can use your Tokens
//! from earlier in the process with that verifier to request an [access token][]. This access
//! token can then be saved and cached for future use.
//!
//! ## `Response<T>`
//!
//! Every method that calls Twitter and carries rate-limit information wraps its return value in a
//! [`Response`][] struct, that transmits this information to your app. From there, you can handle
//! the rate-limit information to hold off on that kind of request, or simply grab its `response`
//! field to get the output of whatever method you called.
//!
//! [`Response`]: struct.Response.html

#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_qualifications)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate url;
extern crate rand;
extern crate crypto;
extern crate rustc_serialize;
extern crate mime;
extern crate chrono;
extern crate regex;

mod auth;
pub mod error;
pub mod user;
pub mod entities;
pub mod cursor;
pub mod tweet;
pub mod search;
pub mod place;
pub mod direct;
pub mod service;
mod links;
mod common;

pub use auth::{Token, request_token, authorize_url, authenticate_url, access_token, verify_tokens};
pub use common::{Response, ResponseIter, WebResponse};
<commit_msg>add a module listing to top-level docs<commit_after>//! A library for interacting with Twitter.
//!
//! Please see [the repository][] and its enclosed examples for tips on working with this library
//! while it's still in progress.
//!
//! [the repository]: https://github.com/QuietMisdreavus/twitter-rs
//!
//! ## Getting Started
//!
//! The very first thing you'll need to do to get access to the Twitter API is to head to
//! [Twitter's Application Manager][twitter-apps] and create an app. Once you've done that, there
//! are two sets of keys immediately available to you. First are the "consumer key" and "consumer
//! secret", that are used to represent you as the application author when signing requests. These
//! keys are given to every single API call regardless of permission level. Related are an "access
//! token" and "access token secret", that can be used to skip the authentication steps if you're
//! only interacting with your own account or with no account in particular. Generally, if you want
//! to read or write to a particular user's stream, you'll need to request authorization and get an
//! access token to work on their behalf.
//!
//! [twitter-apps]: https://apps.twitter.com/
//!
//! The process to get an access token for a specific user (with this library) has three basic
//! steps:
//!
//! 1. Log your request with Twitter by getting a [request token][].
//! 2. Direct the user to grant permission to your application by sending them to an
//!    [authenticate][] or [authorize][] URL, depending on the nature of your app.
//! 3. Convert the verifier given by the permission request into an [access token][].
//!
//! [request token]: fn.request_token.html
//! [authorize]: fn.authorize_url.html
//! [authenticate]: fn.authenticate_url.html
//! [access token]: fn.access_token.html
//!
//! The process changes some smaller details depending on whether your application is web- or
//! mobile-based, as opposed to desktop-based or in another situation where redirecting users to a
//! web browser and back automatically is difficult or impossible. In the former case where URLs
//! can be used to direct the user into and out of your app, give Twitter a "callback URL" when
//! setting up your request token, and redirect the user to an [authenticate][] URL to grant your
//! app permissions. When the user accepts the request, they will be redirected back to this URL to
//! get back to your app, with the original request token and a verifier given to your app to
//! signify their acceptance.
//!
//! On the other hand, if you can't use the callback URL in this fashion, you can instead use the
//! "PIN-based Auth" version of the flow. In this version, give a "callback URL" of "oob" when
//! setting up your request token, and use an [authorize][] URL. When the user grants the
//! permissions request in this fashion, they are given a numeric PIN that can be given back to
//! your app to use as a verifier.
//!
//! Either way, when you have a "verifier" from either of these methods, you can use your Tokens
//! from earlier in the process with that verifier to request an [access token][]. This access
//! token can then be saved and cached for future use.
//!
//! ## `Response<T>`
//!
//! Every method that calls Twitter and carries rate-limit information wraps its return value in a
//! [`Response`][] struct, that transmits this information to your app. From there, you can handle
//! the rate-limit information to hold off on that kind of request, or simply grab its `response`
//! field to get the output of whatever method you called.
//!
//! [`Response`]: struct.Response.html
//!
//! ## Modules
//!
//! As there are many actions available in the Twitter API, egg-mode divides them roughly into
//! several modules by their shared purpose. Here's a sort of high-level overview, in rough order
//! from "most important" to "less directly used":
//!
//! ### Primary actions
//!
//! These could be considered the "core" actions within the Twitter API that egg-mode has made
//! available.
//!
//! * `tweet`: This module lets you act on tweets. Here you can find actions to load a user's
//!   timeline, post a new tweet, or like and retweet individual posts.
//! * `user`: This module lets you act on users, be it by following or unfollowing them, loading
//!   their profile information, blocking or muting them, or showing the relationship between two
//!   users.
//! * `search`: Due to the complexity of searching for tweets, it gets its own module.
//! * `direct`: Here you can work with a user's Direct Messages, either by loading DMs they've sent
//!   or received, or by sending new ones.
//!
//! ### Secondary actions
//!
//! These modules still contain direct actions for Twitter, but they can be considered as having
//! more of a helper role than something you might use directly.
//!
//! * `place`: Here are actions that look up physical locations that can be attached to tweets, as
//!   well at the `Place` struct that appears on tweets with locations attached.
//! * `service`: These are some miscellaneous methods that show information about the Twitter
//!   service as a whole, like loading the maximum length of t.co URLs or loading the current Terms
//!   of Service or Privacy Policy.
//!
//! ### Helper structs
//!
//! These modules contain some implementations that wrap some pattern seen in multiple "action"
//! modules.
//!
//! * `cursor`: This contains a helper trait and some helper structs that allow effective cursoring
//!   through certain collections of results from Twitter.
//! * `entities`: Whenever some text can be returned that may contain links, hashtags, media, or
//!   user mentions, its metadata is parsed into something that lives in this module.
//! * `error`: Any interaction with Twitter may result in an error condition, be it from finding a
//!   tweet or user that doesn't exist or the network connection being unavailable. All the error
//!   types are aggregated into an enum in this module.

#![warn(missing_docs)]
#![warn(unused_extern_crates)]
#![warn(unused_qualifications)]

#[macro_use] extern crate hyper;
#[macro_use] extern crate lazy_static;
extern crate url;
extern crate rand;
extern crate crypto;
extern crate rustc_serialize;
extern crate mime;
extern crate chrono;
extern crate regex;

mod auth;
pub mod error;
pub mod user;
pub mod entities;
pub mod cursor;
pub mod tweet;
pub mod search;
pub mod place;
pub mod direct;
pub mod service;
mod links;
mod common;

pub use auth::{Token, request_token, authorize_url, authenticate_url, access_token, verify_tokens};
pub use common::{Response, ResponseIter, WebResponse};
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

extern crate cairo_sys as ffi;
extern crate libc;
extern crate glib;
extern crate c_vec;

pub use ffi::enums;
pub use ffi::cairo_rectangle_t as Rectangle;

pub use context::{
    Context,
    RectangleVec,
};

pub use paths::{
    Path,
    PathSegments,
    PathSegment
};

pub use enums::{
    Status,
    Antialias,
    FillRule,
    LineCap,
    LineJoin,
    Operator,
    PathDataType,
    Format,
    SurfaceType,
};

pub use error::{
    BorrowError,
    IoError,
};

pub use patterns::{
    //Traits
    Pattern,
    Gradient,

    //Structs
    LinearGradient,
    RadialGradient,
    SolidPattern,
    SurfacePattern,
};

#[cfg(feature = "v1_12")]
pub use patterns::{
    Mesh,
    MeshCorner,
};

pub use fonts::{
    FontFace,
    FontSlant,
    FontWeight,
    ScaledFont,
    FontOptions,

    Glyph,
    FontExtents,
    TextExtents,
    TextCluster,
};

pub use matrices::{
    Matrix,
    MatrixTrait,
};

pub use rectangle::RectangleInt;

pub use surface::Surface;

pub use image_surface::{
    ImageSurface,
    ImageSurfaceData,
};

#[cfg(feature = "xcb")]
pub use xcb::{
    XCBConnection,
    XCBSurface,
    Device,
    XCBDrawable,
    XCBPixmap,
    XCBRenderPictFormInfo,
    XCBScreen,
    XCBVisualType,
};

pub mod prelude;

mod fonts;
mod context;
mod error;
mod image_surface;
#[cfg(feature = "png")]
mod image_surface_png;
mod paths;
mod patterns;
mod rectangle;
mod surface;
mod matrices;
#[cfg(feature = "xcb")]
mod xcb;

#[cfg(windows)]
mod win32_surface;

#[cfg(windows)]
pub use win32_surface::Win32Surface;
<commit_msg>Reexport forgotten sys enums used in Pattern public functions<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

extern crate cairo_sys as ffi;
extern crate libc;
extern crate glib;
extern crate c_vec;

pub use ffi::enums;
pub use ffi::cairo_rectangle_t as Rectangle;

pub use context::{
    Context,
    RectangleVec,
};

pub use paths::{
    Path,
    PathSegments,
    PathSegment
};

pub use enums::{
    Status,
    Antialias,
    Content,
    Extend,
    FillRule,
    Filter,
    LineCap,
    LineJoin,
    Operator,
    PathDataType,
    Format,
    SurfaceType,
};

pub use error::{
    BorrowError,
    IoError,
};

pub use patterns::{
    //Traits
    Pattern,
    Gradient,

    //Structs
    LinearGradient,
    RadialGradient,
    SolidPattern,
    SurfacePattern,
};

#[cfg(feature = "v1_12")]
pub use patterns::{
    Mesh,
    MeshCorner,
};

pub use fonts::{
    FontFace,
    FontSlant,
    FontWeight,
    ScaledFont,
    FontOptions,

    Glyph,
    FontExtents,
    TextExtents,
    TextCluster,
};

pub use matrices::{
    Matrix,
    MatrixTrait,
};

pub use rectangle::RectangleInt;

pub use surface::Surface;

pub use image_surface::{
    ImageSurface,
    ImageSurfaceData,
};

#[cfg(feature = "xcb")]
pub use xcb::{
    XCBConnection,
    XCBSurface,
    Device,
    XCBDrawable,
    XCBPixmap,
    XCBRenderPictFormInfo,
    XCBScreen,
    XCBVisualType,
};

pub mod prelude;

mod fonts;
mod context;
mod error;
mod image_surface;
#[cfg(feature = "png")]
mod image_surface_png;
mod paths;
mod patterns;
mod rectangle;
mod surface;
mod matrices;
#[cfg(feature = "xcb")]
mod xcb;

#[cfg(windows)]
mod win32_surface;

#[cfg(windows)]
pub use win32_surface::Win32Surface;
<|endoftext|>