<commit_before>use gl;
use gl::types::*;
use texture::{Texture2dBinder, TextureCubeMapBinder};
use uniform_data::{UniformDatum, UniformDatumType, UniformPrimitiveType};
use types::GLError;

unsafe fn _active_texture(idx: u32) {
    gl::ActiveTexture(gl::TEXTURE0 + (idx as GLenum));
    dbg_gl_error! {
        GLError::InvalidEnum => "`texture` is out of bounds (expected to be GL_TEXTUREi, 0 <= i < GL_MAX_TEXTURE_IMAGE_UNITS)",
        _ => "Unknown error"
    }
}

pub trait TextureUnit {
    fn idx() -> u32;

    fn active(&mut self) -> TextureUnitBinding {
        unsafe {
            _active_texture(Self::idx());
            TextureUnitBinding::current_at_idx(Self::idx())
        }
    }
}

// TODO: Use a macro, or const generic parameters:
// https://github.com/rust-lang/rfcs/issues/273
// https://github.com/rust-lang/rfcs/issues/1038
pub struct TextureUnit0;
pub struct TextureUnit1;
pub struct TextureUnit2;
pub struct TextureUnit3;
pub struct TextureUnit4;
pub struct TextureUnit5;
pub struct TextureUnit6;
pub struct TextureUnit7;

impl TextureUnit for TextureUnit0 { fn idx() -> u32 { 0 } }
impl TextureUnit for TextureUnit1 { fn idx() -> u32 { 1 } }
impl TextureUnit for TextureUnit2 { fn idx() -> u32 { 2 } }
impl TextureUnit for TextureUnit3 { fn idx() -> u32 { 3 } }
impl TextureUnit for TextureUnit4 { fn idx() -> u32 { 4 } }
impl TextureUnit for TextureUnit5 { fn idx() -> u32 { 5 } }
impl TextureUnit for TextureUnit6 { fn idx() -> u32 { 6 } }
impl TextureUnit for TextureUnit7 { fn idx() -> u32 { 7 } }

// NOTE: Ensure the number of each texture unit matches its index in the tuple
// TODO: Use macros + integer-level types to refactor this
pub struct TextureUnitsOf<T0, T1, T2, T3, T4, T5, T6, T7>(pub T0,
                                                          pub T1,
                                                          pub T2,
                                                          pub T3,
                                                          pub T4,
                                                          pub T5,
                                                          pub T6,
                                                          pub T7);

pub type TextureUnits = TextureUnitsOf<TextureUnit0,
                                       TextureUnit1,
                                       TextureUnit2,
                                       TextureUnit3,
                                       TextureUnit4,
                                       TextureUnit5,
                                       TextureUnit6,
                                       TextureUnit7>;

impl<T0, T1, T2, T3, T4, T5, T6, T7> TextureUnitsOf<T0,
                                                    T1,
                                                    T2,
                                                    T3,
                                                    T4,
                                                    T5,
                                                    T6,
                                                    T7>
{
    pub unsafe fn current() -> TextureUnits {
        TextureUnitsOf(TextureUnit0,
                       TextureUnit1,
                       TextureUnit2,
                       TextureUnit3,
                       TextureUnit4,
                       TextureUnit5,
                       TextureUnit6,
                       TextureUnit7)
    }

    pub unsafe fn active_nth(&self, idx: u32) -> TextureUnitBinding {
        _active_texture(idx);
        TextureUnitBinding::current_at_idx(idx)
    }
}

pub struct TextureUnitBinding {
    idx: u32,
    pub texture_2d: Texture2dBinder,
    pub texture_cube_map: TextureCubeMapBinder
}

impl TextureUnitBinding {
    unsafe fn current_at_idx(idx: u32) -> Self {
        TextureUnitBinding {
            idx: idx,
            texture_2d: Texture2dBinder,
            texture_cube_map: TextureCubeMapBinder
        }
    }

    pub fn gl_idx(&self) -> u32 {
        self.idx
    }

    pub fn sampler(&self) -> TextureSampler {
        TextureSampler { idx: self.idx as i32 }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct TextureSampler { idx: i32 }

unsafe impl UniformDatum for TextureSampler {
    fn uniform_datum_type() -> UniformDatumType {
        UniformDatumType::Vec1(UniformPrimitiveType::Int)
    }
}

#[macro_export]
macro_rules! bind_texture_cube_map {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_cube_map.bind($texture)
    }
}

#[macro_export]
macro_rules! bind_texture_2d {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_2d.bind($texture)
    }
}
<commit_msg>Add `TextureUnitOf.split_at*` methods<commit_after>use std::borrow::{Borrow, BorrowMut};
use gl;
use gl::types::*;
use texture::{Texture2dBinder, TextureCubeMapBinder};
use uniform_data::{UniformDatum, UniformDatumType, UniformPrimitiveType};
use types::GLError;

unsafe fn _active_texture(idx: u32) {
    gl::ActiveTexture(gl::TEXTURE0 + (idx as GLenum));
    dbg_gl_error! {
        GLError::InvalidEnum => "`texture` is out of bounds (expected to be GL_TEXTUREi, 0 <= i < GL_MAX_TEXTURE_IMAGE_UNITS)",
        _ => "Unknown error"
    }
}

pub trait TextureUnit {
    fn idx() -> u32;

    fn active(&mut self) -> TextureUnitBinding {
        unsafe {
            _active_texture(Self::idx());
            TextureUnitBinding::current_at_idx(Self::idx())
        }
    }
}

// TODO: Use a macro, or const generic parameters:
// https://github.com/rust-lang/rfcs/issues/273
// https://github.com/rust-lang/rfcs/issues/1038
pub struct TextureUnit0;
pub struct TextureUnit1;
pub struct TextureUnit2;
pub struct TextureUnit3;
pub struct TextureUnit4;
pub struct TextureUnit5;
pub struct TextureUnit6;
pub struct TextureUnit7;

impl TextureUnit for TextureUnit0 { fn idx() -> u32 { 0 } }
impl TextureUnit for TextureUnit1 { fn idx() -> u32 { 1 } }
impl TextureUnit for TextureUnit2 { fn idx() -> u32 { 2 } }
impl TextureUnit for TextureUnit3 { fn idx() -> u32 { 3 } }
impl TextureUnit for TextureUnit4 { fn idx() -> u32 { 4 } }
impl TextureUnit for TextureUnit5 { fn idx() -> u32 { 5 } }
impl TextureUnit for TextureUnit6 { fn idx() -> u32 { 6 } }
impl TextureUnit for TextureUnit7 { fn idx() -> u32 { 7 } }

// NOTE: Ensure the number of each texture unit matches its index in the tuple
// TODO: Use macros + integer-level types to refactor this
pub struct TextureUnitsOf<T0, T1, T2, T3, T4, T5, T6, T7>(pub T0,
                                                          pub T1,
                                                          pub T2,
                                                          pub T3,
                                                          pub T4,
                                                          pub T5,
                                                          pub T6,
                                                          pub T7);

pub type TextureUnits = TextureUnitsOf<TextureUnit0,
                                       TextureUnit1,
                                       TextureUnit2,
                                       TextureUnit3,
                                       TextureUnit4,
                                       TextureUnit5,
                                       TextureUnit6,
                                       TextureUnit7>;

