<commit_before>#[macro_use]
extern crate log;

use std::io::{self, Read, Write};
use std::ops::Add;
use std::convert::From;

const SOH: u8 = 0x01;
const STX: u8 = 0x02;
const EOT: u8 = 0x04;
const ACK: u8 = 0x06;
const DLE: u8 = 0x10;
const NAK: u8 = 0x15;
const CAN: u8 = 0x18;
const CRC: u8 = 0x67;

pub type Result<T> = std::result::Result<T, Error>;

pub enum Error {
    Io(io::Error),
    ExhaustedRetries,
    Canceled,
}

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

enum Checksum {
    Standard,
    CRC16,
}

pub fn xmodem_send<D: Read + Write, R: Read>(dev: &mut D, stream: &mut R, max_retries: u32) -> Result<()> {
    debug!("Starting XMODEM transfer");
    let checksum_mode = try!(xmodem_send_start(dev, max_retries));
    debug!("First byte received. Sending stream.");
    try!(xmodem_send_stream(dev, stream, max_retries));
    debug!("Sending EOT");
    try!(xmodem_finish_send(dev, max_retries));

    Ok(())
}

fn xmodem_send_start<D: Read + Write>(dev: &mut D, max_retries: u32) -> Result<Checksum> {
    let mut errors = 0u32;
    let mut cancels = 0u32;
    loop {
        match dev.bytes().next() {
            Some(Ok(c)) => {
                match c {
                    NAK => {
                        debug!("Standard checksum requested");
                        return Ok(Checksum::Standard);
                    }
                    CRC => {
                        debug!("16-bit CRC requested");
                        return Ok(Checksum::CRC16);
                    }
                    CAN => {
                        warn!("Cancel (CAN) byte received");
                        cancels += 1;
                    },
                    c => warn!("Unknown byte received at start of XMODEM transfer: {}", c),
                }
            },
            Some(Err(err)) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timed out waiting for start of XMODEM transfer.");
                } else {
                    return Err(From::from(err));
                }
            },
            None => warn!("No bytes available waiting for start of XMODEM transfer"),
        }

        errors += 1;

        if cancels >= 2 {
            error!("Transmission canceled: received two cancel (CAN) bytes \
                    at start of XMODEM transfer");
            return Err(Error::Canceled);
        }

        if errors >= max_retries {
            error!("Exhausted max retries ({}) at start of XMODEM transfer.", max_retries);
            // TODO send CAN in this case.
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn xmodem_send_stream<D: Read + Write, R: Read>(dev: &mut D, stream: &mut R, max_retries: u32) -> Result<()> {
    let mut errors = 0u32;
    let mut block_num = 0u32;
    let pad = 0x1a;
    let block_size = 128;
    loop {
        let mut buff = vec![pad; block_size + 3];
        let n = try!(stream.read(&mut buff[3..]));
        if n == 0 {
            debug!("Reached EOF");
            return Ok(());
        }

        block_num += 1;
        buff[0] = SOH;
        buff[1] = (block_num & 0xFF) as u8;
        buff[2] = 0xFF - buff[1];
        // TODO support 16-bit CRC.
        let checksum = calc_checksum(&buff);
        buff.push(checksum);

        debug!("Sending block {}", block_num);
        try!(dev.write_all(&buff));

        match dev.bytes().next() {
            Some(Ok(c)) => {
                if c == ACK {
                    debug!("Received ACK for block {}", block_num);
                    continue
                } else {
                    warn!("Expected ACK, got {}", c);
                }
            },
            Some(Err(err)) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timeout waiting for ACK for block {}", block_num);
                } else {
                    return Err(From::from(err));
                }
            },
            None => warn!("No bytes available waiting for ACK"),
        }

        errors += 1;

        if errors >= max_retries {
            error!("Exhausted max retries ({}) while sending block {} in XMODEM transfer",
                   max_retries, block_num);
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn xmodem_finish_send<D: Read + Write>(dev: &mut D, max_retries: u32) -> Result<()> {
    let mut errors = 0u32;
    loop {
        try!(dev.write_all(&[EOT]));

        match dev.bytes().next() {
            Some(Ok(c)) => {
                if c == ACK {
                    info!("XMODEM transmission successful");
                    return Ok(());
                } else {
                    warn!("Expected ACK, got {}", c);
                }
            },
            Some(Err(err)) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timeout waiting for ACK for EOT");
                } else {
                    return Err(From::from(err));
                }
            },
            None => warn!("No bytes available waiting for ACK"),
        }

        errors += 1;

        if errors >= max_retries {
            error!("Exhausted max retries ({}) while waiting for ACK for EOT", max_retries);
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn calc_checksum(data: &[u8]) -> u8 {
    data.iter().fold(0, Add::add)
}
<commit_msg>Added a better way to get a single byte.<commit_after>#[macro_use]
extern crate log;

use std::io::{self, Read, Write};
use std::ops::Add;
use std::convert::From;

const SOH: u8 = 0x01;
const STX: u8 = 0x02;
const EOT: u8 = 0x04;
const ACK: u8 = 0x06;
const DLE: u8 = 0x10;
const NAK: u8 = 0x15;
const CAN: u8 = 0x18;
const CRC: u8 = 0x67;

pub type Result<T> = std::result::Result<T, Error>;

pub enum Error {
    Io(io::Error),
    ExhaustedRetries,
    Canceled,
}

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

enum Checksum {
    Standard,
    CRC16,
}

pub fn xmodem_send<D: Read + Write, R: Read>(dev: &mut D, stream: &mut R, max_retries: u32) -> Result<()> {
    debug!("Starting XMODEM transfer");
    let checksum_mode = try!(xmodem_send_start(dev, max_retries));
    debug!("First byte received. Sending stream.");
    try!(xmodem_send_stream(dev, stream, max_retries));
    debug!("Sending EOT");
    try!(xmodem_finish_send(dev, max_retries));

    Ok(())
}

fn xmodem_send_start<D: Read + Write>(dev: &mut D, max_retries: u32) -> Result<Checksum> {
    let mut errors = 0u32;
    let mut cancels = 0u32;
    loop {
        match get_byte(dev) {
            Ok(c) => {
                match c {
                    NAK => {
                        debug!("Standard checksum requested");
                        return Ok(Checksum::Standard);
                    }
                    CRC => {
                        debug!("16-bit CRC requested");
                        return Ok(Checksum::CRC16);
                    }
                    CAN => {
                        warn!("Cancel (CAN) byte received");
                        cancels += 1;
                    },
                    c => warn!("Unknown byte received at start of XMODEM transfer: {}", c),
                }
            },
            Err(err) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timed out waiting for start of XMODEM transfer.");
                } else {
                    return Err(From::from(err));
                }
            },
        }

        errors += 1;

        if cancels >= 2 {
            error!("Transmission canceled: received two cancel (CAN) bytes \
                    at start of XMODEM transfer");
            return Err(Error::Canceled);
        }

        if errors >= max_retries {
            error!("Exhausted max retries ({}) at start of XMODEM transfer.", max_retries);
            // TODO send CAN in this case.
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn xmodem_send_stream<D: Read + Write, R: Read>(dev: &mut D, stream: &mut R, max_retries: u32) -> Result<()> {
    let mut errors = 0u32;
    let mut block_num = 0u32;
    let pad = 0x1a;
    let block_size = 128;
    loop {
        let mut buff = vec![pad; block_size + 3];
        let n = try!(stream.read(&mut buff[3..]));
        if n == 0 {
            debug!("Reached EOF");
            return Ok(());
        }

        block_num += 1;
        buff[0] = SOH;
        buff[1] = (block_num & 0xFF) as u8;
        buff[2] = 0xFF - buff[1];
        // TODO support 16-bit CRC.
        let checksum = calc_checksum(&buff);
        buff.push(checksum);

        debug!("Sending block {}", block_num);
        try!(dev.write_all(&buff));

        match get_byte(dev) {
            Ok(c) => {
                if c == ACK {
                    debug!("Received ACK for block {}", block_num);
                    continue
                } else {
                    warn!("Expected ACK, got {}", c);
                }
                // TODO handle CAN bytes
            },
            Err(err) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timeout waiting for ACK for block {}", block_num);
                } else {
                    return Err(From::from(err));
                }
            },
        }

        errors += 1;

        if errors >= max_retries {
            error!("Exhausted max retries ({}) while sending block {} in XMODEM transfer",
                   max_retries, block_num);
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn xmodem_finish_send<D: Read + Write>(dev: &mut D, max_retries: u32) -> Result<()> {
    let mut errors = 0u32;
    loop {
        try!(dev.write_all(&[EOT]));

        match get_byte(dev) {
            Ok(c) => {
                if c == ACK {
                    info!("XMODEM transmission successful");
                    return Ok(());
                } else {
                    warn!("Expected ACK, got {}", c);
                }
            },
            Err(err) => {
                if err.kind() == io::ErrorKind::TimedOut {
                    warn!("Timeout waiting for ACK for EOT");
                } else {
                    return Err(From::from(err));
                }
            },
        }

        errors += 1;

        if errors >= max_retries {
            error!("Exhausted max retries ({}) while waiting for ACK for EOT", max_retries);
            return Err(Error::ExhaustedRetries);
        }
    }
}

fn calc_checksum(data: &[u8]) -> u8 {
    data.iter().fold(0, Add::add)
}

fn get_byte<R: Read>(reader: &mut R) -> std::io::Result<u8> {
    let mut buff = [0];
    try!(reader.read_exact(&mut buff));
    Ok(buff[0])
}
<|endoftext|>


<commit_before>
//! A semi-safe, semi-stateless wrapper around OpenGL 3.3 Core. This library provides various
//! utilities to make using OpenGL 3.3 safer. It uses rust's type system to encode some information
//! which helps prevent common errors. This library is primarily intended to be used for games,
//! but you can also use it to create other graphics applications.
//!
//! Some points to get started:
//!
//!  - Use [`gondola::run`] to launch your game.
//!  - Use a [`VertexBuffer`] to do basic drawing.
//!  - Use [`GameState::gen_input_manager`] to get access to keyboard/mouse state.
//!
//! [`GameState::gen_input_manager`]: struct.GameState.html#method.gen_input_manager
//! [`VertexBuffer`]:                 buffer/struct.VertexBuffer.html
//! [`gondola::run`]:                 fn.run.html

extern crate gl;
extern crate glutin;
extern crate png;
extern crate cable_math;
extern crate rusttype;
#[macro_use]
extern crate bitflags;
#[cfg(feature = "serialize")]
extern crate serde;

mod color;
mod input;

pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod util;
pub mod framebuffer;
pub mod font;
pub mod ui;

pub use color::*;
pub use input::*;
pub use util::graphics;

use cable_math::Vec2;
use std::time::{Instant, Duration};
use std::sync::mpsc;

/// The most generic result type possible. Used in top-level
pub type GameResult<T> = Result<T, Box<std::error::Error>>;

/// Creates a new window and runs the given game in this window. This function does
/// not return until the game exits.
///
/// # Example
/// ```rust,no_run
/// extern crate gondola;
///
/// use gondola::{Game, GameResult, GameState};
///
/// fn main() {
///     gondola::run::<Pong>();
/// }
///
/// struct Pong {
///     // All data neded for game is defined here
/// }
///
/// impl Game for Pong {
///     fn setup(state: &mut GameState) -> GameResult<Pong> {
///         Ok(Pong {})
///     }
///
///     fn update(&mut self, delta: u32, state: &mut GameState) {
///         // All logic goes here.
///     }
///
///     fn draw(&mut self, state: &GameState) {
///         // All rendering goes here
///     }
/// }
/// ```
pub fn run<T: Game + Sized>() {
    // Create window
    let window = glutin::Window::new().unwrap();
    unsafe {
        window.make_current().unwrap();
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    }
    window.set_title(T::name());

    // Set up game state
    let mut state = GameState::new();
    state.win_size = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        Vec2::new(width, height)
    };
    graphics::viewport(0, 0, state.win_size.x, state.win_size.y);

    // Set up game
    let mut game = match T::setup(&mut state) {
        Err(err) => {
            println!("Failed to launch game:\n{}", err);
            panic!();
        },
        Ok(game) => game,
    };

    // We run a resize event here, because some platforms don't send a Resized event on startup.
    game.on_resize(&state);

    let mut delta: u64 = 16;

    'main_loop:
    loop {
        let start_time = Instant::now();

        // Events
        for event in window.poll_events() {
            match event {
                glutin::Event::Closed => break 'main_loop,
                glutin::Event::Resized(..) => {
                    let (width, height) = window.get_inner_size_pixels().unwrap();
                    let changed = state.win_size.x != width || state.win_size.y != height;

                    if width != 0 && height != 0 && changed {
                        state.win_size = Vec2::new(width, height);
                        graphics::viewport(0, 0, state.win_size.x, state.win_size.y);
                        game.on_resize(&state);
                    }
                },
                glutin::Event::Focused(focused) => {
                    state.focused = focused;

                    if focused {
                        let glutin_cursor_state = match state.cursor_state {
                            CursorState::Normal => glutin::CursorState::Normal,
                            CursorState::Hidden => glutin::CursorState::Hide,
                            CursorState::HiddenGrabbed => glutin::CursorState::Hide,
                            CursorState::Grabbed => glutin::CursorState::Grab,
                        };
                        window.set_cursor_state(glutin_cursor_state).unwrap();
                    } else {
                        window.set_cursor_state(glutin::CursorState::Normal).unwrap();
                    }
                },
                other => {
                    let custom_event = match other {
                        glutin::Event::MouseMoved(x, y) => {
                            let pos = Vec2::new(x as i32, y as i32);
                            let mut delta = pos - state.prev_cursor_pos;
                            state.prev_cursor_pos = pos;

                            // set_cursor_position creates mose-moved events, we want to ignore those
                            if state.cursor_state == CursorState::HiddenGrabbed {
                                let center = state.win_size / 2;
                                let center = Vec2::new(center.x as i32, center.y as i32);
                                if pos == center {
                                    continue;
                                }

                                // The focused state is almost exclusively used to control the
                                // camera. When we don't have focus we don't want the camera to
                                // move even if the cursor is moving around above the screen.
                                // Because of this we just disable mouse deltas in that case.
                                if !state.focused {
                                    delta = Vec2::zero();
                                }
                            }

                            Event::MouseMoved { delta, pos }
                        },

                        // We usually dont want to create a custom event, so unless we have custom
                        // logic for a specific event type we just pass on the glutin event.
                        e => Event::GlutinEvent(e),
                    };

                    // Send events to receivers, and remove those which are unable to receive.
                    state.event_sinks.retain(|sink| {
                        sink.send(custom_event.clone()).is_ok()
                    });
                },
            }
        }

        // Input state changes
        for input_state_change in state.state_change_request_receiver.try_iter() {
            match input_state_change {
                StateRequest::ChangeCursorState(new_state) => {
                    state.cursor_state = new_state;

                    let glutin_cursor_state = match new_state {
                        CursorState::Normal => glutin::CursorState::Normal,
                        CursorState::Hidden => glutin::CursorState::Hide,
                        CursorState::HiddenGrabbed => glutin::CursorState::Hide,
                        CursorState::Grabbed => glutin::CursorState::Grab,
                    };
                    window.set_cursor_state(glutin_cursor_state).unwrap();
                },
            }
        }

        if state.cursor_state == CursorState::HiddenGrabbed && state.focused {
            let center = state.win_size / 2;
            let center = Vec2::new(center.x as i32, center.y as i32);
            window.set_cursor_position(center.x, center.y).unwrap();
        }

        // Logic and rendering
        game.update(delta as u32, &mut state);
        game.draw(&state);
        window.swap_buffers().unwrap();
        graphics::print_errors();

        if state.exit {
            break 'main_loop;
        }

        // Timing
        if let Some(target_delta) = state.target_delta {
            let target_delta = Duration::from_millis(target_delta as u64);
            let elapsed = start_time.elapsed();
            if elapsed < target_delta {
                std::thread::sleep(target_delta - elapsed); // This is not very precice :/
            }
        }
        let delta_dur = start_time.elapsed();
        delta = delta_dur.as_secs()*1000 + (delta_dur.subsec_nanos() as u64)/1000000;

        // Calculate average framerate
        state.frame_accumulator += 1;
        state.delta_accumulator += delta as u32;
        if state.delta_accumulator > 500 { // Update every half second
            let frames = state.frame_accumulator as f32;
            let time = (state.delta_accumulator as f32) * 0.001;

            state.average_framerate = frames / time;

            state.frame_accumulator = 0;
            state.delta_accumulator = 0;
        }
    }

    game.close();
}

/// General info about the currently running game. Passed as a parameter to
/// most [`Game`](trait.Game.html) methods.
pub struct GameState {
    /// The size of the window in which this game is running, in pixels.
    pub win_size: Vec2<u32>,
    /// If set to true the game will exit after rendering.
    pub exit: bool,
    /// The number of milliseconds per frame this game should aim to run at. Set to 16
    /// for 60 fps. If the main loop takes less time than this amount the game will
    /// sleep until a total of `target_delta` has ellapsed. If set to `None` the game will
    /// never sleep, and run as fast as possible.
    pub target_delta: Option<u32>,
    /// The number of frames that where displayed in the last second. This number is updated every
    /// half second. Note that this is only an average; it does not reflect rapid fluctuations of
    /// delta times.
    pub average_framerate: f32,
    /// If true the game window currently has focus.
    pub focused: bool,

    // Used to calculate framerate
    frame_accumulator: u32,
    delta_accumulator: u32,

    event_sinks: Vec<mpsc::Sender<Event>>,
    state_change_request_receiver: mpsc::Receiver<StateRequest>,
    state_change_request_sender: mpsc::Sender<StateRequest>,

    prev_cursor_pos: Vec2<i32>,
    cursor_state: CursorState,
}

/// Used with [`gondola::run`](fn.run.html)
pub trait Game: Sized {
    /// Called before the main loop. Resources and initial state should be set up here.
    fn setup(state: &mut GameState) -> GameResult<Self>;
    /// Called once every frame, before drawing.
    fn update(&mut self, delta: u32, state: &mut GameState);
    /// Called once every frame, after updating.
    fn draw(&mut self, state: &GameState);

    /// Called whenever the game window is resized
    fn on_resize(&mut self, _state: &GameState) {}
    /// Called after the main game loop exists. This method is not called if the main
    /// loop `panic!`s.
    fn close(&mut self) {} // Most simple games dont need any special logic here

    fn name() -> &'static str { "Unnamed game (Override Game::name to change title)" }
}

impl GameState {
    fn new() -> GameState {
        let (state_change_request_sender, state_change_request_receiver) = mpsc::channel();

        GameState {
            win_size: Vec2::zero(),
            exit: false,
            target_delta: Some(15),

            average_framerate: -1.0,
            frame_accumulator: 0,
            delta_accumulator: 0,

            focused: false, // We get a Focused(true) event once the window opens

            event_sinks: Vec::new(),
            state_change_request_receiver: state_change_request_receiver,
            state_change_request_sender: state_change_request_sender,

            prev_cursor_pos: Vec2::zero(),
            cursor_state: CursorState::Normal,
        }
    }

    /// Generates a new receiver for glutin events. All events not consumed by the
    /// game itself will be received by this receiver. Note that all receiver receive
    /// all events, there is no notion of event consumption.
    pub fn gen_event_receiver(&mut self) -> mpsc::Receiver<Event> {
        let (sender, receiver) = mpsc::channel();
        self.event_sinks.push(sender);
        receiver
    }

    /// Generates a new sender to transmit state change requests to the game core asynchronously.
    pub fn gen_request_sender(&self) -> mpsc::Sender<StateRequest> {
        self.state_change_request_sender.clone()
    }

    /// Creates a new input manager which can be used to access the state of input devices.
    pub fn gen_input_manager(&mut self) -> InputManager {
        let receiver = self.gen_event_receiver();
        let sender = self.gen_request_sender();
        InputManager::new(receiver, sender)
    }
}

/// Because glutin does not handle some things in a very elegant fashion we have to work around
/// some of its events with custom events.
#[derive(Debug, Clone)]
pub enum Event {
    GlutinEvent(glutin::Event),
    MouseMoved {
        delta: Vec2<i32>,
        pos: Vec2<i32>,
    },
}

#[derive(Debug, Clone)]
pub enum StateRequest {
    ChangeCursorState(CursorState),
}

<commit_msg>Clarified some docs<commit_after>
//! A semi-safe, semi-stateless wrapper around OpenGL 3.3 Core. This library provides various
//! utilities to make using OpenGL 3.3 safer. It uses rust's type system to encode some information
//! which helps prevent common errors. This library is primarily intended to be used for games,
//! but you can also use it to create other graphics applications.
//!
//! Some points to get started:
//!
//!  - Use [`gondola::run`] to launch your game.
//!  - Use a [`VertexBuffer`] to do basic drawing.
//!  - Use [`GameState::gen_input_manager`] to get access to keyboard/mouse state.
//!
//! [`GameState::gen_input_manager`]: struct.GameState.html#method.gen_input_manager
//! [`VertexBuffer`]:                 buffer/struct.VertexBuffer.html
//! [`gondola::run`]:                 fn.run.html

extern crate gl;
extern crate glutin;
extern crate png;
extern crate cable_math;
extern crate rusttype;
#[macro_use]
extern crate bitflags;
#[cfg(feature = "serialize")]
extern crate serde;

mod color;
mod input;

pub mod texture;
#[macro_use]
pub mod shader;
pub mod buffer;
pub mod util;
pub mod framebuffer;
pub mod font;
pub mod ui;

pub use color::*;
pub use input::*;
pub use util::graphics;

use cable_math::Vec2;
use std::time::{Instant, Duration};
use std::sync::mpsc;

/// The most generic result type possible. Used in top-level
pub type GameResult<T> = Result<T, Box<std::error::Error>>;

/// Creates a new window and runs the given game in this window. This function does
/// not return until the game exits.
///
/// # Example
/// ```rust,no_run
/// extern crate gondola;
///
/// use gondola::{Game, GameResult, GameState};
///
/// fn main() {
///     gondola::run::<Pong>();
/// }
///
/// struct Pong {
///     // All data neded for game is defined here
/// }
///
/// impl Game for Pong {
///     fn setup(state: &mut GameState) -> GameResult<Pong> {
///         Ok(Pong {})
///     }
///
///     fn update(&mut self, delta: u32, state: &mut GameState) {
///         // All logic goes here.
///     }
///
///     fn draw(&mut self, state: &GameState) {
///         // All rendering goes here
///     }
/// }
/// ```
pub fn run<T: Game + Sized>() {
    // Create window
    let window = glutin::Window::new().unwrap();
    unsafe {
        window.make_current().unwrap();
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);
    }
    window.set_title(T::name());

    // Set up game state
    let mut state = GameState::new();
    state.win_size = {
        let (width, height) = window.get_inner_size_pixels().unwrap();
        Vec2::new(width, height)
    };
    graphics::viewport(0, 0, state.win_size.x, state.win_size.y);

    // Set up game
    let mut game = match T::setup(&mut state) {
        Err(err) => {
            println!("Failed to launch game:\n{}", err);
            panic!();
        },
        Ok(game) => game,
    };

    // We run a resize event here, because some platforms don't send a Resized event on startup.
    game.on_resize(&state);

    let mut delta: u64 = 16;

    'main_loop:
    loop {
        let start_time = Instant::now();

        // Events
        for event in window.poll_events() {
            match event {
                glutin::Event::Closed => break 'main_loop,
                glutin::Event::Resized(..) => {
                    let (width, height) = window.get_inner_size_pixels().unwrap();
                    let changed = state.win_size.x != width || state.win_size.y != height;

                    if width != 0 && height != 0 && changed {
                        state.win_size = Vec2::new(width, height);
                        graphics::viewport(0, 0, state.win_size.x, state.win_size.y);
                        game.on_resize(&state);
                    }
                },
                glutin::Event::Focused(focused) => {
                    state.focused = focused;

                    if focused {
                        let glutin_cursor_state = match state.cursor_state {
                            CursorState::Normal => glutin::CursorState::Normal,
                            CursorState::Hidden => glutin::CursorState::Hide,
                            CursorState::HiddenGrabbed => glutin::CursorState::Hide,
                            CursorState::Grabbed => glutin::CursorState::Grab,
                        };
                        window.set_cursor_state(glutin_cursor_state).unwrap();
                    } else {
                        window.set_cursor_state(glutin::CursorState::Normal).unwrap();
                    }
                },
                other => {
                    let custom_event = match other {
                        glutin::Event::MouseMoved(x, y) => {
                            let pos = Vec2::new(x as i32, y as i32);
                            let mut delta = pos - state.prev_cursor_pos;
                            state.prev_cursor_pos = pos;

                            // set_cursor_position creates mose-moved events, we want to ignore those
                            if state.cursor_state == CursorState::HiddenGrabbed {
                                let center = state.win_size / 2;
                                let center = Vec2::new(center.x as i32, center.y as i32);
                                if pos == center {
                                    continue;
                                }

                                // The focused state is almost exclusively used to control the
                                // camera. When we don't have focus we don't want the camera to
                                // move even if the cursor is moving around above the screen.
                                // Because of this we just disable mouse deltas in that case.
                                if !state.focused {
                                    delta = Vec2::zero();
                                }
                            }

                            Event::MouseMoved { delta, pos }
                        },

                        // We usually dont want to create a custom event, so unless we have custom
                        // logic for a specific event type we just pass on the glutin event.
                        e => Event::GlutinEvent(e),
                    };

                    // Send events to receivers, and remove those which are unable to receive.
                    state.event_sinks.retain(|sink| {
                        sink.send(custom_event.clone()).is_ok()
                    });
                },
            }
        }

        // Input state changes
        for input_state_change in state.state_change_request_receiver.try_iter() {
            match input_state_change {
                StateRequest::ChangeCursorState(new_state) => {
                    state.cursor_state = new_state;

                    let glutin_cursor_state = match new_state {
                        CursorState::Normal => glutin::CursorState::Normal,
                        CursorState::Hidden => glutin::CursorState::Hide,
                        CursorState::HiddenGrabbed => glutin::CursorState::Hide,
                        CursorState::Grabbed => glutin::CursorState::Grab,
                    };
                    window.set_cursor_state(glutin_cursor_state).unwrap();
                },
            }
        }

        if state.cursor_state == CursorState::HiddenGrabbed && state.focused {
            let center = state.win_size / 2;
            let center = Vec2::new(center.x as i32, center.y as i32);
            window.set_cursor_position(center.x, center.y).unwrap();
        }

        // Logic and rendering
        game.update(delta as u32, &mut state);
        game.draw(&state);
        window.swap_buffers().unwrap();
        graphics::print_errors();

        if state.exit {
            break 'main_loop;
        }

        // Timing
        if let Some(target_delta) = state.target_delta {
            let target_delta = Duration::from_millis(target_delta as u64);
            let elapsed = start_time.elapsed();
            if elapsed < target_delta {
                std::thread::sleep(target_delta - elapsed); // This is not very precice :/
            }
        }
        let delta_dur = start_time.elapsed();
        delta = delta_dur.as_secs()*1000 + (delta_dur.subsec_nanos() as u64)/1000000;

        // Calculate average framerate
        state.frame_accumulator += 1;
        state.delta_accumulator += delta as u32;
        if state.delta_accumulator > 500 { // Update every half second
            let frames = state.frame_accumulator as f32;
            let time = (state.delta_accumulator as f32) * 0.001;

            state.average_framerate = frames / time;

            state.frame_accumulator = 0;
            state.delta_accumulator = 0;
        }
    }

    game.close();
}

/// General info about the currently running game. Passed as a parameter to
/// most [`Game`](trait.Game.html) methods.
pub struct GameState {
    /// The size of the window in which this game is running, in pixels.
    pub win_size: Vec2<u32>,
    /// If set to true the game will exit after rendering.
    pub exit: bool,
    /// If true the game window currently has focus.
    pub focused: bool,

    /// The number of milliseconds per frame this game should aim to run at. Set to 16
    /// for 60 fps. If the main loop takes less time than this amount the game will
    /// sleep until a total of `target_delta` has ellapsed. If set to `None` the game will
    /// never sleep, and run as fast as possible.
    pub target_delta: Option<u32>,
    /// The number of frames that where displayed in the last second. This number is updated every
    /// half second. Note that this is only an average; it does not reflect rapid fluctuations of
    /// delta times.
    pub average_framerate: f32,
    // Used to calculate framerate
    frame_accumulator: u32,
    delta_accumulator: u32,

    event_sinks: Vec<mpsc::Sender<Event>>,
    state_change_request_receiver: mpsc::Receiver<StateRequest>,
    state_change_request_sender: mpsc::Sender<StateRequest>,

    // To work around some input issue we need to track some input state here. Most input state
    // is however tracked by the input manager.
    prev_cursor_pos: Vec2<i32>,
    cursor_state: CursorState,
}

/// Used with [`gondola::run`](fn.run.html)
pub trait Game: Sized {
    /// Called before the main loop. Resources and initial state should be set up here.
    fn setup(state: &mut GameState) -> GameResult<Self>;
    /// Called once every frame, before drawing.
    fn update(&mut self, delta: u32, state: &mut GameState);
    /// Called once every frame, after updating.
    fn draw(&mut self, state: &GameState);

    /// Called whenever the game window is resized. This function is guaranteed to be called
    /// once whenever the game is started. When called, this function is allways called before
    /// `update` and `resize`.
    fn on_resize(&mut self, _state: &GameState) {}
    /// Called after the main game loop exists. This method is not called if the main
    /// loop `panic!`s. Most simple games don't need any logic here.
    fn close(&mut self) {}

    /// The name dipslayed in the title bar of the games window.
    fn name() -> &'static str { "Unnamed game (Override Game::name to change title)" }
}

impl GameState {
    fn new() -> GameState {
        let (state_change_request_sender, state_change_request_receiver) = mpsc::channel();

        GameState {
            win_size: Vec2::zero(),
            exit: false,
            target_delta: Some(15),

            average_framerate: -1.0,
            frame_accumulator: 0,
            delta_accumulator: 0,

            focused: false, // We get a Focused(true) event once the window opens

            event_sinks: Vec::new(),
            state_change_request_receiver: state_change_request_receiver,
            state_change_request_sender: state_change_request_sender,

            prev_cursor_pos: Vec2::zero(),
            cursor_state: CursorState::Normal,
        }
    }

    /// Generates a new receiver for glutin events. All events not consumed by the
    /// game itself will be received by this receiver. Note that all receiver receive
    /// all events, there is no notion of event consumption.
    pub fn gen_event_receiver(&mut self) -> mpsc::Receiver<Event> {
        let (sender, receiver) = mpsc::channel();
        self.event_sinks.push(sender);
        receiver
    }

    /// Generates a new sender to transmit state change requests to the game core asynchronously.
    pub fn gen_request_sender(&self) -> mpsc::Sender<StateRequest> {
        self.state_change_request_sender.clone()
    }

    /// Creates a new input manager which can be used to access the state of input devices.
    pub fn gen_input_manager(&mut self) -> InputManager {
        let receiver = self.gen_event_receiver();
        let sender = self.gen_request_sender();
        InputManager::new(receiver, sender)
    }
}

/// Because glutin does not handle some things in a very elegant fashion we have to work around
/// some of its events with custom events.
#[derive(Debug, Clone)]
pub enum Event {
    GlutinEvent(glutin::Event),
    MouseMoved {
        delta: Vec2<i32>,
        pos: Vec2<i32>,
    },
}

#[derive(Debug, Clone)]
pub enum StateRequest {
    ChangeCursorState(CursorState),
}

<|endoftext|>


<commit_before>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate rusoto_core;

extern crate chrono;
extern crate hyper;
extern crate log;
extern crate md5;
extern crate rustc_serialize;
extern crate serde;
// Only bring in serde_derive for services that use it.
#[cfg(feature = "needs_serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate xml;

pub use rusoto_core::*;

pub use rusoto_core::credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                                  EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                                  ProvideAwsCredentials, DefaultCredentialsProvider,
                                  DefaultCredentialsProviderSync, claims,
                                  AutoRefreshingProviderSync, AutoRefreshingProvider,
                                  BaseAutoRefreshingProvider};

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "autoscaling")]
pub mod autoscaling;
#[allow(unused_imports)]
#[cfg(feature = "cloudformation")]
pub mod cloudformation;
#[cfg(feature = "cloudfront")]
pub mod cloudfront;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudsearch")]
pub mod cloudsearch;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "cloudwatch")]
pub mod cloudwatch;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elasticache")]
pub mod elasticache;
#[cfg(feature = "elasticbeanstalk")]
pub mod elasticbeanstalk;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "elb")]
pub mod elb;
#[cfg(feature = "elbv2")]
pub mod elbv2;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "importexport")]
pub mod importexport;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "lambda")]
pub mod lambda;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "redshift")]
pub mod redshift;
#[cfg(feature = "rds")]
pub mod rds;
#[cfg(feature = "route53")]
pub mod route53;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sdb")]
pub mod sdb;
#[cfg(feature = "ses")]
pub mod ses;
#[cfg(feature = "sns")]
pub mod sns;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "sts")]
pub mod sts;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<commit_msg>Correctly fix compilation errors.<commit_after>#![crate_name = "rusoto"]
#![crate_type = "lib"]
#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use std::default::Default;
//!
//! use rusoto::{DefaultCredentialsProvider, Region};
//! use rusoto::dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate rusoto_core;

