<commit_before>//! A probability-theory toolbox.

#[cfg(test)]
extern crate assert;

extern crate num;
extern crate rand;
extern crate special;

pub use ::rand::Rng as Generator;
pub use ::rand::thread_rng as generator;

pub mod distributions;

/// An interface for a probability distribution.
pub trait Distribution {
    type Item;

    /// Compute the cumulative distribution function (CDF) at point `x`.
    fn cdf(&self, x: Self::Item) -> f64;

    /// Compute the inverse of the cumulative distribution function at probability `p`.
    fn inv_cdf(&self, p: f64) -> Self::Item;

    /// Compute the probability density function (PDF) as point `x`.
    fn pdf(&self, x: Self::Item) -> f64;

    /// Draw a random sample.
    fn sample<G: Generator>(&self, generator: &mut G) -> Self::Item;
}

/// A means of drawing a sequence of samples from a probability distribution.
///
/// # Example
///
/// ```
/// use probability::generator;
/// use probability::Sampler;
/// use probability::distributions::Uniform;
///
/// let uniform = Uniform::new(0.0, 1.0);
/// let samples = Sampler(&uniform, &mut generator()).take(10).collect::<Vec<_>>();
/// ```
pub struct Sampler<D, G>(pub D, pub G);

impl<'a, T, D, G> Iterator for Sampler<&'a D, &'a mut G>
    where D: Distribution<Item=T>, G: Generator {

    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        Some(self.0.sample(self.1))
    }
}
<commit_msg>Fix a typo<commit_after>//! A probability-theory toolbox.

#[cfg(test)]
extern crate assert;

extern crate num;
extern crate rand;
extern crate special;

pub use ::rand::Rng as Generator;
pub use ::rand::thread_rng as generator;

pub mod distributions;

/// An interface for a probability distribution.
pub trait Distribution {
    type Item;

    /// Compute the cumulative distribution function (CDF) at point `x`.
    fn cdf(&self, x: Self::Item) -> f64;

    /// Compute the inverse of the cumulative distribution function at probability `p`.
    fn inv_cdf(&self, p: f64) -> Self::Item;

    /// Compute the probability density function (PDF) at point `x`.
    fn pdf(&self, x: Self::Item) -> f64;

    /// Draw a random sample.
    fn sample<G: Generator>(&self, generator: &mut G) -> Self::Item;
}

/// A means of drawing a sequence of samples from a probability distribution.
///
/// # Example
///
/// ```
/// use probability::generator;
/// use probability::Sampler;
/// use probability::distributions::Uniform;
///
/// let uniform = Uniform::new(0.0, 1.0);
/// let samples = Sampler(&uniform, &mut generator()).take(10).collect::<Vec<_>>();
/// ```
pub struct Sampler<D, G>(pub D, pub G);

impl<'a, T, D, G> Iterator for Sampler<&'a D, &'a mut G>
    where D: Distribution<Item=T>, G: Generator {

    type Item = T;

    #[inline]
    fn next(&mut self) -> Option<T> {
        Some(self.0.sample(self.1))
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Claxon, a FLAC decoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![allow(dead_code)] // TODO: Remove for v0.2
#![feature(core, zero_one)]

use std::io;
use error::{Error, FlacResult};
use frame::{FrameReader};
use input::ReadExt;
use metadata::{MetadataBlock, MetadataBlockReader, StreamInfo};

mod crc;
mod input;
pub mod error;
pub mod frame;
pub mod sample;
pub mod subframe;
pub mod metadata;

/// A FLAC decoder that can decode the stream from the underlying reader.
///
/// TODO: Is stream a good name? Should it be called reader/decoder?
/// TODO: Add an example.
pub struct FlacStream<'r> {
    streaminfo: StreamInfo,
    metadata_blocks: Vec<MetadataBlock>,
    input: &'r mut (io::Read + 'r)
}

fn read_stream_header<R: io::Read>(input: &mut R) -> FlacResult<()> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(Error::InvalidStreamHeader); }
    Ok(())
}

impl<'r> FlacStream<'r> {
    /// Constructs a flac stream from the given input.
    ///
    /// This will read all metadata and stop at the first audio frame.
    pub fn new<R>(input: &mut R) -> FlacResult<FlacStream> where R: io::Read {
        // A flac stream first of all starts with a stream header.
        try!(read_stream_header(input));

        // Start a new scope, because the input reader must be available again
        // for the frame reader next.
        let (streaminfo, metadata_blocks) = {
            // Next are one or more metadata blocks. The flac specification
            // dictates that the streaminfo block is the first block. The metadata
            // block reader will yield at least one element, so the unwrap is safe.
            let mut metadata_iter = MetadataBlockReader::new(input);
            let streaminfo_block = try!(metadata_iter.next().unwrap());
            let streaminfo = match streaminfo_block {
                MetadataBlock::StreamInfo(info) => info,
                _ => return Err(Error::MissingStreamInfoBlock)
            };

            // There might be more metadata blocks, read and store them.
            let mut metadata_blocks = Vec::new();
            for block_result in metadata_iter {
                match block_result {
                    Err(error) => return Err(error),
                    Ok(block) => metadata_blocks.push(block)
                }
            }

            (streaminfo, metadata_blocks)
        };

        // The flac stream will contain the reader that will read frames.
        let flac_stream = FlacStream {
            streaminfo: streaminfo,
            metadata_blocks: metadata_blocks,
            input: input
        };

        Ok(flac_stream)
    }

    /// Returns the streaminfo metadata.
    pub fn streaminfo(&self) -> &StreamInfo {
        &self.streaminfo
    }

    /// Returns an iterator that decodes a single frame on every iteration.
    pub fn blocks<S: sample::Sample>(&'r mut self) -> FrameReader<'r, S> {
        FrameReader::new(&mut self.input)
    }
}
<commit_msg>use new name for unstable feature<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Claxon, a FLAC decoding library.
//!
//! TODO: Add some examples here.

#![warn(missing_docs)]
#![allow(dead_code)] // TODO: Remove for v0.2
#![feature(iter_arith, zero_one)]

use std::io;
use error::{Error, FlacResult};
use frame::{FrameReader};
use input::ReadExt;
use metadata::{MetadataBlock, MetadataBlockReader, StreamInfo};

mod crc;
mod input;
pub mod error;
pub mod frame;
pub mod sample;
pub mod subframe;
pub mod metadata;

/// A FLAC decoder that can decode the stream from the underlying reader.
///
/// TODO: Is stream a good name? Should it be called reader/decoder?
/// TODO: Add an example.
pub struct FlacStream<'r> {
    streaminfo: StreamInfo,
    metadata_blocks: Vec<MetadataBlock>,
    input: &'r mut (io::Read + 'r)
}

fn read_stream_header<R: io::Read>(input: &mut R) -> FlacResult<()> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(Error::InvalidStreamHeader); }
    Ok(())
}

impl<'r> FlacStream<'r> {
    /// Constructs a flac stream from the given input.
    ///
    /// This will read all metadata and stop at the first audio frame.
    pub fn new<R>(input: &mut R) -> FlacResult<FlacStream> where R: io::Read {
        // A flac stream first of all starts with a stream header.
        try!(read_stream_header(input));

        // Start a new scope, because the input reader must be available again
        // for the frame reader next.
        let (streaminfo, metadata_blocks) = {
            // Next are one or more metadata blocks. The flac specification
            // dictates that the streaminfo block is the first block. The metadata
            // block reader will yield at least one element, so the unwrap is safe.
            let mut metadata_iter = MetadataBlockReader::new(input);
            let streaminfo_block = try!(metadata_iter.next().unwrap());
            let streaminfo = match streaminfo_block {
                MetadataBlock::StreamInfo(info) => info,
                _ => return Err(Error::MissingStreamInfoBlock)
            };

            // There might be more metadata blocks, read and store them.
            let mut metadata_blocks = Vec::new();
            for block_result in metadata_iter {
                match block_result {
                    Err(error) => return Err(error),
                    Ok(block) => metadata_blocks.push(block)
                }
            }

            (streaminfo, metadata_blocks)
        };

        // The flac stream will contain the reader that will read frames.
        let flac_stream = FlacStream {
            streaminfo: streaminfo,
            metadata_blocks: metadata_blocks,
            input: input
        };

        Ok(flac_stream)
    }