impl<T0, T1, T2, T3, T4, T5, T6, T7> TextureUnitsOf<T0,
                                                    T1,
                                                    T2,
                                                    T3,
                                                    T4,
                                                    T5,
                                                    T6,
                                                    T7>
{
    pub unsafe fn current() -> TextureUnits {
        TextureUnitsOf(TextureUnit0,
                       TextureUnit1,
                       TextureUnit2,
                       TextureUnit3,
                       TextureUnit4,
                       TextureUnit5,
                       TextureUnit6,
                       TextureUnit7)
    }

    pub fn split_at_0<'a>(&'a self)
        -> (
            &'a TextureUnit0,
            TextureUnitsOf<(),
                           &'a T1,
                           &'a T2,
                           &'a T3,
                           &'a T4,
                           &'a T5,
                           &'a T6,
                           &'a T7>
        )
        where T0: Borrow<TextureUnit0>
    {
        (
            self.0.borrow(),
            TextureUnitsOf((),
                           &self.1,
                           &self.2,
                           &self.3,
                           &self.4,
                           &self.5,
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_0_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit0,
            TextureUnitsOf<(),
                           &'a mut T1,
                           &'a mut T2,
                           &'a mut T3,
                           &'a mut T4,
                           &'a mut T5,
                           &'a mut T6,
                           &'a mut T7>
        )
        where T0: BorrowMut<TextureUnit0>
    {
        (
            self.0.borrow_mut(),
            TextureUnitsOf((),
                           &mut self.1,
                           &mut self.2,
                           &mut self.3,
                           &mut self.4,
                           &mut self.5,
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_1<'a>(&'a self)
        -> (
            &'a TextureUnit1,
            TextureUnitsOf<&'a T0,
                           (),
                           &'a T2,
                           &'a T3,
                           &'a T4,
                           &'a T5,
                           &'a T6,
                           &'a T7>
        )
        where T1: Borrow<TextureUnit1>
    {
        (
            self.1.borrow(),
            TextureUnitsOf(&self.0,
                           (),
                           &self.2,
                           &self.3,
                           &self.4,
                           &self.5,
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_1_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit1,
            TextureUnitsOf<&'a mut T0,
                           (),
                           &'a mut T2,
                           &'a mut T3,
                           &'a mut T4,
                           &'a mut T5,
                           &'a mut T6,
                           &'a mut T7>
        )
        where T1: BorrowMut<TextureUnit1>
    {
        (
            self.1.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           (),
                           &mut self.2,
                           &mut self.3,
                           &mut self.4,
                           &mut self.5,
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_2<'a>(&'a self)
        -> (
            &'a TextureUnit2,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           (),
                           &'a T3,
                           &'a T4,
                           &'a T5,
                           &'a T6,
                           &'a T7>
        )
        where T2: Borrow<TextureUnit2>
    {
        (
            self.2.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           (),
                           &self.3,
                           &self.4,
                           &self.5,
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_2_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit2,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           (),
                           &'a mut T3,
                           &'a mut T4,
                           &'a mut T5,
                           &'a mut T6,
                           &'a mut T7>
        )
        where T2: BorrowMut<TextureUnit2>
    {
        (
            self.2.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           (),
                           &mut self.3,
                           &mut self.4,
                           &mut self.5,
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_3<'a>(&'a self)
        -> (
            &'a TextureUnit3,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           &'a T2,
                           (),
                           &'a T4,
                           &'a T5,
                           &'a T6,
                           &'a T7>
        )
        where T3: Borrow<TextureUnit3>
    {
        (
            self.3.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           &self.2,
                           (),
                           &self.4,
                           &self.5,
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_3_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit3,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           &'a mut T2,
                           (),
                           &'a mut T4,
                           &'a mut T5,
                           &'a mut T6,
                           &'a mut T7>
        )
        where T3: BorrowMut<TextureUnit3>
    {
        (
            self.3.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           &mut self.2,
                           (),
                           &mut self.4,
                           &mut self.5,
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_4<'a>(&'a self)
        -> (
            &'a TextureUnit4,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           &'a T2,
                           &'a T3,
                           (),
                           &'a T5,
                           &'a T6,
                           &'a T7>
        )
        where T4: Borrow<TextureUnit4>
    {
        (
            self.4.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           &self.2,
                           &self.3,
                           (),
                           &self.5,
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_4_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit4,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           &'a mut T2,
                           &'a mut T3,
                           (),
                           &'a mut T5,
                           &'a mut T6,
                           &'a mut T7>
        )
        where T4: BorrowMut<TextureUnit4>
    {
        (
            self.4.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           &mut self.2,
                           &mut self.3,
                           (),
                           &mut self.5,
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_5<'a>(&'a self)
        -> (
            &'a TextureUnit5,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           &'a T2,
                           &'a T3,
                           &'a T4,
                           (),
                           &'a T6,
                           &'a T7>
        )
        where T5: Borrow<TextureUnit5>
    {
        (
            self.5.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           &self.2,
                           &self.3,
                           &self.4,
                           (),
                           &self.6,
                           &self.7)
        )
    }

    pub fn split_at_5_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit5,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           &'a mut T2,
                           &'a mut T3,
                           &'a mut T4,
                           (),
                           &'a mut T6,
                           &'a mut T7>
        )
        where T5: BorrowMut<TextureUnit5>
    {
        (
            self.5.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           &mut self.2,
                           &mut self.3,
                           &mut self.4,
                           (),
                           &mut self.6,
                           &mut self.7)
        )
    }

    pub fn split_at_6<'a>(&'a self)
        -> (
            &'a TextureUnit6,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           &'a T2,
                           &'a T3,
                           &'a T4,
                           &'a T5,
                           (),
                           &'a T7>
        )
        where T6: Borrow<TextureUnit6>
    {
        (
            self.6.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           &self.2,
                           &self.3,
                           &self.4,
                           &self.5,
                           (),
                           &self.7)
        )
    }

    pub fn split_at_6_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit6,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           &'a mut T2,
                           &'a mut T3,
                           &'a mut T4,
                           &'a mut T5,
                           (),
                           &'a mut T7>
        )
        where T6: BorrowMut<TextureUnit6>
    {
        (
            self.6.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           &mut self.2,
                           &mut self.3,
                           &mut self.4,
                           &mut self.5,
                           (),
                           &mut self.7)
        )
    }

    pub fn split_at_7<'a>(&'a self)
        -> (
            &'a TextureUnit7,
            TextureUnitsOf<&'a T0,
                           &'a T1,
                           &'a T2,
                           &'a T3,
                           &'a T4,
                           &'a T5,
                           &'a T6,
                           ()>
        )
        where T7: Borrow<TextureUnit7>
    {
        (
            self.7.borrow(),
            TextureUnitsOf(&self.0,
                           &self.1,
                           &self.2,
                           &self.3,
                           &self.4,
                           &self.5,
                           &self.6,
                           ())
        )
    }

    pub fn split_at_7_mut<'a>(&'a mut self)
        -> (
            &'a mut TextureUnit7,
            TextureUnitsOf<&'a mut T0,
                           &'a mut T1,
                           &'a mut T2,
                           &'a mut T3,
                           &'a mut T4,
                           &'a mut T5,
                           &'a mut T6,
                           ()>
        )
        where T7: BorrowMut<TextureUnit7>
    {
        (
            self.7.borrow_mut(),
            TextureUnitsOf(&mut self.0,
                           &mut self.1,
                           &mut self.2,
                           &mut self.3,
                           &mut self.4,
                           &mut self.5,
                           &mut self.6,
                           ())
        )
    }

    pub unsafe fn active_nth(&self, idx: u32) -> TextureUnitBinding {
        _active_texture(idx);
        TextureUnitBinding::current_at_idx(idx)
    }
}

pub struct TextureUnitBinding {
    idx: u32,
    pub texture_2d: Texture2dBinder,
    pub texture_cube_map: TextureCubeMapBinder
}

impl TextureUnitBinding {
    unsafe fn current_at_idx(idx: u32) -> Self {
        TextureUnitBinding {
            idx: idx,
            texture_2d: Texture2dBinder,
            texture_cube_map: TextureCubeMapBinder
        }
    }

    pub fn gl_idx(&self) -> u32 {
        self.idx
    }

    pub fn sampler(&self) -> TextureSampler {
        TextureSampler { idx: self.idx as i32 }
    }
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct TextureSampler { idx: i32 }

unsafe impl UniformDatum for TextureSampler {
    fn uniform_datum_type() -> UniformDatumType {
        UniformDatumType::Vec1(UniformPrimitiveType::Int)
    }
}

#[macro_export]
macro_rules! bind_texture_cube_map {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_cube_map.bind($texture)
    }
}

#[macro_export]
macro_rules! bind_texture_2d {
    ($gl_tex_unit:expr, $texture:expr) => {
        $gl_tex_unit.texture_2d.bind($texture)
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![license = "MIT/ASL2"]
#![crate_name = "rust-crypto"]

#![feature(asm)]
#![feature(macro_rules)]
#![feature(simd)]
#![feature(slicing_syntax)]

extern crate serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod digest;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<commit_msg>Fix unused attribute warning regarding the license attribute<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![crate_name = "rust-crypto"]

#![feature(asm)]
#![feature(macro_rules)]
#![feature(simd)]
#![feature(slicing_syntax)]

extern crate serialize;
extern crate time;
#[cfg(test)] extern crate test;

pub mod aes;
pub mod aessafe;
pub mod bcrypt;
pub mod bcrypt_pbkdf;
pub mod blake2b;
pub mod blockmodes;
pub mod blowfish;
pub mod buffer;
pub mod chacha20;
mod cryptoutil;
pub mod digest;
pub mod fortuna;
pub mod ghash;
pub mod hmac;
pub mod mac;
pub mod md5;
pub mod pbkdf2;
pub mod poly1305;
pub mod rc4;
pub mod ripemd160;
pub mod salsa20;
pub mod scrypt;
pub mod sha1;
pub mod sha2;
pub mod symmetriccipher;
pub mod util;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod aesni;
<|endoftext|>


<commit_before>use termbox_simple::Termbox;
use term_input::Key;

use std::convert::From;
use std::rc::Rc;

use time::Tm;
use time;

use config::Style;
use config;
use trie::Trie;
use tui::exit_dialogue::ExitDialogue;
use tui::msg_area::MsgArea;
use tui::termbox;
use tui::text_field::TextField;
use tui::widget::{WidgetRet, Widget};

/// A messaging screen is just a text field to type messages and msg area to
/// show incoming/sent messages.
pub struct MessagingUI {
    /// Incoming and sent messages appear
    msg_area: MsgArea,

    /// Stacked user input fields. Topmost one handles keypresses.
    input_field: Vec<Box<Widget>>,

    width: i32,
    height: i32,

    // All nicks in the channel. Need to keep this up-to-date to be able to
    // properly highlight mentions.
    //
    // Rc to be able to share with dynamic messages.
    nicks: Rc<Trie>,

    current_nick: Option<Rc<String>>,
    draw_current_nick: bool,

    last_activity_line: Option<ActivityLine>,
    last_activity_ts: Option<Timestamp>,
}

/// Like `time::Tm`, but we only care about hour and minute parts.
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct Timestamp {
    hour: i32,
    min: i32,
}

impl Timestamp {
    pub fn now() -> Timestamp {
        Timestamp::from(time::now())
    }

    fn stamp(&self, msg_area: &mut MsgArea) {
        msg_area.set_style(config::TIMESTAMP);
        msg_area.add_text(&format!("{:02}:{:02} ", self.hour, self.min));
    }
}

impl From<Tm> for Timestamp {
    fn from(tm: Tm) -> Timestamp {
        Timestamp { hour: tm.tm_hour, min: tm.tm_min }
    }
}

/// An activity line is just a line that we update on joins / leaves /
/// disconnects. We group activities that happen in the same minute to avoid
/// redundantly showing lines.
struct ActivityLine {
    ts: Timestamp,
    line_idx: usize,
}

impl MessagingUI {
    pub fn new(width : i32, height : i32) -> MessagingUI {
        MessagingUI {
            msg_area: MsgArea::new(width, height - 1),
            input_field: vec![Box::new(TextField::new(width))],
            width: width,
            height: height,
            nicks: Rc::new(Trie::new()),
            current_nick: None,
            draw_current_nick: true,
            last_activity_line: None,
            last_activity_ts: None,
        }
    }

    pub fn set_nick(&mut self, nick: Rc<String>) {
        self.current_nick = Some(nick);
    }

    pub fn get_nick(&self) -> Option<Rc<String>> {
        self.current_nick.clone()
    }

    pub fn draw(&self, tb: &mut Termbox, pos_x: i32, pos_y: i32) {
        self.msg_area.draw(tb, pos_x, pos_y);

        if let &Some(ref nick) = &self.current_nick {
            if self.draw_current_nick {
                let nick_color = self.get_nick_color(nick);
                let style = Style { fg: nick_color as u16, bg: config::USER_MSG.bg };
                termbox::print_chars(
                    tb,
                    pos_x,
                    pos_y + self.height - 1,
                    style,
                    &mut nick.chars());
                tb.change_cell(
                    pos_x + nick.len() as i32,
                    pos_y + self.height - 1,
                    ':',
                    config::USER_MSG.fg | config::TB_BOLD,
                    config::USER_MSG.bg);
                self.input_field.draw(
                    tb,
                    pos_x + nick.len() as i32 + 2,
                    pos_y + self.height - 1);
            } else {
                self.input_field.draw(tb, pos_x, pos_y + self.height - 1);
            }
        } else {
            self.input_field.draw(tb, pos_x, pos_y + self.height - 1);
        }
    }

    pub fn keypressed(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Ctrl('c') => {
                self.toggle_exit_dialogue();
                WidgetRet::KeyHandled
            },

            Key::Ctrl('u') => {
                self.msg_area.page_up();
                WidgetRet::KeyHandled
            },

            Key::Ctrl('d') => {
                self.msg_area.page_down();
                WidgetRet::KeyHandled
            },

            Key::PageUp => {
                self.msg_area.page_up();
                WidgetRet::KeyHandled
            },

            Key::PageDown => {
                self.msg_area.page_down();
                WidgetRet::KeyHandled
            },

            Key::ShiftUp => {
                self.msg_area.scroll_up();
                WidgetRet::KeyHandled
            },

            Key::ShiftDown => {
                self.msg_area.scroll_down();
                WidgetRet::KeyHandled
            },

            Key::Tab => {
                self.input_field.event(Box::new(self.nicks.clone()));
                WidgetRet::KeyHandled
            },

            key => {
                match self.input_field.keypressed(key) {
                    WidgetRet::Remove => {
                        self.input_field.pop();
                        WidgetRet::KeyHandled
                    },
                    ret => ret,
                }
            },
        }
    }

    pub fn resize(&mut self, width: i32, height: i32) {
        self.width = width;
        self.height = height;
        self.msg_area.resize(width, height - 1);

        let nick_width = match &self.current_nick {
            &None =>
                0,
            &Some(ref rc) =>
                // +2 for ": "
                rc.len() as i32 + 2,
        };

        self.draw_current_nick =
            (nick_width as f32) <= (width as f32) * (30f32 / 100f32);

        let widget_width =
            if self.draw_current_nick { width - nick_width } else { width };

        for w in &mut self.input_field {
            w.resize(widget_width, 1);
        }
    }

    fn toggle_exit_dialogue(&mut self) {
        assert!(self.input_field.len() > 0);
        // FIXME: This is a bit too fragile I think. Since we only stack an exit
        // dialogue on top of the input field at the moment, checking the len()
        // is fine. If we decide to stack more stuff it'll break.
        if self.input_field.len() == 1 {
            self.input_field.push(Box::new(ExitDialogue::new(self.width)));
        } else {
            self.input_field.pop();
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Adding new messages

impl MessagingUI {

    fn add_timestamp(&mut self, ts: Timestamp) {
        if let Some(ts_) = self.last_activity_ts {
            if ts_ != ts {
                ts.stamp(&mut self.msg_area);
            }
        } else {
            ts.stamp(&mut self.msg_area);

        }
        self.last_activity_ts = Some(ts);
    }

    pub fn show_topic(&mut self, topic: &str, ts: Timestamp) {
        self.add_timestamp(ts);

        self.msg_area.set_style(config::TOPIC);
        self.msg_area.add_text(&format!("Channel topic is: \"{}\"", topic));

        self.msg_area.flush_line();
    }

    pub fn add_client_err_msg(&mut self, msg : &str) {
        self.reset_activity_line();

        self.msg_area.set_style(config::ERR_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_client_msg(&mut self, msg : &str) {
        self.reset_activity_line();

        self.msg_area.set_style(config::USER_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
        self.reset_activity_line();
    }

    pub fn add_privmsg(&mut self, sender: &str, msg: &str, ts: Timestamp, higlight: bool) {
        self.reset_activity_line();
        self.add_timestamp(ts);

        {
            let nick_color = self.get_nick_color(sender);
            let style = Style { fg: nick_color as u16, bg: config::USER_MSG.bg };
            self.msg_area.set_style(style);
            self.msg_area.add_text(sender);
        }

        self.msg_area.set_style(Style { fg: config::USER_MSG.fg | config::TB_BOLD, bg: config::USER_MSG.bg });
        self.msg_area.add_text(": ");

        self.msg_area.set_style(
            if higlight {
                config::HIGHLIGHT
            } else {
                config::USER_MSG
            });

        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_msg(&mut self, msg: &str, ts: Timestamp) {
        self.reset_activity_line();

        self.add_timestamp(ts);
        self.msg_area.set_style(config::USER_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_err_msg(&mut self, msg: &str, ts: Timestamp) {
        self.reset_activity_line();

        self.add_timestamp(ts);
        self.msg_area.set_style(config::ERR_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    fn get_nick_color(&self, sender: &str) -> u8 {
        // Anything works as long as it's fast
        let mut hash: usize = 5381;
        for c in sender.chars() {
            hash = hash * 33 + (c as usize);
        }
        config::NICK_COLORS[hash % config::NICK_COLORS.len()]
    }
}

////////////////////////////////////////////////////////////////////////////////
// Keeping nick list up-to-date

impl MessagingUI {
    pub fn join(&mut self, nick: &str, ts: Option<Timestamp>) {
        Rc::get_mut(&mut self.nicks).unwrap().insert(nick);

        if let Some(ts) = ts {
            let line_idx = self.get_activity_line_idx(ts);
            self.msg_area.modify_line(line_idx, |line| {
                line.set_style(config::JOIN);
                line.add_char('+');
                line.add_text(nick);
                line.add_char(' ');
            });
        }
    }

    pub fn part(&mut self, nick: &str, ts: Option<Timestamp>) {
        Rc::get_mut(&mut self.nicks).unwrap().remove(nick);

        if let Some(ts) = ts {
            let line_idx = self.get_activity_line_idx(ts);
            self.msg_area.modify_line(line_idx, |line| {
                line.set_style(config::PART);
                line.add_char('-');
                line.add_text(nick);
                line.add_char(' ');
            });
        }
    }

    pub fn nick(&mut self, old_nick: &str, new_nick: &str, ts: Timestamp) {
        Rc::get_mut(&mut self.nicks).unwrap().remove(old_nick);
        Rc::get_mut(&mut self.nicks).unwrap().insert(new_nick);

        let line_idx = self.get_activity_line_idx(ts);
        self.msg_area.modify_line(line_idx, |line| {
            line.set_style(config::NICK);
            line.add_text(old_nick);
            line.add_text("->");
            line.add_text(new_nick);
            line.add_char(' ');
        });
    }

    pub fn has_nick(&self, nick : &str) -> bool {
        self.nicks.contains(nick)
    }

    fn reset_activity_line(&mut self) {
        self.last_activity_line = None;
    }

    fn get_activity_line_idx(&mut self, ts: Timestamp) -> usize {
        // borrow checker strikes again
        if let Some(ref mut l) = self.last_activity_line {
            if l.ts == ts {
                return l.line_idx;
            }
        }

        self.add_timestamp(ts);
        let line_idx = self.msg_area.flush_line();
        self.last_activity_line = Some(ActivityLine {
            ts: ts,
            line_idx: line_idx,
        });
        line_idx
    }
}
<commit_msg>Use wrapping add/mul in string hash function to avoid debug build failures<commit_after>use termbox_simple::Termbox;
use term_input::Key;

use std::convert::From;
use std::rc::Rc;

use time::Tm;
use time;

use config::Style;
use config;
use trie::Trie;
use tui::exit_dialogue::ExitDialogue;
use tui::msg_area::MsgArea;
use tui::termbox;
use tui::text_field::TextField;
use tui::widget::{WidgetRet, Widget};

/// A messaging screen is just a text field to type messages and msg area to
/// show incoming/sent messages.
pub struct MessagingUI {
    /// Incoming and sent messages appear
    msg_area: MsgArea,

    /// Stacked user input fields. Topmost one handles keypresses.
    input_field: Vec<Box<Widget>>,

    width: i32,
    height: i32,

    // All nicks in the channel. Need to keep this up-to-date to be able to
    // properly highlight mentions.
    //
    // Rc to be able to share with dynamic messages.
    nicks: Rc<Trie>,

    current_nick: Option<Rc<String>>,
    draw_current_nick: bool,

    last_activity_line: Option<ActivityLine>,
    last_activity_ts: Option<Timestamp>,
}

/// Like `time::Tm`, but we only care about hour and minute parts.
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct Timestamp {
    hour: i32,
    min: i32,
}

impl Timestamp {
    pub fn now() -> Timestamp {
        Timestamp::from(time::now())
    }

    fn stamp(&self, msg_area: &mut MsgArea) {
        msg_area.set_style(config::TIMESTAMP);
        msg_area.add_text(&format!("{:02}:{:02} ", self.hour, self.min));
    }
}

impl From<Tm> for Timestamp {
    fn from(tm: Tm) -> Timestamp {
        Timestamp { hour: tm.tm_hour, min: tm.tm_min }
    }
}

/// An activity line is just a line that we update on joins / leaves /
/// disconnects. We group activities that happen in the same minute to avoid
/// redundantly showing lines.
struct ActivityLine {
    ts: Timestamp,
    line_idx: usize,
}

impl MessagingUI {
    pub fn new(width : i32, height : i32) -> MessagingUI {
        MessagingUI {
            msg_area: MsgArea::new(width, height - 1),
            input_field: vec![Box::new(TextField::new(width))],
            width: width,
            height: height,
            nicks: Rc::new(Trie::new()),
            current_nick: None,
            draw_current_nick: true,
            last_activity_line: None,
            last_activity_ts: None,
        }
    }

    pub fn set_nick(&mut self, nick: Rc<String>) {
        self.current_nick = Some(nick);
    }

    pub fn get_nick(&self) -> Option<Rc<String>> {
        self.current_nick.clone()
    }

    pub fn draw(&self, tb: &mut Termbox, pos_x: i32, pos_y: i32) {
        self.msg_area.draw(tb, pos_x, pos_y);

        if let &Some(ref nick) = &self.current_nick {
            if self.draw_current_nick {
                let nick_color = self.get_nick_color(nick);
                let style = Style { fg: nick_color as u16, bg: config::USER_MSG.bg };
                termbox::print_chars(
                    tb,
                    pos_x,
                    pos_y + self.height - 1,
                    style,
                    &mut nick.chars());
                tb.change_cell(
                    pos_x + nick.len() as i32,
                    pos_y + self.height - 1,
                    ':',
                    config::USER_MSG.fg | config::TB_BOLD,
                    config::USER_MSG.bg);
                self.input_field.draw(
                    tb,
                    pos_x + nick.len() as i32 + 2,
                    pos_y + self.height - 1);
            } else {
                self.input_field.draw(tb, pos_x, pos_y + self.height - 1);
            }
        } else {
            self.input_field.draw(tb, pos_x, pos_y + self.height - 1);
        }
    }

    pub fn keypressed(&mut self, key : Key) -> WidgetRet {
        match key {
            Key::Ctrl('c') => {
                self.toggle_exit_dialogue();
                WidgetRet::KeyHandled
            },

            Key::Ctrl('u') => {
                self.msg_area.page_up();
                WidgetRet::KeyHandled
            },

            Key::Ctrl('d') => {
                self.msg_area.page_down();
                WidgetRet::KeyHandled
            },

            Key::PageUp => {
                self.msg_area.page_up();
                WidgetRet::KeyHandled
            },

            Key::PageDown => {
                self.msg_area.page_down();
                WidgetRet::KeyHandled
            },

            Key::ShiftUp => {
                self.msg_area.scroll_up();
                WidgetRet::KeyHandled
            },

            Key::ShiftDown => {
                self.msg_area.scroll_down();
                WidgetRet::KeyHandled
            },

            Key::Tab => {
                self.input_field.event(Box::new(self.nicks.clone()));
                WidgetRet::KeyHandled
            },

            key => {
                match self.input_field.keypressed(key) {
                    WidgetRet::Remove => {
                        self.input_field.pop();
                        WidgetRet::KeyHandled
                    },
                    ret => ret,
                }
            },
        }
    }

    pub fn resize(&mut self, width: i32, height: i32) {
        self.width = width;
        self.height = height;
        self.msg_area.resize(width, height - 1);

        let nick_width = match &self.current_nick {
            &None =>
                0,
            &Some(ref rc) =>
                // +2 for ": "
                rc.len() as i32 + 2,
        };

        self.draw_current_nick =
            (nick_width as f32) <= (width as f32) * (30f32 / 100f32);

        let widget_width =
            if self.draw_current_nick { width - nick_width } else { width };

        for w in &mut self.input_field {
            w.resize(widget_width, 1);
        }
    }

    fn toggle_exit_dialogue(&mut self) {
        assert!(self.input_field.len() > 0);
        // FIXME: This is a bit too fragile I think. Since we only stack an exit
        // dialogue on top of the input field at the moment, checking the len()
        // is fine. If we decide to stack more stuff it'll break.
        if self.input_field.len() == 1 {
            self.input_field.push(Box::new(ExitDialogue::new(self.width)));
        } else {
            self.input_field.pop();
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
// Adding new messages

impl MessagingUI {

    fn add_timestamp(&mut self, ts: Timestamp) {
        if let Some(ts_) = self.last_activity_ts {
            if ts_ != ts {
                ts.stamp(&mut self.msg_area);
            }
        } else {
            ts.stamp(&mut self.msg_area);

        }
        self.last_activity_ts = Some(ts);
    }

    pub fn show_topic(&mut self, topic: &str, ts: Timestamp) {
        self.add_timestamp(ts);

        self.msg_area.set_style(config::TOPIC);
        self.msg_area.add_text(&format!("Channel topic is: \"{}\"", topic));

        self.msg_area.flush_line();
    }

    pub fn add_client_err_msg(&mut self, msg : &str) {
        self.reset_activity_line();

        self.msg_area.set_style(config::ERR_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_client_msg(&mut self, msg : &str) {
        self.reset_activity_line();

        self.msg_area.set_style(config::USER_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
        self.reset_activity_line();
    }

    pub fn add_privmsg(&mut self, sender: &str, msg: &str, ts: Timestamp, higlight: bool) {
        self.reset_activity_line();
        self.add_timestamp(ts);

        {
            let nick_color = self.get_nick_color(sender);
            let style = Style { fg: nick_color as u16, bg: config::USER_MSG.bg };
            self.msg_area.set_style(style);
            self.msg_area.add_text(sender);
        }

        self.msg_area.set_style(Style { fg: config::USER_MSG.fg | config::TB_BOLD, bg: config::USER_MSG.bg });
        self.msg_area.add_text(": ");

        self.msg_area.set_style(
            if higlight {
                config::HIGHLIGHT
            } else {
                config::USER_MSG
            });

        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_msg(&mut self, msg: &str, ts: Timestamp) {
        self.reset_activity_line();

        self.add_timestamp(ts);
        self.msg_area.set_style(config::USER_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    pub fn add_err_msg(&mut self, msg: &str, ts: Timestamp) {
        self.reset_activity_line();

        self.add_timestamp(ts);
        self.msg_area.set_style(config::ERR_MSG);
        self.msg_area.add_text(msg);
        self.msg_area.flush_line();
    }

    fn get_nick_color(&self, sender: &str) -> u8 {
        // Anything works as long as it's fast
        let mut hash: usize = 5381;
        for c in sender.chars() {
            hash = hash.wrapping_mul(33).wrapping_add(c as usize);
        }
        config::NICK_COLORS[hash % config::NICK_COLORS.len()]
    }
}

////////////////////////////////////////////////////////////////////////////////
// Keeping nick list up-to-date

impl MessagingUI {
    pub fn join(&mut self, nick: &str, ts: Option<Timestamp>) {
        Rc::get_mut(&mut self.nicks).unwrap().insert(nick);

        if let Some(ts) = ts {
            let line_idx = self.get_activity_line_idx(ts);
            self.msg_area.modify_line(line_idx, |line| {
                line.set_style(config::JOIN);
                line.add_char('+');
                line.add_text(nick);
                line.add_char(' ');
            });
        }
    }

    pub fn part(&mut self, nick: &str, ts: Option<Timestamp>) {
        Rc::get_mut(&mut self.nicks).unwrap().remove(nick);

        if let Some(ts) = ts {
            let line_idx = self.get_activity_line_idx(ts);
            self.msg_area.modify_line(line_idx, |line| {
                line.set_style(config::PART);
                line.add_char('-');
                line.add_text(nick);
                line.add_char(' ');
            });
        }
    }

    pub fn nick(&mut self, old_nick: &str, new_nick: &str, ts: Timestamp) {
        Rc::get_mut(&mut self.nicks).unwrap().remove(old_nick);
        Rc::get_mut(&mut self.nicks).unwrap().insert(new_nick);

        let line_idx = self.get_activity_line_idx(ts);
        self.msg_area.modify_line(line_idx, |line| {
            line.set_style(config::NICK);
            line.add_text(old_nick);
            line.add_text("->");
            line.add_text(new_nick);
            line.add_char(' ');
        });
    }

    pub fn has_nick(&self, nick : &str) -> bool {
        self.nicks.contains(nick)
    }

    fn reset_activity_line(&mut self) {
        self.last_activity_line = None;
    }

    fn get_activity_line_idx(&mut self, ts: Timestamp) -> usize {
        // borrow checker strikes again
        if let Some(ref mut l) = self.last_activity_line {
            if l.ts == ts {
                return l.line_idx;
            }
        }

        self.add_timestamp(ts);
        let line_idx = self.msg_area.flush_line();
        self.last_activity_line = Some(ActivityLine {
            ts: ts,
            line_idx: line_idx,
        });
        line_idx
    }
}
<|endoftext|>


<commit_before>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

//! Fixed-size vector type

use std::ops::{Add, Sub, Mul, Div, BitXor};
use std::cmp::PartialEq;
use super::matrix::Matrix3;

/// 3 dimensional vector type, implementing all usual operations
#[derive(Copy, Clone, Debug)]
pub struct Vector3D {
    /// First component of the vector
    pub x: f64,
    /// Second component of the vector
    pub y: f64,
    /// Third component of the vector
    pub z: f64,
}

impl Vector3D {
    /// Create a new Vector3D with components `x`, `y`, `z`
    pub fn new(x: f64, y: f64, z: f64) -> Vector3D {
        Vector3D{x: x, y: y, z: z}
    }
    /// Return the squared euclidean norm of a Vector3D
    #[inline]
    pub fn norm2(&self) -> f64 {
        (*self) * (*self)
    }
    /// Return the euclidean norm of a Vector3D
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }
    /// Normalize a Vector3D
    #[inline]
    pub fn normalized(&self) -> Vector3D {
        *self / self.norm()
    }
    /// Tensorial product between vectors
    pub fn tensorial(&self, other: &Vector3D) -> Matrix3 {
        Matrix3::new(self.x * other.x, self.x * other.y, self.x * other.z,
                     self.y * other.x, self.y * other.y, self.y * other.z,
                     self.z * other.x, self.z * other.y, self.z * other.z)
    }
}

/// Add two vectors
impl Add for Vector3D {
    type Output = Vector3D;
    fn add(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x + other.x, self.y + other.y, self.z + other.z)
    }
}

/// Substract two vectors
impl Sub for Vector3D {
    type Output = Vector3D;
    fn sub(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x - other.x, self.y - other.y, self.z - other.z)
    }
}

/// Multiply by a scalar on the right hand side
impl Mul<f64> for Vector3D {
    type Output = Vector3D;
    fn mul(self, other: f64) -> Vector3D {
        Vector3D::new(self.x * other, self.y * other, self.z * other)
    }
}

/// Multiply by a scalar on the left hand side
impl Mul<Vector3D> for f64 {
    type Output = Vector3D;
    fn mul(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self * other.x, self * other.y, self * other.z)
    }
}

/// Scalar product between vectors
impl Mul<Vector3D> for Vector3D {
    type Output = f64;
    fn mul(self, other: Vector3D) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

/// Vectorial product will use the a^b notation.
impl BitXor<Vector3D> for Vector3D {
    type Output = Vector3D;
    fn bitxor(self, other: Vector3D) -> Vector3D {
        let x = self.y * other.z - self.z * other.y;
        let y = self.z * other.x - self.x * other.z;
        let z = self.x * other.y - self.y * other.x;
        Vector3D::new(x, y, z)
    }
}

/// Dividing a vector by a scalar
impl Div<f64> for Vector3D {
    type Output = Vector3D;
    fn div(self, other: f64) -> Vector3D {
        Vector3D::new(self.x / other, self.y / other, self.z / other)
    }
}

/// Comparing two vectors
impl PartialEq for Vector3D {
    fn eq(&self, other: &Vector3D) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

/******************************************************************************/

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

    #[test]
    fn add() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a + b;
        assert_eq!(c, Vector3D::new(8.1, -5.0, 12.1));
    }

    #[test]
    fn sub() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a - b;
        assert_eq!(c, Vector3D::new(-4.1, 12.0, -2.5));
    }

    #[test]
    fn mul() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = 2.0;

        let c = b * a;
        assert_eq!(c, Vector3D::new(4.0, 7.0, 9.6));

        let b = 1.5;
        let c = a * b;
        assert_eq!(c, Vector3D::new(3.0, 5.25, 7.199999999999999));
    }

    #[test]
    fn dot_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a * b;
        assert_eq!(c, 18.1);
    }

    #[test]
    fn cross_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a ^ b;
        assert_eq!(c*a, 0.0);

        let a = Vector3D::new(1.0, 0.0, 0.0);
        let b = Vector3D::new(0.0, 1.0, 0.0);

        let c = a ^ b;
        assert_eq!(c, Vector3D::new(0.0, 0.0, 1.0));
    }
}
<commit_msg>Add unary minus operator to Vector3D<commit_after>/*
 * Cymbalum, Molecular Simulation in Rust
 * Copyright (C) 2015 Guillaume Fraux
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/
*/

//! Fixed-size vector type

use std::ops::{Add, Sub, Neg, Mul, Div, BitXor};
use std::cmp::PartialEq;
use super::matrix::Matrix3;

/// 3 dimensional vector type, implementing all usual operations
#[derive(Copy, Clone, Debug)]
pub struct Vector3D {
    /// First component of the vector
    pub x: f64,
    /// Second component of the vector
    pub y: f64,
    /// Third component of the vector
    pub z: f64,
}

impl Vector3D {
    /// Create a new Vector3D with components `x`, `y`, `z`
    pub fn new(x: f64, y: f64, z: f64) -> Vector3D {
        Vector3D{x: x, y: y, z: z}
    }
    /// Return the squared euclidean norm of a Vector3D
    #[inline]
    pub fn norm2(&self) -> f64 {
        (*self) * (*self)
    }
    /// Return the euclidean norm of a Vector3D
    #[inline]
    pub fn norm(&self) -> f64 {
        f64::sqrt(self.norm2())
    }
    /// Normalize a Vector3D
    #[inline]
    pub fn normalized(&self) -> Vector3D {
        *self / self.norm()
    }
    /// Tensorial product between vectors
    pub fn tensorial(&self, other: &Vector3D) -> Matrix3 {
        Matrix3::new(self.x * other.x, self.x * other.y, self.x * other.z,
                     self.y * other.x, self.y * other.y, self.y * other.z,
                     self.z * other.x, self.z * other.y, self.z * other.z)
    }
}

/// Add two vectors
impl Add for Vector3D {
    type Output = Vector3D;
    fn add(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x + other.x, self.y + other.y, self.z + other.z)
    }
}

/// Substract two vectors
impl Sub for Vector3D {
    type Output = Vector3D;
    fn sub(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self.x - other.x, self.y - other.y, self.z - other.z)
    }
}

/// Unary - operator
impl Neg for Vector3D {
    type Output = Vector3D;
    fn neg(self) -> Vector3D {
        Vector3D::new(-self.x, -self.y, -self.z)
    }
}

/// Multiply by a scalar on the right hand side
impl Mul<f64> for Vector3D {
    type Output = Vector3D;
    fn mul(self, other: f64) -> Vector3D {
        Vector3D::new(self.x * other, self.y * other, self.z * other)
    }
}

/// Multiply by a scalar on the left hand side
impl Mul<Vector3D> for f64 {
    type Output = Vector3D;
    fn mul(self, other: Vector3D) -> Vector3D {
        Vector3D::new(self * other.x, self * other.y, self * other.z)
    }
}

/// Scalar product between vectors
impl Mul<Vector3D> for Vector3D {
    type Output = f64;
    fn mul(self, other: Vector3D) -> f64 {
        self.x * other.x + self.y * other.y + self.z * other.z
    }
}

/// Vectorial product will use the a^b notation.
impl BitXor<Vector3D> for Vector3D {
    type Output = Vector3D;
    fn bitxor(self, other: Vector3D) -> Vector3D {
        let x = self.y * other.z - self.z * other.y;
        let y = self.z * other.x - self.x * other.z;
        let z = self.x * other.y - self.y * other.x;
        Vector3D::new(x, y, z)
    }
}

/// Dividing a vector by a scalar
impl Div<f64> for Vector3D {
    type Output = Vector3D;
    fn div(self, other: f64) -> Vector3D {
        Vector3D::new(self.x / other, self.y / other, self.z / other)
    }
}

/// Comparing two vectors
impl PartialEq for Vector3D {
    fn eq(&self, other: &Vector3D) -> bool {
        self.x == other.x && self.y == other.y && self.z == other.z
    }
}

/******************************************************************************/

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

    #[test]
    fn add() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a + b;
        assert_eq!(c, Vector3D::new(8.1, -5.0, 12.1));
    }

    #[test]
    fn sub() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a - b;
        assert_eq!(c, Vector3D::new(-4.1, 12.0, -2.5));

        let d = -c;
        assert_eq!(d, Vector3D::new(4.1, -12.0, 2.5));
    }

    #[test]
    fn mul() {
        let a = Vector3D::new(2.0, 3.5, 4.8);
        let b = 2.0;

        let c = b * a;
        assert_eq!(c, Vector3D::new(4.0, 7.0, 9.6));

        let b = 1.5;
        let c = a * b;
        assert_eq!(c, Vector3D::new(3.0, 5.25, 7.199999999999999));
    }

    #[test]
    fn dot_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a * b;
        assert_eq!(c, 18.1);
    }

    #[test]
    fn cross_product() {
        let a = Vector3D::new(2.1, 3.5, 4.8);
        let b = Vector3D::new(6.1, -8.5, 7.3);

        let c = a ^ b;
        assert_eq!(c*a, 0.0);

        let a = Vector3D::new(1.0, 0.0, 0.0);
        let b = Vector3D::new(0.0, 1.0, 0.0);

        let c = a ^ b;
        assert_eq!(c, Vector3D::new(0.0, 0.0, 1.0));
    }
}
<|endoftext|>


<commit_before>
extern crate rand;
//extern crate time;

//use time::PreciseTime;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::FileStreamReader;
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;
use std::str;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    //A server doesn't need a remote_connection
    remote_connection : Option<SocketAddrV4>
}

impl EndPoint{

    pub fn new(remote : &str, port : &str, is_server : bool) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        if is_server{
            Ok(EndPoint{
                local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
                remote_connection : None
            })
        }
        else{
            Ok(EndPoint{
                local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 9990),
                remote_connection : Some(SocketAddrV4::new(ipv4, 6900))
            })
        }
    }

    pub fn start_listen(&mut self)->Result<(), Error>{
        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Start servicing requests from a client
        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        let mut last_blk_id = 0u16;
        match buf[1]{
            1 => { //RRQ
                println!("RRQ received");
                //Get filename to be sent from the packet
                let mut  i = 2;
                while buf[i] != '\0' as u8{
                    i += 1;
                }
                let filename = str::from_utf8(&buf[2..i]);
                println!("file requested: {}", filename.unwrap());
                // Send data via the socket
                let mut fs = FileStreamReader::new(String::from(filename.unwrap())).unwrap();
                let (mut buf, num_bytes_read) = fs.next().unwrap();
                let v = self.create_data_packet(last_blk_id, &buf, num_bytes_read);
                try!(socket.send_to(v.as_slice(), src));
                //TODO start timer here
                loop{
                    //Get ACK
                    let (amt, src) = try!(socket.recv_from(&mut buf));
                    if buf[1] == 4{
                        println!("ACK received");
                        last_blk_id += 1;
                        let (buf, num_bytes_read) = fs.next().unwrap();
                        let v = self.create_data_packet(last_blk_id, &buf, num_bytes_read);
                        try!(socket.send_to(v.as_slice(), src));
                    }
                }
            },
            4 => {

            },
            _ => {panic!("unrecognized packet type")}
        }

        Ok(())

    }

    fn create_data_packet(&mut self, blk_id : u16, buf : &[u8], num_bytes : usize) -> Vec<u8>{
        let mut v = Vec::with_capacity(num_bytes + 4);
        v.push(0);
        v.push(PacketType::DATA as u8);
        v.push((blk_id >> 8) as u8);
        v.push((blk_id & 0x00FF) as u8);
        v.extend_from_slice(&buf[0..num_bytes]);
        v
    }

    fn create_rrq_wrq_packet(&self, p_type: PacketType, file_name: &str, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push('\0' as u8);
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }

    pub fn get(&mut self, files : &[&str], mode : &'static str) -> Result<(), Error>{
        let socket = try!(UdpSocket::bind(self.local_connection));
        let mut buf  = [0; 516];
        for file in files{
            //start with a RRQ
            println!("sending RRQ request");
            let packet = self.create_rrq_wrq_packet(PacketType::RRQ, file, mode);
            try!(socket.send_to(packet.as_slice(), self.remote_connection.unwrap()));

            loop{
                //get the first block of the requested file
                let (amt, src) = try!(socket.recv_from(&mut buf));
                println!("Received block");
                //println!("{:?}", &buf[0..amt]);
                match buf[1]{
                    3 =>{
                        let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;
                        let block_size = amt - 4;
                        println!("{:?}", block_size);
                        if block_size == 0{
                            break;
                        }

                        //send ACK
                        let low = block_num & 0x00FF;
                        let high = (block_num & 0xFF00) >> 8;

                        println!("Sending ACK");
                        socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);

                    },
                    _ => {}
                }
                //Flush buf for next read
                //TODO fix this:
                for i in 0..516{
                    buf[0] = 0;
                }
            }

        }

        Ok(())
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<commit_msg>Write data blocks to file<commit_after>
extern crate rand;
//extern crate time;

//use time::PreciseTime;
use std::net::{Ipv4Addr, SocketAddrV4, UdpSocket};
use file_stream_iter::{FileStreamReader, FileStreamWriter};
use std::io::Error;
use tftp_specific::PacketType;
use std::str::FromStr;
use std::net::AddrParseError;
use std::error;
use std::str;

pub struct EndPoint{
    local_connection : SocketAddrV4,
    //A server doesn't need a remote_connection
    remote_connection : Option<SocketAddrV4>
}

impl EndPoint{

    pub fn new(remote : &str, port : &str, is_server : bool) -> Result<EndPoint, AddrParseError>{

        let ipv4 = try!(get_ip_from(remote));
        if is_server{
            Ok(EndPoint{
                local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 6900),
                remote_connection : None
            })
        }
        else{
            Ok(EndPoint{
                local_connection : SocketAddrV4::new(Ipv4Addr::new(127,0,0,1), 9990),
                remote_connection : Some(SocketAddrV4::new(ipv4, 6900))
            })
        }
    }

    pub fn start_listen(&mut self)->Result<(), Error>{
        // Bind the socket
        let socket = try!(UdpSocket::bind(self.local_connection));

        // Start servicing requests from a client
        // Read from the socket
        let mut buf = [0u8; 516]; //UDP packet is 516 bytes
        let (amt, src) = try!(socket.recv_from(&mut buf));
        let mut last_blk_id = 0u16;
        match buf[1]{
            1 => { //RRQ
                println!("RRQ received");
                //Get filename to be sent from the packet
                let mut  i = 2;
                while buf[i] != '\0' as u8{
                    i += 1;
                }
                let filename = str::from_utf8(&buf[2..i]);
                println!("file requested: {}", filename.unwrap());
                // Send data via the socket
                let mut fs = FileStreamReader::new(String::from(filename.unwrap())).unwrap();
                let (mut buf, num_bytes_read) = fs.next().unwrap();
                let v = self.create_data_packet(last_blk_id, &buf, num_bytes_read);
                try!(socket.send_to(v.as_slice(), src));
                //TODO start timer here
                loop{
                    //Get ACK
                    let (amt, src) = try!(socket.recv_from(&mut buf));
                    if buf[1] == 4{
                        println!("ACK received");
                        last_blk_id += 1;
                        let (buf, num_bytes_read) = fs.next().unwrap();
                        let v = self.create_data_packet(last_blk_id, &buf, num_bytes_read);
                        try!(socket.send_to(v.as_slice(), src));
                    }
                }
            },
            4 => {

            },
            _ => {panic!("unrecognized packet type")}
        }

        Ok(())

    }

    fn create_data_packet(&mut self, blk_id : u16, buf : &[u8], num_bytes : usize) -> Vec<u8>{
        let mut v = Vec::with_capacity(num_bytes + 4);
        v.push(0);
        v.push(PacketType::DATA as u8);
        v.push((blk_id >> 8) as u8);
        v.push((blk_id & 0x00FF) as u8);
        v.extend_from_slice(&buf[0..num_bytes]);
        v
    }

    fn create_rrq_wrq_packet(&self, p_type: PacketType, file_name: &str, mode : &'static str)->Vec<u8>{
        let mut v = Vec::with_capacity(2+file_name.len()+1+mode.len()+1);
        v.push(0);
        v.push(p_type as u8);
        v.extend(file_name.as_bytes());
        v.push('\0' as u8);
        v.push(0);//zero terminator
        v.extend(mode.as_bytes());
        v.push(0);//zero terminator
        v
    }

    pub fn get(&mut self, files : &[&str], mode : &'static str) -> Result<(), Error>{
        let socket = try!(UdpSocket::bind(self.local_connection));
        let mut buf  = [0; 516];
        for file in files{
            //start with a RRQ
            println!("sending RRQ request");
            let packet = self.create_rrq_wrq_packet(PacketType::RRQ, file, mode);
            try!(socket.send_to(packet.as_slice(), self.remote_connection.unwrap()));
            //TODO remove the hardcoded filename
            let mut writer = FileStreamWriter::new(String::from("/home/abhi/code/rust/fei/target/debug/bar.txt")).unwrap();

            loop{
                //get the first block of the requested file
                let (amt, src) = try!(socket.recv_from(&mut buf));
                println!("Received block");
                println!("Total bytes read {}", amt);

                match buf[1]{
                    3 =>{
                        let block_size = amt - 4;
                        println!("File block size is {:?}", block_size);
                        if block_size == 0{
                            println!("Empty block recvd");
                            writer.close();
                            break;
                        }
                        println!("Appending to file");
                        writer.append(&buf[4..4+block_size]);
                        let block_num : u16 = 0u16 | (buf[2] as u16) << 8 |  buf[3] as u16;

                        //send ACK
                        let low = block_num & 0x00FF;
                        let high = (block_num & 0xFF00) >> 8;

                        println!("Sending ACK");
                        socket.send_to(&[0,PacketType::ACK as u8, high as u8, low as u8], src);

                    },
                    _ => {}
                }
                //Flush buf for next read
                //TODO fix this:
                for i in 0..516{
                    buf[0] = 0;
                }
            }

        }

        Ok(())
    }
}

fn get_ip_from(ip : &str) -> Result<Ipv4Addr, AddrParseError>{
    Ipv4Addr::from_str(ip)
}

<|endoftext|>


<commit_before>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::StreamProducer;

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  /// Failed parsing the blocking strategy inside the frame header.
  BlockingStrategyParser,
  /// Failed parsing the blocking sample inside the frame header.
  BlockingSampleParser,
  /// Failed parsing the channel bits inside the frame header.
  ChannelBitsParser,
  /// Failed parsing the UTF-8 header inside the frame header.
  UTF8HeaderParser,
  /// Failed parsing the UTF-8 body inside the frame header.
  UTF8BodyParser,
  /// Failed parsing the secondary block size inside the frame header.
  BlockSizeParser,
  /// Failed parsing the secondary sample rate inside the frame header.
  SampleRateParser,
  /// Failed parsing the CRC-8 inside the frame header.
  CRC8Parser,
  /// Failed parsing the frame footer, also known as the CRC-16.
  FrameFooterParser,
  /// Failed parsing the subframe header.
  SubframeHeaderParser,
  /// Failed parsing the leading zero for a unary value.
  LeadingZerosParser,
  /// Failed parsing a Constant subframe data.
  ConstantParser,
  /// Failed parsing a Verbatim subframe data.
  VerbatimParser,
  /// Failed parsing a Fixed subframe data.
  FixedParser,
  /// Failed parsing a LPC subframe data.
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  /// An incorrect sync code with the frame header.
  InvalidSyncCode,
  /// A block sample that could cause sync-fooling.
  InvalidBlockSample,
  /// One or more bits are reserved values.
  InvalidChannelBits,
  /// An error occurred in building the UTF-8 value.
  InvalidUTF8,
  /// The stored CRC-8 doesn't match the one generated from the bytes within
  /// the frame header.
  InvalidCRC8,
  /// The stored CRC-16 doesn't match the one generated from the bytes
  /// within the entire frame.
  InvalidCRC16,
  /// A subframe header that could cause sync-fooling.
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    to_custom_error!(input, nom::be_u32, Unknown)
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<commit_msg>Add a macro for repeating of trait implementations<commit_after>use nom::{self, IResult, Needed};

use std::io::{self, Read};
use std::ptr;
use std::cmp;

use super::{Sample, StreamProducer};

/// Represent the different kinds of errors.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ErrorKind {
  /// Error from I/O.
  IO(io::ErrorKind),
  /// A parser stopped midway and need more bytes to consume.
  Incomplete(usize),
  /// A parser has completes and there is still more bytes to consume.
  Continue,
  /// A parser has completes and there is no more bytes to consume.
  EndOfInput,
  /// A non-specified error.
  Unknown,
  // Parser Error
  /// Failed parsing the "fLaC" header token.
  HeaderParser,
  /// Failed parsing a metadata header.
  MetadataHeaderParser,
  /// Failed parsing the metadata block `StreamInfo`.
  StreamInfoParser,
  /// Failed parsing the metadata block `Padding`.
  PaddingParser,
  /// Failed parsing the metadata block `Application`.
  ApplicationParser,
  /// Failed parsing the metadata block `SeekTable`.
  SeekTableParser,
  /// Failed parsing the metadata block `VorbisComment`.
  VorbisCommentParser,
  /// Failed parsing the metadata block `CueSheet`.
  CueSheetParser,
  /// Failed parsing the metadata block `Picture`.
  PictureParser,
  /// Failed parsing the metadata block `Unknown`.
  UnknownParser,
  /// Failed parsing the blocking strategy inside the frame header.
  BlockingStrategyParser,
  /// Failed parsing the blocking sample inside the frame header.
  BlockingSampleParser,
  /// Failed parsing the channel bits inside the frame header.
  ChannelBitsParser,
  /// Failed parsing the UTF-8 header inside the frame header.
  UTF8HeaderParser,
  /// Failed parsing the UTF-8 body inside the frame header.
  UTF8BodyParser,
  /// Failed parsing the secondary block size inside the frame header.
  BlockSizeParser,
  /// Failed parsing the secondary sample rate inside the frame header.
  SampleRateParser,
  /// Failed parsing the CRC-8 inside the frame header.
  CRC8Parser,
  /// Failed parsing the frame footer, also known as the CRC-16.
  FrameFooterParser,
  /// Failed parsing the subframe header.
  SubframeHeaderParser,
  /// Failed parsing the leading zero for a unary value.
  LeadingZerosParser,
  /// Failed parsing a Constant subframe data.
  ConstantParser,
  /// Failed parsing a Verbatim subframe data.
  VerbatimParser,
  /// Failed parsing a Fixed subframe data.
  FixedParser,
  /// Failed parsing a LPC subframe data.
  LPCParser,
  // Invalid Error
  /// A block type, base on the number, that is outside the range (0-126).
  InvalidBlockType,
  /// An incorrect sync code with the frame header.
  InvalidSyncCode,
  /// A block sample that could cause sync-fooling.
  InvalidBlockSample,
  /// One or more bits are reserved values.
  InvalidChannelBits,
  /// An error occurred in building the UTF-8 value.
  InvalidUTF8,
  /// The stored CRC-8 doesn't match the one generated from the bytes within
  /// the frame header.
  InvalidCRC8,
  /// The stored CRC-16 doesn't match the one generated from the bytes
  /// within the entire frame.
  InvalidCRC16,
  /// A subframe header that could cause sync-fooling.
  InvalidSubframeHeader,
  // Not Found
  /// Some metadata block was not found with a specific filter.
  NotFound,
}

/// Structure that hold a slice of bytes.
pub struct ByteStream<'a> {
  offset: usize,
  bytes: &'a [u8],
}

impl<'a> ByteStream<'a> {
  /// Construct a `ByteStream` based on the passed in byte slice.
  pub fn new(bytes: &'a [u8]) -> Self {
    ByteStream {
      offset: 0,
      bytes: bytes,
    }
  }

  /// Return the number of bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.bytes.len() - self.offset
  }

  /// Return true if the stream contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }
}

impl<'a> StreamProducer for ByteStream<'a> {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.is_empty() {
      return Err(ErrorKind::EndOfInput);
    }

    match f(&self.bytes[self.offset..]) {
      IResult::Done(i, o)    => {
        self.offset += self.len() - i.len();

        Ok(o)
      }
      IResult::Incomplete(n) => {
        let mut needed = self.len();

        if let Needed::Size(size) = n {
          needed = size;
        }

        Err(ErrorKind::Incomplete(needed))
      }
      IResult::Error(e)      => {
        match e {
          nom::Err::Code(k)               |
          nom::Err::Node(k, _)            |
          nom::Err::Position(k, _)        |
          nom::Err::NodePosition(k, _, _) => {
            if let nom::ErrorKind::Custom(kind) = k {
              Err(kind)
            } else {
              Err(ErrorKind::Unknown)
            }
          }
        }
      },
    }
  }
}

// Growable buffer of bytes.
//
// Mainly used to the `ReadStream` structure but can be used seperately for
// manually filling with some `Read` source.
pub struct Buffer {
  data: Vec<u8>,
  filled: usize,
  offset: usize,
}

impl Buffer {
  // Default constructor for `Buffer`
  pub fn new() -> Self {
    Self::with_capacity(1024)
  }

  // Explicitly set the buffer capacity.
  pub fn with_capacity(capacity: usize) -> Self {
    let mut buffer = Vec::with_capacity(capacity);

    unsafe {
      buffer.set_len(capacity);
    }

    Buffer {
      data: buffer,
      filled: 0,
      offset: 0,
    }
  }

  // Return the number of read bytes that haven't been consumed yet.
  #[inline]
  pub fn len(&self) -> usize {
    self.filled - self.offset
  }

  // Return true if buffer contains no more bytes.
  #[inline]
  pub fn is_empty(&self) -> bool {
    self.len() == 0
  }

  // The set length of the unlining buffer.
  #[inline]
  pub fn capacity(&self) -> usize {
    self.data.len()
  }

  // Return a reference to the slice of unread bytes.
  pub fn as_slice(&self) -> &[u8] {
    &self.data[self.offset..self.filled]
  }

  // Fill the buffer with bytes from a `Read` source.
  pub fn fill<R: Read>(&mut self, reader: &mut R) -> io::Result<usize> {
    reader.read(&mut self.data[self.filled..]).map(|consumed| {
      self.filled += consumed;

      consumed
    })
  }

  // Resize the current buffer
  //
  // This will only allocate data when the size requests is larger than the
  // current capacity of the buffer, otherwise it moves the currently filled
  // data to the beginning of the buffer.
  pub fn resize(&mut self, size: usize) {
    if size > self.data.capacity() {
      self.data.reserve(size);

      let capacity = self.data.capacity();

      unsafe {
        self.data.set_len(capacity);
      }
    }

    if self.data.len() - self.filled < size  {
      let length  = self.filled - self.offset;
      let mut_ptr = self.data.as_mut_ptr();

      unsafe {
        let offset_ptr  = self.data.as_ptr().offset(self.offset as isize);

        ptr::copy(offset_ptr, mut_ptr, length);
      }

      self.filled -= self.offset;
      self.offset  = 0;
    }
  }

  // Move the offset by the amount of consumed bytes.
  pub fn consume(&mut self, consumed: usize) {
    self.offset += consumed;
  }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum ParserState {
  Incomplete,
  EndOfInput,
}

fn fill<R: Read>(buffer: &mut Buffer, reader: &mut R, needed: usize)
                 -> io::Result<usize> {
  let mut read = 0;

  if buffer.len() < needed {
    buffer.resize(needed);

    while buffer.len() < needed {
      let size_read = try!(buffer.fill(reader));

      if size_read > 0 {
        read += size_read;
      } else {
        break;
      }
    }
  }

  Ok(read)
}

/// Structure that hold a reader for a source of bytes.
pub struct ReadStream<R: Read> {
  reader: R,
  buffer: Buffer,
  needed: usize,
  state: ParserState,
}

impl<R> ReadStream<R> where R: Read {
  /// Constructor for `ReadStream` based on a `Read` source.
  pub fn new(reader: R) -> Self {
    ReadStream {
      reader: reader,
      buffer: Buffer::new(),
      needed: 0,
      state: ParserState::Incomplete,
    }
  }

  // Fill the stream with bytes from a `Read` source.
  fn fill(&mut self) -> io::Result<usize> {
    let needed = cmp::max(1, self.needed);

    fill(&mut self.buffer, &mut self.reader, needed).map(|consumed| {
      if self.buffer.len() < needed {
        self.state = ParserState::EndOfInput;
      }

      consumed
    })
  }
}

fn from_iresult<T>(buffer: &Buffer, result: IResult<&[u8], T, ErrorKind>)
                   -> Result<(usize, T), ErrorKind> {
  match result {
    IResult::Done(i, o)    => Ok((buffer.len() - i.len(), o)),
    IResult::Incomplete(n) => {
      let mut needed = buffer.capacity() + 1024;

      if let Needed::Size(size) = n {
        needed = size;
      }

      Err(ErrorKind::Incomplete(needed))
    }
    IResult::Error(e)      => {
      match e {
        nom::Err::Code(k)               |
        nom::Err::Node(k, _)            |
        nom::Err::Position(k, _)        |
        nom::Err::NodePosition(k, _, _) => {
          if let nom::ErrorKind::Custom(kind) = k {
            Err(kind)
          } else {
            Err(ErrorKind::Unknown)
          }
        }
      }
    },
  }
}

impl<R> StreamProducer for ReadStream<R> where R: Read {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind> {
    if self.state != ParserState::EndOfInput {
      try!(self.fill().map_err(|e| ErrorKind::IO(e.kind())));
    }

    let mut buffer = &mut self.buffer;

    if buffer.is_empty() {
      self.state = ParserState::EndOfInput;

      return Err(ErrorKind::EndOfInput);
    }

    let result = {
      let iresult = f(buffer.as_slice());

      from_iresult(&buffer, iresult)
    };

    match result {
      Ok((consumed, o)) => {
        buffer.consume(consumed);

        Ok(o)
      }
      Err(kind)         => {
        if let ErrorKind::Incomplete(needed) = kind {
          self.needed = needed;

          Err(ErrorKind::Continue)
        } else {
          Err(kind)
        }
      }
    }
  }
}

macro_rules! sample (
  ($normal: ident, $extended: ident, $bits_per_sample: expr) => (
    impl Sample for $extended {
      type Normal = $normal;

      #[inline]
      fn size() -> usize { $bits_per_sample }

      fn to_normal(sample: Self) -> Option<Self::Normal> {
        use std::$normal;

        let min = $normal::min_value() as $extended;
        let max = $normal::max_value() as $extended;

        if sample > min && sample < max {
          Some(sample as $normal)
        } else {
          None
        }
      }
    }
  )
);

#[cfg(test)]
mod tests {
  use super::*;
  use utility::StreamProducer;
  use nom::{self, IResult};

  #[inline]
  fn be_u32(input: &[u8]) -> IResult<&[u8], u32, ErrorKind> {
    to_custom_error!(input, nom::be_u32, Unknown)
  }

  #[test]
  fn test_buffer() {
    let mut buffer = Buffer::new();
    let bytes      = b"Hello World";
    let mut reader = &bytes[..];

    assert!(buffer.is_empty());
    assert_eq!(buffer.capacity(), 1024);

    let bytes_read = buffer.fill(&mut reader).unwrap_or(0);
    let bytes_len  = bytes.len();

    assert_eq!(bytes_read, bytes_len);
    assert_eq!(buffer.len(), bytes_len);
    assert_eq!(buffer.as_slice(), bytes);

    buffer.resize(512);
    assert_eq!(buffer.capacity(), 1024);
  }

  #[test]
  fn test_byte_stream() {
    let bytes      = b"Hello World";
    let mut stream = ByteStream::new(bytes);

    assert_eq!(stream.len(), bytes.len());

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444);
    assert_eq!(stream.len(), 7);
  }

  #[test]
  fn test_read_stream() {
    let bytes      = b"Hello World";
    let mut stream = ReadStream::new(&bytes[..]);

    let result = stream.parse(be_u32).unwrap_or(0);

    assert_eq!(result, 1214606444)
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Weak};

use chrono::Local;
use console::{style, Color};
use indicatif::ProgressBar;
use lazy_static::lazy_static;
use parking_lot::RwLock;

lazy_static! {
    static ref PROGRESS_BAR: RwLock<Option<Weak<ProgressBar>>> = RwLock::new(None);
    static ref MAX_LEVEL: AtomicUsize =
        AtomicUsize::new(unsafe { mem::transmute(log::LevelFilter::Warn) });
}

pub fn max_level() -> log::LevelFilter {
    unsafe { mem::transmute(MAX_LEVEL.load(Ordering::Relaxed)) }
}

pub fn set_max_level(level: log::LevelFilter) {
    MAX_LEVEL.store(unsafe { mem::transmute(level) }, Ordering::Relaxed);
}

/// A simple logger
pub struct Logger;

impl Logger {
    fn get_actual_level(&self, metadata: &log::Metadata<'_>) -> log::Level {
        let mut level = metadata.level();
        if level == log::Level::Debug
            && (metadata.target() == "tokio_reactor"
                || metadata.target().starts_with("hyper::proto::"))
        {
            level = log::Level::Trace;
        }
        level
    }
}

impl log::Log for Logger {
    fn enabled(&self, metadata: &log::Metadata<'_>) -> bool {
        self.get_actual_level(metadata) <= max_level()
    }

    fn log(&self, record: &log::Record<'_>) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let level = self.get_actual_level(record.metadata());
        let (level_name, level_color) = match level {
            log::Level::Error => ("ERROR", Color::Red),
            log::Level::Warn => ("WARN ", Color::Red),
            log::Level::Info => ("INFO ", Color::Cyan),
            log::Level::Debug => ("DEBUG", Color::Yellow),
            log::Level::Trace => ("TRACE", Color::Magenta),
        };
        let short_target = record.target().split("::").next().unwrap_or("");
        let msg = format!(
            "{} {} {}{}",
            style(format!("  {}  ", level_name)).bg(level_color).black(),
            style(Local::now()).dim(),
            style(record.args()),
            style(if short_target != "sentry_cli" {
                format!("  (from {})", short_target)
            } else {
                "".to_string()
            })
            .dim(),
        );

        if let Some(pb) = get_progress_bar() {
            pb.println(msg);
        } else {
            writeln!(io::stderr(), "{}", msg).ok();
        }
    }

    fn flush(&self) {}
}

pub fn set_progress_bar(pb: Option<Weak<ProgressBar>>) {
    *PROGRESS_BAR.write() = pb;
}

fn get_progress_bar() -> Option<Arc<ProgressBar>> {
    PROGRESS_BAR.read().as_ref()?.upgrade()
}
<commit_msg>ref: Filter non-error goblin logs (#1169)<commit_after>use std::io;
use std::io::Write;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Weak};

use chrono::Local;
use console::{style, Color};
use indicatif::ProgressBar;
use lazy_static::lazy_static;
use parking_lot::RwLock;

lazy_static! {
    static ref PROGRESS_BAR: RwLock<Option<Weak<ProgressBar>>> = RwLock::new(None);
    static ref MAX_LEVEL: AtomicUsize =
        AtomicUsize::new(unsafe { mem::transmute(log::LevelFilter::Warn) });
}

pub fn max_level() -> log::LevelFilter {
    unsafe { mem::transmute(MAX_LEVEL.load(Ordering::Relaxed)) }
}

pub fn set_max_level(level: log::LevelFilter) {
    MAX_LEVEL.store(unsafe { mem::transmute(level) }, Ordering::Relaxed);
}

/// A simple logger
pub struct Logger;

impl Logger {
    fn get_actual_level(&self, metadata: &log::Metadata) -> log::Level {
        let mut level = metadata.level();
        if level == log::Level::Debug
            && (metadata.target() == "tokio_reactor"
                || metadata.target().starts_with("hyper::proto::"))
        {
            level = log::Level::Trace;
        }
        level
    }
}

impl log::Log for Logger {
    fn enabled(&self, metadata: &log::Metadata) -> bool {
        self.get_actual_level(metadata) <= max_level()
    }

    fn log(&self, record: &log::Record) {
        if !self.enabled(record.metadata()) {
            return;
        }

        let level = self.get_actual_level(record.metadata());
        let (level_name, level_color) = match level {
            log::Level::Error => ("ERROR", Color::Red),
            log::Level::Warn => ("WARN ", Color::Red),
            log::Level::Info => ("INFO ", Color::Cyan),
            log::Level::Debug => ("DEBUG", Color::Yellow),
            log::Level::Trace => ("TRACE", Color::Magenta),
        };
        let short_target = record.target().split("::").next().unwrap_or("");
        let msg = format!(
            "{} {} {}{}",
            style(format!("  {}  ", level_name)).bg(level_color).black(),
            style(Local::now()).dim(),
            style(record.args()),
            style(if short_target != "sentry_cli" {
                format!("  (from {})", short_target)
            } else {
                "".to_string()
            })
            .dim(),
        );

        if should_skip_log(record) {
            return;
        }

        if let Some(pb) = get_progress_bar() {
            pb.println(msg);
        } else {
            writeln!(io::stderr(), "{}", msg).ok();
        }
    }

    fn flush(&self) {}
}

fn should_skip_log(record: &log::Record) -> bool {
    let level = record.metadata().level();
    let target = record.target();

    // We want to filter everything that is non-error from `goblin` crate,
    // as `symbolicator` is responsible for making sure all warnings are handled correctly.
    if target.starts_with("goblin") && level != log::LevelFilter::Error {
        return true;
    }

    false
}

pub fn set_progress_bar(pb: Option<Weak<ProgressBar>>) {
    *PROGRESS_BAR.write() = pb;
}

fn get_progress_bar() -> Option<Arc<ProgressBar>> {
    PROGRESS_BAR.read().as_ref()?.upgrade()
}
<|endoftext|>