extern crate chrono;
extern crate hyper;
// Logging macro is part of rest-json services
#[cfg(feature = "needs_serde_derive")]
#[macro_use]
extern crate log;
extern crate md5;
extern crate rustc_serialize;
extern crate serde;
// Only bring in serde_derive for services that use it.
#[cfg(feature = "needs_serde_derive")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate xml;

pub use rusoto_core::*;

pub use rusoto_core::credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                                  EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                                  ProvideAwsCredentials, DefaultCredentialsProvider,
                                  DefaultCredentialsProviderSync, claims,
                                  AutoRefreshingProviderSync, AutoRefreshingProvider,
                                  BaseAutoRefreshingProvider};

#[cfg(test)]
mod mock;

#[cfg(feature = "acm")]
pub mod acm;
#[cfg(feature = "autoscaling")]
pub mod autoscaling;
#[allow(unused_imports)]
#[cfg(feature = "cloudformation")]
pub mod cloudformation;
#[cfg(feature = "cloudfront")]
pub mod cloudfront;
#[cfg(feature = "cloudhsm")]
pub mod cloudhsm;
#[cfg(feature = "cloudsearch")]
pub mod cloudsearch;
#[cfg(feature = "cloudtrail")]
pub mod cloudtrail;
#[cfg(feature = "cloudwatch")]
pub mod cloudwatch;
#[cfg(feature = "codecommit")]
pub mod codecommit;
#[cfg(feature = "codedeploy")]
pub mod codedeploy;
#[cfg(feature = "codepipeline")]
pub mod codepipeline;
#[cfg(feature = "cognito-identity")]
pub mod cognitoidentity;
#[cfg(feature = "config")]
pub mod config;
#[cfg(feature = "datapipeline")]
pub mod datapipeline;
#[cfg(feature = "devicefarm")]
pub mod devicefarm;
#[cfg(feature = "directconnect")]
pub mod directconnect;
#[cfg(feature = "ds")]
pub mod ds;
#[cfg(feature = "dynamodb")]
pub mod dynamodb;
#[cfg(feature = "dynamodbstreams")]
pub mod dynamodbstreams;
#[cfg(feature = "ec2")]
pub mod ec2;
#[cfg(feature = "ecr")]
pub mod ecr;
#[cfg(feature = "ecs")]
pub mod ecs;
#[cfg(feature = "emr")]
pub mod emr;
#[cfg(feature = "elasticache")]
pub mod elasticache;
#[cfg(feature = "elasticbeanstalk")]
pub mod elasticbeanstalk;
#[cfg(feature = "elastictranscoder")]
pub mod elastictranscoder;
#[cfg(feature = "elb")]
pub mod elb;
#[cfg(feature = "elbv2")]
pub mod elbv2;
#[cfg(feature = "events")]
pub mod events;
#[cfg(feature = "firehose")]
pub mod firehose;
#[cfg(feature = "iam")]
pub mod iam;
#[cfg(feature = "importexport")]
pub mod importexport;
#[cfg(feature = "inspector")]
pub mod inspector;
#[cfg(feature = "iot")]
pub mod iot;
#[cfg(feature = "kinesis")]
pub mod kinesis;
#[cfg(feature = "kms")]
pub mod kms;
#[cfg(feature = "lambda")]
pub mod lambda;
#[cfg(feature = "logs")]
pub mod logs;
#[cfg(feature = "machinelearning")]
pub mod machinelearning;
#[cfg(feature = "marketplacecommerceanalytics")]
pub mod marketplacecommerceanalytics;
#[cfg(feature = "opsworks")]
pub mod opsworks;
#[cfg(feature = "redshift")]
pub mod redshift;
#[cfg(feature = "rds")]
pub mod rds;
#[cfg(feature = "route53")]
pub mod route53;
#[cfg(feature = "route53domains")]
pub mod route53domains;
#[cfg(feature = "s3")]
pub mod s3;
#[cfg(feature = "sdb")]
pub mod sdb;
#[cfg(feature = "ses")]
pub mod ses;
#[cfg(feature = "sns")]
pub mod sns;
#[cfg(feature = "sqs")]
pub mod sqs;
#[cfg(feature = "ssm")]
pub mod ssm;
#[cfg(feature = "storagegateway")]
pub mod storagegateway;
#[cfg(feature = "sts")]
pub mod sts;
#[cfg(feature = "swf")]
pub mod swf;
#[cfg(feature = "waf")]
pub mod waf;
#[cfg(feature = "workspaces")]
pub mod workspaces;