    /// Returns the streaminfo metadata.
    pub fn streaminfo(&self) -> &StreamInfo {
        &self.streaminfo
    }

    /// Returns an iterator that decodes a single frame on every iteration.
    pub fn blocks<S: sample::Sample>(&'r mut self) -> FrameReader<'r, S> {
        FrameReader::new(&mut self.input)
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate event;
extern crate shader_version;
extern crate input;
extern crate gl;
extern crate current;

// External crates.
use std::mem::transmute;
use event::{
    Window,
    WindowSettings,
};
use event::window::{ ShouldClose, Size };
use event::window::{ PollEvent, SwapBuffers };
use event::window::{ CaptureCursor, SetCaptureCursor };
use input::{ keyboard, mouse, InputEvent };
use shader_version::opengl::OpenGL;
use current::{ Get, Modifier, Set };

/// A widow implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    settings: WindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        sdl2::init(sdl2::INIT_EVERYTHING);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );
        if settings.samples != 0 {
            sdl2::video::gl_set_attribute(sdl2::video::GLMultiSampleBuffers, 1);
            sdl2::video::gl_set_attribute(
                sdl2::video::GLMultiSampleSamples,
                settings.samples as int
            );
        }

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            settings: settings,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_mut(CaptureCursor(false));
    }
}

impl Get<ShouldClose> for Sdl2Window {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for Sdl2Window {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl SwapBuffers for Sdl2Window {
    fn swap_buffers(&mut self) {
        self.window.gl_swap_window();
    }
}

impl PollEvent<InputEvent> for Sdl2Window {
    fn poll_event(&mut self) -> Option<InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; }
            sdl2::event::TextInputEvent(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::MouseWheelEvent(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::ResizedWindowEventId, w, h) => {
                return Some(input::Resize(w as u32, h as u32));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::FocusGainedWindowEventId, _, _) => {
                return Some(input::Focus(true));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::FocusLostWindowEventId, _, _) => {
                return Some(input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

impl Modifier<Sdl2Window> for CaptureCursor {
    fn modify(self, _window: &mut Sdl2Window) {
        let CaptureCursor(enabled) = self;
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }
}

impl SetCaptureCursor for Sdl2Window {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Window for Sdl2Window {
    fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_drawable_size();
        (w as u32, h as u32)
    }

    fn close(&mut self) {
        self.should_close = true;
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}
<commit_msg>Updated to latest piston-event<commit_after>#![deny(missing_docs)]

//! A SDL2 window back-end for the Piston game engine.

extern crate sdl2;
extern crate event;
extern crate shader_version;
extern crate input;
extern crate gl;
extern crate current;

// External crates.
use std::mem::transmute;
use event::{
    Window,
    WindowSettings,
};
use event::window::{ ShouldClose, SetShouldClose, Size };
use event::window::{ PollEvent, SwapBuffers };
use event::window::{ CaptureCursor, SetCaptureCursor };
use input::{ keyboard, mouse, InputEvent };
use shader_version::opengl::OpenGL;
use current::{ Get, Modifier, Set };

/// A widow implemented by SDL2 back-end.
pub struct Sdl2Window {
    /// SDL window handle
    pub window: sdl2::video::Window,
    /// Allow dead code because this keeps track of the OpenGL context.
    /// Will be released on drop.
    #[allow(dead_code)]
    pub context: sdl2::video::GLContext,
    settings: WindowSettings,
    should_close: bool,
    last_pressed_key: Option<sdl2::keycode::KeyCode>,
    mouse_relative: Option<(f64, f64)>,
}

impl Sdl2Window {
    /// Creates a new game window for SDL2.
    pub fn new(opengl: OpenGL, settings: WindowSettings) -> Sdl2Window {
        sdl2::init(sdl2::INIT_EVERYTHING);
        let (major, minor) = opengl.get_major_minor();
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMajorVersion, major);
        sdl2::video::gl_set_attribute(sdl2::video::GLContextMinorVersion, minor);
        sdl2::video::gl_set_attribute(
            sdl2::video::GLContextProfileMask,
            sdl2::video::ll::SDL_GL_CONTEXT_PROFILE_CORE as int
        );
        if settings.samples != 0 {
            sdl2::video::gl_set_attribute(sdl2::video::GLMultiSampleBuffers, 1);
            sdl2::video::gl_set_attribute(
                sdl2::video::GLMultiSampleSamples,
                settings.samples as int
            );
        }

        let window = sdl2::video::Window::new(
            settings.title.as_slice(),
            sdl2::video::PosCentered,
            sdl2::video::PosCentered,
            settings.size[0] as int,
            settings.size[1] as int,
            sdl2::video::OPENGL| sdl2::video::RESIZABLE
        ).unwrap();
        if settings.fullscreen {
            window.set_fullscreen(sdl2::video::FTTrue);
        }

        // Send text input events.
        sdl2::keyboard::start_text_input();

        let context = window.gl_create_context().unwrap();

        // Load the OpenGL function pointers
        gl::load_with(|s| unsafe {
            transmute(sdl2::video::gl_get_proc_address(s))
        });

        Sdl2Window {
            settings: settings,
            should_close: false,
            last_pressed_key: None,
            window: window,
            context: context,
            mouse_relative: None,
        }
    }
}

impl Drop for Sdl2Window {
    fn drop(&mut self) {
        self.set_mut(CaptureCursor(false));
    }
}

impl Get<ShouldClose> for Sdl2Window {
    fn get(&self) -> ShouldClose {
        ShouldClose(self.should_close)
    }
}

impl Get<Size> for Sdl2Window {
    fn get(&self) -> Size {
        let (w, h) = self.window.get_size();
        Size([w as u32, h as u32])
    }
}

impl SwapBuffers for Sdl2Window {
    fn swap_buffers(&mut self) {
        self.window.gl_swap_window();
    }
}

impl PollEvent<InputEvent> for Sdl2Window {
    fn poll_event(&mut self) -> Option<InputEvent> {
        match self.mouse_relative {
            Some((x, y)) => {
                self.mouse_relative = None;
                return Some(input::Move(input::MouseRelative(x, y)));
            }
            None => {}
        }
        match sdl2::event::poll_event() {
            sdl2::event::QuitEvent(_) => { self.should_close = true; }
            sdl2::event::TextInputEvent(_, _, text) => { return Some(input::Text(text)); }
            sdl2::event::KeyDownEvent(_, _, key, _, _) => {
                // SDL2 repeats the key down event.
                // If the event is the same as last one, ignore it.
                match self.last_pressed_key {
                    Some(x) if x == key => return self.poll_event(),
                    _ => {}
                };
                self.last_pressed_key = Some(key);

                if self.settings.exit_on_esc
                && key == sdl2::keycode::EscapeKey {
                    self.should_close = true;
                } else {
                    return Some(input::Press(input::Keyboard(sdl2_map_key(key))));
                }
            }
            sdl2::event::KeyUpEvent(_, _, key, _, _) => {
                // Reset the last pressed key.
                self.last_pressed_key = match self.last_pressed_key {
                    Some(x) if x == key => None,
                    x => x,
                };

                return Some(input::Release(input::Keyboard(sdl2_map_key(key))));
            }
            sdl2::event::MouseButtonDownEvent(_, _, _, button, _, _) => {
                return Some(input::Press(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseButtonUpEvent(_, _, _, button, _, _) => {
                return Some(input::Release(input::Mouse(sdl2_map_mouse(button))));
            }
            sdl2::event::MouseMotionEvent(_, _, _, _, x, y, dx, dy) => {
                // Send relative move movement next time.
                self.mouse_relative = Some((dx as f64, dy as f64));
                return Some(input::Move(input::MouseCursor(x as f64, y as f64)));
            },
            sdl2::event::MouseWheelEvent(_, _, _, x, y) => {
                return Some(input::Move(input::MouseScroll(x as f64, y as f64)));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::ResizedWindowEventId, w, h) => {
                return Some(input::Resize(w as u32, h as u32));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::FocusGainedWindowEventId, _, _) => {
                return Some(input::Focus(true));
            }
            sdl2::event::WindowEvent(_, _, sdl2::event::FocusLostWindowEventId, _, _) => {
                return Some(input::Focus(false));
            }
            _ => {}
        }
        None
    }
}

impl Modifier<Sdl2Window> for CaptureCursor {
    fn modify(self, _window: &mut Sdl2Window) {
        let CaptureCursor(enabled) = self;
        sdl2::mouse::set_relative_mouse_mode(enabled)
    }
}

impl SetCaptureCursor for Sdl2Window {
    fn set_capture_cursor(&mut self, val: CaptureCursor) {
        self.set_mut(val);
    }
}

impl Modifier<Sdl2Window> for ShouldClose {
    fn modify(self, window: &mut Sdl2Window) {
        let ShouldClose(val) = self;
        window.should_close = val;
    }
}

impl SetShouldClose for Sdl2Window {
    fn set_should_close(&mut self, val: ShouldClose) {
        self.set_mut(val);
    }
}

impl Window for Sdl2Window {
    fn get_settings<'a>(&'a self) -> &'a WindowSettings {
        &self.settings
    }

    fn get_draw_size(&self) -> (u32, u32) {
        let (w, h) = self.window.get_drawable_size();
        (w as u32, h as u32)
    }
}

/// Maps a SDL2 key to piston-input key.
pub fn sdl2_map_key(keycode: sdl2::keycode::KeyCode) -> keyboard::Key {
    use std::num::FromPrimitive;
    FromPrimitive::from_u64(keycode as u64).unwrap()
}

/// Maps a SDL2 mouse button to piston-input button.
pub fn sdl2_map_mouse(button: sdl2::mouse::Mouse) -> mouse::Button {
    match button {
        sdl2::mouse::LeftMouse => mouse::Left,
        sdl2::mouse::RightMouse => mouse::Right,
        sdl2::mouse::MiddleMouse => mouse::Middle,
        sdl2::mouse::X1Mouse => mouse::X1,
        sdl2::mouse::X2Mouse => mouse::X2,
        sdl2::mouse::UnknownMouse(_) => mouse::Unknown,
    }
}
<|endoftext|>


<commit_before>pub mod lines;

#[macro_use]
extern crate nom;

extern crate regex;
extern crate memmap;

use std::io::{BufReader, BufRead};
use std::fs::File;

use memmap::{Mmap, Protection};

use regex::Regex;
use nom::*;

// pub mod lang;

pub enum Lang {
    C, /* C_CPP_HEADER,
        * Rust,
        * Haskell,
        * Perl,
        * BourneShell, */
}
use self::Lang::*;

// Why partialeq and not total?
#[derive(Debug, PartialEq)]
pub struct Count {
    pub code: u32,
    pub comment: u32,
    pub blank: u32,
    pub lines: u32,
}

fn lang_from_extension(ext: &str) -> Lang {
    match ext {
        "c" => C,
        // "rs" => Rust,
        // "h" => C_CPP_HEADER,
        // "hs" => Haskell,
        // "perl" => Perl,
        // "sh" => BourneShell,
        _ => panic!("unrecognized ext"),
    }
}

// fn couter_for_lang(lang: Lang) -> Counter {
//     return match lang {
//         C => {
//             Counter {
//                 is_comment: |line: &str| true,
//                 is_code: |line: &str| true,
//             }
//         }
//     };
// }

// TODO(cgag): this is a horrible mess.
pub fn count_regex(filepath: &str) -> Count {
    let f = File::open(filepath).unwrap();
    let reader = BufReader::new(f);

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let single_comment = Regex::new(r"^\s*//").unwrap();
    let multi_comment_start_with_blank = Regex::new(r"^\s*/\*").unwrap();
    let multi_comment_start = Regex::new(r"/\*").unwrap();
    let multi_comment_end = Regex::new(r"\s*\*/").unwrap();
    let blank = Regex::new(r"^[:space:]*$").unwrap();

    let mut in_comment = false;
    for line in reader.lines() {
        let line = line.unwrap();
        lines += 1;

        if in_comment {
            comments += 1;
            if multi_comment_end.is_match(&line) {
                in_comment = false;
            }
            continue;
        }

        // TODO(cgag): try parsers, regex, operating on non-utf8, etc.
        // Only escelate to utf8 if needed?  When is it needed?
        if blank.is_match(&line) {
            blanks += 1;
        } else if single_comment.is_match(&line) {
            comments += 1;
        } else if multi_comment_start.is_match(&line) {
            if multi_comment_start_with_blank.is_match(&line) {
                comments += 1;
                if multi_comment_end.is_match(&line) {
                    continue;
                } else {
                    in_comment = true
                }
            } else {
                code += 1;
                if multi_comment_end.is_match(&line) {
                    continue;
                } else {
                    in_comment = true
                }
            }
        } else {
            code += 1;
        }
    }

    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}

enum State {
    // In multiline comment
    // InSingleLineComment,
    // InMultiLineComment,
    InComment,
    // Haven't yet encounteered a non-whitespace char.
    LineStart,
    InCode,
}
use self::State::*;

pub fn count_manual_bytes_with_iterator(filepath: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blank = 0;

    Count {
        code: code,
        comment: comments,
        blank: blank,
        lines: lines,
    }
}

pub fn count_manual_bytes_try1(filepath: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    // TODO(cgag): not actually fure if this is how you represent this
    // let vtab = b'\x0B';
    // let ffeed = b'\x0C';

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blank = 0;

    let mut state = LineStart;

    let mut prev_byte: &u8 = &0;
    for byte in bytes {
        state = match byte {
            &b' ' | &b'\t' | &b'\r' | &b'\x0B' | &b'\x0C' => {
                match state {
                    _ => state,
                }
            }
            &b'/' => {
                match state {
                    InCode => InCode,
                    LineStart => {
                        if prev_byte == &b'/' {
                            InComment
                        } else {
                            LineStart
                        }
                    }
                    InComment => {
                        if prev_byte == &b'*' {
                            comments += 1;
                            LineStart
                        } else {
                            InComment
                        }
                    }
                }
            }
            &b'*' => {
                match state {
                    LineStart => {
                        if prev_byte == &b'/' {
                            InComment
                        } else {
                            InCode
                        }
                    }
                    InCode => InCode,
                    InComment => InComment,
                }
            }
            &b'\n' => {
                lines += 1;
                match state {
                    InCode => {
                        code += 1;
                        LineStart
                    }
                    InComment => {
                        comments += 1;
                        InComment
                    }
                    LineStart => {
                        blank += 1;
                        LineStart
                    }
                }
            }
            &_ => {
                match state {
                    LineStart => InCode,
                    InCode => InCode,
                    InComment => InComment,
                }
            }
        };
        prev_byte = byte;
    }

    Count {
        code: code,
        comment: comments,
        blank: blank,
        lines: lines,
    }
}

// pub fn count_nom(filepath: &str) -> Count {
//     let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
//     let bytes: &[u8] = unsafe { fmmap.as_slice() };

//     // let p = named!(blank, many0!(is_space));
//     Count {
//         code: 0,
//         comment: 0,
//         blank: 0,
//         lines: 0,
//     }
// }
<commit_msg>add line iterator for [u8]<commit_after>pub mod lines;

#[macro_use]
extern crate nom;

extern crate regex;
extern crate memmap;
extern crate memchr;

use std::io::{BufReader, BufRead};
use std::fs::File;

use memmap::{Mmap, Protection};
use memchr::memchr;

use regex::Regex;
use nom::*;

// pub mod lang;

pub enum Lang {
    C, /* C_CPP_HEADER,
        * Rust,
        * Haskell,
        * Perl,
        * BourneShell, */
}
use self::Lang::*;

// Why is it called partialEq?
#[derive(Debug, PartialEq)]
pub struct Count {
    pub code: u32,
    pub comment: u32,
    pub blank: u32,
    pub lines: u32,
}

fn lang_from_extension(ext: &str) -> Lang {
    match ext {
        "c" => C,
        // "rs" => Rust,
        // "h" => C_CPP_HEADER,
        // "hs" => Haskell,
        // "perl" => Perl,
        // "sh" => BourneShell,
        _ => panic!("unrecognized ext"),
    }
}

// fn couter_for_lang(lang: Lang) -> Counter {
//     return match lang {
//         C => {
//             Counter {
//                 is_comment: |line: &str| true,
//                 is_code: |line: &str| true,
//             }
//         }
//     };
// }

// TODO(cgag): this is a horrible mess.
pub fn count_regex(filepath: &str) -> Count {
    let f = File::open(filepath).unwrap();
    let reader = BufReader::new(f);

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blanks = 0;

    let single_comment = Regex::new(r"^\s*//").unwrap();
    let multi_comment_start_with_blank = Regex::new(r"^\s*/\*").unwrap();
    let multi_comment_start = Regex::new(r"/\*").unwrap();
    let multi_comment_end = Regex::new(r"\s*\*/").unwrap();
    let blank = Regex::new(r"^[:space:]*$").unwrap();

    let mut in_comment = false;
    for line in reader.lines() {
        let line = line.unwrap();
        lines += 1;

        if in_comment {
            comments += 1;
            if multi_comment_end.is_match(&line) {
                in_comment = false;
            }
            continue;
        }

        // TODO(cgag): try parsers, regex, operating on non-utf8, etc.
        // Only escelate to utf8 if needed?  When is it needed?
        if blank.is_match(&line) {
            blanks += 1;
        } else if single_comment.is_match(&line) {
            comments += 1;
        } else if multi_comment_start.is_match(&line) {
            if multi_comment_start_with_blank.is_match(&line) {
                comments += 1;
                if multi_comment_end.is_match(&line) {
                    continue;
                } else {
                    in_comment = true
                }
            } else {
                code += 1;
                if multi_comment_end.is_match(&line) {
                    continue;
                } else {
                    in_comment = true
                }
            }
        } else {
            code += 1;
        }
    }

    Count {
        code: code,
        comment: comments,
        blank: blanks,
        lines: lines,
    }
}

enum State {
    // In multiline comment
    // InSingleLineComment,
    // InMultiLineComment,
    InComment,
    // Haven't yet encounteered a non-whitespace char.
    LineStart,
    InCode,
}
use self::State::*;

struct AsciiLines<'a> {
    buf: &'a [u8],
    pos: usize,
}

struct Ascii<'a>(&'a [u8]);
impl<'a> Ascii<'a> {
    fn lines(&self) -> AsciiLines {
        AsciiLines {
            buf: self.0,
            pos: 0,
        }
    }
}

// Appears to work, now we just neeed
impl<'a> Iterator for AsciiLines<'a> {
    type Item = &'a [u8];

    fn next(&mut self) -> Option<&'a [u8]> {
        match memchr(b'\n', &self.buf[self.pos..self.buf.len()]) {
            Some(n) => {
                let start = self.pos;
                self.pos = self.pos + n + 1;
                Some(&self.buf[start..self.pos])
            }
            None => {
                if self.pos == self.buf.len() {
                    return None;
                }
                let start = self.pos;
                self.pos = self.buf.len();
                Some(&self.buf[start..self.pos])
            }
        }
    }
}

pub fn count_manual_bytes_with_iterator(filepath: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    let mut lines = 0;
    let code = 0;
    let comments = 0;
    let blank = 0;

    for line in Ascii(bytes).lines() {
        lines += 1;
    }

    Count {
        code: code,
        comment: comments,
        blank: blank,
        lines: lines,
    }
}

pub fn count_manual_bytes_try1(filepath: &str) -> Count {
    let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
    let bytes: &[u8] = unsafe { fmmap.as_slice() };

    // TODO(cgag): not actually fure if this is how you represent this
    // let vtab = b'\x0B';
    // let ffeed = b'\x0C';

    let mut lines = 0;
    let mut code = 0;
    let mut comments = 0;
    let mut blank = 0;

    let mut state = LineStart;

    let mut prev_byte: &u8 = &0;
    for byte in bytes {
        state = match byte {
            &b' ' | &b'\t' | &b'\r' | &b'\x0B' | &b'\x0C' => {
                match state {
                    _ => state,
                }
            }
            &b'/' => {
                match state {
                    InCode => InCode,
                    LineStart => {
                        if prev_byte == &b'/' {
                            InComment
                        } else {
                            LineStart
                        }
                    }
                    InComment => {
                        if prev_byte == &b'*' {
                            comments += 1;
                            LineStart
                        } else {
                            InComment
                        }
                    }
                }
            }
            &b'*' => {
                match state {
                    LineStart => {
                        if prev_byte == &b'/' {
                            InComment
                        } else {
                            InCode
                        }
                    }
                    InCode => InCode,
                    InComment => InComment,
                }
            }
            &b'\n' => {
                lines += 1;
                match state {
                    InCode => {
                        code += 1;
                        LineStart
                    }
                    InComment => {
                        comments += 1;
                        InComment
                    }
                    LineStart => {
                        blank += 1;
                        LineStart
                    }
                }
            }
            &_ => {
                match state {
                    LineStart => InCode,
                    InCode => InCode,
                    InComment => InComment,
                }
            }
        };
        prev_byte = byte;
    }

    Count {
        code: code,
        comment: comments,
        blank: blank,
        lines: lines,
    }
}

// pub fn count_nom(filepath: &str) -> Count {
//     let fmmap = Mmap::open_path(filepath, Protection::Read).expect("mmap err");
//     let bytes: &[u8] = unsafe { fmmap.as_slice() };

//     // let p = named!(blank, many0!(is_space));
//     Count {
//         code: 0,
//         comment: 0,
//         blank: 0,
//         lines: 0,
//     }
// }
<|endoftext|>


<commit_before>#![feature(try_from)]
extern crate rayon;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[macro_use]
pub mod math;
pub mod ray;
pub mod geometry;
pub mod lights;
pub mod intersection;
pub mod color;
pub mod scene;
pub mod camera;
pub mod material;
pub mod renderer;
pub mod mesh_loader;
pub mod config;

pub use self::scene::Scene;
pub use self::color::Color;
pub use self::ray::Ray;
pub use self::camera::Camera;
pub use self::material::{IllumninationModel, Material, MaterialTemplate};
pub use self::renderer::{Renderer, SuperSampling};
pub use self::config::Config;
<commit_msg>[Project] Optimize imports/exports<commit_after>#![feature(try_from)]
extern crate rayon;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

#[macro_use]
mod math;
mod geometry;
mod ray;
mod lights;
mod intersection;

pub mod color;
pub mod material;
pub mod scene;
pub mod camera;
pub mod renderer;
pub mod mesh_loader;
mod config;

pub use self::scene::Scene;
pub use self::color::Color;
pub use self::camera::Camera;
pub use self::material::{IllumninationModel, Material, MaterialTemplate};
pub use self::renderer::{Renderer, SuperSampling};
pub use self::config::Config;
<|endoftext|>


<commit_before>// Copyright 2014-2016 The Stainless Developers. See the LICENSE file at the top-level directory of
// this distrubution.
//
// Licensed under the MIT license. This file may not be copied, modified, or distributed except
// according to those terms.

#![feature(plugin_registrar, quote, rustc_private)]
#![deny(missing_docs, warnings)]

//! > Stainless is a lightweight, flexible, unopinionated testing framework.
//!
//! **Note that stainless currently requires the nightly version of the Rust compiler!**
//!
//! ## Installation
//!
//! Add stainless as a dependency in your `Cargo.toml` file
//! ``` toml
//! [dev-dependencies]
//! stainless = "*"
//! ```
//!
//! Add the following lines to the top of your
//! [root module](https://doc.rust-lang.org/book/crates-and-modules.html).
//! That file is normally called `src/main.rs` for executables and
//! `src/lib.rs` for libraries:
//!
//! ``` rust
//! #![feature(plugin)]
//! #![cfg_attr(test, plugin(stainless))]
//! ```
//!
//! This will make stainless available when you run the tests using `cargo
//! test`.
//!
//! ## Overview
//!
//! Stainless exports the `describe!` syntax extension, which allows you
//! to quickly generate complex testing hierarchies and reduce boilerplate
//! through `before_each` and `after_each`.
//!
//! Stainless currently supports the following types of subblocks:
//!
//! * `before_each` and `after_each`
//! * `it`, `failing`, and `ignore`
//! * `bench`
//! * nested `describe!`
//!
//! `before_each` and `after_each` allow you to group common
//! initialization and teardown for a group of tests into a single block,
//! shortening your tests.
//!
//! `it` generates tests which use `before_each` and `after_each`.
//! `failing` does the same, except the generated tests are marked with
//! `#[should_panic]`. It optionally takes an argument which is matched against the
//! failure message. `ignore` is equivalent to marking a test with `#[ignore]` which
//! disables the test by default.
//!
//! `bench` allows you to generate benchmarks in the same fashion, though
//! *`before_each` and `after_each` blocks do not currently affect `bench`
//! blocks*.
//!
//! Nested `describe!` blocks allow you to better organize your tests into
//! small units and gives you granular control over where `before_each`
//! and `after_each` apply. Of course the `before_each` and `after_each`
//! blocks of the wrapping `describe!` blocks are executed as well.
//!
//! Together, these 4 types of subblocks give you more flexibility and
//! control than the built in testing infrastructure.
//!
//! ## Example
//!
//! ```rust
//! describe! stainless {
//!     before_each {
//!         // Start up a test.
//!         let mut stainless = true;
//!     }
//!
//!     it "makes organizing tests easy" {
//!         // Do the test.
//!         assert!(stainless);
//!     }
//!
//!     after_each {
//!         // End the test.
//!         stainless = false;
//!     }
//!
//!     bench "something simple" (bencher) {
//!         bencher.iter(|| 2 * 2)
//!     }
//!
//!     describe! nesting {
//!
//!         before_each {
//!           let mut inner_stainless = true;
//!         }
//!
//!         after_each {
//!           inner_stainless = false;
//!         }
//!
//!         it "makes it simple to categorize tests" {
//!             // It even generates submodules!
//!             assert_eq!(2, 2);
//!         }
//!     }
//! }
//! ```
//!
//! Expands to (roughly):
//!
//! ```rust
//! mod stainless {
//!     #[test]
//!     fn makes_organizing_tests_easy() {
//!         let mut stainless = true;
//!         assert!(stainless);
//!         stainless = false;
//!     }
//!
//!     #[bench]
//!     fn something_simple(bencher: &mut test::Bencher) {
//!         bencher.iter(|| 2 * 2)
//!     }
//!
//!     mod nesting {
//!         #[test]
//!         fn makes_it_simple_to_categorize_tests() {
//!             let mut stainless = true;
//!             let mut inner_stainless = true;
//!             assert_eq!(2, 2);
//!             inner_stainless = false;
//!             stainless = false;
//!         }
//!     }
//! }
//! ```
//!
//! ## Importing modules
//!
//! At this point it is not possible to put `use` statements inside the
//! `describe!` blocks. To allow usage of data structures from other
//! modules and crates each `describe!` block comes with a silent `pub use
//! super::*;` in it. That way everything you `pub use` in the containing
//! module is available in your tests.
//!
//! ```rust
//! #[cfg(test)]
//! mod tests {
//!     pub use std::collections::HashMap;
//!
//!     describe! stainless {
//!         it "can use HashMap" {
//!             let map = HashMap::new();
//!         }
//!     }
//! }
//! ```
//!
//! ## License
//!
//! MIT. See the LICENSE file for details.
//!
//! ## Authors
//!
//! See Cargo.toml for the full list of authors.

extern crate syntax;
extern crate rustc_plugin;

use self::describe::describe;
use rustc_plugin as plugin;
use syntax::parse::token;

mod describe;
mod parse;
mod test;
mod bench;
mod generate;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut plugin::Registry) {
    reg.register_syntax_extension(
        token::intern("describe"),
        syntax::ext::base::IdentTT(Box::new(describe), None, false)
    );
}
<commit_msg>Updated documentation in lib.rs<commit_after>// Copyright 2014-2016 The Stainless Developers. See the LICENSE file at the top-level directory of
// this distrubution.
//
// Licensed under the MIT license. This file may not be copied, modified, or distributed except
// according to those terms.

#![feature(plugin_registrar, quote, rustc_private)]
#![deny(missing_docs, warnings)]

//! > Stainless is a lightweight, flexible, unopinionated testing framework.
//!
//! **Note that stainless currently requires the nightly version of the Rust compiler!**
//!
//! ## Installation
//!
//! Add stainless as a dependency in your `Cargo.toml` file
//! ``` toml
//! [dev-dependencies]
//! stainless = "*"
//! ```
//!
//! Add the following lines to the top of your
//! [root module](https://doc.rust-lang.org/book/crates-and-modules.html).
//! That file is normally called `src/main.rs` for executables and
//! `src/lib.rs` for libraries:
//!
//! ``` rust
//! #![feature(plugin)]
//! #![cfg_attr(test, plugin(stainless))]
//! ```
//!
//! This will make stainless available when you run the tests using `cargo
//! test`.
//! When using stainless only with a library, make sure to run tests using
//! `cargo test --lib`.
//!
//! ## Overview
//!
//! Stainless exports the `describe!` syntax extension, which allows you
//! to quickly generate complex testing hierarchies and reduce boilerplate
//! through `before_each` and `after_each`.
//!
//! Stainless currently supports the following types of subblocks:
//!
//! * `before_each` and `after_each`
//! * `it`, `failing`, and `ignore`
//! * `bench`
//! * nested `describe!`
//!
//! `before_each` and `after_each` allow you to group common
//! initialization and teardown for a group of tests into a single block,
//! shortening your tests.
//!
//! `it` generates tests which use `before_each` and `after_each`.
//! `failing` does the same, except the generated tests are marked with
//! `#[should_panic]`. It optionally takes an argument which is matched against the
//! failure message. `ignore` is equivalent to marking a test with `#[ignore]` which
//! disables the test by default.
//!
//! `bench` allows you to generate benchmarks in the same fashion, though
//! *`before_each` and `after_each` blocks do not currently affect `bench`
//! blocks*.
//!
//! Nested `describe!` blocks allow you to better organize your tests into
//! small units and gives you granular control over where `before_each`
//! and `after_each` apply. Of course the `before_each` and `after_each`
//! blocks of the wrapping `describe!` blocks are executed as well.
//!
//! Together, these 4 types of subblocks give you more flexibility and
//! control than the built in testing infrastructure.
//!
//! ## Example
//!
//! ```rust
//! describe! stainless {
//!     before_each {
//!         // Start up a test.
//!         let mut stainless = true;
//!     }
//!
//!     it "makes organizing tests easy" {
//!         // Do the test.
//!         assert!(stainless);
//!     }
//!
//!     after_each {
//!         // End the test.
//!         stainless = false;
//!     }
//!
//!     bench "something simple" (bencher) {
//!         bencher.iter(|| 2 * 2)
//!     }
//!
//!     describe! nesting {
//!
//!         before_each {
//!           let mut inner_stainless = true;
//!         }
//!
//!         after_each {
//!           inner_stainless = false;
//!         }
//!
//!         it "makes it simple to categorize tests" {
//!             // It even generates submodules!
//!             assert_eq!(2, 2);
//!         }
//!     }
//! }
//! ```
//!
//! Expands to (roughly):
//!
//! ```rust
//! mod stainless {
//!     #[test]
//!     fn makes_organizing_tests_easy() {
//!         let mut stainless = true;
//!         assert!(stainless);
//!         stainless = false;
//!     }
//!
//!     #[bench]
//!     fn something_simple(bencher: &mut test::Bencher) {
//!         bencher.iter(|| 2 * 2)
//!     }
//!
//!     mod nesting {
//!         #[test]
//!         fn makes_it_simple_to_categorize_tests() {
//!             let mut stainless = true;
//!             let mut inner_stainless = true;
//!             assert_eq!(2, 2);
//!             inner_stainless = false;
//!             stainless = false;
//!         }
//!     }
//! }
//! ```
//!
//! ## Importing modules
//!
//! At this point it is not possible to put `use` statements inside the
//! `describe!` blocks. To allow usage of data structures from other
//! modules and crates each `describe!` block comes with a silent `pub use
//! super::*;` in it. That way everything you `pub use` in the containing
//! module is available in your tests.
//!
//! ```rust
//! #[cfg(test)]
//! mod tests {
//!     pub use std::collections::HashMap;
//!
//!     describe! stainless {
//!         it "can use HashMap" {
//!             let map = HashMap::new();
//!         }
//!     }
//! }
//! ```
//!
//! ## License
//!
//! MIT. See the LICENSE file for details.
//!
//! ## Authors
//!
//! See Cargo.toml for the full list of authors.

extern crate syntax;
extern crate rustc_plugin;

use self::describe::describe;
use rustc_plugin as plugin;
use syntax::parse::token;

mod describe;
mod parse;
mod test;
mod bench;
mod generate;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut plugin::Registry) {
    reg.register_syntax_extension(
        token::intern("describe"),
        syntax::ext::base::IdentTT(Box::new(describe), None, false)
    );
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate hyper;
extern crate rustc_serialize;

use std::fmt;
use std::io::{self, Read};
use std::error::Error;
use std::result;

use hyper::Client;
use hyper::status::StatusCode;

use rustc_serialize::json;

header! { (XStarfighterAuthorization, "X-Starfighter-Authorization") => [String] }

#[derive(RustcDecodable, RustcEncodable)]
struct Heartbeat {
    ok: bool,
    error: String,
}

#[derive(RustcDecodable, RustcEncodable)]
struct VenueHeartbeat {
    ok: bool,
    // venue is not present on error
    venue: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct Quote {
    ok: bool,
    symbol: String,
    venue: String,
    bid: Option<usize>,
    ask: Option<usize>,
    bid_size: Option<usize>,
    ask_size: Option<usize>,
    bid_depth: Option<usize>,
    ask_depth: Option<usize>,
    last: usize,
    last_size: Option<usize>,
    last_trade: Option<String>,
    quote_time: Option<String>,
}

// We ran into some trouble where "buy" in json wouldn't decode to
// OrderDirection::Buy, but will decode to OrderDirection::buy.
// Instead of fighting it just turn off camel case warnings for this enum.
#[allow(non_camel_case_types)]
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderDirection {
    buy,
    sell,
}

// https://starfighter.readme.io/docs/place-new-order#order-types
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderType {
    Limit,
    Market,
    FillOrKill,
    ImmediateOrCancel,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct Fill {
    price: Option<usize>,
    qty: Option<usize>,
    ts: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct OrderStatus {
    ok: bool,
    symbol: Option<String>,
    venue: Option<String>,
    direction: Option<OrderDirection>,
    original_qty: Option<usize>,
    qty: Option<usize>,
    price: Option<usize>,
    order_type: Option<OrderType>,
    id: Option<usize>,
    account: Option<String>,
    ts: Option<String>,
    fills: Vec<Fill>,
    total_filled: Option<usize>,
    open: Option<bool>
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockTicker {
    name: String,
    symbol: String,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockList {
    ok: bool,
    symbols: Vec< StockTicker>,
}

#[derive(Debug)]
pub enum StockfighterError {
    ApiDown,
    VenueDown(String), // Also means unknown venue
    ApiError,
    Hyper(hyper::error::Error),
    JsonDecoder(rustc_serialize::json::DecoderError),
    Io(io::Error),
}

impl From<hyper::error::Error> for StockfighterError {
    fn from(err: hyper::error::Error) -> Self {
        StockfighterError::Hyper(err)
    }
}

impl From<rustc_serialize::json::DecoderError> for StockfighterError {
    fn from(err: rustc_serialize::json::DecoderError) -> Self {
        StockfighterError::JsonDecoder(err)
    }
}

impl From<io::Error> for StockfighterError {
    fn from(err: io::Error) -> Self {
        StockfighterError::Io(err)
    }
}

impl fmt::Display for StockfighterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StockfighterError::ApiDown => write!(f, "API down"),
            StockfighterError::VenueDown(ref venue) => write!(f, "Venue down: {}", venue),
            StockfighterError::ApiError => write!(f, "API error"),
            StockfighterError::Hyper(ref err) => write!(f, "{}", err),
            StockfighterError::JsonDecoder(ref err) => write!(f, "{}", err),
            StockfighterError::Io(ref err) => write!(f, "{}", err),
        }
    }
}

impl Error for StockfighterError {
    fn description(&self) -> &str {
        match *self {
            StockfighterError::ApiDown => "API down",
            StockfighterError::VenueDown(_) => "Venue down",
            StockfighterError::ApiError => "API error",
            StockfighterError::Hyper(ref err) => err.description(),
            StockfighterError::JsonDecoder(ref err) => err.description(),
            StockfighterError::Io(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StockfighterError::Hyper(ref err) => Some(err as &Error),
            StockfighterError::JsonDecoder(ref err) => Some(err as &Error),
            StockfighterError::Io(ref err) => Some(err as &Error),
            _ => None
        }
    }
}

pub type Result<T> = result::Result<T, StockfighterError>;

pub struct Stockfighter {
    api_key: String,
}

impl Stockfighter {

    pub fn new<S>(api_key: S) -> Stockfighter where S: Into<String> {
        Stockfighter { api_key: api_key.into() }
    }

    /// Check that the Stockfighter API is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.heartbeat().is_ok());
    /// ```
    pub fn heartbeat(&self) -> Result<()> {
        let client = Client::new();
        let mut res = try!(client
            .get("https://api.stockfighter.io/ob/api/heartbeat")
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiDown);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let hb: Heartbeat = try!(json::decode(&body));

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::ApiDown)
        }
    }

    /// Check that a specific venue is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
    /// ```
    pub fn venue_heartbeat(&self, venue: &str) -> Result<()> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/heartbeat", venue);
        let client = Client::new();
        let mut res = try!(client
            .get(&url)
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let hb: VenueHeartbeat = try!(json::decode(&body));

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::VenueDown(venue.to_owned()))
        }
    }

