<commit_before>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::ptr;
use iup_sys::*;
use super::{Control, UnwrapHandle};
use super::handle_rc::HandleRc;
use super::attributes::{
    OrientationAttribute,
    set_str_attribute,
    get_str_attribute_slice,
};

pub trait Container : Control {
    fn append(&self, new_child: &Control) -> Result<(), ()> {
        unsafe {
            if IupAppend(self.handle(), new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    fn insert(&self, ref_child: Option<&Control>, new_child: &Control) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupInsert(self.handle(), ref_child, new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }
}

pub trait NonDialogContainer : Container {
    fn refresh_children(&self) {
        unsafe {
            IupRefreshChildren(self.handle());
        }
    }
}

// Be sure that the Vec is not dropped before the *mut *mut Ihandle is used.
fn wrapper_to_handles(controls: Option<&[&::Control]>)
-> (Option<Vec<*mut Ihandle>>, *mut *mut Ihandle)
{
    let mut controls: Option<Vec<_>> = controls.map(|slice| {
        let mut v: Vec<*mut Ihandle> = slice.iter().map(|c| c.handle()).collect();
        v.push(ptr::null_mut()); // array has to be null terminated
        v
    });
    let p = controls.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut());
    (controls, p)
}

#[derive(Clone)]
pub struct Fill(HandleRc);

impl Fill {
    pub fn new() -> Fill {
        unsafe {
            ::iup_open();
            let handle = IupFill();
            Fill(HandleRc::new(handle))
        }
    }
}

impl_control_traits!(Fill);

#[macro_export]
macro_rules! fill { // This is a macro for consistency, even though it could just be a function.
    () => { Fill::new() };
}

#[derive(Clone)]
pub struct Hbox(HandleRc);

impl Hbox {
    pub fn new(children: Option<&[&::Control]>) -> Hbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Hbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Hbox {
        let handle = IupHboxv(children);
        Hbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Hbox);

impl Container for Hbox {}

#[macro_export]
macro_rules! hbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Hbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { hbox!($($c),*) };
}

#[derive(Clone)]
pub struct Vbox(HandleRc);

impl Vbox {
    pub fn new(children: Option<&[&::Control]>) -> Vbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Vbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Vbox {
        let handle = IupVboxv(children);
        Vbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Vbox);

impl Container for Vbox {}

#[macro_export]
macro_rules! vbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Vbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { vbox!($($c),*) };
}

pub enum NumDiv {
    Fixed(u32),
    Auto,
}

#[derive(Clone)]
pub struct GridBox(HandleRc);

impl GridBox {
    pub fn new(children: Option<&[&::Control]>) -> GridBox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            GridBox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> GridBox {
        let handle = IupGridBoxv(children);
        GridBox(HandleRc::new(handle))
    }

    pub fn alignment_lin(&self, line: u32) -> ::VAlignment {
        unsafe {
            let attr = format!("ALIGNMENTLIN{}", line);
            ::VAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_lin(&self, line: u32, alignment: ::VAlignment) {
        set_str_attribute(self.handle(), &format!("ALIGNMENTLIN{}", line), alignment.to_str());
    }

    pub fn alignment_lin_all(&self) -> ::VAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTLIN");
            ::VAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_lin_all(&self, alignment: ::VAlignment) {
        set_str_attribute(self.handle(), "ALIGNMENTLIN", alignment.to_str());
    }

    pub fn alignment_col(&self, column: u32) -> ::HAlignment {
        unsafe {
            let attr = format!("ALIGNMENTCOL{}", column);
            ::HAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_col(&self, column: u32, alignment: ::HAlignment) {
        set_str_attribute(self.handle(), &format!("ALIGNMENTCOL{}", column), alignment.to_str());
    }

    pub fn alignment_col_all(&self) -> ::HAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTCOL");
            ::HAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_col_all(&self, alignment: ::HAlignment) {
        set_str_attribute(self.handle(), "ALIGNMENTCOL", alignment.to_str());
    }

    pub fn num_div(&self) -> NumDiv {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMDIV");
            if s.as_bytes() == b"AUTO" {
                NumDiv::Auto
            } else {
                NumDiv::Fixed(s.parse().expect("could not convert NUMDIV to an integer"))
            }
        }
    }

    pub fn set_num_div(&self, num: NumDiv) {
        match num {
            NumDiv::Fixed(i) => set_str_attribute(self.handle(), "NUMDIV", &i.to_string()),
            NumDiv::Auto => set_str_attribute(self.handle(), "NUMDIV", "AUTO"),
        }
    }

    pub fn num_lin(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMLIN");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn num_col(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMCOL");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }
}

impl_control_traits!(GridBox);

impl Container for GridBox {}

impl OrientationAttribute for GridBox {}

#[macro_export]
macro_rules! grid_box {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { GridBox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { grid_box!($($c),*) };
}
<commit_msg>Add `child_count` and a note about its performance<commit_after>/* Copyright 2015 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

use std::ptr;
use iup_sys::*;
use super::{Control, UnwrapHandle};
use super::handle_rc::HandleRc;
use super::attributes::{
    OrientationAttribute,
    set_str_attribute,
    get_str_attribute_slice,
};

pub trait Container : Control {
    fn append(&self, new_child: &Control) -> Result<(), ()> {
        unsafe {
            if IupAppend(self.handle(), new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    fn insert(&self, ref_child: Option<&Control>, new_child: &Control) -> Result<(), ()> {
        unsafe {
            let ref_child = ref_child.map(|c| c.handle()).unwrap_or(ptr::null_mut());
            if IupInsert(self.handle(), ref_child, new_child.handle()) == ptr::null_mut() {
                Err(())
            } else {
                Ok(())
            }
        }
    }

    /// Returns the number of children of the specified control.
    ///
    /// Warning: Since children are stored as a linked list, getting the count is O(n).
    fn child_count(&self) -> usize {
        unsafe {
            IupGetChildCount(self.handle()) as usize
        }
    }
}

pub trait NonDialogContainer : Container {
    fn refresh_children(&self) {
        unsafe {
            IupRefreshChildren(self.handle());
        }
    }
}

// Be sure that the Vec is not dropped before the *mut *mut Ihandle is used.
fn wrapper_to_handles(controls: Option<&[&::Control]>)
-> (Option<Vec<*mut Ihandle>>, *mut *mut Ihandle)
{
    let mut controls: Option<Vec<_>> = controls.map(|slice| {
        let mut v: Vec<*mut Ihandle> = slice.iter().map(|c| c.handle()).collect();
        v.push(ptr::null_mut()); // array has to be null terminated
        v
    });
    let p = controls.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut());
    (controls, p)
}

#[derive(Clone)]
pub struct Fill(HandleRc);

impl Fill {
    pub fn new() -> Fill {
        unsafe {
            ::iup_open();
            let handle = IupFill();
            Fill(HandleRc::new(handle))
        }
    }
}

impl_control_traits!(Fill);

#[macro_export]
macro_rules! fill { // This is a macro for consistency, even though it could just be a function.
    () => { Fill::new() };
}

#[derive(Clone)]
pub struct Hbox(HandleRc);

impl Hbox {
    pub fn new(children: Option<&[&::Control]>) -> Hbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Hbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Hbox {
        let handle = IupHboxv(children);
        Hbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Hbox);

impl Container for Hbox {}

#[macro_export]
macro_rules! hbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Hbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { hbox!($($c),*) };
}

#[derive(Clone)]
pub struct Vbox(HandleRc);

impl Vbox {
    pub fn new(children: Option<&[&::Control]>) -> Vbox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            Vbox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> Vbox {
        let handle = IupVboxv(children);
        Vbox(HandleRc::new(handle))
    }
}

impl_control_traits!(Vbox);

impl Container for Vbox {}

#[macro_export]
macro_rules! vbox {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { Vbox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { vbox!($($c),*) };
}

pub enum NumDiv {
    Fixed(u32),
    Auto,
}

#[derive(Clone)]
pub struct GridBox(HandleRc);

impl GridBox {
    pub fn new(children: Option<&[&::Control]>) -> GridBox {
        unsafe {
            ::iup_open();
            let (_children, children_handles) = wrapper_to_handles(children);
            GridBox::from_handles(children_handles)
        }
    }

    pub unsafe fn from_handles(children: *mut *mut Ihandle) -> GridBox {
        let handle = IupGridBoxv(children);
        GridBox(HandleRc::new(handle))
    }

    pub fn alignment_lin(&self, line: u32) -> ::VAlignment {
        unsafe {
            let attr = format!("ALIGNMENTLIN{}", line);
            ::VAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_lin(&self, line: u32, alignment: ::VAlignment) {
        set_str_attribute(self.handle(), &format!("ALIGNMENTLIN{}", line), alignment.to_str());
    }

    pub fn alignment_lin_all(&self) -> ::VAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTLIN");
            ::VAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_lin_all(&self, alignment: ::VAlignment) {
        set_str_attribute(self.handle(), "ALIGNMENTLIN", alignment.to_str());
    }

    pub fn alignment_col(&self, column: u32) -> ::HAlignment {
        unsafe {
            let attr = format!("ALIGNMENTCOL{}", column);
            ::HAlignment::from_str(get_str_attribute_slice(self.handle(), &attr).as_bytes())
        }
    }

    pub fn set_alignment_col(&self, column: u32, alignment: ::HAlignment) {
        set_str_attribute(self.handle(), &format!("ALIGNMENTCOL{}", column), alignment.to_str());
    }

    pub fn alignment_col_all(&self) -> ::HAlignment {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "ALIGNMENTCOL");
            ::HAlignment::from_str(s.as_bytes())
        }
    }

    pub fn set_alignment_col_all(&self, alignment: ::HAlignment) {
        set_str_attribute(self.handle(), "ALIGNMENTCOL", alignment.to_str());
    }

    pub fn num_div(&self) -> NumDiv {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMDIV");
            if s.as_bytes() == b"AUTO" {
                NumDiv::Auto
            } else {
                NumDiv::Fixed(s.parse().expect("could not convert NUMDIV to an integer"))
            }
        }
    }

    pub fn set_num_div(&self, num: NumDiv) {
        match num {
            NumDiv::Fixed(i) => set_str_attribute(self.handle(), "NUMDIV", &i.to_string()),
            NumDiv::Auto => set_str_attribute(self.handle(), "NUMDIV", "AUTO"),
        }
    }

    pub fn num_lin(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMLIN");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }

    pub fn num_col(&self) -> u32 {
        unsafe {
            let s = get_str_attribute_slice(self.handle(), "NUMCOL");
            s.parse().expect("could not convert NUMLIN to an integer")
        }
    }
}

impl_control_traits!(GridBox);

impl Container for GridBox {}

impl OrientationAttribute for GridBox {}

#[macro_export]
macro_rules! grid_box {
    ($($c:expr),*) => {
        {
            use std::ptr;
            let mut handles = Vec::new();
            $(
                // The control has to be stored in a binding to ensure it isn't dropped before
                // it is added as a child of the container. (Otherwise, the control is destroyed.)
                let c = $c;
                handles.push(c.handle());
            )*
            handles.push(ptr::null_mut());
            unsafe { GridBox::from_handles(handles.as_mut_ptr()) }
        }
    };
    ($($c:expr,)*) => { grid_box!($($c),*) };
}
<|endoftext|>


<commit_before>use std::mem;
use std::collections::{VecDeque, HashMap, HashSet};

use rand::{self, Rng, ChaChaRng};

use ogg::{OggTrack, OggTrackBuf};
use ogg::vorbis::{Comments, VorbisHeader};
use ireul_interface::proxy::track::model::{self, Handle};

struct HandleAllocator<R> {
    rng: R,
    limit: usize,
    allocated: HashSet<u64>,
}

impl<R> HandleAllocator<R> where R: Rng {
    pub fn new(rng: R, limit: usize) -> HandleAllocator<R> {
        HandleAllocator {
            rng: rng,
            limit: limit,
            allocated: HashSet::new(),
        }
    }

    pub fn generate(&mut self) -> Result<Handle, ()> {
        if self.limit <= self.allocated.len() {
            return Err(());
        }

        let new_handle;
        loop {
            let foo = self.rng.next_u64();
            if !self.allocated.contains(&foo) {
                new_handle = foo;
                break;
            }
        }

        println!("EMITTING HANDLE {:#x}", new_handle);
        self.allocated.insert(new_handle);
        Ok(Handle(new_handle))
    }

    pub fn dispose(&mut self, handle: Handle) -> Result<(), Handle> {
        match self.allocated.remove(&handle.0) {
            true => Ok(()),
            false => Err(handle),
        }
    }
}

#[derive(Clone)]
pub struct Track {
    handle: Handle,
    data: OggTrackBuf,
    comments: Comments,

    artist: String,
    album: String,
    title: String,

    sample_rate: u64,
    sample_count: u64,
}

impl Track {
    pub fn from_ogg_track(handle: Handle, ogg: OggTrackBuf) -> Track {
        use std::ascii::AsciiExt;

        let id_header = match VorbisHeader::find_identification(ogg.pages()) {
            Ok(header) => header.identification_header(),
            Err(_) => None
        }.expect("Invalid OggTrackBuf");

        let comments = match VorbisHeader::find_comments(ogg.pages()) {
            Ok(header) => header.comments(),
            Err(_) => None
        }.expect("Invalid OggTrackBuf");

        let mut sample_count = 0;
        for page in ogg.pages() {
            let page_pos = page.position();
            if sample_count < page_pos {
                sample_count = page_pos;
            }
        }

        let mut artist: Option<String> = None;
        let mut album: Option<String> = None;
        let mut title: Option<String> = None;

        for &(ref key, ref val) in comments.comments.iter() {
            if key.eq_ignore_ascii_case("ARTIST") {
                artist = Some(val.clone());
            }
            if key.eq_ignore_ascii_case("ALBUM") {
                album = Some(val.clone());
            }
            if key.eq_ignore_ascii_case("TITLE") {
                title = Some(val.clone());
            }
        }

        Track {
            handle: handle,
            data: ogg,
            comments: comments,

            artist: artist.unwrap_or_else(|| "".to_string()),
            album: album.unwrap_or_else(|| "".to_string()),
            title: title.unwrap_or_else(|| "".to_string()),

            sample_rate: id_header.audio_sample_rate as u64,
            sample_count: sample_count,
        }
    }

    pub fn into_inner(self) -> OggTrackBuf {
        self.data
    }

    pub fn get_track_info(&self) -> model::TrackInfo {
        model::TrackInfo {
            handle: self.handle,

            artist: self.artist.clone(),
            album: self.album.clone(),
            title: self.title.clone(),

            sample_rate: self.sample_rate,
            sample_count: self.sample_count,
            sample_position: 0,
        }
    }
}

pub struct PlayQueue {
    halloc: HandleAllocator<ChaChaRng>,
    items: VecDeque<Track>,
    history: VecDeque<model::TrackInfo>,
}

impl PlayQueue {
    pub fn new(limit: usize) -> PlayQueue {
        let rng: ChaChaRng = rand::thread_rng().gen();
        PlayQueue {
            halloc: HandleAllocator::new(rng, limit),
            items: VecDeque::new(),
            history: VecDeque::new(),
        }
    }

    #[allow(dead_code)] // queue manip stub
    pub fn reorder(&mut self, handle_ord: &[Handle]) {
        let old_items: VecDeque<Track> = mem::replace(&mut self.items, VecDeque::new());

        let mut map: HashMap<Handle, Track> = old_items.into_iter().map(|pq| (pq.handle, pq)).collect();

        for handle in handle_ord.iter() {
            match map.remove(handle) {
                Some(item) => {
                    self.items.push_back(item);
                },
                None => (),
            }
        }
    }

    #[allow(dead_code)] // queue manip stub
    pub fn remove_by_handle(&mut self, handle: Handle) {
        let old_items: VecDeque<Track> = mem::replace(&mut self.items, VecDeque::new());
        for item in old_items.into_iter() {
            if item.handle != handle {
                self.items.push_back(item);
            }
        }
    }

    pub fn add_track(&mut self, track: &OggTrack) -> Result<Handle, PlayQueueError> {
        let handle = try!(self.halloc.generate()
                .map_err(|()| PlayQueueError::Full));

        self.items.push_back(Track::from_ogg_track(handle, track.to_owned()));
        Ok(handle)
    }

    pub fn pop_track(&mut self) -> Option<Track> {
        match self.items.pop_front() {
            Some(track) => {
                self.halloc.dispose(track.handle).unwrap();
                Some(track)
            },
            None => None,
        }
    }

    pub fn track_infos(&self) -> Vec<model::TrackInfo> {
        self.items.iter()
            .map(Track::get_track_info)
            .collect()
    }

    pub fn add_history(&mut self, tinfo: model::TrackInfo) {
        self.history.push_front(tinfo);
        while 10 < self.history.len() {
            self.history.pop_back();
        }
    }

    pub fn get_history(&self) -> Vec<model::TrackInfo> {
        self.history.iter().cloned().collect()
    }
}

pub enum PlayQueueError {
    Full,
}
<commit_msg>core: reverse history<commit_after>use std::mem;
use std::collections::{VecDeque, HashMap, HashSet};

use rand::{self, Rng, ChaChaRng};

use ogg::{OggTrack, OggTrackBuf};
use ogg::vorbis::{Comments, VorbisHeader};
use ireul_interface::proxy::track::model::{self, Handle};

struct HandleAllocator<R> {
    rng: R,
    limit: usize,
    allocated: HashSet<u64>,
}

impl<R> HandleAllocator<R> where R: Rng {
    pub fn new(rng: R, limit: usize) -> HandleAllocator<R> {
        HandleAllocator {
            rng: rng,
            limit: limit,
            allocated: HashSet::new(),
        }
    }

    pub fn generate(&mut self) -> Result<Handle, ()> {
        if self.limit <= self.allocated.len() {
            return Err(());
        }

        let new_handle;
        loop {
            let foo = self.rng.next_u64();
            if !self.allocated.contains(&foo) {
                new_handle = foo;
                break;
            }
        }

        println!("EMITTING HANDLE {:#x}", new_handle);
        self.allocated.insert(new_handle);
        Ok(Handle(new_handle))
    }

    pub fn dispose(&mut self, handle: Handle) -> Result<(), Handle> {
        match self.allocated.remove(&handle.0) {
            true => Ok(()),
            false => Err(handle),
        }
    }
}

#[derive(Clone)]
pub struct Track {
    handle: Handle,
    data: OggTrackBuf,
    comments: Comments,

    artist: String,
    album: String,
    title: String,

    sample_rate: u64,
    sample_count: u64,
}

impl Track {
    pub fn from_ogg_track(handle: Handle, ogg: OggTrackBuf) -> Track {
        use std::ascii::AsciiExt;

        let id_header = match VorbisHeader::find_identification(ogg.pages()) {
            Ok(header) => header.identification_header(),
            Err(_) => None
        }.expect("Invalid OggTrackBuf");

        let comments = match VorbisHeader::find_comments(ogg.pages()) {
            Ok(header) => header.comments(),
            Err(_) => None
        }.expect("Invalid OggTrackBuf");

        let mut sample_count = 0;
        for page in ogg.pages() {
            let page_pos = page.position();
            if sample_count < page_pos {
                sample_count = page_pos;
            }
        }

        let mut artist: Option<String> = None;
        let mut album: Option<String> = None;
        let mut title: Option<String> = None;

        for &(ref key, ref val) in comments.comments.iter() {
            if key.eq_ignore_ascii_case("ARTIST") {
                artist = Some(val.clone());
            }
            if key.eq_ignore_ascii_case("ALBUM") {
                album = Some(val.clone());
            }
            if key.eq_ignore_ascii_case("TITLE") {
                title = Some(val.clone());
            }
        }

        Track {
            handle: handle,
            data: ogg,
            comments: comments,

            artist: artist.unwrap_or_else(|| "".to_string()),
            album: album.unwrap_or_else(|| "".to_string()),
            title: title.unwrap_or_else(|| "".to_string()),

            sample_rate: id_header.audio_sample_rate as u64,
            sample_count: sample_count,
        }
    }

    pub fn into_inner(self) -> OggTrackBuf {
        self.data
    }

    pub fn get_track_info(&self) -> model::TrackInfo {
        model::TrackInfo {
            handle: self.handle,

            artist: self.artist.clone(),
            album: self.album.clone(),
            title: self.title.clone(),

            sample_rate: self.sample_rate,
            sample_count: self.sample_count,
            sample_position: 0,
        }
    }
}

pub struct PlayQueue {
    halloc: HandleAllocator<ChaChaRng>,
    items: VecDeque<Track>,
    history: VecDeque<model::TrackInfo>,
}

impl PlayQueue {
    pub fn new(limit: usize) -> PlayQueue {
        let rng: ChaChaRng = rand::thread_rng().gen();
        PlayQueue {
            halloc: HandleAllocator::new(rng, limit),
            items: VecDeque::new(),
            history: VecDeque::new(),
        }
    }

    #[allow(dead_code)] // queue manip stub
    pub fn reorder(&mut self, handle_ord: &[Handle]) {
        let old_items: VecDeque<Track> = mem::replace(&mut self.items, VecDeque::new());

        let mut map: HashMap<Handle, Track> = old_items.into_iter().map(|pq| (pq.handle, pq)).collect();

        for handle in handle_ord.iter() {
            match map.remove(handle) {
                Some(item) => {
                    self.items.push_back(item);
                },
                None => (),
            }
        }
    }

    #[allow(dead_code)] // queue manip stub
    pub fn remove_by_handle(&mut self, handle: Handle) {
        let old_items: VecDeque<Track> = mem::replace(&mut self.items, VecDeque::new());
        for item in old_items.into_iter() {
            if item.handle != handle {
                self.items.push_back(item);
            }
        }
    }

    pub fn add_track(&mut self, track: &OggTrack) -> Result<Handle, PlayQueueError> {
        let handle = try!(self.halloc.generate()
                .map_err(|()| PlayQueueError::Full));

        self.items.push_back(Track::from_ogg_track(handle, track.to_owned()));
        Ok(handle)
    }

    pub fn pop_track(&mut self) -> Option<Track> {
        match self.items.pop_front() {
            Some(track) => {
                self.halloc.dispose(track.handle).unwrap();
                Some(track)
            },
            None => None,
        }
    }

    pub fn track_infos(&self) -> Vec<model::TrackInfo> {
        self.items.iter()
            .map(Track::get_track_info)
            .collect()
    }

    pub fn add_history(&mut self, tinfo: model::TrackInfo) {
        self.history.push_back(tinfo);
        while 10 < self.history.len() {
            self.history.pop_front();
        }
    }

    pub fn get_history(&self) -> Vec<model::TrackInfo> {
        self.history.iter().cloned().collect()
    }
}

pub enum PlayQueueError {
    Full,
}
<|endoftext|>


<commit_before>use nalgebra;
use num::Num;
use std::cmp;
use std::convert::From;
use std::marker::PhantomData;
use std::ops;

use math::Clamp;

pub trait ClampedRange<T> {
    fn max_value() -> T;
    fn min_value() -> T;
}

pub struct Clamped<T, R>(T, PhantomData<R>)
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>;

impl<T, R> Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    pub fn new(value: T) -> Self {
        Clamped(nalgebra::clamp(value, R::min_value(), R::max_value()), PhantomData)
    }

    pub fn max_value() -> Self {
        Clamped(R::max_value(), PhantomData)
    }

    pub fn min_value() -> Self {
        Clamped(R::min_value(), PhantomData)
    }

    pub fn unclamped(&self) -> T {
        self.0
    }
}

impl<T, R> Clamp<Clamped<T, R>> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clamp(&self, min: Self, max: Self) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T, R> Clone for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clone(&self) -> Self {
        Clamped(self.0, PhantomData)
    }
}

impl<T, R> Copy for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> From<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T, R> cmp::Eq for Clamped<T, R>
    where T: Copy + cmp::Eq + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> cmp::Ord for Clamped<T, R>
    where T: Copy + Num + cmp::Ord + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl<T, R> cmp::PartialEq for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T, R> cmp::PartialEq<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &T) -> bool {
        self.0.eq(other)
    }
}

impl<T, R> cmp::PartialOrd for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl<T, R> cmp::PartialOrd<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        self.0.partial_cmp(other)
    }
}

impl<T, R> ops::Add for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: Self) -> Self::Output {
        Self::new(self.0.add(other.0))
    }
}

impl<T, R> ops::Add<T> for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: T) -> Self::Output {
        Self::new(self.0.add(other))
    }
}

impl<T, R> ops::Deref for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, R> ops::Div for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: Self) -> Self::Output {
        Self::new(self.0.div(other.0))
    }
}

impl<T, R> ops::Div<T> for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: T) -> Self::Output {
        Self::new(self.0.div(other))
    }
}

impl<T, R> ops::Mul for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: Self) -> Self::Output {
        Self::new(self.0.mul(other.0))
    }
}

impl<T, R> ops::Mul<T> for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: T) -> Self::Output {
        Self::new(self.0.mul(other))
    }
}

impl<T, R> ops::Neg for Clamped<T, R>
    where T: Copy + ops::Neg<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn neg(self) -> Self::Output {
        Self::new(self.0.neg())
    }
}

impl<T, R> ops::Sub for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: Self) -> Self::Output {
        Self::new(self.0.sub(other.0))
    }
}

impl<T, R> ops::Sub<T> for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: T) -> Self::Output {
        Self::new(self.0.sub(other))
    }
}
<commit_msg>Rename `unclamped` to `to_inner`.<commit_after>use nalgebra;
use num::Num;
use std::cmp;
use std::convert::From;
use std::marker::PhantomData;
use std::ops;

use math::Clamp;

pub trait ClampedRange<T> {
    fn max_value() -> T;
    fn min_value() -> T;
}

pub struct Clamped<T, R>(T, PhantomData<R>)
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>;

impl<T, R> Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    pub fn new(value: T) -> Self {
        Clamped(nalgebra::clamp(value, R::min_value(), R::max_value()), PhantomData)
    }

    pub fn max_value() -> Self {
        Clamped(R::max_value(), PhantomData)
    }

    pub fn min_value() -> Self {
        Clamped(R::min_value(), PhantomData)
    }

    pub fn to_inner(&self) -> T {
        self.0
    }
}

impl<T, R> Clamp<Clamped<T, R>> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clamp(&self, min: Self, max: Self) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T, R> Clone for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clone(&self) -> Self {
        Clamped(self.0, PhantomData)
    }
}

impl<T, R> Copy for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> From<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T, R> cmp::Eq for Clamped<T, R>
    where T: Copy + cmp::Eq + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> cmp::Ord for Clamped<T, R>
    where T: Copy + Num + cmp::Ord + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl<T, R> cmp::PartialEq for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T, R> cmp::PartialEq<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &T) -> bool {
        self.0.eq(other)
    }
}

impl<T, R> cmp::PartialOrd for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl<T, R> cmp::PartialOrd<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        self.0.partial_cmp(other)
    }
}

impl<T, R> ops::Add for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: Self) -> Self::Output {
        Self::new(self.0.add(other.0))
    }
}

impl<T, R> ops::Add<T> for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: T) -> Self::Output {
        Self::new(self.0.add(other))
    }
}

impl<T, R> ops::Deref for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, R> ops::Div for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: Self) -> Self::Output {
        Self::new(self.0.div(other.0))
    }
}

impl<T, R> ops::Div<T> for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: T) -> Self::Output {
        Self::new(self.0.div(other))
    }
}

impl<T, R> ops::Mul for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: Self) -> Self::Output {
        Self::new(self.0.mul(other.0))
    }
}

impl<T, R> ops::Mul<T> for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: T) -> Self::Output {
        Self::new(self.0.mul(other))
    }
}

impl<T, R> ops::Neg for Clamped<T, R>
    where T: Copy + ops::Neg<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn neg(self) -> Self::Output {
        Self::new(self.0.neg())
    }
}

impl<T, R> ops::Sub for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: Self) -> Self::Output {
        Self::new(self.0.sub(other.0))
    }
}

impl<T, R> ops::Sub<T> for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: T) -> Self::Output {
        Self::new(self.0.sub(other))
    }
}
<|endoftext|>


<commit_before>use num::{BigUint, One, Zero};

const BITS: usize = 255;
const A24: u32 = 121665;

/// This is horrible
/// and insecure
pub fn x25519(k: &[u8], u: &[u8]) -> Vec<u8> {
    let len = (BITS + 7) / 8;
    assert_eq!(32, k.len());
    assert_eq!(len, u.len());
    let k = decode_scalar(k);
    let x_1 = decode_u_coordinate(u);
    let mut x_2 = One::one();
    let mut z_2 = Zero::zero();
    let mut x_3 = x_1.clone();
    let mut z_3 = One::one();
    let mut swap = Zero::zero();
    let a24: BigUint = A24.into();
    let p: BigUint = (BigUint::from(1u8) << 255) - BigUint::from(19u8);

    for t in (0..BITS).rev() {
        let k_t = (&k >> t) & BigUint::from(1u8);
        swap = swap ^ &k_t;
        cswap(&swap, &mut x_2, &mut x_3);
        cswap(&swap, &mut z_2, &mut z_3);
        swap = k_t;

        let a = (&x_2 + &z_2) % &p;
        let aa = &a * &a % &p;
        let b = (&p + &x_2 - &z_2) % &p;
        let bb = &b * &b % &p;
        let e = (&p + &aa - &bb) % &p;
        let c = (&x_3 + &z_3) % &p;
        let d = (&p + &x_3 - &z_3) % &p;
        let da = d * a % &p;
        let cb = c * b % &p;
        x_3 = (&da + &cb) % &p;
        x_3 = &x_3 * &x_3 % &p;
        z_3 = (&p + da - cb) % &p;
        z_3 = &x_1 * &z_3 * &z_3 % &p;
        x_2 = &aa * bb % &p;
        z_2 = &e * (aa + &a24 * &e) % &p;
    }
    cswap(&swap, &mut x_2, &mut x_3);
    cswap(&swap, &mut z_2, &mut z_3);
    let mut x = (x_2 * pow(z_2, &p) % &p).to_bytes_le();
    while x.len() < len {
        x.push(0);
    }
    x
}

fn decode_u_coordinate(u: &[u8]) -> BigUint {
    let mut u_vec = u.to_vec();
    if BITS % 8 != 0 {
        if let Some(last) = u_vec.last_mut() {
            *last &= (1 << (BITS % 8)) - 1;
        }
    }
    BigUint::from_bytes_le(&u_vec)
}

fn decode_scalar(k: &[u8]) -> BigUint {
    let mut k_vec = k.to_vec();
    k_vec[0] &= 248;
    k_vec[31] &= 127;
    k_vec[31] |= 64;
    BigUint::from_bytes_le(&k_vec)
}

fn cswap(swap: &BigUint, x_2: &mut BigUint, x_3: &mut BigUint) {
    let dummy = mask(swap) & (&*x_2 ^ &*x_3);
    *x_2 = &*x_2 ^ &dummy;
    *x_3 = &*x_3 ^ &dummy;
}

fn mask(swap: &BigUint) -> BigUint {
    (BigUint::from(1u8) << 255) - swap
}

fn pow(z: BigUint, p: &BigUint) -> BigUint {
    let two: BigUint = 2u8.into();
    let mut res: BigUint = One::one();
    let mut base = z;
    let mut exponent = p - &two;
    while exponent > Zero::zero() {
        if &exponent % &two == One::one() {
            res = res * &base % p;
        }
        exponent = exponent >> 1;
        base = &base * &base % p;
    }
    res
}

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

    fn check(x: &str, k: &str, u: &str) {
        assert_eq!(h2b(x), x25519(&h2b(k), &h2b(u)));
    }

    fn check_decode(k: &str, u: &str, k10: &str, u10: &str) {
        assert_eq!(
            BigUint::parse_bytes(k10.as_bytes(), 10).unwrap(),
            decode_scalar(&h2b(k))
        );
        assert_eq!(
            BigUint::parse_bytes(u10.as_bytes(), 10).unwrap(),
            decode_u_coordinate(&h2b(u))
        );
    }

    #[test]
    fn test_x25519() {
        let mut k = "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4";
        let mut u = "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c";
        let mut x = "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552";
        check(x, k, u);

        let mut k10;
        let mut u10;
        k10 = "31029842492115040904895560451863089656472772604678260265531221036453811406496";
        u10 = "34426434033919594451155107781188821651316167215306631574996226621102155684838";
        check_decode(k, u, k10, u10);

        k = "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d";
        u = "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493";
        x = "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957";
        check(x, k, u);

        k10 = "35156891815674817266734212754503633747128614016119564763269015315466259359304";
        u10 = "8883857351183929894090759386610649319417338800022198945255395922347792736741";
        check_decode(k, u, k10, u10);

        let mut k = h2b(
            "0900000000000000000000000000000000000000000000000000000000000000",
        );
        let mut u = k.clone();
        // too slow to do 1 mil iterations right now, or 1000 without --release
        for i in 0..1 {
            let x = x25519(&k, &u);
            if i == 0 {
                assert_eq!(
                    h2b(
                        "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
                    ),
                    x
                );
            } else if i == 999 {
                assert_eq!(
                    h2b(
                        "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
                    ),
                    x
                );
            } else if i == 999999 {
                assert_eq!(
                    h2b(
                        "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
                    ),
                    x
                );
            }
            u = k;
            k = x;
        }
    }
}
<commit_msg>curve25519: gen_pk()<commit_after>use num::{BigUint, One, Zero};

const BITS: usize = 255;
const A24: u32 = 121665;

pub fn gen_pk(sk: &[u8]) -> Vec<u8> {
    let mut u = [0; 32];
    u[0] = 9;
    x25519(sk, &u)
}

/// This is horrible
/// and insecure
pub fn x25519(k: &[u8], u: &[u8]) -> Vec<u8> {
    let len = (BITS + 7) / 8;
    assert_eq!(32, k.len());
    assert_eq!(len, u.len());
    let k = decode_scalar(k);
    let x_1 = decode_u_coordinate(u);
    let mut x_2 = One::one();
    let mut z_2 = Zero::zero();
    let mut x_3 = x_1.clone();
    let mut z_3 = One::one();
    let mut swap = Zero::zero();
    let a24: BigUint = A24.into();
    let p: BigUint = (BigUint::from(1u8) << 255) - BigUint::from(19u8);

    for t in (0..BITS).rev() {
        let k_t = (&k >> t) & BigUint::from(1u8);
        swap = swap ^ &k_t;
        cswap(&swap, &mut x_2, &mut x_3);
        cswap(&swap, &mut z_2, &mut z_3);
        swap = k_t;

        let a = (&x_2 + &z_2) % &p;
        let aa = &a * &a % &p;
        let b = (&p + &x_2 - &z_2) % &p;
        let bb = &b * &b % &p;
        let e = (&p + &aa - &bb) % &p;
        let c = (&x_3 + &z_3) % &p;
        let d = (&p + &x_3 - &z_3) % &p;
        let da = d * a % &p;
        let cb = c * b % &p;
        x_3 = (&da + &cb) % &p;
        x_3 = &x_3 * &x_3 % &p;
        z_3 = (&p + da - cb) % &p;
        z_3 = &x_1 * &z_3 * &z_3 % &p;
        x_2 = &aa * bb % &p;
        z_2 = &e * (aa + &a24 * &e) % &p;
    }
    cswap(&swap, &mut x_2, &mut x_3);
    cswap(&swap, &mut z_2, &mut z_3);
    let mut x = (x_2 * pow(z_2, &p) % &p).to_bytes_le();
    while x.len() < len {
        x.push(0);
    }
    x
}

fn decode_u_coordinate(u: &[u8]) -> BigUint {
    let mut u_vec = u.to_vec();
    if BITS % 8 != 0 {
        if let Some(last) = u_vec.last_mut() {
            *last &= (1 << (BITS % 8)) - 1;
        }
    }
    BigUint::from_bytes_le(&u_vec)
}

fn decode_scalar(k: &[u8]) -> BigUint {
    let mut k_vec = k.to_vec();
    k_vec[0] &= 248;
    k_vec[31] &= 127;
    k_vec[31] |= 64;
    BigUint::from_bytes_le(&k_vec)
}

fn cswap(swap: &BigUint, x_2: &mut BigUint, x_3: &mut BigUint) {
    let dummy = mask(swap) & (&*x_2 ^ &*x_3);
    *x_2 = &*x_2 ^ &dummy;
    *x_3 = &*x_3 ^ &dummy;
}

fn mask(swap: &BigUint) -> BigUint {
    (BigUint::from(1u8) << 255) - swap
}

fn pow(z: BigUint, p: &BigUint) -> BigUint {
    let two: BigUint = 2u8.into();
    let mut res: BigUint = One::one();
    let mut base = z;
    let mut exponent = p - &two;
    while exponent > Zero::zero() {
        if &exponent % &two == One::one() {
            res = res * &base % p;
        }
        exponent = exponent >> 1;
        base = &base * &base % p;
    }
    res
}

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

    fn check(x: &str, k: &str, u: &str) {
        assert_eq!(h2b(x), x25519(&h2b(k), &h2b(u)));
    }

    fn check_decode(k: &str, u: &str, k10: &str, u10: &str) {
        assert_eq!(
            BigUint::parse_bytes(k10.as_bytes(), 10).unwrap(),
            decode_scalar(&h2b(k))
        );
        assert_eq!(
            BigUint::parse_bytes(u10.as_bytes(), 10).unwrap(),
            decode_u_coordinate(&h2b(u))
        );
    }

    #[test]
    fn test_x25519() {
        let mut k = "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4";
        let mut u = "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c";
        let mut x = "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552";
        check(x, k, u);

        let mut k10;
        let mut u10;
        k10 = "31029842492115040904895560451863089656472772604678260265531221036453811406496";
        u10 = "34426434033919594451155107781188821651316167215306631574996226621102155684838";
        check_decode(k, u, k10, u10);

        k = "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d";
        u = "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493";
        x = "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957";
        check(x, k, u);

        k10 = "35156891815674817266734212754503633747128614016119564763269015315466259359304";
        u10 = "8883857351183929894090759386610649319417338800022198945255395922347792736741";
        check_decode(k, u, k10, u10);

        let mut k = h2b(
            "0900000000000000000000000000000000000000000000000000000000000000",
        );
        let mut u = k.clone();
        // too slow to do 1 mil iterations right now, or 1000 without --release
        for i in 0..1 {
            let x = x25519(&k, &u);
            if i == 0 {
                assert_eq!(
                    h2b(
                        "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
                    ),
                    x
                );
            } else if i == 999 {
                assert_eq!(
                    h2b(
                        "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079",
                    ),
                    x
                );
            } else if i == 999999 {
                assert_eq!(
                    h2b(
                        "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424",
                    ),
                    x
                );
            }
            u = k;
            k = x;
        }
    }

    #[test]
    fn test_gen_pk() {
        let sk_a = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a";
        let pk_a = "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a";
        let sk_b = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
        let pk_b = "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f";
        let k = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742";
        assert_eq!(h2b(pk_a), gen_pk(&h2b(sk_a)));
        assert_eq!(h2b(pk_b), gen_pk(&h2b(sk_b)));
        check(k, sk_a, pk_b);
        check(k, sk_b, pk_a);
    }
}
<|endoftext|>


<commit_before>use html5ever::rcdom::NodeEnum::{Element, Text};
use html5ever::rcdom::{Handle, RcDom};
use super::Entry;

pub fn find_entry_elements(dom: &mut RcDom) -> Vec<Option<Entry>> {
    let mut entries = vec![];
    walk_tree(&dom.document, &mut entries);
    entries
}

pub fn walk_tree(h: &Handle, entries: &mut Vec<Option<Entry>>) {
    for e in h.borrow().children.iter() {
        if let Element(ref name, _, ref attrs) = e.borrow().node {
            let tag = &(*name.local.to_ascii_lowercase());
            if let Some(class_attr) = attrs.iter()
                                           .find(|ref x| x.name == qualname!("", "class"))
                                           .and_then(|c| Some(c.clone().value.to_string())) {

                match (tag, class_attr.as_str()) {
                    ("h3", "impl") => entries.push(Entry::new(e.clone(),
                                                              "Method",
                                                              extract_entry_name(&e, "in-band"),
                                                              true)),
                    ("h4", "method") => entries.push(Entry::new(e.clone(),
                                                                "Method",
                                                                extract_entry_name(&e, "fnname"),
                                                                false)),
                    ("h4", "type") => entries.push(Entry::new(e.clone(),
                                                              "Type",
                                                              extract_entry_name(&e, "type"),
                                                              false)),
                    ("section", "content constant") =>
                        entries.push(Entry::new(e.clone(),
                                                "Constant",
                                                extract_entry_name(&e, "constant"),
                                                false)),
                    ("section", "content enum") =>
                        entries.push(Entry::new(e.clone(),
                                                "Enum",
                                                extract_entry_name(&e, "enum"),
                                                false)),
                    ("section", "content fn") =>
                        entries.push(Entry::new(e.clone(),
                                                "Function",
                                                extract_entry_name(&e, "fn"),
                                                false)),
                    ("section", "content macro") =>
                        entries.push(Entry::new(e.clone(),
                                                "Macro",
                                                extract_entry_name(&e, "macro"),
                                                false)),
                    ("section", "content mod") =>
                        entries.push(Entry::new(e.clone(),
                                                "Module",
                                                extract_entry_name(&e, "mod"),
                                                false)),
                    ("section", "content struct") =>
                        entries.push(Entry::new(e.clone(),
                                                "Struct",
                                                extract_entry_name(&e, "struct"),
                                                false)),
                    ("section", "content trait") =>
                        entries.push(Entry::new(e.clone(),
                                                "Trait",
                                                extract_entry_name(&e, "trait"),
                                                false)),
                    (_, _) => {}
                }
            }
        }
        walk_tree(e, entries);
    }
}

pub fn extract_entry_name(e: &Handle, element_class: &str) -> Option<String> {
    find_element_with_class(e, element_class).and_then(|x| get_text(&x))
}

fn find_element_with_class(h: &Handle, class_value: &str) -> Option<Handle> {
    for e in h.borrow().children.iter() {
        if let Element(_, _, ref attrs) = e.borrow().node {
            if attrs.iter()
                    .find(|ref attr| attr.name == qualname!("", "class"))
                    .and_then(|attr| Some(attr.value.to_string() == class_value)) !=
               None {
                return Some(e.clone());
            }
        }

        // recurse down and check children
        if let Some(e) = find_element_with_class(e, class_value) {
            return Some(e);
        }
    }
    None
}

fn get_text(h: &Handle) -> Option<String> {
    let mut text_tokens = Vec::new();
    let node = h.borrow();

    // get all text from current and all descendent elements: hallo heise! -> hallo heise !
    for e in node.children.iter() {
        match e.borrow().node {
            Text(ref t) => text_tokens.push(t.to_string()),
            _ => if let Some(s) = get_text(e) {
                text_tokens.push(s)
            },
        }
    }

    // adjust extracted text: mainly remove white space and some unicode characters
    if text_tokens.len() > 0 {
        Some(String::from(text_tokens.join(" ").trim())
                 .replace("\u{a0}", "")
                 .replace(" >", ">")
                 .replace(" <", "<")
                 .replace("  ", " "))
    } else {
        None
    }
}
<commit_msg>Add comment<commit_after>use html5ever::rcdom::NodeEnum::{Element, Text};
use html5ever::rcdom::{Handle, RcDom};
use super::Entry;

pub fn find_entry_elements(dom: &mut RcDom) -> Vec<Option<Entry>> {
    let mut entries = vec![];
    walk_tree(&dom.document, &mut entries);
    entries
}

pub fn walk_tree(h: &Handle, entries: &mut Vec<Option<Entry>>) {
    for e in h.borrow().children.iter() {
        if let Element(ref name, _, ref attrs) = e.borrow().node {
            let tag = &(*name.local.to_ascii_lowercase());
            if let Some(class_attr) = attrs.iter()
                                           .find(|ref x| x.name == qualname!("", "class"))
                                           .and_then(|c| Some(c.clone().value.to_string())) {

                match (tag, class_attr.as_str()) {
                    ("h3", "impl") => entries.push(Entry::new(e.clone(),
                                                              "Method",
                                                              extract_entry_name(&e, "in-band"),
                                                              true)),
                    ("h4", "method") => entries.push(Entry::new(e.clone(),
                                                                "Method",
                                                                extract_entry_name(&e, "fnname"),
                                                                false)),
                    ("h4", "type") => entries.push(Entry::new(e.clone(),
                                                              "Type",
                                                              extract_entry_name(&e, "type"),
                                                              false)),
                    ("section", "content constant") =>
                        entries.push(Entry::new(e.clone(),
                                                "Constant",
                                                extract_entry_name(&e, "constant"),
                                                false)),
                    ("section", "content enum") =>
                        entries.push(Entry::new(e.clone(),
                                                "Enum",
                                                extract_entry_name(&e, "enum"),
                                                false)),
                    ("section", "content fn") =>
                        entries.push(Entry::new(e.clone(),
                                                "Function",
                                                extract_entry_name(&e, "fn"),
                                                false)),
                    ("section", "content macro") =>
                        entries.push(Entry::new(e.clone(),
                                                "Macro",
                                                extract_entry_name(&e, "macro"),
                                                false)),
                    ("section", "content mod") =>
                        entries.push(Entry::new(e.clone(),
                                                "Module",
                                                extract_entry_name(&e, "mod"),
                                                false)),
                    ("section", "content struct") =>
                        entries.push(Entry::new(e.clone(),
                                                "Struct",
                                                extract_entry_name(&e, "struct"),
                                                false)),
                    ("section", "content trait") =>
                        entries.push(Entry::new(e.clone(),
                                                "Trait",
                                                extract_entry_name(&e, "trait"),
                                                false)),
                    (_, _) => {}
                }
            }
        }
        walk_tree(e, entries);
    }
}

pub fn extract_entry_name(e: &Handle, element_class: &str) -> Option<String> {
    find_element_with_class(e, element_class).and_then(|x| get_text(&x))
}

fn find_element_with_class(h: &Handle, class_value: &str) -> Option<Handle> {
    for e in h.borrow().children.iter() {
        if let Element(_, _, ref attrs) = e.borrow().node {
            if attrs.iter()
                    .find(|ref attr| attr.name == qualname!("", "class"))
                    .and_then(|attr| Some(attr.value.to_string() == class_value)) !=
               None {
                return Some(e.clone());
            }
        }

        // recurse down and check children
        if let Some(e) = find_element_with_class(e, class_value) {
            return Some(e);
        }
    }
    None
}

fn get_text(h: &Handle) -> Option<String> {
    let mut text_tokens = Vec::new();
    let node = h.borrow();

    // get all text from current and all descendent elements: hallo heise! -> hallo heise !
    for e in node.children.iter() {
        match e.borrow().node {
            Text(ref t) => text_tokens.push(t.to_string()),

            // if node is not a text node, recurse down
            _ => if let Some(s) = get_text(e) {
                text_tokens.push(s)
            },
        }
    }

    // adjust extracted text: mainly remove white space and some unicode characters
    if text_tokens.len() > 0 {
        Some(String::from(text_tokens.join(" ").trim())
                 .replace("\u{a0}", "")
                 .replace(" >", ">")
                 .replace(" <", "<")
                 .replace("  ", " "))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>//TODO: should handle memory mapped io (e.g. gpu buffers, cartridge). Also this needs to handle
// mirrored memory and bank switching where appropriate
use std::fmt;

/// Basic struct for memory management
pub struct MMU {
    data: [u8; 65536]
}

impl fmt::Debug for MMU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MMU 64k")
    }
}

impl MMU {

    pub fn new() -> MMU {
        MMU {
            data: [1; 65536]
        }
    }

    /// reads a byte at the memory address specified
    pub fn read_b(&self, addr : u16) -> u8 {
        self.data[addr as usize]
    }

    pub fn write_b(&mut self, addr : u16, data : u8) {
        self.data[addr as usize] = data;
    }

}
<commit_msg>Added initial memory mapping for read<commit_after>use std::fmt;
use std::cell::Cell;

/// The Memory Management Unit.
/// Provides access to all mapped memory in the system, including I/O and graphics.
pub struct MMU {
    pub loading_bios: Cell<bool>,

    data: [u8; 65536]
}

impl fmt::Debug for MMU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MMU 64k")
    }
}

impl MMU {

    pub fn new() -> MMU {
        MMU {
            loading_bios: Cell::new(true),
            data: [1; 65536]
        }
    }

    /// reads a byte at the memory address specified
    pub fn read_b(&self, addr : u16) -> u8 {
        // when PC first reaches 0x100, the BIOS data is not addressable anymore.
        // using Cell sucks, but this is one of the few cases mentioned by official docs where
        // it is an option. Read is logically an immutable operation, but we need to make the
        // bios unaddressable after its first read.
        if self.loading_bios.get() && addr == 0x0100 {
            self.loading_bios.set(false);
        }

        match addr {
            // bios area, 256B long for regular gameboy.
            0 ... 0x00FF if self.loading_bios.get() => {
                0
            },
            // ROM0 area, this is banked memory, it will swap according to selected bank
            0x0000 ... 0x3FFF if !self.loading_bios.get() => {
                0
            },
            // ROM1 area, 16kB unbanked data
            0x4000 ... 0x7FFF => {
                0
            },
            // Graphics, 8kB VRAM
            0x8000 ... 0x9FFF => {
                0
            },
            // Switchable RAM bank, 8kB
            0xA000 ... 0xBFFF => {
                // TODO: handle RAM banks
                self.data[addr as usize]
            },
            // Internal RAM, 8kB
            0xC000 ... 0xDFFF => {
                self.data[addr as usize]
            },
            // Echo of internal RAM, this is less than 8k, up to 0xFDFF,
            0xE000 ... 0xFDFF => {
                // TODO: change address to go to actual RAM location
                0
            },
            // Sprite attribute memory, 160B
            0xFE00 ... 0xFE9F => {
                0
            },
            // empty
            0xFEA0 ... 0xFEFF | 0xFF4C ... 0xFF7F => {
                0
            },
            // I/O ports
            0xFF00 ... 0xFF4B => {
                0
            },
            // More internal RAM
            0xFF80 ... 0xFFFE => {
                0
            },
            // Interrupt Enable register
            0xFFFF => {
                0
            },

            _ => self.data[addr as usize]
        }
    }

    pub fn write_b(&mut self, addr : u16, data : u8) {
        self.data[addr as usize] = data;
    }

}
<|endoftext|>


<commit_before>use super::number::Number;
use super::distance::Distance;

#[derive(Debug)]
pub struct Point<T> {
   pub x: T,
   pub y: T
}

impl<T> Point<T> where T: Number {
   pub fn new(x: T, y: T) -> Self {
      Point {
         x: x,
         y: y
      }
   }
}

impl<T> Distance<Point<T>, T> for Point<T> where T: Number {
   fn distance(&self, other: &Self) -> T {
      let x = other.x - self.x;
      let y = other.y - self.y;
      return (x * x + y * y).sqrt()
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::super::distance::Distance;

   use super::*;

   #[bench]
   fn bench_distance_f64(b: &mut Bencher) {
      let p1 = Point::new(5_f64, 7_f64);
      let p2 = Point::new(3_f64, 2_f64);
      b.iter(|| {
         for _ in 0..black_box(1000) {
            p1.distance(&p2);
         }
      });
   }

   #[bench]
   fn bench_distance_f32(b: &mut Bencher) {
      let p1 = Point::new(5_f32, 7_f32);
      let p2 = Point::new(3_f32, 2_f32);
      b.iter(|| {
         for _ in 0..black_box(1000) {
            p1.distance(&p2);
         }
      });
   }
}
<commit_msg>Fixing the Point::distance benchmarks<commit_after>use super::number::Number;
use super::distance::Distance;

#[derive(Debug)]
pub struct Point<T> {
   pub x: T,
   pub y: T
}

impl<T> Point<T> where T: Number {
   pub fn new(x: T, y: T) -> Self {
      Point {
         x: x,
         y: y
      }
   }
}

impl<T> Distance<Point<T>, T> for Point<T> where T: Number {
   fn distance(&self, other: &Self) -> T {
      let x = other.x - self.x;
      let y = other.y - self.y;
      return (x * x + y * y).sqrt()
   }
}

#[cfg(test)]
mod tests {
   use test::{Bencher, black_box};

   use super::super::distance::Distance;

   use super::*;

   #[bench]
   fn bench_distance_f64(b: &mut Bencher) {
      let p1 = Point::new(5_f64, 7_f64);
      let p2 = Point::new(3_f64, 2_f64);
      b.iter(|| {
         for _ in 0..1000 {
            black_box(
               p1.distance(&p2)
            );
         }
      });
   }

   #[bench]
   fn bench_distance_f32(b: &mut Bencher) {
      let p1 = Point::new(5_f32, 7_f32);
      let p2 = Point::new(3_f32, 2_f32);
      b.iter(|| {
         for _ in 0..1000 {
            black_box(
               p1.distance(&p2)
            );
         }
      });
   }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};

use coreutils::extra::OptionalExt;

fn print_path(path: &str) {
    let mut entries = Vec::new();

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    let dir = fs::read_dir(path).try(&mut stderr);

    for entry_result in dir {
        let entry = entry_result.try(&mut stderr);
        let directory = entry.file_type().map(|x| x.is_dir()).unwrap_or(false);

        let file_name = entry.file_name();
        let path_str = file_name.to_str().try(&mut stderr);
        entries.push(path_str.to_owned());

        if directory {
            entries.last_mut().unwrap().push('/');
        }
    }

    entries.sort();

    for entry in entries {
        stdout.write(entry.as_bytes()).try(&mut stderr);
    }
}

fn main() {
    let path = env::args().nth(1);

    if let Some(ref x) = path {
        print_path(x);
    } else {
        print_path(".");
    } // dafuq borrowck. Really you needa do deref coercions better.
}
<commit_msg>Somebody forgot newlines between entries<commit_after>#![deny(warnings)]

extern crate coreutils;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};

use coreutils::extra::OptionalExt;

fn print_path(path: &str) {
    let mut entries = Vec::new();

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    let dir = fs::read_dir(path).try(&mut stderr);

    for entry_result in dir {
        let entry = entry_result.try(&mut stderr);
        let directory = entry.file_type().map(|x| x.is_dir()).unwrap_or(false);

        let file_name = entry.file_name();
        let path_str = file_name.to_str().try(&mut stderr);
        entries.push(path_str.to_owned());

        if directory {
            entries.last_mut().unwrap().push('/');
        }
    }

    entries.sort();

    for entry in entries {
        stdout.write(entry.as_bytes()).try(&mut stderr);
        stdout.write(b"\n").try(&mut stderr);
    }
}

fn main() {
    let path = env::args().nth(1);

    if let Some(ref x) = path {
        print_path(x);
    } else {
        print_path(".");
    } // dafuq borrowck. Really you needa do deref coercions better.
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate duk;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;
extern crate serde_protobuf;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See https://github.com/dflemstr/rq for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-h|-m|-p <type>|-y] [-J|-C|-H|-M|-P <type>|-Y] [-l <spec>|-q] [--trace] [--] [<query>]
  rq [-l <spec>|-q] [--trace] protobuf add <schema> [--base <path>]

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values (default).
  -J, --output-json
      Output should be formatted as JSON values (default).
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -h, --input-hjson
      Input is a HJSON document.
  -H, --output-hjson
      Output should be formatted as HJSON values.
  -m, --input-message-pack
      Input is formatted as MessagePack.
  -M, --output-message-pack
      Output should be formatted as MessagePack values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').
  -y, --input-yaml
      Input is a series of YAML documents.
  -Y, --output-yaml
      Output should be formatted as YAML documents.

  <query>
      A query indicating how to transform each record.

  --base <path>
      Directories are significant when dealing with protocol buffer
      schemas.  This specifies the base directory used to normalize schema
      file paths [default: .]

  -l <spec>, --log <spec>
      Configure logging using the supplied specification, in the format of
      `env_logger`, for example `rq=info,duk=trace/[0-9]+ objects kept`.
      See: https://doc.rust-lang.org/log/env_logger
  --trace
      Enable (back)trace output on error.
  -q, --quiet
      Log nothing.
"),
        flag_input_protobuf: Option<String>,
        flag_output_protobuf: Option<String>,
        flag_log: Option<String>,
        flag_base: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .version(Some(VERSION.to_owned()))
        .decode()
        .unwrap_or_else(|e| e.exit());

    setup_log(args.flag_log.as_ref().map(String::as_ref), args.flag_quiet);

    main_with_args(&args).unwrap_or_else(|e| log_error(&args, e));
}

fn main_with_args(args: &Args) -> rq::error::Result<()> {
    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            let base = path::Path::new(if let Some(ref b) = args.flag_base {
                b.as_str()
            } else {
                "."
            });
            rq::proto_index::add_file(&paths, base, schema)
        } else {
            unreachable!()
        }
    } else {
        run(&args, &paths)
    }
}

fn run(args: &Args, paths: &rq::config::Paths) -> rq::error::Result<()> {

    let stdin = io::stdin();
    let mut input = stdin.lock();

    if let Some(ref name) = args.flag_input_protobuf {
        let proto_descriptors = try!(load_descriptors(&paths));
        let stream = protobuf::CodedInputStream::new(&mut input);
        let source = try!(rq::value::protobuf::source(&proto_descriptors, name, stream));
        run_source(args, paths, source)
    } else if args.flag_input_cbor {
        let source = rq::value::cbor::source(&mut input);
        run_source(args, paths, source)
    } else if args.flag_input_message_pack {
        let source = rq::value::messagepack::source(&mut input);
        run_source(args, paths, source)
    } else if args.flag_input_hjson {
        let source = try!(rq::value::hjson::source(&mut input));
        run_source(args, paths, source)
    } else if args.flag_input_yaml {
        let source = try!(rq::value::yaml::source(&mut input));
        run_source(args, paths, source)
    } else {
        let source = rq::value::json::source(&mut input);
        run_source(args, paths, source)
    }
}

fn run_source<I>(args: &Args, paths: &rq::config::Paths, source: I) -> rq::error::Result<()>
    where I: rq::value::Source
{
    let mut output = io::stdout();

    if let Some(_) = args.flag_output_protobuf {
        Err(rq::error::Error::unimplemented("protobuf serialization".to_owned()))
    } else if args.flag_output_cbor {
        let sink = rq::value::cbor::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_message_pack {
        let sink = rq::value::messagepack::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_hjson {
        let sink = rq::value::hjson::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_yaml {
        let sink = rq::value::yaml::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else {
        let sink = rq::value::json::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    }
}

fn run_source_sink<I, O>(args: &Args,
                         _paths: &rq::config::Paths,
                         source: I,
                         sink: O)
                         -> rq::error::Result<()>
    where I: rq::value::Source,
          O: rq::value::Sink
{
    let query = try!(rq::query::Query::parse(if args.arg_query.is_empty() {
        "id"
    } else {
        &args.arg_query
    }));

    record_query::run_query(&query, source, sink)
}

fn load_descriptors(paths: &rq::config::Paths)
                    -> rq::error::Result<serde_protobuf::descriptor::Descriptors> {
    let descriptors_proto = try!(rq::proto_index::compile_descriptor_set(paths));
    Ok(serde_protobuf::descriptor::Descriptors::from_proto(&descriptors_proto))
}

fn log_error(args: &Args, error: rq::error::Error) {
    use record_query::error::ErrorKind;

    match *error.kind() {
        ErrorKind::Msg(ref m) => error!("{}", m),
        ErrorKind::Duk(duk::ErrorKind::Js(ref e)) => {
            if let Some(ref stack) = e.stack {
                error!("Error while executing Javascript:");
                for line in stack.lines() {
                    error!("{}", line);
                }
            } else {
                error!("Error while executing Javascript: {}", e.message);
            }
        },
        _ => {
            let main_str = format!("{}", error);
            let mut main_lines = main_str.lines();
            error!("Encountered: {}", main_lines.next().unwrap());
            for line in main_lines {
                error!("  {}", line);
            }
            for e in error.iter().skip(1) {
                let sub_str = format!("{}", e);
                let mut sub_lines = sub_str.lines();
                error!("Caused by: {}", sub_lines.next().unwrap());
                for line in sub_lines {
                    error!("  {}", line);
                }
            }
        },
    }

    if args.flag_trace || env::var("RUST_BACKTRACE").as_ref().map(String::as_str) == Ok("1") {
        error!("");
        error!("Backtrace:");
        for line in format!("{:?}", error.backtrace()).lines() {
            error!("  {}", line);
        }
    } else {
        error!("(Re-run with (-t|--trace) or RUST_BACKTRACE=1 for a backtrace)");
    }
}

fn setup_log(spec: Option<&str>, quiet: bool) {
    use log::LogLevelFilter;

    let mut builder = env_logger::LogBuilder::new();

    if quiet {
        builder.filter(None, LogLevelFilter::Off);
    } else if let Some(s) = spec {
        builder.parse(s);
    } else if let Ok(s) = env::var("RUST_LOG") {
        builder.parse(&s);
    } else {
        builder.filter(None, LogLevelFilter::Info);
    };

    builder.format(format_log_record);

    builder.init().unwrap();
}

fn format_log_record(record: &log::LogRecord) -> String {
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use nix::unistd;
    use nix::sys::ioctl;

    if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
        let normal = Style::new();
        let (front, back) = match record.level() {
            LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
            LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
            LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
            LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
            LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
        };

        let strings = &[back.paint("["),
                        front.paint(format!("{}", record.level())),
                        back.paint("]"),
                        normal.paint(" "),
                        back.paint("["),
                        front.paint(record.location().module_path()),
                        back.paint("]"),
                        normal.paint(" "),
                        back.paint(format!("{}", record.args()))];

        format!("{}", ANSIStrings(strings))
    } else {
        format!("[{}] [{}] {}",
                record.level(),
                record.location().module_path(),
                record.args())
    }

}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<commit_msg>Fix backtrace error messages<commit_after>#![feature(plugin)]
#![plugin(docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate duk;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;
extern crate serde_protobuf;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See https://github.com/dflemstr/rq for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-h|-m|-p <type>|-y] [-J|-C|-H|-M|-P <type>|-Y] [-l <spec>|-q] [--trace] [--] [<query>]
  rq [-l <spec>|-q] [--trace] protobuf add <schema> [--base <path>]

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values (default).
  -J, --output-json
      Output should be formatted as JSON values (default).
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -h, --input-hjson
      Input is a HJSON document.
  -H, --output-hjson
      Output should be formatted as HJSON values.
  -m, --input-message-pack
      Input is formatted as MessagePack.
  -M, --output-message-pack
      Output should be formatted as MessagePack values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').
  -y, --input-yaml
      Input is a series of YAML documents.
  -Y, --output-yaml
      Output should be formatted as YAML documents.

  <query>
      A query indicating how to transform each record.

  --base <path>
      Directories are significant when dealing with protocol buffer
      schemas.  This specifies the base directory used to normalize schema
      file paths [default: .]

  -l <spec>, --log <spec>
      Configure logging using the supplied specification, in the format of
      `env_logger`, for example `rq=info,duk=trace/[0-9]+ objects kept`.
      See: https://doc.rust-lang.org/log/env_logger
  --trace
      Enable (back)trace output on error.
  -q, --quiet
      Log nothing.
"),
        flag_input_protobuf: Option<String>,
        flag_output_protobuf: Option<String>,
        flag_log: Option<String>,
        flag_base: Option<String>);

fn main() {
    let args: Args = Args::docopt()
        .version(Some(VERSION.to_owned()))
        .decode()
        .unwrap_or_else(|e| e.exit());

    setup_log(args.flag_log.as_ref().map(String::as_ref), args.flag_quiet);

    main_with_args(&args).unwrap_or_else(|e| log_error(&args, e));
}

fn main_with_args(args: &Args) -> rq::error::Result<()> {
    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            let base = path::Path::new(if let Some(ref b) = args.flag_base {
                b.as_str()
            } else {
                "."
            });
            rq::proto_index::add_file(&paths, base, schema)
        } else {
            unreachable!()
        }
    } else {
        run(&args, &paths)
    }
}

fn run(args: &Args, paths: &rq::config::Paths) -> rq::error::Result<()> {

    let stdin = io::stdin();
    let mut input = stdin.lock();

    if let Some(ref name) = args.flag_input_protobuf {
        let proto_descriptors = try!(load_descriptors(&paths));
        let stream = protobuf::CodedInputStream::new(&mut input);
        let source = try!(rq::value::protobuf::source(&proto_descriptors, name, stream));
        run_source(args, paths, source)
    } else if args.flag_input_cbor {
        let source = rq::value::cbor::source(&mut input);
        run_source(args, paths, source)
    } else if args.flag_input_message_pack {
        let source = rq::value::messagepack::source(&mut input);
        run_source(args, paths, source)
    } else if args.flag_input_hjson {
        let source = try!(rq::value::hjson::source(&mut input));
        run_source(args, paths, source)
    } else if args.flag_input_yaml {
        let source = try!(rq::value::yaml::source(&mut input));
        run_source(args, paths, source)
    } else {
        let source = rq::value::json::source(&mut input);
        run_source(args, paths, source)
    }
}

fn run_source<I>(args: &Args, paths: &rq::config::Paths, source: I) -> rq::error::Result<()>
    where I: rq::value::Source
{
    let mut output = io::stdout();

    if let Some(_) = args.flag_output_protobuf {
        Err(rq::error::Error::unimplemented("protobuf serialization".to_owned()))
    } else if args.flag_output_cbor {
        let sink = rq::value::cbor::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_message_pack {
        let sink = rq::value::messagepack::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_hjson {
        let sink = rq::value::hjson::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else if args.flag_output_yaml {
        let sink = rq::value::yaml::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    } else {
        let sink = rq::value::json::sink(&mut output);
        run_source_sink(args, paths, source, sink)
    }
}

fn run_source_sink<I, O>(args: &Args,
                         _paths: &rq::config::Paths,
                         source: I,
                         sink: O)
                         -> rq::error::Result<()>
    where I: rq::value::Source,
          O: rq::value::Sink
{
    let query = try!(rq::query::Query::parse(if args.arg_query.is_empty() {
        "id"
    } else {
        &args.arg_query
    }));

    record_query::run_query(&query, source, sink)
}

fn load_descriptors(paths: &rq::config::Paths)
                    -> rq::error::Result<serde_protobuf::descriptor::Descriptors> {
    let descriptors_proto = try!(rq::proto_index::compile_descriptor_set(paths));
    Ok(serde_protobuf::descriptor::Descriptors::from_proto(&descriptors_proto))
}

fn log_error(args: &Args, error: rq::error::Error) {
    use record_query::error::ErrorKind;

    match *error.kind() {
        ErrorKind::Msg(ref m) => error!("{}", m),
        ErrorKind::Duk(duk::ErrorKind::Js(ref e)) => {
            if let Some(ref stack) = e.stack {
                error!("Error while executing Javascript:");
                for line in stack.lines() {
                    error!("{}", line);
                }
            } else {
                error!("Error while executing Javascript: {}", e.message);
            }
        },
        _ => {
            let main_str = format!("{}", error);
            let mut main_lines = main_str.lines();
            error!("Encountered: {}", main_lines.next().unwrap());
            for line in main_lines {
                error!("  {}", line);
            }
            for e in error.iter().skip(1) {
                let sub_str = format!("{}", e);
                let mut sub_lines = sub_str.lines();
                error!("Caused by: {}", sub_lines.next().unwrap());
                for line in sub_lines {
                    error!("  {}", line);
                }
            }
        },
    }

    if args.flag_trace || env::var("RUST_BACKTRACE").as_ref().map(String::as_str) == Ok("1") {
        error!("");
        if let Some(backtrace) = error.backtrace() {
            error!("Backtrace:");
            for line in format!("{:?}", backtrace).lines() {
                error!("  {}", line);
            }
        } else {
            error!("(No backtrace available)");
        }
    } else {
        error!("(Re-run with --trace or RUST_BACKTRACE=1 for a backtrace)");
    }
}

fn setup_log(spec: Option<&str>, quiet: bool) {
    use log::LogLevelFilter;

    let mut builder = env_logger::LogBuilder::new();

    if quiet {
        builder.filter(None, LogLevelFilter::Off);
    } else if let Some(s) = spec {
        builder.parse(s);
    } else if let Ok(s) = env::var("RUST_LOG") {
        builder.parse(&s);
    } else {
        builder.filter(None, LogLevelFilter::Info);
    };

    builder.format(format_log_record);

    builder.init().unwrap();
}

fn format_log_record(record: &log::LogRecord) -> String {
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use nix::unistd;
    use nix::sys::ioctl;

    if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
        let normal = Style::new();
        let (front, back) = match record.level() {
            LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
            LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
            LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
            LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
            LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
        };

        let strings = &[back.paint("["),
                        front.paint(format!("{}", record.level())),
                        back.paint("]"),
                        normal.paint(" "),
                        back.paint("["),
                        front.paint(record.location().module_path()),
                        back.paint("]"),
                        normal.paint(" "),
                        back.paint(format!("{}", record.args()))];

        format!("{}", ANSIStrings(strings))
    } else {
        format!("[{}] [{}] {}",
                record.level(),
                record.location().module_path(),
                record.args())
    }

}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, Some(".foo.Bar".to_owned()));
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, Some("info".to_owned()));
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<|endoftext|>