/*
#[cfg(feature = "gamelift")]
pub mod gamelift;
#[cfg(feature = "support")]
pub mod support;
*/
<|endoftext|>


<commit_before>#![warn(missing_docs)]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://jarusk.github.io/spork")]
//! Some sample documentation
//!

#[cfg(test)]
mod tests {
    //! The tests module
    #[test]
    /// Our first test
    fn it_works() {
    }
}
<commit_msg>Cleaned out excess code<commit_after>#![warn(missing_docs)]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://jarusk.github.io/spork")]
//! Some sample documentation
//!
<|endoftext|>


<commit_before>#![feature(asm)]
#![no_std]

#[macro_use]
#[allow(unstable)]
extern crate core;

pub use context::Context;

mod std { pub use core::*; }

mod context;
mod stack;

mod arch;
mod platform;
<commit_msg>use std in test configurations<commit_after>#![feature(asm)]
#![no_std]

#[macro_use]
#[allow(unstable)]
extern crate core;

#[cfg(test)]
#[macro_use]
extern crate std;

pub use context::Context;

#[cfg(not(test))]
mod std { pub use core::*; }

mod context;
mod stack;

mod arch;
mod platform;
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate crc;
extern crate inflate;
#[macro_use]
extern crate slog;

use byteorder::ByteOrder;
use byteorder::ReadBytesExt;