    /// Get a quick look at the most recent trade information for a stock.
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
    /// ```
    pub fn quote(&self, venue: &str, stock: &str) -> Result<Quote> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/quote", venue, stock);

        let client = Client::new();

        let mut res = try!(client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let quote = try!(json::decode::<Quote>(&body));

        match quote.ok {
            true => Ok(quote),
            false => Err(StockfighterError::ApiError)
        }
    }

    /// List the stocks available for trading on a venue
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.stocks_on_a_venue("TESTEX").is_ok());
    /// ```
    pub fn stocks_on_a_venue( &self, venue : &str ) -> Result<StockList> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks", venue );

        let client = Client::new();

        let mut res = try!(client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let stocklist = try!(json::decode::<StockList>(&body));

        match stocklist.ok {
            true => Ok(stocklist),
            false => Err(StockfighterError::ApiError)
        }
    }

    pub fn existing_order_status(&self, id: usize, venue: &str, stock: &str) -> Result<OrderStatus> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/orders/{}", venue, stock, id);

        let client = Client::new();

        let mut res = try!(client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix clone here.
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let order_status = try!(json::decode::<OrderStatus>(&body));

        match order_status.ok {
            true => Ok(order_status),
            false => Err(StockfighterError::ApiError)
        }
    }
}

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