use crc::crc32::Hasher32;

use std::fs::File;
use std::io::BufReader;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::str;

const GZIP_IDENTIFIER: [u8; 2] = [0x1f, 0x8b];
const BGZF_IDENTIFIER: [u8; 2] = [0x42, 0x43];

const DEFLATE: u8 = 8;

const EXTRA: u8 = 1 << 2;

pub fn version() -> &'static str {
    return option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
}

enum BGZFBlockInformation {
    EOF,
    Size(u32)
}

fn check_block(reader: &mut BufReader<File>, blocks_count: &mut u64, logger: &slog::Logger) -> Result<BGZFBlockInformation, Error> {
    let mut header_digest = crc::crc32::Digest::new(crc::crc32::IEEE);

    let mut gzip_identifier = [0u8; 2];
    let read_bytes = reader.read(&mut gzip_identifier)?;
    if read_bytes == 0 {
        return Ok(BGZFBlockInformation::EOF);
    }
    if read_bytes != 2 || gzip_identifier != GZIP_IDENTIFIER {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip identitifer not found"));
    }
    *blocks_count += 1;
    debug!(logger, "Checking block {}", blocks_count);
    header_digest.write(&gzip_identifier);

    let mut compression_method = [0u8; 1];
    reader.read_exact(&mut compression_method)?;
    if compression_method[0] != DEFLATE {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip compression method is not deflate"));
    }
    header_digest.write(&compression_method);

    let mut flags = [0u8; 1];
    reader.read_exact(&mut flags)?;
    if flags[0] != EXTRA {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected gzip flags"));
    }
    header_digest.write(&flags);

    let mut modification_time = [0u8; 4];
    reader.read_exact(&mut modification_time)?;
    header_digest.write(&modification_time);

    let mut extra_flags = [0u8; 1];
    reader.read_exact(&mut extra_flags)?;
    header_digest.write(&extra_flags);

    let mut operating_system = [0u8; 1];
    reader.read_exact(&mut operating_system)?;
    header_digest.write(&operating_system);

    let mut block_size = 0u16;
    let mut extra_field_length_bytes = [0u8; 2];
    reader.read_exact(&mut extra_field_length_bytes)?;
    let extra_field_length = byteorder::LittleEndian::read_u16(&extra_field_length_bytes);
    debug!(logger, "\tExtra field length of {} bytes", extra_field_length);
    header_digest.write(&extra_field_length_bytes);

    let mut remaining_extra_field_length = extra_field_length;
    while remaining_extra_field_length > 0 {
        let mut subfield_identifier = [0u8; 2];
        reader.read_exact(&mut subfield_identifier)?;
        header_digest.write(&subfield_identifier);

        let mut subfield_length_bytes = [0u8; 2];
        reader.read_exact(&mut subfield_length_bytes)?;
        let subfield_length = byteorder::LittleEndian::read_u16(&subfield_length_bytes);
        debug!(logger, "\t\tSubfield length of {} bytes", subfield_length);
        header_digest.write(&subfield_length_bytes);

        if subfield_identifier == BGZF_IDENTIFIER {
            debug!(logger, "\t\t\tSubfield is bgzf metadata");

            if subfield_length != 2 {
                return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size is not a 16 bits number"));
            }

            let mut block_size_bytes = [0u8; 2];
            reader.read_exact(&mut block_size_bytes)?;
            block_size = byteorder::LittleEndian::read_u16(&block_size_bytes) + 1;
            debug!(logger, "\t\t\t\tbgzf block size is {} bytes", block_size);
            header_digest.write(&block_size_bytes);
        } else {
            reader.seek(SeekFrom::Current(subfield_length as i64))?;
        }

        remaining_extra_field_length -= 4 + subfield_length;
    }
    if block_size == 0 {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size not found in gzip extra field"));
    }

    let mut payload_digest = crc::crc32::Digest::new(crc::crc32::IEEE);
    let payload_size;
    {
        let mut deflated_bytes = vec![];
        let mut deflate_reader = reader.take((block_size - extra_field_length - 20u16) as u64);
        deflate_reader.read_to_end(&mut deflated_bytes)?;
        let inflated_bytes = match inflate::inflate_bytes(&deflated_bytes) {
            Ok(inflated_bytes) => inflated_bytes,
            Err(error) => return Err(Error::new(ErrorKind::InvalidData, format!("Invalid bam file: unable to inflate payload: {}", error))),
        };
        payload_digest.write(&inflated_bytes);
        payload_size = inflated_bytes.len();
    }

    let mut data_crc32 = [0u8; 4];
    reader.read_exact(&mut data_crc32)?;
    let payload_crc32 = payload_digest.sum32();

    if data_crc32[0] != ((payload_crc32 & 0xff) as u8) ||
       data_crc32[1] != (((payload_crc32 >> 8) & 0xff) as u8) ||
       data_crc32[2] != (((payload_crc32 >> 16) & 0xff) as u8) ||
       data_crc32[3] != (((payload_crc32 >> 24) & 0xff) as u8) {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: incorrect payload CRC32"));
    }

    let data_size = reader.read_u32::<byteorder::LittleEndian>()?;
    debug!(logger, "\tData size is {} bytes", data_size);
    if data_size as usize != payload_size {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: incorrect payload size"));
    }

    debug!(logger, "\tAt offset {}", reader.seek(SeekFrom::Current(0))?);

    return Ok(BGZFBlockInformation::Size(data_size));
}

pub fn check(bamfile: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Checking integrity of {}…", bamfile);

    let mut reader = BufReader::new(File::open(bamfile)?);

    let mut blocks_count = 0u64;
    let mut data_size = 0u32;
    loop {
        data_size = match check_block(&mut reader, &mut blocks_count, &logger)? {
            BGZFBlockInformation::EOF => if data_size == 0u32 { break } else { return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected end of file while last bgzf block was not empty")); },
            BGZFBlockInformation::Size(data_size) => data_size,
        };
    }

    println!("bam file statistics:");
    println!("{: >7} bgzf blocks found", blocks_count);
    println!("{: >7} corrupted blocks found", 0);
    Ok(())
}

pub fn repair(bamfile: &str, output: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Repairing {} and writing output to {}…", bamfile, output);

    error!(logger, "bamrescue::repair() is not yet implemented");
    unimplemented!();
}
<commit_msg>Never compute the header CRC16<commit_after>extern crate byteorder;
extern crate crc;
extern crate inflate;
#[macro_use]
extern crate slog;

use byteorder::ReadBytesExt;

use crc::crc32::Hasher32;

use std::fs::File;
use std::io::BufReader;
use std::io::Error;
use std::io::ErrorKind;
use std::io::Read;
use std::io::Seek;
use std::io::SeekFrom;
use std::str;

const GZIP_IDENTIFIER: [u8; 2] = [0x1f, 0x8b];
const BGZF_IDENTIFIER: [u8; 2] = [0x42, 0x43];

const DEFLATE: u8 = 8;

const EXTRA: u8 = 1 << 2;

pub fn version() -> &'static str {
    return option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
}

enum BGZFBlockInformation {
    EOF,
    Size(u32)
}

fn check_block(reader: &mut BufReader<File>, blocks_count: &mut u64, logger: &slog::Logger) -> Result<BGZFBlockInformation, Error> {
    let mut gzip_identifier = [0u8; 2];
    let read_bytes = reader.read(&mut gzip_identifier)?;
    if read_bytes == 0 {
        return Ok(BGZFBlockInformation::EOF);
    }
    if read_bytes != 2 || gzip_identifier != GZIP_IDENTIFIER {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip identitifer not found"));
    }
    *blocks_count += 1;
    debug!(logger, "Checking block {}", blocks_count);

    let mut compression_method = [0u8; 1];
    reader.read_exact(&mut compression_method)?;
    if compression_method[0] != DEFLATE {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: gzip compression method is not deflate"));
    }

    let mut flags = [0u8; 1];
    reader.read_exact(&mut flags)?;
    if flags[0] != EXTRA {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected gzip flags"));
    }

    let mut modification_time = [0u8; 4];
    reader.read_exact(&mut modification_time)?;

    let mut extra_flags = [0u8; 1];
    reader.read_exact(&mut extra_flags)?;

    let mut operating_system = [0u8; 1];
    reader.read_exact(&mut operating_system)?;

    let mut block_size = 0u16;

    let extra_field_length = reader.read_u16::<byteorder::LittleEndian>()?;
    debug!(logger, "\tExtra field length of {} bytes", extra_field_length);

    let mut remaining_extra_field_length = extra_field_length;
    while remaining_extra_field_length > 0 {
        let mut subfield_identifier = [0u8; 2];
        reader.read_exact(&mut subfield_identifier)?;

        let subfield_length = reader.read_u16::<byteorder::LittleEndian>()?;
        debug!(logger, "\t\tSubfield length of {} bytes", subfield_length);

        if subfield_identifier == BGZF_IDENTIFIER {
            debug!(logger, "\t\t\tSubfield is bgzf metadata");

            if subfield_length != 2 {
                return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size is not a 16 bits number"));
            }

            block_size = reader.read_u16::<byteorder::LittleEndian>()? + 1;
            debug!(logger, "\t\t\t\tbgzf block size is {} bytes", block_size);
        } else {
            reader.seek(SeekFrom::Current(subfield_length as i64))?;
        }

        remaining_extra_field_length -= 4 + subfield_length;
    }
    if block_size == 0 {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: bgzf block size not found in gzip extra field"));
    }

    let mut payload_digest = crc::crc32::Digest::new(crc::crc32::IEEE);
    let payload_size;
    {
        let mut deflated_bytes = vec![];
        let mut deflate_reader = reader.take((block_size - extra_field_length - 20u16) as u64);
        deflate_reader.read_to_end(&mut deflated_bytes)?;
        let inflated_bytes = match inflate::inflate_bytes(&deflated_bytes) {
            Ok(inflated_bytes) => inflated_bytes,
            Err(error) => return Err(Error::new(ErrorKind::InvalidData, format!("Invalid bam file: unable to inflate payload: {}", error))),
        };
        payload_digest.write(&inflated_bytes);
        payload_size = inflated_bytes.len();
    }

    let mut data_crc32 = [0u8; 4];
    reader.read_exact(&mut data_crc32)?;
    let payload_crc32 = payload_digest.sum32();

    if data_crc32[0] != ((payload_crc32 & 0xff) as u8) ||
       data_crc32[1] != (((payload_crc32 >> 8) & 0xff) as u8) ||
       data_crc32[2] != (((payload_crc32 >> 16) & 0xff) as u8) ||
       data_crc32[3] != (((payload_crc32 >> 24) & 0xff) as u8) {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: incorrect payload CRC32"));
    }

    let data_size = reader.read_u32::<byteorder::LittleEndian>()?;
    debug!(logger, "\tData size is {} bytes", data_size);
    if data_size as usize != payload_size {
        return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: incorrect payload size"));
    }

    debug!(logger, "\tAt offset {}", reader.seek(SeekFrom::Current(0))?);

    return Ok(BGZFBlockInformation::Size(data_size));
}

pub fn check(bamfile: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Checking integrity of {}…", bamfile);

    let mut reader = BufReader::new(File::open(bamfile)?);

    let mut blocks_count = 0u64;
    let mut data_size = 0u32;
    loop {
        data_size = match check_block(&mut reader, &mut blocks_count, &logger)? {
            BGZFBlockInformation::EOF => if data_size == 0u32 { break } else { return Err(Error::new(ErrorKind::InvalidData, "Invalid bam file: unexpected end of file while last bgzf block was not empty")); },
            BGZFBlockInformation::Size(data_size) => data_size,
        };
    }

    println!("bam file statistics:");
    println!("{: >7} bgzf blocks found", blocks_count);
    println!("{: >7} corrupted blocks found", 0);
    Ok(())
}