    #[test]
    fn test_heartbeat() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.heartbeat().is_ok());
    }

    #[test]
    fn test_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
        match sf.venue_heartbeat("INVALID") {
            Err(StockfighterError::VenueDown(ref s)) if s == "INVALID" => {},
            _ => panic!()
        }
    }

    #[test]
    fn test_quote() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
        assert_eq!(true, sf.quote("INVALID", "FOOBAR").is_err());
        assert_eq!(true, sf.quote("TESTEX", "INVALID").is_err());
        assert_eq!(true, sf.quote("INVALID", "INVALID").is_err());
    }

    #[test]
    fn test_stocks_on_a_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.stocks_on_a_venue("TESTEX").is_ok());
        println!("{:?}", sf.stocks_on_a_venue("TESTEX") );
        match sf.stocks_on_a_venue("INVALID") {
            Err(StockfighterError::VenueDown(ref s)) if s == "INVALID" => {},
            _ => panic!()
        }
    }

    #[test]
    fn test_existing_order_status() {
        // TODO Create an is_ok test when we figure out how to test this without an API key.
        // As of now an is_ok test will pass with an existing order and an API key.
        let sf = Stockfighter::new("");
        assert!(sf.existing_order_status(1212, "TESTEX", "INVALID").is_err());
    }
}
<commit_msg>Issue #15 Get the status for all orders in a stock<commit_after>#[macro_use]
extern crate hyper;
extern crate rustc_serialize;