pub fn repair(bamfile: &str, output: &str, logger: &slog::Logger) -> Result<(), Error> {
    info!(logger, "Repairing {} and writing output to {}…", bamfile, output);

    error!(logger, "bamrescue::repair() is not yet implemented");
    unimplemented!();
}
<|endoftext|>


<commit_before>#![warn(warnings)]
#![cfg_attr(test, deny(warnings))]

//! A small library for reading and writing BMP images.
//!
//! The library supports uncompressed BMP Version 3 images.
//! The different decoding and encoding schemes is shown in the table below.
//!
//! |Scheme | Decoding | Encoding | Compression |
//! |-------|----------|----------|-------------|
//! | 24 bpp| ✓        | ✓        | No          |
//! | 8 bpp | ✓        | ✗        | No          |
//! | 4 bpp | ✓        | ✗        | No          |
//! | 1 bpp | ✓        | ✗        | No          |
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate bmp;
//! use bmp::{Image, Pixel};
//!
//! fn main() {
//!     let mut img = Image::new(256, 256);
//!
//!     for (x, y) in img.coordinates() {
//!         img.set_pixel(x, y, px!(x, y, 200));
//!     }
//!     let _ = img.save("img.bmp");
//! }
//! ```
//!

extern crate byteorder;

use std::convert::{AsRef};
use std::fmt;
use std::fs;
use std::io;
use std::io::{Cursor, Read, Write};
use std::iter::Iterator;

use ::CompressionType::*;
use ::BmpVersion::*;

pub use decoder::{BmpError, BmpErrorKind, BmpResult};

#[cfg(test)]
mod tests;

/// The pixel data used in the `Image`.
///
/// It has three values for the `red`, `blue` and `green` color channels, respectively.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Pixel {
    pub r: u8,
    pub g: u8,
    pub b: u8
}

/// Macro to generate a `Pixel` from `r`, `g` and `b` values.
#[macro_export]
macro_rules! px {
    ($r:expr, $g:expr, $b:expr) => {
        Pixel { r: $r as u8, g: $g as u8, b: $b as u8 }
    }
}

macro_rules! file_size {
    ($bpp:expr, $width:expr, $height:expr) => {{
        let header_size = 2 + 12 + 40;
        let row_size = (($bpp as f32 * $width as f32 + 31.0) / 32.0).floor() as u32 * 4;
        (header_size as u32, $height as u32 * row_size)
    }}
}

/// Common color constants accessible by names.
pub mod consts;

mod decoder;
mod encoder;

#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
enum BmpVersion {
    Version1,
    Version2,
    Version3,
    Version3NT,
    Version4,
}