use std::fmt;
use std::io::{self, Read};
use std::error::Error;
use std::result;

use hyper::Client;
use hyper::status::StatusCode;

use rustc_serialize::json;

header! { (XStarfighterAuthorization, "X-Starfighter-Authorization") => [String] }

#[derive(RustcDecodable, RustcEncodable)]
struct Heartbeat {
    ok: bool,
    error: String,
}

#[derive(RustcDecodable, RustcEncodable)]
struct VenueHeartbeat {
    ok: bool,
    // venue is not present on error
    venue: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct Quote {
    ok: bool,
    symbol: String,
    venue: String,
    bid: Option<usize>,
    ask: Option<usize>,
    bid_size: Option<usize>,
    ask_size: Option<usize>,
    bid_depth: Option<usize>,
    ask_depth: Option<usize>,
    last: usize,
    last_size: Option<usize>,
    last_trade: Option<String>,
    quote_time: Option<String>,
}

// We ran into some trouble where "buy" in json wouldn't decode to
// OrderDirection::Buy, but will decode to OrderDirection::buy.
// Instead of fighting it just turn off camel case warnings for this enum.
#[allow(non_camel_case_types)]
#[derive(RustcDecodable, RustcEncodable, Debug)]
#[allow(non_snake_case)] //when I make it order_type it doesn't work
pub struct Order {
    ok: bool,
    symbol: String,
    venue: String,
    direction: String,
    original_qty: Option<usize>,
    qty: Option<usize>,
    price: Option<usize>,
    orderType: String,
    id: usize,
    account: String,
    ts: Option<String>,
    fills: Vec<Fill>,
    total_filled: Option<usize>,
    open: bool
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct Fill {
    price: Option<usize>,
    qty: Option<usize>,
    ts: Option<String>
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderDirection {
    buy,
    sell,
}

// https://starfighter.readme.io/docs/place-new-order#order-types
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderType {
    Limit,
    Market,
    FillOrKill,
    ImmediateOrCancel,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct OrderStatus {
    ok: bool,
    symbol: Option<String>,
    venue: Option<String>,
    direction: Option<OrderDirection>,
    original_qty: Option<usize>,
    qty: Option<usize>,
    price: Option<usize>,
    order_type: Option<OrderType>,
    id: Option<usize>,
    account: Option<String>,
    ts: Option<String>,
    fills: Vec<Fill>,
    total_filled: Option<usize>,
    open: Option<bool>
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockTicker {
    name: String,
    symbol: String,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockList {
    ok: bool,
    symbols: Vec< StockTicker>,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockOrdersStatuses {
    ok: bool,
    venue: String,
    orders: Vec< Order >
}

#[derive(Debug)]
pub enum StockfighterError {
    ApiDown,
    VenueDown(String), // Also means unknown venue
    ApiError,
    Hyper(hyper::error::Error),
    JsonDecoder(rustc_serialize::json::DecoderError),
    Io(io::Error),
}

impl From<hyper::error::Error> for StockfighterError {
    fn from(err: hyper::error::Error) -> Self {
        StockfighterError::Hyper(err)
    }
}

impl From<rustc_serialize::json::DecoderError> for StockfighterError {
    fn from(err: rustc_serialize::json::DecoderError) -> Self {
        StockfighterError::JsonDecoder(err)
    }
}

impl From<io::Error> for StockfighterError {
    fn from(err: io::Error) -> Self {
        StockfighterError::Io(err)
    }
}

impl fmt::Display for StockfighterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StockfighterError::ApiDown => write!(f, "API down"),
            StockfighterError::VenueDown(ref venue) => write!(f, "Venue down: {}", venue),
            StockfighterError::ApiError => write!(f, "API error"),
            StockfighterError::Hyper(ref err) => write!(f, "{}", err),
            StockfighterError::JsonDecoder(ref err) => write!(f, "{}", err),
            StockfighterError::Io(ref err) => write!(f, "{}", err),
        }
    }
}

impl Error for StockfighterError {
    fn description(&self) -> &str {
        match *self {
            StockfighterError::ApiDown => "API down",
            StockfighterError::VenueDown(_) => "Venue down",
            StockfighterError::ApiError => "API error",
            StockfighterError::Hyper(ref err) => err.description(),
            StockfighterError::JsonDecoder(ref err) => err.description(),
            StockfighterError::Io(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StockfighterError::Hyper(ref err) => Some(err as &Error),
            StockfighterError::JsonDecoder(ref err) => Some(err as &Error),
            StockfighterError::Io(ref err) => Some(err as &Error),
            _ => None
        }
    }
}

pub type Result<T> = result::Result<T, StockfighterError>;

pub struct Stockfighter {
    api_key: String,
}

impl Stockfighter {

    pub fn new<S>(api_key: S) -> Stockfighter where S: Into<String> {
        Stockfighter { api_key: api_key.into() }
    }

    /// Check that the Stockfighter API is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.heartbeat().is_ok());
    /// ```
    pub fn heartbeat(&self) -> Result<()> {
        let client = Client::new();
        let mut res = try!(client
            .get("https://api.stockfighter.io/ob/api/heartbeat")
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiDown);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let hb: Heartbeat = try!(json::decode(&body));

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::ApiDown)
        }
    }

    /// Check that a specific venue is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
    /// ```
    pub fn venue_heartbeat(&self, venue: &str) -> Result<()> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/heartbeat", venue);
        let client = Client::new();
        let mut res = try!(client
            .get(&url)
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let hb: VenueHeartbeat = try!(json::decode(&body));

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::VenueDown(venue.to_owned()))
        }
    }

    /// Get a quick look at the most recent trade information for a stock.
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
    /// ```
    pub fn quote(&self, venue: &str, stock: &str) -> Result<Quote> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/quote", venue, stock);

        let client = Client::new();

        let mut res = try!(client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let quote = try!(json::decode::<Quote>(&body));

        match quote.ok {
            true => Ok(quote),
            false => Err(StockfighterError::ApiError)
        }
    }

    /// List the stocks available for trading on a venue
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.stocks_on_a_venue("TESTEX").is_ok());
    /// ```
    pub fn stocks_on_a_venue(&self, venue: &str) -> Result<StockList> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks", venue );

        let client = Client::new();

        let mut res = try!(client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let stocklist = try!(json::decode::<StockList>(&body));

        match stocklist.ok {
            true => Ok(stocklist),
            false => Err(StockfighterError::ApiError)
        }
    }

    pub fn existing_order_status(&self, id: usize, venue: &str, stock: &str) -> Result<OrderStatus> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/orders/{}", venue, stock, id);

        let client = Client::new();

        let mut res = try!(
            client
                .get(&url)
                .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix clone here.
                .send()
        );

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let order_status = try!(json::decode::<OrderStatus>(&body));

        match order_status.ok {
            true => Ok(order_status),
            false => Err(StockfighterError::ApiError)
        }
    }

    // https://starfighter.readme.io/docs/status-for-all-orders-in-a-stock
    pub fn status_for_all_orders_on_a_stock(&self, venue: &str, account: &str, stock: &str) -> Result<StockOrdersStatuses> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/accounts/{}/stocks/{}/orders", venue, account, stock );

        let client = Client::new();

        let mut res = try!(client
                           .get(&url)
                           .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
                           .send());

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        try!(res.read_to_string(&mut body));

        let stock_statuses = try!(json::decode::<StockOrdersStatuses>(&body));

        match stock_statuses.ok {
            true => Ok(stock_statuses),
            false => Err(StockfighterError::ApiError)
        }
    }
}

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

    #[test]
    fn test_heartbeat() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.heartbeat().is_ok());
    }

    #[test]
    fn test_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
        match sf.venue_heartbeat("INVALID") {
            Err(StockfighterError::VenueDown(ref s)) if s == "INVALID" => {},
            _ => panic!()
        }
    }

    #[test]
    fn test_quote() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
        assert_eq!(true, sf.quote("INVALID", "FOOBAR").is_err());
        assert_eq!(true, sf.quote("TESTEX", "INVALID").is_err());
        assert_eq!(true, sf.quote("INVALID", "INVALID").is_err());
    }

    #[test]
    fn test_stocks_on_a_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.stocks_on_a_venue("TESTEX").is_ok());
        println!("{:?}", sf.stocks_on_a_venue("TESTEX") );
        match sf.stocks_on_a_venue("INVALID") {
            Err(StockfighterError::VenueDown(ref s)) if s == "INVALID" => {},
            _ => panic!()
        }
    }

    #[test]
    fn test_existing_order_status() {
        // TODO Create an is_ok test when we figure out how to test this without an API key.
        // As of now an is_ok test will pass with an existing order and an API key.
        let sf = Stockfighter::new("");
        assert!(sf.existing_order_status(1212, "TESTEX", "INVALID").is_err());
    }

    #[test]
    fn test_status_for_all_orders_on_a_stock() {
        // TODO Create an is_ok test when we figure out how to test this without an API key.
        // As of now an is_ok test will pass with an existing order and an API key.
        let sf = Stockfighter::new("");
        assert!(sf.status_for_all_orders_on_a_stock("TESTEX", "BA12DFEI12", "INVALID").is_err());
    }
}
<|endoftext|>