impl AsRef<str> for BmpVersion {
    fn as_ref(&self) -> &str {
        match *self {
            Version1   => "BMP Version 1",
            Version2   => "BMP Version 2",
            Version3   => "BMP Version 3",
            Version3NT => "BMP Version 3 NT",
            Version4   => "BMP Version 4",
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum CompressionType {
    Uncompressed,
    Rle8bit,
    Rle4bit,
    // Only for BMP version 4
    BitfieldsEncoding,
}

impl CompressionType {
    fn from_u32(val: u32) -> CompressionType {
        match val {
            1 => Rle8bit,
            2 => Rle4bit,
            3 => BitfieldsEncoding,
            _ => Uncompressed,
        }
    }
}

impl AsRef<str> for CompressionType {
    fn as_ref(&self) -> &str {
        match *self {
            Rle8bit           => "RLE 8-bit",
            Rle4bit           => "RLE 4-bit",
            BitfieldsEncoding => "Bitfields Encoding",
            Uncompressed      => "Uncompressed",
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct BmpHeader {
    file_size: u32,
    creator1: u16,
    creator2: u16,
    pixel_offset: u32
}

impl BmpHeader {
    pub fn new(header_size: u32, data_size: u32) -> BmpHeader {
        BmpHeader {
            file_size: header_size + data_size,
            creator1: 0 /* Unused */,
            creator2: 0 /* Unused */,
            pixel_offset: header_size
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct BmpDibHeader {
    header_size: u32,
    width: i32,
    height: i32,
    num_planes: u16,
    bits_per_pixel: u16,
    compress_type: u32,
    data_size: u32,
    hres: i32,
    vres: i32,
    num_colors: u32,
    num_imp_colors: u32,
}

impl BmpDibHeader {
    pub fn new(width: i32, height: i32) -> BmpDibHeader {
        let row_size = ((24.0 * width as f32 + 31.0) / 32.0).floor() as u32 * 4;
        let pixel_array_size = row_size * height as u32;

        BmpDibHeader {
            header_size: 40,
            width: width,
            height: height,
            num_planes: 1,
            bits_per_pixel: 24,
            compress_type: 0,
            data_size: pixel_array_size,
            hres: 1000,
            vres: 1000,
            num_colors: 0,
            num_imp_colors: 0
        }
    }
}

/// The image type provided by the library.
///
/// It exposes functions to initialize or read BMP images from disk, common modification of pixel
/// data, and saving to disk.
///
/// The image is accessed in row-major order from top to bottom,
/// where point (0, 0) is defined to be in the upper left corner of the image.
///
/// Currently, only uncompressed BMP images are supported.
#[derive(Clone, Eq, PartialEq)]
pub struct Image {
    header: BmpHeader,
    dib_header: BmpDibHeader,
    color_palette: Option<Vec<Pixel>>,
    width: u32,
    height: u32,
    padding: u32,
    data: Vec<Pixel>
}

impl fmt::Debug for Image {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Image {}\n", '{')?;
        write!(f, "\theader: {:?},\n", self.header)?;
        write!(f, "\tdib_header: {:?},\n", self.dib_header)?;
        write!(f, "\tcolor_palette: {:?},\n", self.color_palette)?;
        write!(f, "\twidth: {:?},\n", self.width)?;
        write!(f, "\theight: {:?},\n", self.height)?;
        write!(f, "\tpadding: {:?},\n", self.padding)?;
        write!(f, "{}", '}')
    }
}

impl Image {
    /// Returns a new BMP Image with the `width` and `height` specified. It is initialized to
    /// a black image by default.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 80);
    /// ```
    pub fn new(width: u32, height: u32) -> Image {
        let mut data = Vec::with_capacity((width * height) as usize);
        for _ in 0 .. width * height {
            data.push(px!(0, 0, 0));
        }

        let (header_size, data_size) = file_size!(24, width, height);
        Image {
            header: BmpHeader::new(header_size, data_size),
            dib_header: BmpDibHeader::new(width as i32, height as i32),
            color_palette: None,
            width: width,
            height: height,
            padding: width % 4,
            data: data
        }
    }

    /// Returns the `width` of the Image.
    #[inline]
    pub fn get_width(&self) -> u32 {
        self.width
    }

    /// Returns the `height` of the Image.
    #[inline]
    pub fn get_height(&self) -> u32 {
        self.height
    }

    /// Set the pixel value at the position of `width` and `height`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 80);
    /// img.set_pixel(10, 10, bmp::consts::RED);
    /// ```
    #[inline]
    pub fn set_pixel(&mut self, x: u32, y: u32, val: Pixel) {
        self.data[((self.height - y - 1) * self.width + x) as usize] = val;
    }

    /// Returns the pixel value at the position of `width` and `height`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let img = bmp::Image::new(100, 80);
    /// assert_eq!(bmp::consts::BLACK, img.get_pixel(10, 10));
    /// ```
    #[inline]
    pub fn get_pixel(&self, x: u32, y: u32) -> Pixel {
        self.data[((self.height - y - 1) * self.width + x) as usize]
    }

    /// Returns a new `ImageIndex` that iterates over the image dimensions in top-bottom order.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 100);
    /// for (x, y) in img.coordinates() {
    ///     img.set_pixel(x, y, bmp::consts::BLUE);
    /// }
    /// ```
    #[inline]
    pub fn coordinates(&self) -> ImageIndex {
        ImageIndex::new(self.width as u32, self.height as u32)
    }

    /// Saves the image to the path specified by `name`. The function will overwrite the contents
    /// if a file already exists with the same name.
    ///
    /// The function returns the `io::Result` from the underlying `Reader`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 100);
    /// let _ = img.save("black.bmp").unwrap_or_else(|e| {
    ///     panic!("Failed to save: {}", e)
    /// });
    /// ```
    pub fn save(&self, name: &str) -> io::Result<()> {
        // only 24 bpp encoding supported
        let bmp_data = encoder::encode_image(self)?;
        let mut bmp_file = fs::File::create(name)?;
        bmp_file.write(&bmp_data)?;
        Ok(())
    }
}

/// Returns a `BmpResult`, either containing an `Image` or a `BmpError`.
///
/// # Example
///
/// ```
/// extern crate bmp;
///
/// let img = bmp::open("test/rgbw.bmp").unwrap_or_else(|e| {
///    panic!("Failed to open: {}", e);
/// });
/// ```
pub fn open(name: &str) -> BmpResult<Image> {
    let mut bytes = Vec::new();
    let mut f = fs::File::open(name)?;
    f.read_to_end(&mut bytes)?;
    let mut bmp_data = Cursor::new(bytes);

    decoder::decode_image(&mut bmp_data)
}

/// An `Iterator` returning the `x` and `y` coordinates of an image.
///
/// It supports iteration over an image in row-major order,
/// starting from in the upper left corner of the image.
#[derive(Clone, Copy)]
pub struct ImageIndex {
    width: u32,
    height: u32,
    x: u32,
    y: u32
}

impl ImageIndex {
    fn new(width: u32, height: u32) -> ImageIndex {
        ImageIndex {
            width: width,
            height: height,
            x: 0,
            y: 0
        }
    }
}

impl Iterator for ImageIndex {
    type Item = (u32, u32);

    fn next(&mut self) -> Option<(u32, u32)> {
        if self.x < self.width && self.y < self.height {
            let this = Some((self.x, self.y));
            self.x += 1;
            if self.x == self.width {
                self.x = 0;
                self.y += 1;
            }
            this
        } else {
            None
        }
    }
}
<commit_msg>implement new function for Pixel<commit_after>#![warn(warnings)]
#![cfg_attr(test, deny(warnings))]

//! A small library for reading and writing BMP images.
//!
//! The library supports uncompressed BMP Version 3 images.
//! The different decoding and encoding schemes is shown in the table below.
//!
//! |Scheme | Decoding | Encoding | Compression |
//! |-------|----------|----------|-------------|
//! | 24 bpp| ✓        | ✓        | No          |
//! | 8 bpp | ✓        | ✗        | No          |
//! | 4 bpp | ✓        | ✗        | No          |
//! | 1 bpp | ✓        | ✗        | No          |
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate bmp;
//! use bmp::{Image, Pixel};
//!
//! fn main() {
//!     let mut img = Image::new(256, 256);
//!
//!     for (x, y) in img.coordinates() {
//!         img.set_pixel(x, y, px!(x, y, 200));
//!     }
//!     let _ = img.save("img.bmp");
//! }
//! ```
//!

extern crate byteorder;

use std::convert::{AsRef};
use std::fmt;
use std::fs;
use std::io;
use std::io::{Cursor, Read, Write};
use std::iter::Iterator;

use ::CompressionType::*;
use ::BmpVersion::*;

pub use decoder::{BmpError, BmpErrorKind, BmpResult};

#[cfg(test)]
mod tests;

/// The pixel data used in the `Image`.
///
/// It has three values for the `red`, `blue` and `green` color channels, respectively.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Pixel {
    pub r: u8,
    pub g: u8,
    pub b: u8
}

impl Pixel {
    pub fn new(r: u8, g: u8, b: u8) -> Pixel {
        Pixel { r: r, g: g, b: b }
    }
}

/// Macro to generate a `Pixel` from `r`, `g` and `b` values.
#[macro_export]
macro_rules! px {
    ($r:expr, $g:expr, $b:expr) => {
        Pixel { r: $r as u8, g: $g as u8, b: $b as u8 }
    }
}

macro_rules! file_size {
    ($bpp:expr, $width:expr, $height:expr) => {{
        let header_size = 2 + 12 + 40;
        let row_size = (($bpp as f32 * $width as f32 + 31.0) / 32.0).floor() as u32 * 4;
        (header_size as u32, $height as u32 * row_size)
    }}
}

/// Common color constants accessible by names.
pub mod consts;

mod decoder;
mod encoder;

#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
enum BmpVersion {
    Version1,
    Version2,
    Version3,
    Version3NT,
    Version4,
}

impl AsRef<str> for BmpVersion {
    fn as_ref(&self) -> &str {
        match *self {
            Version1   => "BMP Version 1",
            Version2   => "BMP Version 2",
            Version3   => "BMP Version 3",
            Version3NT => "BMP Version 3 NT",
            Version4   => "BMP Version 4",
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum CompressionType {
    Uncompressed,
    Rle8bit,
    Rle4bit,
    // Only for BMP version 4
    BitfieldsEncoding,
}

impl CompressionType {
    fn from_u32(val: u32) -> CompressionType {
        match val {
            1 => Rle8bit,
            2 => Rle4bit,
            3 => BitfieldsEncoding,
            _ => Uncompressed,
        }
    }
}

impl AsRef<str> for CompressionType {
    fn as_ref(&self) -> &str {
        match *self {
            Rle8bit           => "RLE 8-bit",
            Rle4bit           => "RLE 4-bit",
            BitfieldsEncoding => "Bitfields Encoding",
            Uncompressed      => "Uncompressed",
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct BmpHeader {
    file_size: u32,
    creator1: u16,
    creator2: u16,
    pixel_offset: u32
}

impl BmpHeader {
    pub fn new(header_size: u32, data_size: u32) -> BmpHeader {
        BmpHeader {
            file_size: header_size + data_size,
            creator1: 0 /* Unused */,
            creator2: 0 /* Unused */,
            pixel_offset: header_size
        }
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
struct BmpDibHeader {
    header_size: u32,
    width: i32,
    height: i32,
    num_planes: u16,
    bits_per_pixel: u16,
    compress_type: u32,
    data_size: u32,
    hres: i32,
    vres: i32,
    num_colors: u32,
    num_imp_colors: u32,
}

impl BmpDibHeader {
    pub fn new(width: i32, height: i32) -> BmpDibHeader {
        let row_size = ((24.0 * width as f32 + 31.0) / 32.0).floor() as u32 * 4;
        let pixel_array_size = row_size * height as u32;

        BmpDibHeader {
            header_size: 40,
            width: width,
            height: height,
            num_planes: 1,
            bits_per_pixel: 24,
            compress_type: 0,
            data_size: pixel_array_size,
            hres: 1000,
            vres: 1000,
            num_colors: 0,
            num_imp_colors: 0
        }
    }
}

/// The image type provided by the library.
///
/// It exposes functions to initialize or read BMP images from disk, common modification of pixel
/// data, and saving to disk.
///
/// The image is accessed in row-major order from top to bottom,
/// where point (0, 0) is defined to be in the upper left corner of the image.
///
/// Currently, only uncompressed BMP images are supported.
#[derive(Clone, Eq, PartialEq)]
pub struct Image {
    header: BmpHeader,
    dib_header: BmpDibHeader,
    color_palette: Option<Vec<Pixel>>,
    width: u32,
    height: u32,
    padding: u32,
    data: Vec<Pixel>
}

impl fmt::Debug for Image {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "Image {}\n", '{')?;
        write!(f, "\theader: {:?},\n", self.header)?;
        write!(f, "\tdib_header: {:?},\n", self.dib_header)?;
        write!(f, "\tcolor_palette: {:?},\n", self.color_palette)?;
        write!(f, "\twidth: {:?},\n", self.width)?;
        write!(f, "\theight: {:?},\n", self.height)?;
        write!(f, "\tpadding: {:?},\n", self.padding)?;
        write!(f, "{}", '}')
    }
}

impl Image {
    /// Returns a new BMP Image with the `width` and `height` specified. It is initialized to
    /// a black image by default.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 80);
    /// ```
    pub fn new(width: u32, height: u32) -> Image {
        let mut data = Vec::with_capacity((width * height) as usize);
        for _ in 0 .. width * height {
            data.push(px!(0, 0, 0));
        }

        let (header_size, data_size) = file_size!(24, width, height);
        Image {
            header: BmpHeader::new(header_size, data_size),
            dib_header: BmpDibHeader::new(width as i32, height as i32),
            color_palette: None,
            width: width,
            height: height,
            padding: width % 4,
            data: data
        }
    }

    /// Returns the `width` of the Image.
    #[inline]
    pub fn get_width(&self) -> u32 {
        self.width
    }

    /// Returns the `height` of the Image.
    #[inline]
    pub fn get_height(&self) -> u32 {
        self.height
    }

    /// Set the pixel value at the position of `width` and `height`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 80);
    /// img.set_pixel(10, 10, bmp::consts::RED);
    /// ```
    #[inline]
    pub fn set_pixel(&mut self, x: u32, y: u32, val: Pixel) {
        self.data[((self.height - y - 1) * self.width + x) as usize] = val;
    }

    /// Returns the pixel value at the position of `width` and `height`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let img = bmp::Image::new(100, 80);
    /// assert_eq!(bmp::consts::BLACK, img.get_pixel(10, 10));
    /// ```
    #[inline]
    pub fn get_pixel(&self, x: u32, y: u32) -> Pixel {
        self.data[((self.height - y - 1) * self.width + x) as usize]
    }

    /// Returns a new `ImageIndex` that iterates over the image dimensions in top-bottom order.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 100);
    /// for (x, y) in img.coordinates() {
    ///     img.set_pixel(x, y, bmp::consts::BLUE);
    /// }
    /// ```
    #[inline]
    pub fn coordinates(&self) -> ImageIndex {
        ImageIndex::new(self.width as u32, self.height as u32)
    }

    /// Saves the image to the path specified by `name`. The function will overwrite the contents
    /// if a file already exists with the same name.
    ///
    /// The function returns the `io::Result` from the underlying `Reader`.
    ///
    /// # Example
    ///
    /// ```
    /// extern crate bmp;
    ///
    /// let mut img = bmp::Image::new(100, 100);
    /// let _ = img.save("black.bmp").unwrap_or_else(|e| {
    ///     panic!("Failed to save: {}", e)
    /// });
    /// ```
    pub fn save(&self, name: &str) -> io::Result<()> {
        // only 24 bpp encoding supported
        let bmp_data = encoder::encode_image(self)?;
        let mut bmp_file = fs::File::create(name)?;
        bmp_file.write(&bmp_data)?;
        Ok(())
    }
}

/// Returns a `BmpResult`, either containing an `Image` or a `BmpError`.
///
/// # Example
///
/// ```
/// extern crate bmp;
///
/// let img = bmp::open("test/rgbw.bmp").unwrap_or_else(|e| {
///    panic!("Failed to open: {}", e);
/// });
/// ```
pub fn open(name: &str) -> BmpResult<Image> {
    let mut bytes = Vec::new();
    let mut f = fs::File::open(name)?;
    f.read_to_end(&mut bytes)?;
    let mut bmp_data = Cursor::new(bytes);

    decoder::decode_image(&mut bmp_data)
}

/// An `Iterator` returning the `x` and `y` coordinates of an image.
///
/// It supports iteration over an image in row-major order,
/// starting from in the upper left corner of the image.
#[derive(Clone, Copy)]
pub struct ImageIndex {
    width: u32,
    height: u32,
    x: u32,
    y: u32
}

impl ImageIndex {
    fn new(width: u32, height: u32) -> ImageIndex {
        ImageIndex {
            width: width,
            height: height,
            x: 0,
            y: 0
        }
    }
}

impl Iterator for ImageIndex {
    type Item = (u32, u32);

    fn next(&mut self) -> Option<(u32, u32)> {
        if self.x < self.width && self.y < self.height {
            let this = Some((self.x, self.y));
            self.x += 1;
            if self.x == self.width {
                self.x = 0;
                self.y += 1;
            }
            this
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>//#![deny(warnings)]
#[macro_use]
extern crate error_chain;

extern crate svgbob;
extern crate csv;
extern crate comrak;
extern crate typed_arena;
use typed_arena::Arena;
use comrak::{parse_document, format_html, ComrakOptions};
use comrak::nodes::{AstNode, NodeValue, NodeHtmlBlock};
use std::collections::HashMap;
use errors::*;
use svgbob::Grid;

mod errors {
    error_chain!{
    }
}

fn build_cells(text: &Vec<Vec<Option<&String>>>) -> String {
    let mut buff = String::new();
    for line in text{
        for l in line{
            match *l{
                Some(ref l) => buff.push_str(&format!("
{}
",l)),
                None => buff.push_str("

"),
            }
        }
    }
    buff
}

/// convert bob ascii diagrams to svg
fn bob_handler(s: &str, settings: &Settings) -> Result<String> {
    let now = std::time::SystemTime::now();
    let grid = Grid::from_str(s, &svgbob::Settings::compact());
    let (width, height) = grid.get_size();
    let svg = grid.get_svg();
    let text = grid.get_all_text();
    let cells = build_cells(&text);
    let content = format!("
{}
",width, height, cells);
    let lens = if settings.enable_lens{ format!("
{}
",content) } else { "".to_string() };
    let bob_container = format!("
{}{}
",width, height, svg, lens);
    println!("took bob handler: {:?}", now.elapsed());
    Ok(bob_container)
}

/// convert csv content into html table
fn csv_handler(s: &str, settings: &Settings) -> Result<String>{
    let now = std::time::SystemTime::now();
    let mut buff = String::new();
    let mut rdr = csv::Reader::from_string(s);
    buff.push_str("
");
    buff.push_str("
");
    for header in rdr.byte_headers(){
        buff.push_str("
");
        for h in header{
            buff.push_str(&format!("{}	", String::from_utf8(h).unwrap_or("".into())));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    buff.push_str("
");
    for record in rdr.byte_records().map(|r| r.unwrap()) {
        buff.push_str("
");
        for r in record{
            buff.push_str(&format!("{}	",String::from_utf8(r).unwrap_or("".into())));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    println!("csv handler took: {:?}", now.elapsed());
    Ok(buff)
}

pub struct Settings{
    enable_lens: bool,
}

impl Default for Settings{

    fn default() -> Self {
        Settings{
            enable_lens: false
        }
    }
}

pub fn parse(arg: &str) -> String {
    parse_with_settings(arg, &Settings::default())
}

pub fn parse_include_lens(arg: &str) -> String {
    parse_with_settings(arg, &Settings{enable_lens: true})
}

pub fn parse_with_settings(arg: &str, settings: &Settings) -> String{
    let now = std::time::SystemTime::now();
    let mut plugins:HashMap<String, Box<Fn(&str, &Settings)-> Result<String>>>  = HashMap::new();
    plugins.insert("bob".into(), Box::new(bob_handler));
    plugins.insert("csv".into(), Box::new(csv_handler));
    let html = parse_via_comrak(arg, &plugins, settings);
    println!("sponge down parse took: {:?}", now.elapsed());
    html
}

pub fn parse_bob(arg: &str) -> String{
    bob_handler(arg, &Settings::default()).unwrap()
}

pub fn parse_csv(arg: &str) -> Result<String> {
    csv_handler(arg, &Settings::default())
}

/// Plugin info, format:
/// [<selector>] <plugin_name>[@version][://<URI>]
/// example:
/// #table1 csv://data_file.csv
#[allow(dead_code)]
struct PluginInfo{
    selector: Option<String>,
    plugin_name: String,
    version: Option<String>,
    uri: Option<String>,
}

fn parse_via_comrak(arg: &str, plugins: &HashMap<String, Box<Fn(&str, &Settings) -> Result<String>>>, settings: &Settings)->String{

    // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
    let arena = Arena::new();
    let option = ComrakOptions {
        hardbreaks: true,
        github_pre_lang: true,
        width: 0,
        ext_strikethrough: true,
        ext_tagfilter: true,
        ext_table: true,
        ext_autolink: true,
        ext_tasklist: true,
        ext_superscript: false,
    };

    let root = parse_document(
        &arena,
        arg,
        &option);

    fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
        where F : Fn(&'a AstNode<'a>) {
        f(node);
        for c in node.children() {
            iter_nodes(c, f);
        }
    }

    iter_nodes(root, &|node| {
        let ref mut value = node.data.borrow_mut().value;
        let new_value = match value{
            &mut NodeValue::CodeBlock(ref codeblock) => {
                match plugins.get(&codeblock.info) {
                    Some(handler) => {
                        match handler(&codeblock.literal, settings){
                            Ok(out) => {
                                NodeValue::HtmlBlock(
                                    NodeHtmlBlock{
                                        literal: out,
                                        block_type: 0
                                    }
                                )
                            },
                            Err(_) => {
                                NodeValue::CodeBlock(codeblock.clone())
                            }
                        }
                    }
                    None => {
                        NodeValue::CodeBlock(codeblock.clone())
                    }
                }
            }
            _ => value.to_owned(),
        };
        *value = new_value;
    });

    let html: String = format_html(root, &ComrakOptions::default());
    html
}
<commit_msg>update to comrak 0.2.5<commit_after>//#![deny(warnings)]
#[macro_use]
extern crate error_chain;

extern crate svgbob;
extern crate csv;
extern crate comrak;
extern crate typed_arena;
use typed_arena::Arena;
use comrak::{parse_document, format_html, ComrakOptions};
use comrak::nodes::{AstNode, NodeValue, NodeHtmlBlock};
use std::collections::HashMap;
use errors::*;
use svgbob::Grid;

mod errors {
    error_chain!{
    }
}

fn build_cells(text: &Vec<Vec<Option<&String>>>) -> String {
    let mut buff = String::new();
    for line in text{
        for l in line{
            match *l{
                Some(ref l) => buff.push_str(&format!("
{}
",l)),
                None => buff.push_str("

"),
            }
        }
    }
    buff
}

/// convert bob ascii diagrams to svg
fn bob_handler(s: &str, settings: &Settings) -> Result<String> {
    let now = std::time::SystemTime::now();
    let grid = Grid::from_str(s, &svgbob::Settings::compact());
    let (width, height) = grid.get_size();
    let svg = grid.get_svg();
    let text = grid.get_all_text();
    let cells = build_cells(&text);
    let content = format!("
{}
",width, height, cells);
    let lens = if settings.enable_lens{ format!("
{}
",content) } else { "".to_string() };
    let bob_container = format!("
{}{}
",width, height, svg, lens);
    println!("took bob handler: {:?}", now.elapsed());
    Ok(bob_container)
}

/// convert csv content into html table
fn csv_handler(s: &str, settings: &Settings) -> Result<String>{
    let now = std::time::SystemTime::now();
    let mut buff = String::new();
    let mut rdr = csv::Reader::from_string(s);
    buff.push_str("
");
    buff.push_str("
");
    for header in rdr.byte_headers(){
        buff.push_str("
");
        for h in header{
            buff.push_str(&format!("{}	", String::from_utf8(h).unwrap_or("".into())));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    buff.push_str("
");
    for record in rdr.byte_records().map(|r| r.unwrap()) {
        buff.push_str("
");
        for r in record{
            buff.push_str(&format!("{}	",String::from_utf8(r).unwrap_or("".into())));
        }
        buff.push_str("
");
    }
    buff.push_str("
");
    buff.push_str("
");
    println!("csv handler took: {:?}", now.elapsed());
    Ok(buff)
}

pub struct Settings{
    enable_lens: bool,
}

impl Default for Settings{

    fn default() -> Self {
        Settings{
            enable_lens: false
        }
    }
}

pub fn parse(arg: &str) -> String {
    parse_with_settings(arg, &Settings::default())
}

pub fn parse_include_lens(arg: &str) -> String {
    parse_with_settings(arg, &Settings{enable_lens: true})
}

pub fn parse_with_settings(arg: &str, settings: &Settings) -> String{
    let now = std::time::SystemTime::now();
    let mut plugins:HashMap<String, Box<Fn(&str, &Settings)-> Result<String>>>  = HashMap::new();
    plugins.insert("bob".into(), Box::new(bob_handler));
    plugins.insert("csv".into(), Box::new(csv_handler));
    let html = parse_via_comrak(arg, &plugins, settings);
    println!("sponge down parse took: {:?}", now.elapsed());
    html
}

pub fn parse_bob(arg: &str) -> String{
    bob_handler(arg, &Settings::default()).unwrap()
}

pub fn parse_csv(arg: &str) -> Result<String> {
    csv_handler(arg, &Settings::default())
}

/// Plugin info, format:
/// [<selector>] <plugin_name>[@version][://<URI>]
/// example:
/// #table1 csv://data_file.csv
#[allow(dead_code)]
struct PluginInfo{
    selector: Option<String>,
    plugin_name: String,
    version: Option<String>,
    uri: Option<String>,
}

fn parse_via_comrak(arg: &str, plugins: &HashMap<String, Box<Fn(&str, &Settings) -> Result<String>>>, settings: &Settings)->String{

    // The returned nodes are created in the supplied Arena, and are bound by its lifetime.
    let arena = Arena::new();
    let option = ComrakOptions {
        hardbreaks: true,
        github_pre_lang: true,
        width: 0,
        ext_strikethrough: true,
        ext_tagfilter: true,
        ext_table: true,
        ext_autolink: true,
        ext_tasklist: true,
        ext_superscript: false,
        ext_header_ids: None,
        ext_footnotes: true,
    };

    let root = parse_document(
        &arena,
        arg,
        &option);

    fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
        where F : Fn(&'a AstNode<'a>) {
        f(node);
        for c in node.children() {
            iter_nodes(c, f);
        }
    }

    iter_nodes(root, &|node| {
        let ref mut value = node.data.borrow_mut().value;
        let new_value = match value{
            &mut NodeValue::CodeBlock(ref codeblock) => {
                let codeblock_info = String::from_utf8(codeblock.info.to_owned()).unwrap();
                match plugins.get(&codeblock_info) {
                    Some(handler) => {
                        let codeblock_literal = String::from_utf8(codeblock.literal.to_owned()).unwrap();
                        match handler(&codeblock_literal, settings){
                            Ok(out) => {
                                NodeValue::HtmlBlock(
                                    NodeHtmlBlock{
                                        literal: out.as_bytes().to_vec(),
                                        block_type: 0
                                    }
                                )
                            },
                            Err(_) => {
                                NodeValue::CodeBlock(codeblock.clone())
                            }
                        }
                    }
                    None => {
                        NodeValue::CodeBlock(codeblock.clone())
                    }
                }
            }
            _ => value.to_owned(),
        };
        *value = new_value;
    });

    let mut html = vec![];

    format_html(root, &ComrakOptions::default(), &mut html);
    String::from_utf8(html).unwrap()
}
<|endoftext|>