<commit_before>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    let handle = match stream {
        Stream::Stdout => winapi::STD_OUTPUT_HANDLE,
        Stream::Stderr => winapi::STD_ERROR_HANDLE,
        Stream::Stdin => winapi::STD_INPUT_HANDLE,
    };

    unsafe {
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                kernel32::GetConsoleMode(kernel32::GetStdHandle(winapi::STD_INPUT_HANDLE),
                                         &mut out) != 0
            }
            out => {
                // note: there is no CONERR, only CONOUT
                let handle = kernel32::CreateFileA(b"CONOUT$\0".as_ptr() as *const i8,
                                                   winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                                                   winapi::FILE_SHARE_WRITE,
                                                   ::std::ptr::null_mut(),
                                                   winapi::OPEN_EXISTING,
                                                   0,
                                                   ::std::ptr::null_mut());
                // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
                let mut buffer_info = ::std::mem::uninitialized();
                let ret = kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer_info);
                let last_err = kernel32::GetLastError();
                panic!("is invalid? {:#?}  result {:#?} last err {:#?}",
                       winapi::INVALID_HANDLE_VALUE == handle,
                       ret,
                       last_err);
                ret != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<commit_msg>clean up for release<commit_after>//! atty is a simple utility that answers one question
//! > is this a tty?
//!
//! usage is just as simple
//!
//! ```
//! if atty::is(atty::Stream::Stdout) {
//!   println!("i'm a tty")
//! }
//! ```
//!
//! ```
//! if atty::isnt(atty::Stream::Stdout) {
//!   println!("i'm not a tty")
//! }
//! ```

extern crate libc;

/// possible stream sources
pub enum Stream {
    Stdout,
    Stderr,
    Stdin,
}

/// returns true if this is a tty
#[cfg(unix)]
pub fn is(stream: Stream) -> bool {
    let fd = match stream {
        Stream::Stdout => libc::STDOUT_FILENO,
        Stream::Stderr => libc::STDERR_FILENO,
        Stream::Stdin => libc::STDIN_FILENO,
    };
    unsafe { libc::isatty(fd) != 0 }
}

/// returns true if this is a tty
#[cfg(windows)]
pub fn is(stream: Stream) -> bool {
    extern crate kernel32;
    extern crate winapi;

    unsafe {
        match stream {
            Stream::Stdin => {
                let mut out = 0;
                kernel32::GetConsoleMode(kernel32::GetStdHandle(winapi::STD_INPUT_HANDLE),
                                         &mut out) != 0
            }
            _ => {
                // note: there is no CONERR, only CONOUT
                let handle = kernel32::CreateFileA(b"CONOUT$\0".as_ptr() as *const i8,
                                                   winapi::GENERIC_READ | winapi::GENERIC_WRITE,
                                                   winapi::FILE_SHARE_WRITE,
                                                   ::std::ptr::null_mut(),
                                                   winapi::OPEN_EXISTING,
                                                   0,
                                                   ::std::ptr::null_mut());
                // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683171(v=vs.85).aspx
                let mut buffer_info = ::std::mem::uninitialized();
                kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer_info) != 0
            }
        }

    }
}

/// returns true if this is _not_ a tty
pub fn isnt(stream: Stream) -> bool {
    !is(stream)
}

#[cfg(test)]
mod tests {
    use super::{is, Stream};

    #[test]
    fn is_err() {
        assert!(is(Stream::Stderr))
    }

    #[test]
    fn is_out() {
        assert!(is(Stream::Stdout))
    }

    #[test]
    fn is_in() {
        assert!(is(Stream::Stdin))
    }
}
<|endoftext|>