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

//! # Commands
//!
//! This crate provides a command system for use in Rust.
//!
//! It provides a general command system which can be used
//! in a variety of environments, including GUI applications
//! and command line utilities. This is inspired by elements
//! of the Lisp Machine, the Common Lisp Interface Manager
//! (CLIM), router command line interfaces, and the TOPS-20
//! command line among other things.
//!
//! * Commands can be defined and grouped into command tables.
//! * Commands can be hooked up with a ``Parser`` for implementing
//!   command line interfaces with completion and parameter validation.
//!
//! This library is in the early stages of development and
//! not everything works yet.

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

pub mod command_table;
pub mod menu_definition;
pub mod parser;
pub mod tokenizer;
pub mod util;
<commit_msg>lib docs: Link to Parser docs.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! # Commands
//!
//! This crate provides a command system for use in Rust.
//!
//! It provides a general command system which can be used
//! in a variety of environments, including GUI applications
//! and command line utilities. This is inspired by elements
//! of the Lisp Machine, the Common Lisp Interface Manager
//! (CLIM), router command line interfaces, and the TOPS-20
//! command line among other things.
//!
//! * Commands can be defined and grouped into command tables.
//! * Commands can be hooked up with a [`Parser`] for implementing
//!   command line interfaces with completion and parameter validation.
//!
//! This library is in the early stages of development and
//! not everything works yet.
//!
//! [`Parser`]: parser/struct.Parser.html

#![warn(missing_docs)]
#![deny(trivial_numeric_casts,
        unsafe_code, unstable_features,
        unused_import_braces, unused_qualifications)]

pub mod command_table;
pub mod menu_definition;
pub mod parser;
pub mod tokenizer;
pub mod util;
<|endoftext|>


<commit_before>//! Iterator-based `linspace` and `logspace` functions

#![allow(unstable)]
#![deny(missing_docs, warnings)]
#![feature(plugin)]

#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
#[plugin]
extern crate quickcheck_macros;

use std::num::{Float, self};

#[cfg(test)]
mod test;

/// Iterator that yields equally spaced numbers in the linear scale
#[derive(Copy)]
pub struct Linspace<T: Float> {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Linspace<T> where T: Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some(self.start + self.step * num::cast(self.stop).unwrap())
        }
    }
}

impl<T> Iterator for Linspace<T> where T: Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * num::cast(self.state).unwrap();
            self.state += 1;
            Some(next)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Iterator that yields equally spaced numbers in the logarithmic scale
#[derive(Copy)]
pub struct Logspace<T: Float> {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Logspace<T> where T: Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some((self.start + self.step * num::cast(self.stop).unwrap()).exp())
        }
    }
}

impl<T> Iterator for Logspace<T> where T: Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * num::cast(self.state).unwrap();
            self.state += 1;
            Some(next.exp())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Returns an iterator that yields `n` evenly spaced numbers over the `[start, end]` interval
///
/// # Panics
///
/// Panics if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![2., 2.25, 2.5, 2.75, 3.], linspace(2., 3., 5).collect())
/// assert_eq!(vec![3., 2.75, 2.5, 2.25, 2.], linspace(2., 3., 5).rev().collect())
/// ```
pub fn linspace<T>(start: T, end: T, n: usize) -> Linspace<T> where T: Float {
    assert!(start <= end);

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        Float::zero()
    } else {
        (end - start) / num::cast(n - 1).unwrap()
    };

    Linspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}

/// Logarithmic version of `linspace`
///
/// # Panics
///
/// Panics if `start` or `end` is a non-positive number, or if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![0.1, 1., 10., 100.], logspace(0.1, 100., 4).collect())
/// assert_eq!(vec![100., 10., 1., 0.1], logspace(0.1, 100., 4).rev().collect())
/// ```
pub fn logspace<T>(start: T, end: T, n: usize) -> Logspace<T> where T: Float {
    assert!(start > Float::zero() && end > Float::zero() && start <= end);

    let (start, end) = (start.ln(), end.ln());

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        Float::zero()
    } else {
        (end - start) / num::cast(n - 1).unwrap()
    };

    Logspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}
<commit_msg>refactor: add feature gates to suppress warnings<commit_after>//! Iterator-based `linspace` and `logspace` functions

#![deny(missing_docs, warnings)]
#![feature(core)]
#![feature(plugin)]
#![feature(std_misc)]

#[cfg(test)]
extern crate quickcheck;
#[cfg(test)]
#[plugin]
extern crate quickcheck_macros;

use std::num::{Float, self};

#[cfg(test)]
mod test;

/// Iterator that yields equally spaced numbers in the linear scale
#[derive(Copy)]
pub struct Linspace<T: Float> {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Linspace<T> where T: Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some(self.start + self.step * num::cast(self.stop).unwrap())
        }
    }
}

impl<T> Iterator for Linspace<T> where T: Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * num::cast(self.state).unwrap();
            self.state += 1;
            Some(next)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Iterator that yields equally spaced numbers in the logarithmic scale
#[derive(Copy)]
pub struct Logspace<T: Float> {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Logspace<T> where T: Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some((self.start + self.step * num::cast(self.stop).unwrap()).exp())
        }
    }
}

impl<T> Iterator for Logspace<T> where T: Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * num::cast(self.state).unwrap();
            self.state += 1;
            Some(next.exp())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Returns an iterator that yields `n` evenly spaced numbers over the `[start, end]` interval
///
/// # Panics
///
/// Panics if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![2., 2.25, 2.5, 2.75, 3.], linspace(2., 3., 5).collect())
/// assert_eq!(vec![3., 2.75, 2.5, 2.25, 2.], linspace(2., 3., 5).rev().collect())
/// ```
pub fn linspace<T>(start: T, end: T, n: usize) -> Linspace<T> where T: Float {
    assert!(start <= end);

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        Float::zero()
    } else {
        (end - start) / num::cast(n - 1).unwrap()
    };

    Linspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}

/// Logarithmic version of `linspace`
///
/// # Panics
///
/// Panics if `start` or `end` is a non-positive number, or if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![0.1, 1., 10., 100.], logspace(0.1, 100., 4).collect())
/// assert_eq!(vec![100., 10., 1., 0.1], logspace(0.1, 100., 4).rev().collect())
/// ```
pub fn logspace<T>(start: T, end: T, n: usize) -> Logspace<T> where T: Float {
    assert!(start > Float::zero() && end > Float::zero() && start <= end);

    let (start, end) = (start.ln(), end.ln());

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        Float::zero()
    } else {
        (end - start) / num::cast(n - 1).unwrap()
    };

    Logspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}
<|endoftext|>


<commit_before>//! A WARC (Web ARChive) library

pub mod error;
pub use error::Error;

mod file;
pub use file::File;

pub mod header;

pub mod parser;

mod record;
pub use record::Record;

mod record_type;
pub use record_type::RecordType;

mod truncated_type;
pub use truncated_type::TruncatedType;
<commit_msg>fix re-export for error::Error<commit_after>//! A WARC (Web ARChive) library

mod error;
pub use error::Error;

mod file;
pub use file::File;

pub mod header;

pub mod parser;

mod record;
pub use record::Record;

mod record_type;
pub use record_type::RecordType;

mod truncated_type;
pub use truncated_type::TruncatedType;
<|endoftext|>


<commit_before>#![feature(slicing_syntax)]
#![crate_type = "lib"]
#![crate_name = "suruga"]
#![allow(missing_copy_implementations)]

#[macro_use]
extern crate log;

pub use tls::Tls;
pub use client::TlsClient;

#[macro_use]
pub mod macros;
pub mod util;

// basic crypto primitives
pub mod crypto {
    pub mod sha2;
    pub mod p256;
    pub mod poly1305;
    pub mod chacha20;
}

pub mod tls_result;
#[macro_use]
pub mod tls_item;
pub mod record;

// TLS AEAD cipehrsuites
pub mod cipher;

pub mod signature;
pub mod alert;
pub mod handshake;

pub mod tls;
pub mod client;

#[cfg(test)] mod test;
<commit_msg>Disable unstable warnings for now<commit_after>#![crate_type = "lib"]
#![crate_name = "suruga"]

#![allow(missing_copy_implementations)]

#![feature(slicing_syntax)]
#![allow(unstable)]

#[macro_use]
extern crate log;

pub use tls::Tls;
pub use client::TlsClient;

#[macro_use]
pub mod macros;
pub mod util;

// basic crypto primitives
pub mod crypto {
    pub mod sha2;
    pub mod p256;
    pub mod poly1305;
    pub mod chacha20;
}

pub mod tls_result;
#[macro_use]
pub mod tls_item;
pub mod record;

// TLS AEAD cipehrsuites
pub mod cipher;

pub mod signature;
pub mod alert;
pub mod handshake;

pub mod tls;
pub mod client;

#[cfg(test)] mod test;
<|endoftext|>


<commit_before>extern crate memmap;
#[macro_use]
extern crate log;

mod msf_index;

use std::fmt;
use std::path::Path;
use std::error::Error;
use std::str;

use memmap::{Mmap, Protection};

pub use self::msf_index::{MsfIndex, MsfParseError};

#[derive(Debug)]
pub enum CueParseError {
    MsfParseError(MsfParseError),
    ParseIntError(std::num::ParseIntError),
    IoError(std::io::Error),
    InvalidCommandError(String),
    InvalidTrackLine,
    InvalidTrackNumber,
    NoTracks,
    UnknownTrackType(String),
    UnknownBinMode(String),
    InvalidIndexLine,
    InvalidIndexNumber,
    NoBinFiles,
    FileNameParseError,
    TrackCommandWithoutBinFile,
    PregapCommandWithoutTrack,
    IndexCommandWithoutTrack,
    Utf8Error(str::Utf8Error)
}

impl Error for CueParseError {
    fn description(&self) -> &str {
        "Could not parse Cuesheet"
    }

    fn cause(&self) -> Option<&Error> {
        use CueParseError::*;
        match *self {
            MsfParseError(ref inner_err) => Some(inner_err),
            IoError(ref inner_err) => Some(inner_err),
            _ => None
        }
    }
}

impl fmt::Display for CueParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use CueParseError::*;
        match *self {
            MsfParseError(ref e) => e.fmt(f),
            IoError(ref e) => e.fmt(f),
            InvalidCommandError(ref s) => write!(f, "Invalid Command: {}", s),
            UnknownTrackType(ref s) => write!(f, "Unknown Track Type: {}", s),
            UnknownBinMode(ref s) => write!(f, "Unknown Binary File Mode: {}", s),
            NoBinFiles => write!(f, "No image files referenced in the cue sheet"),
            _ => write!(f, "{}", self.description())
        }
    }
}

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

impl From<std::num::ParseIntError> for CueParseError {
    fn from(err: std::num::ParseIntError) -> CueParseError {
        CueParseError::ParseIntError(err)
    }
}

impl From<str::Utf8Error> for CueParseError {
    fn from(err: str::Utf8Error) -> CueParseError {
        CueParseError::Utf8Error(err)
    }
}

impl From<MsfParseError> for CueParseError {
    fn from(err: MsfParseError) -> CueParseError {
        CueParseError::MsfParseError(err)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BinMode {
    Binary,
    Wave,
    Mp3,
    Aiff,
    Motorola
}

impl BinMode {
    fn try_from_str(s: &str) -> Result<BinMode, CueParseError> {
        use self::BinMode::*;
        let s_uppercase = s.trim().to_uppercase();
        match s_uppercase.as_str() {
            "BINARY" => Ok(Binary),
            "WAVE" => Ok(Wave),
            "MP3" => Ok(Mp3),
            "AIFF" => Ok(Aiff),
            "MOTOROLA" => Ok(Motorola),
            _ => Err(CueParseError::UnknownBinMode(s_uppercase.clone()))
        }
    }
}

#[derive(Clone, Copy, Debug)]
enum TrackType {
    // 2352 Bytes User Data, 2352 Bytes Raw Data
    Audio,
    // 2048 Bytes User Data, 2352 Bytes Raw Data
    Mode1,
    // 2336 Bytes User Data, 2352 Bytes Raw Data
    Mode2
}

impl TrackType {
    fn try_from_str(s: &str) -> Result<TrackType, CueParseError> {
        use self::TrackType::*;
        let s_uppercase = s.trim().to_uppercase();
        match s_uppercase.as_str() {
            "AUDIO" => Ok(Audio),
            "MODE1" => Ok(Mode1),
            "MODE2" | "MODE2/2352" => Ok(Mode2),
            _ => Err(CueParseError::UnknownTrackType(s_uppercase.clone()))
        }
    }
}

#[derive(Clone)]
struct Track {
    track_type: TrackType,
    indices: Vec<MsfIndex>
}

struct BinFile {
    file: Mmap,
    bin_mode: BinMode,
    tracks: Vec<Track>
}

pub struct Cuesheet {
    bin_files: Vec<BinFile>
}

fn parse_file_line(line: &str, cue_dir: Option<&Path>) -> Result<BinFile, CueParseError> {
    let line = line.trim();
    let quote_matches = line.match_indices("\"").collect::<Vec<_>>();
    if quote_matches.len() != 2 {
        return Err(CueParseError::FileNameParseError);
    }
    // Extract the filename surrounded by quotes
    let bin_filename = &line[(quote_matches[0].0 + 1)..quote_matches[1].0];
    let bin_mode_str = line.rsplit(|c: char| c.is_whitespace()).next().unwrap();

    let file = if let Some(cue_dir) = cue_dir {
        Mmap::open_path(cue_dir.join(bin_filename), Protection::Read)?
    } else {
        Mmap::open_path(bin_filename, Protection::Read)?
    };
    if file.len() % 2352 != 0 {
        warn!("Size of file \"{}\" is not a multiple of 2352 bytes.", bin_filename);
    }
    Ok(BinFile {
        file: file,
        bin_mode: BinMode::try_from_str(bin_mode_str)?,
        tracks: Vec::new()
    })
}

fn parse_track_line(line: &str) -> Result<(Track, u8), CueParseError> {
    let line = line.trim();
    let line_elems = line.split_whitespace().collect::<Vec<&str>>();
    if line_elems.len() < 3 {
        return Err(CueParseError::InvalidTrackLine);
    }
    let track_number = line_elems[1].parse()?;
    let track_type = TrackType::try_from_str(line_elems[2])?;
    let track = Track {
        track_type: track_type,
        indices: Vec::new()
    };
    Ok((track, track_number))
}

fn parse_index_line(line: &str) -> Result<(MsfIndex, u8), CueParseError> {
    let line = line.trim();
    let line_elems = line.split_whitespace().collect::<Vec<&str>>();
    if line_elems.len() < 3 {
        return Err(CueParseError::InvalidIndexLine);
    }
    let index_number = line_elems[1].parse()?;
    let index = MsfIndex::try_from_str(line_elems[2])?;
    Ok((index, index_number))
}

impl Cuesheet {
    pub fn open_cue<P>(path: P) -> Result<Cuesheet, CueParseError>
        where P: AsRef<Path>
    {
        let cue_file = Mmap::open_path(path.as_ref().clone(), Protection::Read)?;
        let cue_bytes = unsafe { cue_file.as_slice() } ;
        let cue_str = str::from_utf8(cue_bytes)?;

        let mut bin_files: Vec<BinFile> = Vec::new();
        let mut current_bin_file: Option<BinFile> = None;
        let mut current_track: Option<Track> = None;
        let mut current_track_number = 0;

        for line in cue_str.lines() {
            if let Some(command) = line.split_whitespace().next() {
                let cmd_uppercase = command.to_uppercase();
                match cmd_uppercase.as_str() {
                    "FILE" => {
                        if let Some(prev_bin_file) = current_bin_file {
                            bin_files.push(prev_bin_file);
                        }
                        current_bin_file = Some(parse_file_line(line, path.as_ref().parent())?);
                        if current_bin_file.as_ref().unwrap().bin_mode != BinMode::Binary {
                            warn!("No bin file modes apart from Binary supported yet.");
                        }
                    }
                    "TRACK" => {
                        if let Some(ref mut bin_file) = current_bin_file {
                            if let Some(prev_track) = current_track {
                                bin_file.tracks.push(prev_track);
                            }
                            let (next_track, next_track_number) = parse_track_line(line)?;
                            if next_track_number != current_track_number + 1 {
                                return Err(CueParseError::InvalidTrackNumber);
                            }
                            current_track_number = next_track_number;
                            current_track = Some(next_track);
                            debug!("New track, number: {}, mode: {:?}",
                                current_track_number,
                                current_track.as_ref().unwrap().track_type);
                        } else {
                            return Err(CueParseError::TrackCommandWithoutBinFile);
                        }
                    }
                    "PERFORMER" | "TITLE" => {} // TODO
                    "PREGAP" => {
                        // TODO: Handle this command properly
                        if let None = current_track {
                            return Err(CueParseError::PregapCommandWithoutTrack);
                        }
                    }
                    "INDEX" => {
                        // TODO: Handle "INDEX 00", seems to be used for
                        // connecting two tracks together when playing an
                        // audio CD continuously.

                        if let Some(ref mut track) = current_track {
                            let (index, index_number) = parse_index_line(line)?;
                            if index_number as usize != track.indices.len() + 1 {
                                return Err(CueParseError::InvalidIndexNumber);
                            }
                            track.indices.push(index);
                        } else {
                            return Err(CueParseError::IndexCommandWithoutTrack);
                        }
                    }
                    "REM" => {
                        // TODO: Get ReplayGain information if present
                    }
                    _ =>  {
                        return Err(CueParseError::InvalidCommandError(cmd_uppercase.clone()));
                    }
                }
            }
        }
        if let Some(last_bin_file) = current_bin_file {
            bin_files.push(last_bin_file);
        } else {
            return Err(CueParseError::NoBinFiles);
        }
        if let Some(last_track) = current_track {
            bin_files.last_mut().unwrap().tracks.push(last_track);
        } else {
            return Err(CueParseError::NoTracks);
        }
        Ok(Cuesheet{ bin_files: bin_files })
    }

    pub fn get_num_bin_files(&self) -> usize {
        self.bin_files.len()
    }

    pub fn get_num_tracks(&self) -> usize {
        std::iter::Sum::sum(self.bin_files.iter().map(|x| x.tracks.len()))
    }

    // Returns the sector's full 2352 bytes, regardless of the track type
    pub fn get_full_sector(&self, msf: &MsfIndex) -> &[u8] {
        // TODO: Make multi-bin compatible
        let offset = msf.to_offset();
        let slice = unsafe { &self.bin_files[0].file.as_slice()[offset..offset + 2352] };
        slice
    }
}

#[cfg(test)]
mod tests {
}<commit_msg>Support parsing cue sheets with pregap info<commit_after>extern crate memmap;
#[macro_use]
extern crate log;

mod msf_index;

use std::fmt;
use std::path::Path;
use std::error::Error;
use std::str;

use memmap::{Mmap, Protection};

pub use self::msf_index::{MsfIndex, MsfParseError};

#[derive(Debug)]
pub enum CueParseError {
    MsfParseError(MsfParseError),
    ParseIntError(std::num::ParseIntError),
    IoError(std::io::Error),
    InvalidCommandError(String),
    InvalidTrackLine,
    InvalidTrackNumber,
    NoTracks,
    TrackWithoutIndex01,
    UnknownTrackType(String),
    UnknownBinMode(String),
    InvalidPregapLine,
    InvalidIndexLine,
    InvalidIndexNumber,
    NoBinFiles,
    FileNameParseError,
    TrackCommandWithoutBinFile,
    PregapCommandWithoutTrack,
    IndexCommandWithoutTrack,
    Utf8Error(str::Utf8Error)
}

impl Error for CueParseError {
    fn description(&self) -> &str {
        "Could not parse Cuesheet"
    }

    fn cause(&self) -> Option<&Error> {
        use CueParseError::*;
        match *self {
            MsfParseError(ref inner_err) => Some(inner_err),
            IoError(ref inner_err) => Some(inner_err),
            _ => None
        }
    }
}

impl fmt::Display for CueParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use CueParseError::*;
        match *self {
            MsfParseError(ref e) => e.fmt(f),
            IoError(ref e) => e.fmt(f),
            InvalidCommandError(ref s) => write!(f, "Invalid Command: {}", s),
            UnknownTrackType(ref s) => write!(f, "Unknown Track Type: {}", s),
            UnknownBinMode(ref s) => write!(f, "Unknown Binary File Mode: {}", s),
            NoBinFiles => write!(f, "No image files referenced in the cue sheet"),
            _ => write!(f, "{}", self.description())
        }
    }
}

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

impl From<std::num::ParseIntError> for CueParseError {
    fn from(err: std::num::ParseIntError) -> CueParseError {
        CueParseError::ParseIntError(err)
    }
}

impl From<str::Utf8Error> for CueParseError {
    fn from(err: str::Utf8Error) -> CueParseError {
        CueParseError::Utf8Error(err)
    }
}

impl From<MsfParseError> for CueParseError {
    fn from(err: MsfParseError) -> CueParseError {
        CueParseError::MsfParseError(err)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BinMode {
    Binary,
    Wave,
    Mp3,
    Aiff,
    Motorola
}

impl BinMode {
    fn try_from_str(s: &str) -> Result<BinMode, CueParseError> {
        use self::BinMode::*;
        let s_uppercase = s.trim().to_uppercase();
        match s_uppercase.as_str() {
            "BINARY" => Ok(Binary),
            "WAVE" => Ok(Wave),
            "MP3" => Ok(Mp3),
            "AIFF" => Ok(Aiff),
            "MOTOROLA" => Ok(Motorola),
            _ => Err(CueParseError::UnknownBinMode(s_uppercase.clone()))
        }
    }
}

#[derive(Clone, Copy, Debug)]
enum TrackType {
    // 2352 Bytes User Data, 2352 Bytes Raw Data
    Audio,
    // 2048 Bytes User Data, 2352 Bytes Raw Data
    Mode1,
    // 2336 Bytes User Data, 2352 Bytes Raw Data
    Mode2
}

impl TrackType {
    fn try_from_str(s: &str) -> Result<TrackType, CueParseError> {
        use self::TrackType::*;
        let s_uppercase = s.trim().to_uppercase();
        match s_uppercase.as_str() {
            "AUDIO" => Ok(Audio),
            "MODE1" => Ok(Mode1),
            "MODE2" | "MODE2/2352" => Ok(Mode2),
            _ => Err(CueParseError::UnknownTrackType(s_uppercase.clone()))
        }
    }
}

#[derive(Clone)]
enum Pregap {
    Index00(MsfIndex),
    Silence(MsfIndex)
}

#[derive(Clone)]
struct Track {
    track_type: TrackType,
    pregap: Option<Pregap>,
    indices: Vec<MsfIndex>
}

struct BinFile {
    file: Mmap,
    bin_mode: BinMode,
    tracks: Vec<Track>
}

pub struct Cuesheet {
    bin_files: Vec<BinFile>
}

fn parse_file_line(line: &str, cue_dir: Option<&Path>) -> Result<BinFile, CueParseError> {
    let line = line.trim();
    let quote_matches = line.match_indices("\"").collect::<Vec<_>>();
    if quote_matches.len() != 2 {
        return Err(CueParseError::FileNameParseError);
    }
    // Extract the filename surrounded by quotes
    let bin_filename = &line[(quote_matches[0].0 + 1)..quote_matches[1].0];
    let bin_mode_str = line.rsplit(|c: char| c.is_whitespace()).next().unwrap();

    let file = if let Some(cue_dir) = cue_dir {
        Mmap::open_path(cue_dir.join(bin_filename), Protection::Read)?
    } else {
        Mmap::open_path(bin_filename, Protection::Read)?
    };
    if file.len() % 2352 != 0 {
        warn!("Size of file \"{}\" is not a multiple of 2352 bytes.", bin_filename);
    }
    Ok(BinFile {
        file: file,
        bin_mode: BinMode::try_from_str(bin_mode_str)?,
        tracks: Vec::new()
    })
}

fn parse_track_line(line: &str) -> Result<(Track, u8), CueParseError> {
    let line = line.trim();
    let line_elems = line.split_whitespace().collect::<Vec<&str>>();
    if line_elems.len() < 3 {
        return Err(CueParseError::InvalidTrackLine);
    }
    let track_number = line_elems[1].parse()?;
    let track_type = TrackType::try_from_str(line_elems[2])?;
    let track = Track {
        track_type: track_type,
        pregap: None,
        indices: Vec::new()
    };
    Ok((track, track_number))
}

fn parse_index_line(line: &str) -> Result<(MsfIndex, u8), CueParseError> {
    let line = line.trim();
    let line_elems = line.split_whitespace().collect::<Vec<&str>>();
    if line_elems.len() < 3 {
        return Err(CueParseError::InvalidIndexLine);
    }
    let index_number = line_elems[1].parse()?;
    let index = MsfIndex::try_from_str(line_elems[2])?;
    Ok((index, index_number))
}

fn parse_pregap_line(line: &str) -> Result<MsfIndex, CueParseError> {
    let line = line.trim();
    let line_elems = line.split_whitespace().collect::<Vec<&str>>();
    if line_elems.len() != 2 {
        return Err(CueParseError::InvalidPregapLine);
    }
    let index = MsfIndex::try_from_str(line_elems[1])?;
    Ok(index)
}

impl Cuesheet {
    pub fn open_cue<P>(path: P) -> Result<Cuesheet, CueParseError>
        where P: AsRef<Path>
    {
        let cue_file = Mmap::open_path(path.as_ref().clone(), Protection::Read)?;
        let cue_bytes = unsafe { cue_file.as_slice() } ;
        let cue_str = str::from_utf8(cue_bytes)?;

        let mut bin_files: Vec<BinFile> = Vec::new();
        let mut current_bin_file: Option<BinFile> = None;
        let mut current_track: Option<Track> = None;
        let mut current_track_number = 0;

        for line in cue_str.lines() {
            if let Some(command) = line.split_whitespace().next() {
                let cmd_uppercase = command.to_uppercase();
                match cmd_uppercase.as_str() {
                    "FILE" => {
                        if let Some(prev_bin_file) = current_bin_file {
                            bin_files.push(prev_bin_file);
                        }
                        current_bin_file = Some(parse_file_line(line, path.as_ref().parent())?);
                        if current_bin_file.as_ref().unwrap().bin_mode != BinMode::Binary {
                            warn!("No bin file modes apart from Binary supported yet.");
                        }
                    }
                    "TRACK" => {
                        if let Some(ref mut bin_file) = current_bin_file {
                            if let Some(prev_track) = current_track {
                                if prev_track.indices.len() == 0 {
                                    return Err(CueParseError::TrackWithoutIndex01);
                                }
                                bin_file.tracks.push(prev_track);
                            }
                            let (next_track, next_track_number) = parse_track_line(line)?;
                            if next_track_number != current_track_number + 1 {
                                return Err(CueParseError::InvalidTrackNumber);
                            }
                            current_track_number = next_track_number;
                            current_track = Some(next_track);
                            debug!("New track, number: {}, mode: {:?}",
                                current_track_number,
                                current_track.as_ref().unwrap().track_type);
                        } else {
                            return Err(CueParseError::TrackCommandWithoutBinFile);
                        }
                    }
                    "PERFORMER" | "TITLE" => {} // TODO
                    "PREGAP" => {
                        if let Some(ref mut track) = current_track {
                            if track.pregap.is_some() {
                                // FIXME: Maybe use a more descriptive error message?
                                return Err(CueParseError::InvalidIndexNumber);
                            }
                            track.pregap = Some(Pregap::Silence(parse_pregap_line(line)?));
                        } else {
                            return Err(CueParseError::PregapCommandWithoutTrack);
                        }
                    }
                    "INDEX" => {
                        if let Some(ref mut track) = current_track {
                            let (index, index_number) = parse_index_line(line)?;
                            if index_number == 0 {
                                if track.pregap.is_some() {
                                    // FIXME: Maybe use a more descriptive error message?
                                    return Err(CueParseError::InvalidIndexNumber);
                                }
                                track.pregap = Some(Pregap::Index00(index));
                            } else if index_number as usize != track.indices.len() + 1 {
                                return Err(CueParseError::InvalidIndexNumber);
                            } else {
                                track.indices.push(index);
                            }
                        } else {
                            return Err(CueParseError::IndexCommandWithoutTrack);
                        }
                    }
                    "REM" => {
                        // TODO: Get ReplayGain information if present
                    }
                    _ =>  {
                        return Err(CueParseError::InvalidCommandError(cmd_uppercase.clone()));
                    }
                }
            }
        }
        if let Some(last_bin_file) = current_bin_file {
            bin_files.push(last_bin_file);
        } else {
            return Err(CueParseError::NoBinFiles);
        }
        if let Some(last_track) = current_track {
            bin_files.last_mut().unwrap().tracks.push(last_track);
        } else {
            return Err(CueParseError::NoTracks);
        }
        Ok(Cuesheet{ bin_files: bin_files })
    }

    pub fn get_num_bin_files(&self) -> usize {
        self.bin_files.len()
    }

    pub fn get_num_tracks(&self) -> usize {
        std::iter::Sum::sum(self.bin_files.iter().map(|x| x.tracks.len()))
    }

    // Returns the sector's full 2352 bytes, regardless of the track type
    pub fn get_full_sector(&self, msf: &MsfIndex) -> &[u8] {
        // TODO: Make multi-bin compatible
        let offset = msf.to_offset();
        let slice = unsafe { &self.bin_files[0].file.as_slice()[offset..offset + 2352] };
        slice
    }
}

#[cfg(test)]
mod tests {
}<|endoftext|>


<commit_before>/// Functions for use in euler projects

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unnecessary_qualification)]
#[warn(non_uppercase_statics)]
#[warn(missing_doc)]

use std::collections::TrieSet;

use std::collections::HashMap;

pub mod primesieve;

/// Count the number of occurrences of each value in an iterator
pub fn counter<K : std::hash::Hash + Eq, I : Iterator<K>>(mut list : I) -> HashMap<K, uint> {
	let mut counter : HashMap<K, uint> = HashMap::new();
	for key in list {
		counter.insert_or_update_with(key, 1, |_, v| {*v += 1});
	}
	counter
}

pub fn isqrt(n : uint) -> Option<uint> {
	if n <= 1 {return Some(n);}
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	//println!("New x: {}", x);

	while x*x != n {
		usedset.insert(x);
		// let addx = x + n / x;
		x = (x + n / x + 1) / 2;
		//println!("New x: {} ({})", x, addx);
		if usedset.contains(&x) {
			//println!("Seen! {} ({}, {})", x, x*x, n);
			return None;
		}
	}
	Some(x)
}

#[test]
fn test_square(){
	assert_eq!(isqrt(4), Some(2));
	assert_eq!(isqrt(5), None);

	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for _ in range(0u, 1000u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
	}

	for &n in ntests.iter(){
		println!("n: {}, n*n: {}", n, n*n);
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		assert_eq!(isqrt(n*n), Some(n));
		if n > 1 {
			assert_eq!(isqrt(n*n - 1), None);
		} else {
			assert_eq!(isqrt(n*n - 1), Some(0));
		}
		assert_eq!(isqrt(n*n + 1), None);
	}
}
<commit_msg>Added isqrt function<commit_after>/// Functions for use in euler projects

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unnecessary_qualification)]
#[warn(non_uppercase_statics)]
#[warn(missing_doc)]

use std::collections::TrieSet;

use std::collections::HashMap;

pub use primesieve::PrimeSet;

pub mod primesieve;

/// Count the number of occurrences of each value in an iterator
pub fn counter<K : std::hash::Hash + Eq, I : Iterator<K>>(mut list : I) -> HashMap<K, uint> {
	let mut counter : HashMap<K, uint> = HashMap::new();
	for key in list {
		counter.insert_or_update_with(key, 1, |_, v| {*v += 1});
	}
	counter
}

pub fn isqrt_opt(n : uint) -> Option<uint> {
	if n <= 1 {return Some(n);}
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	//println!("New x: {}", x);

	while x*x != n {
		usedset.insert(x);
		// let addx = x + n / x;
		x = (x + n / x + 1) / 2;
		//println!("New x: {} ({})", x, addx);
		if usedset.contains(&x) {
			//println!("Seen! {} ({}, {})", x, x*x, n);
			return None;
		}
	}
	Some(x)
}

pub fn isqrt(n : uint) -> uint {
	if n <= 1 { return n; }
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	while x*x != n {
		usedset.insert(x);
		let lastx = x;
		x = (x + n / x + 1) / 2;
		//if usedset.contains(&x) {
		if x == lastx {
			if x*x < n {
				return x;
			} else {
				return x-1;
			}
		}
	}
	return x
}

pub fn is_palindrome(n : uint) -> bool {
	let s = n.to_string();
	//let s_rev = String::from_utf8(s.into_bytes().iter().rev().collect());
	let s_rev = s.as_slice().as_bytes().iter().rev();
	let s_rev_vec : Vec<u8> = s_rev.map(|&b| b).collect();
	let s_rev = String::from_utf8(s_rev_vec);
	match s_rev {
		Ok(s2) => {s == s2},
		_ => false
	}
}

#[test]
fn test_square(){
	assert_eq!(isqrt_opt(4), Some(2));
	assert_eq!(isqrt_opt(5), None);

	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for _ in range(0u, 1000u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
	}

	for &n in ntests.iter(){
		println!("n: {}, n*n: {}", n, n*n);
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		assert_eq!(isqrt_opt(n*n), Some(n));
		if n > 1 {
			assert_eq!(isqrt_opt(n*n - 1), None);
		} else {
			assert_eq!(isqrt_opt(n*n - 1), Some(0));
		}
		assert_eq!(isqrt_opt(n*n + 1), None);
	}
}

#[test]
fn test_isqrt(){
	assert_eq!(isqrt(0), 0);
	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for i in range(1u, 1001u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
		ntests.push(i);
	}

	for &n in ntests.iter() {
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		let x = isqrt(n);
		assert!(x*x <= n);
		assert!((x+1)*(x+1) > n);
		assert_eq!(isqrt(n*n - 1), n-1);
		assert_eq!(isqrt(n*n + 1), n);
	}
}

#[test]
fn test_palindrome(){
	assert!(is_palindrome(1));
	assert!(is_palindrome(2));
	assert!(is_palindrome(8));
	assert!(!is_palindrome(10));
	assert!(!is_palindrome(12));
	assert!(!is_palindrome(100));
	assert!(!is_palindrome(11110));
	assert!(!is_palindrome(21111));
	assert!(!is_palindrome(12131));
	assert!(is_palindrome(11));
	assert!(is_palindrome(111));
	assert!(is_palindrome(232));
	assert!(is_palindrome(181));
}
<|endoftext|>


<commit_before>//! Quick Csv reader which performs **very** well.
//!
//! ## Example
//!
//! First, create a `Csv` from a `BufRead` reader, a file or a string
//!
//! ```rust
//! extern crate quick_csv;
//!
//! fn main() {
//!     let data = "a,b\r\nc,d\r\ne,f";
//!     let csv = quick_csv::Csv::from_string(data);
//!     for row in csv.into_iter() {
//!         // work on csv row ...
//!         if let Ok(_) = row {
//!             println!("new row!");
//!         } else {
//!             println!("cannot read next line");
//!         }
//!     }
//! }
//! ```
//!
//! `Row` is on the other hand provides 3 methods to access csv columns:
//! - `columns`:
//!   - iterator over columns.
//!   - Iterator item is a `&str`, which means you only have to `parse()` it to the needed type and you're done
//!
//!   ```rust
//!   # let row = quick_csv::Csv::from_string("a,b,c,d,e,38,f").next().unwrap().unwrap();
//!   let mut cols = row.columns().expect("cannot convert to utf8");
//!   let fifth = cols.nth(5).unwrap().parse::<f64>().unwrap();
//!   println!("Doubled fifth column: {}", fifth * 2.0);
//!   ```
//!
//! - `decode`:
//!   - deserialize into you `Decodable` struct, a-la rust-csv.
//!   - most convenient way to deal with your csv data
//!
//!   ```rust
//!   let row = quick_csv::Csv::from_string("a,b,54").next().unwrap().unwrap();
//!   if let Ok((col1, col2, col3)) = row.decode::<(String, u64, f64)>() {
//!       println!("col1: '{}', col2: {}, col3: {}", col1, col2, col3);
//!   }
//!   ```
//!
//! - `bytes_columns`:
//!   - similar to `columns` but columns are of type `&[u8]`, which means you may want to convert it to &str first
//!   - performance gain compared to `columns` is minimal, use it only if you *really* need to as it is less convenient

#![deny(missing_docs)]

extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::iter::Iterator;
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

const UTF8_BOM: &'static [u8] = b"\xef\xbb\xbf";

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// header
    headers: Option<Vec<String>>,
    /// flexible column count
    flexible: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
    /// line count
    current_line: usize,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(mut reader: B) -> Csv<B> {
        let result = try_consume_utf8_bom(&mut reader);

        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            headers: None,
            flexible: false,
            len: None,
            exit: result.is_err(),
            current_line: 0,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Sets flexible columns
    pub fn flexible(mut self, flexible: bool) -> Csv<B> {
        self.flexible = flexible;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        let _ = self.headers();
        self
    }

   /// gets first row as Vec<String>
    pub fn headers(&mut self) -> Vec<String> {
        if let Some(ref h) = self.headers {
            return h.clone();
        }
        if self.has_header {
            if let Some(r) = self.next() {
                if let Ok(r) = r {
                    let h = r.decode().ok().unwrap_or_else(Vec::new);
                    self.headers = Some(h.clone());
                    return h;
                }
            }
        }
        Vec::new()
    }

    /// Get column count
    pub fn column_count(&self) -> Option<usize> {
        self.len
    }

    /// Gets the current line number
    ///
    /// Useful if you get an error and want to investigate the source
    pub fn current_line(&self) -> usize {
        self.current_line
    }

    fn try_consume_utf8_bom(reader: &mut B) -> Result<()> {
        if try!(reader.fill_buf()).starts_with(UTF8_BOM) {
            reader.consume(UTF8_BOM.len());
        }

        Ok(())
    }
}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv `Row`s
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(Vec::new, Vec::with_capacity);
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c && !self.flexible {
                        self.exit = true;
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                self.current_line += 1;
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns(&self) -> Result<Columns> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::Io(io::Error::new(io::ErrorKind::InvalidData,
                                    "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns(&self) -> BytesColumns {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

    /// `Row` is empty if there is no columns
    pub fn is_empty(&self) -> bool {
        self.cols.is_empty()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
macro_rules! consume_quote {
    ($bytes: expr, $delimiter: expr, $in_quote: expr,
     $start: expr, $buf: expr, $available: expr, $quote_count: expr) => {
        $in_quote = false;
        loop {
            match $bytes.next() {
                Some((_, &b'\"')) => {
                    match $bytes.clone().next() {
                        Some((i, &b'\"')) => {
                            $bytes.next(); // escaping quote
                            $buf.extend_from_slice(&$available[$start..i]);
                            $start = i + 1;
                            $quote_count += 1;
                        },
                        None | Some((_, &b'\r')) | Some((_, &b'\n')) => break,
                        Some((_, d)) if *d == $delimiter => break,
                        Some((_, _)) => return Err(Error::UnescapedQuote),
                    }
                },
                None => {
                    $in_quote = true;
                    break;
                },
                _ => (),
            }
        }
    }
}

/// Reads an entire line into memory
fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
                         delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    let mut quote_count = 0;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();
            let mut start = 0;

            // previous buffer was exhausted without exiting from quotes
            if in_quote {
                consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        done = true;
                        used = i + 1;
                        buf.extend_from_slice(&available[start..i]);
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i - quote_count); }
                    },
                    None => {
                        used = available.len();
                        buf.extend_from_slice(&available[start..used]);
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}

fn try_consume_utf8_bom<B: BufRead>(reader: &mut B) -> Result<()> {
    if try!(reader.fill_buf()).starts_with(UTF8_BOM) {
        reader.consume(UTF8_BOM.len());
    }

    Ok(())
}<commit_msg>remove unused function<commit_after>//! Quick Csv reader which performs **very** well.
//!
//! ## Example
//!
//! First, create a `Csv` from a `BufRead` reader, a file or a string
//!
//! ```rust
//! extern crate quick_csv;
//!
//! fn main() {
//!     let data = "a,b\r\nc,d\r\ne,f";
//!     let csv = quick_csv::Csv::from_string(data);
//!     for row in csv.into_iter() {
//!         // work on csv row ...
//!         if let Ok(_) = row {
//!             println!("new row!");
//!         } else {
//!             println!("cannot read next line");
//!         }
//!     }
//! }
//! ```
//!
//! `Row` is on the other hand provides 3 methods to access csv columns:
//! - `columns`:
//!   - iterator over columns.
//!   - Iterator item is a `&str`, which means you only have to `parse()` it to the needed type and you're done
//!
//!   ```rust
//!   # let row = quick_csv::Csv::from_string("a,b,c,d,e,38,f").next().unwrap().unwrap();
//!   let mut cols = row.columns().expect("cannot convert to utf8");
//!   let fifth = cols.nth(5).unwrap().parse::<f64>().unwrap();
//!   println!("Doubled fifth column: {}", fifth * 2.0);
//!   ```
//!
//! - `decode`:
//!   - deserialize into you `Decodable` struct, a-la rust-csv.
//!   - most convenient way to deal with your csv data
//!
//!   ```rust
//!   let row = quick_csv::Csv::from_string("a,b,54").next().unwrap().unwrap();
//!   if let Ok((col1, col2, col3)) = row.decode::<(String, u64, f64)>() {
//!       println!("col1: '{}', col2: {}, col3: {}", col1, col2, col3);
//!   }
//!   ```
//!
//! - `bytes_columns`:
//!   - similar to `columns` but columns are of type `&[u8]`, which means you may want to convert it to &str first
//!   - performance gain compared to `columns` is minimal, use it only if you *really* need to as it is less convenient

#![deny(missing_docs)]

extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader};
use std::iter::Iterator;
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

const UTF8_BOM: &'static [u8] = b"\xef\xbb\xbf";

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// header
    headers: Option<Vec<String>>,
    /// flexible column count
    flexible: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
    /// line count
    current_line: usize,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(mut reader: B) -> Csv<B> {
        let result = try_consume_utf8_bom(&mut reader);

        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            headers: None,
            flexible: false,
            len: None,
            exit: result.is_err(),
            current_line: 0,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Sets flexible columns
    pub fn flexible(mut self, flexible: bool) -> Csv<B> {
        self.flexible = flexible;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        let _ = self.headers();
        self
    }

   /// gets first row as Vec<String>
    pub fn headers(&mut self) -> Vec<String> {
        if let Some(ref h) = self.headers {
            return h.clone();
        }
        if self.has_header {
            if let Some(r) = self.next() {
                if let Ok(r) = r {
                    let h = r.decode().ok().unwrap_or_else(Vec::new);
                    self.headers = Some(h.clone());
                    return h;
                }
            }
        }
        Vec::new()
    }

    /// Get column count
    pub fn column_count(&self) -> Option<usize> {
        self.len
    }

    /// Gets the current line number
    ///
    /// Useful if you get an error and want to investigate the source
    pub fn current_line(&self) -> usize {
        self.current_line
    }

}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv `Row`s
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(Vec::new, Vec::with_capacity);
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c && !self.flexible {
                        self.exit = true;
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                self.current_line += 1;
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns(&self) -> Result<Columns> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::Io(io::Error::new(io::ErrorKind::InvalidData,
                                    "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns(&self) -> BytesColumns {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

    /// `Row` is empty if there is no columns
    pub fn is_empty(&self) -> bool {
        self.cols.is_empty()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
macro_rules! consume_quote {
    ($bytes: expr, $delimiter: expr, $in_quote: expr,
     $start: expr, $buf: expr, $available: expr, $quote_count: expr) => {
        $in_quote = false;
        loop {
            match $bytes.next() {
                Some((_, &b'\"')) => {
                    match $bytes.clone().next() {
                        Some((i, &b'\"')) => {
                            $bytes.next(); // escaping quote
                            $buf.extend_from_slice(&$available[$start..i]);
                            $start = i + 1;
                            $quote_count += 1;
                        },
                        None | Some((_, &b'\r')) | Some((_, &b'\n')) => break,
                        Some((_, d)) if *d == $delimiter => break,
                        Some((_, _)) => return Err(Error::UnescapedQuote),
                    }
                },
                None => {
                    $in_quote = true;
                    break;
                },
                _ => (),
            }
        }
    }
}

/// Reads an entire line into memory
fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
                         delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    let mut quote_count = 0;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();
            let mut start = 0;

            // previous buffer was exhausted without exiting from quotes
            if in_quote {
                consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            consume_quote!(bytes, delimiter, in_quote, start, buf, available, quote_count);
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        done = true;
                        used = i + 1;
                        buf.extend_from_slice(&available[start..i]);
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i - quote_count); }
                    },
                    None => {
                        used = available.len();
                        buf.extend_from_slice(&available[start..used]);
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}

fn try_consume_utf8_bom<B: BufRead>(reader: &mut B) -> Result<()> {
    if try!(reader.fill_buf()).starts_with(UTF8_BOM) {
        reader.consume(UTF8_BOM.len());
    }

    Ok(())
}
<|endoftext|>


<commit_before>#![feature(no_std,lang_items,asm,core,alloc,collections,step_by)]
#![no_std]

#![crate_type="staticlib"]
#![crate_name="rustcode"]

#[macro_use]
extern crate core;
extern crate alloc;
extern crate collections;

use core::prelude::*;
use core::fmt::Write;
use core::atomic::Ordering;
use alloc::boxed::Box;
use collections::string::String;

extern crate rlibc;

#[macro_use]
mod notex;
#[macro_use]
mod mutex;

mod machine;
mod console;
mod vga;
mod mmu;
mod gdt;
mod acpi;
mod interrupts;
mod paging;
mod malloc;
mod smp;

use vga::Color::*;

pub use interrupts::{idtDesc};
pub use interrupts::{double_fault_handler, gpf_handler,
                     page_fault_handler, kbd_interrupt_handler };
pub use malloc::{rust_allocate, rust_reallocate, rust_reallocate_inplace,
                 rust_deallocate, rust_usable_size, rust_stats_print };
pub use smp::{SMP_STACK_PTR, SMP_CR3};

#[lang="start"]
#[no_mangle]
pub fn k_main() {
    if smp::processor_count.fetch_add(1, Ordering::SeqCst) == 0 {
        paging::init();
        interrupts::init_idt();
        // YOU MAY NOW PAGE FAULT
        let smp_info = acpi::smp_info();
        interrupts::init(&(*smp_info).io_apics);
        smp::init(&(*smp_info).processors);

        let greet = "Hello from bare-bones Rust";
        let _ = write!(console::Console, "SMP at {:p}", smp_info);
//        let _ = console::Console.write_str("Hello");
        for i in 0..vga::ROWS {
            for j in 0..vga::COLS {
            vga::write_char_with_color(i, j, ' ', White, LightBlue);
            }
        }
        vga::paint_color(0, 0, 30, White, LightGreen);
        vga::write_string(10, 5, greet);
        vga::move_cursor(10, 5 + greet.len());
        vga::write_string_with_color(11, 10, "Test", Black, LightRed);

        let heap = Box::new('H');
        let heap2 = Box::new('!');
        vga::write_char(15,4,*heap);
        vga::write_char_with_color(15, 5, *heap2, LightGray, Pink);

        let mut string = String::from_str("Hello, ");
        string.push_str("paging");
        vga::write_string(3,5,&string);
        unsafe { *(0xB0_00_00_01 as *mut u32) = 0xcafecafe; }
        unsafe { *(0xA0_00_10_00 as *mut mmu::Descriptor) = gdt::gdt_get(1); }
        let processors = smp::processor_count.load(Ordering::SeqCst) as u8 + '0' as u8;
        vga::write_char(4, 4, processors as char);
    }
    else { // Non-main processor
        interrupts::apic::enable_lapic();
        loop {};
    }
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}

#[lang = "panic_fmt"]
#[inline(always)]
fn panic_fmt() -> ! { unsafe { ::core::intrinsics::abort() } }
<commit_msg>Revert "Print pointer value"<commit_after>#![feature(no_std,lang_items,asm,core,alloc,collections,step_by)]
#![no_std]

#![crate_type="staticlib"]
#![crate_name="rustcode"]

#[macro_use]
extern crate core;
extern crate alloc;
extern crate collections;

use core::prelude::*;
use core::fmt::Write;
use core::atomic::Ordering;
use alloc::boxed::Box;
use collections::string::String;

extern crate rlibc;

#[macro_use]
mod notex;
#[macro_use]
mod mutex;

mod machine;
mod console;
mod vga;
mod mmu;
mod gdt;
mod acpi;
mod interrupts;
mod paging;
mod malloc;
mod smp;

use vga::Color::*;

pub use interrupts::{idtDesc};
pub use interrupts::{double_fault_handler, gpf_handler,
                     page_fault_handler, kbd_interrupt_handler };
pub use malloc::{rust_allocate, rust_reallocate, rust_reallocate_inplace,
                 rust_deallocate, rust_usable_size, rust_stats_print };
pub use smp::{SMP_STACK_PTR, SMP_CR3};

#[lang="start"]
#[no_mangle]
pub fn k_main() {
    if smp::processor_count.fetch_add(1, Ordering::SeqCst) == 0 {
        paging::init();
        interrupts::init_idt();
        // YOU MAY NOW PAGE FAULT
        let smp_info = acpi::smp_info();
        interrupts::init(&(*smp_info).io_apics);
        smp::init(&(*smp_info).processors);

        let greet = "Hello from bare-bones Rust";
        let _ = console::Console.write_str("Hello");
        for i in 0..vga::ROWS {
            for j in 0..vga::COLS {
            vga::write_char_with_color(i, j, ' ', White, LightBlue);
            }
        }
        vga::paint_color(0, 0, 30, White, LightGreen);
        vga::write_string(10, 5, greet);
        vga::move_cursor(10, 5 + greet.len());
        vga::write_string_with_color(11, 10, "Test", Black, LightRed);

        let heap = Box::new('H');
        let heap2 = Box::new('!');
        vga::write_char(15,4,*heap);
        vga::write_char_with_color(15, 5, *heap2, LightGray, Pink);

        let mut string = String::from_str("Hello, ");
        string.push_str("paging");
        vga::write_string(3,5,&string);
        unsafe { *(0xB0_00_00_01 as *mut u32) = 0xcafecafe; }
        unsafe { *(0xA0_00_10_00 as *mut mmu::Descriptor) = gdt::gdt_get(1); }
        let processors = smp::processor_count.load(Ordering::SeqCst) as u8 + '0' as u8;
        vga::write_char(4, 4, processors as char);
    }
    else { // Non-main processor
        interrupts::apic::enable_lapic();
        loop {};
    }
}

#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}

#[lang = "panic_fmt"]
#[inline(always)]
fn panic_fmt() -> ! { unsafe { ::core::intrinsics::abort() } }
<|endoftext|>


<commit_before>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}?auth={}", uri, auth_token)
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('?');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::trim_right(path, "/");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "?" + args
        } else {
            url
        };

        Firebase {
            base_uri: url
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None)
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data))
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data))
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data))
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None)
    }

    fn request(&self, method: Method, data: Option<&str>) -> Response {
        let url: &str = &self.base_uri;
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(_) => "Unable to parse"
        };

        Response {
            body: body.to_string(),
            code: res.get_code(),
        }
    }

    pub fn get_url(&self) -> &str {
        return &self.base_uri;
    }
}

pub enum Params<'l> {
    OrderBy(&'l str),
    LimitToFirst(u32),
    LimitToLast(u32),
    StartAt(u32),
    EndAt(u32),
    EqualTo(u32),
    Shallow(bool),
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        self.code < 400
    }
}
<commit_msg>First API of request parameters for GET calls<commit_after>extern crate curl;

use std::str;
use curl::http;

mod util;

pub struct Firebase {
    base_uri: String,
}

impl Firebase {
    pub fn new(base_uri: &str) -> Self {
        Firebase {
            base_uri: base_uri.to_string(),
        }
    }

    pub fn authenticated(base_uri: &str, auth_token: &str) -> Self {
        let uri = util::trim_right(base_uri, "/");
        Firebase {
            base_uri: format!("{}?auth={}", uri, auth_token),
        }
    }

    pub fn at(&self, path: &str) -> Self {
        let mut components = self.base_uri.split('?');

        let base = components.next().unwrap();
        let base = util::trim_right(base, ".json");
        let path = util::trim_right(path, "/");
        let path = util::add_right(path, ".json");
        let url  = util::join(base, &path, "/");

        let url = if let Some(args) = components.next() {
            url + "?" + args
        } else {
            url
        };

        Firebase {
            base_uri: url,
        }
    }

    pub fn get(&self) -> Response {
        self.request(Method::GET, None, None)
    }

    fn get_params(&self, params: String) -> Response {
        self.request(Method::GET, None, Some(params))
    }

    pub fn set(&self, data: &str) -> Response {
        self.request(Method::PUT, Some(data), None)
    }

    pub fn push(&self, data: &str) -> Response {
        self.request(Method::POST, Some(data), None)
    }

    pub fn update(&self, data: &str) -> Response {
        self.request(Method::PATCH, Some(data), None)
    }

    pub fn delete(&self) -> Response {
        self.request(Method::DELETE, None, None)
    }

    fn request(&self, method: Method, data: Option<&str>, params: Option<String>) -> Response {
        let url = if let Some(args) = params {
            if self.base_uri.find("?").is_some() {
                format!("{}&{}", &self.base_uri, args)
            } else {
                format!("{}?{}", &self.base_uri, args)
            }
        } else {
            // TODO: FIX SO THIS DOESN'T HAPPEN
            self.base_uri.clone()
        };

        let url: &str = &url;
        let mut handler = http::handle();

        let req = match method {
            Method::GET     => handler.get(url),
            Method::POST    => handler.post(url, data.unwrap()),
            Method::PUT     => handler.put(url, data.unwrap()),
            Method::PATCH   => handler.patch(url, data.unwrap()),
            Method::DELETE  => handler.delete(url)
        };
        let res = req.exec().unwrap();

        let body = match str::from_utf8(res.get_body()) {
            Ok(b) => b,
            Err(_) => "Unable to parse"
        };

        Response {
            body: body.to_string(),
            code: res.get_code(),
        }
    }

    pub fn get_url(&self) -> &str {
        return &self.base_uri;
    }

    pub fn orderBy(&self, key: &str) -> ParamsRequest {
        self.params_request(orderByStr(key))
    }

    pub fn limitToFirst(&self, count: u32) -> ParamsRequest {
        self.params_request(limitToFirstStr(count))
    }

    pub fn limitToLast(&self, count: u32) -> ParamsRequest {
        self.params_request(limitToLastStr(count))
    }

    pub fn startAt(&self, index: u32) -> ParamsRequest {
        self.params_request(startAtStr(index))
    }

    pub fn endAt(&self, index: u32) -> ParamsRequest {
        self.params_request(endAtStr(index))
    }

    pub fn equalTo(&self, value: u32) -> ParamsRequest {
        self.params_request(equalToStr(value))
    }

    pub fn shallow(&self, flag: bool) -> ParamsRequest {
        self.params_request(shallowStr(flag))
    }

    fn params_request(&self, param: String) -> ParamsRequest {
        ParamsRequest {
            firebase: &self,
            params: vec![param],
        }
    }
}

pub struct ParamsRequest<'l> {
    firebase: &'l Firebase,
    params: Vec<String>,
}

impl<'l> ParamsRequest<'l> {
    pub fn orderBy(&mut self, key: &str) -> &Self {
        self.params.push(orderByStr(key));
        self
    }

    pub fn limitToFirst(&mut self, count: u32) -> &Self {
        self.params.push(limitToFirstStr(count));
        self
    }

    pub fn limitToLast(&mut self, count: u32) -> &Self {
        self.params.push(limitToLastStr(count));
        self
    }

    pub fn startAt(&mut self, index: u32) -> &Self {
        self.params.push(startAtStr(index));
        self
    }

    pub fn endAt(&mut self, index: u32) -> &Self {
        self.params.push(endAtStr(index));
        self
    }

    pub fn equalTo(&mut self, value: u32) -> &Self {
        self.params.push(equalToStr(value));
        self
    }

    pub fn shallow(&mut self, flag: bool) -> &Self {
        self.params.push(shallowStr(flag));
        self
    }

    pub fn get(&self) -> Response {
        Firebase::get_params(self.firebase, self.params.connect("&"))
    }
}

fn orderByStr(key: &str) -> String {
    format!("orderBy={}", key)
}

fn limitToFirstStr(count: u32) -> String {
    format!("limitToFirst={}", count)
}

fn limitToLastStr(count: u32) -> String {
    format!("limitToLast={}", count)
}

fn startAtStr(index: u32) -> String {
    format!("startAt={}", index)
}

fn endAtStr(index: u32) -> String {
    format!("endAt={}", index)
}

fn equalToStr(value: u32) -> String {
    format!("equalTo={}", value)
}

fn shallowStr(flag: bool) -> String {
    format!("shallow={}", flag)
}

enum Method {
    GET,
    POST,
    PUT,
    PATCH,
    DELETE,
}

pub struct Response {
    pub body: String,
    pub code: u32,
}

impl Response {
    pub fn is_success(&self) -> bool {
        self.code < 400
    }
}
<|endoftext|>


<commit_before>//! Rust bindings for [libpcuid](https://github.com/anrieff/libcpuid)
//! CPU detection and feature extraction library.
//!
//! `rust-cpuid` provides a high-level interface for getting information
//! about the features of the CPU that runs your code. All the essential
//! work is done by the `libcpuid` C library and exposed through Rust's
//! FFI mechanism as a simple and convenient API.
//!
//! # Available features
//!
//! * CPU vendor, brand and codename detection
//! * information about number of cores (both physical and logical)
//! * cache size
//! * clock frequency
//!
//! # Installation
//!
//! First - download, and build libcpuid as [described in the readme](https://github.com/anrieff/libcpuid). Install it by running `make install` (you may want to run `ldconfig` afterwards).
//!
//! Add to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies.cpuid]
//! git = "https://github.com/zsiciarz/rust-cpuid.git"
//! ```
//!
//! # Example
//!
//! ```rust
//! extern crate cpuid;
//!
//! fn main () {
//!     match cpuid::identify() {
//!         Ok(info) => {
//!             println!("Found: {} CPU, model: {}", info.vendor, info.codename);
//!             println!("The full brand string is: {}", info.brand);
//!             println!("Hardware AES support: {}", if info.has_feature(cpuid::AES) { "yes" } else { "no" });
//!         },
//!         Err(err) => println!("cpuid error: {}", err),
//!     };
//!     match cpuid::clock_frequency() {
//!         Some(frequency) => println!("CPU speed: {} MHz", frequency),
//!         None => println!("Couldn't get CPU speed."),
//!     };
//! }
//! ```

extern crate libc;

use std::c_str::CString;
use std::mem;

mod ffi;

/// A struct holding information about CPU features.
///
/// This data structure is returned by `identify()`. You can consult
/// [libcpuid docs for cpu_id_t](http://libcpuid.sourceforge.net/doxy/structcpu__id__t.html)
/// for more detailed descriptions of these fields.
pub struct CpuInfo {
    /// CPU vendor string, for example *GenuineIntel*.
    pub vendor: String,
    /// Brand string, for example *Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz*.
    pub brand: String,
    /// Brief CPU codename, such as *Sandy Bridge (Core i5)*.
    pub codename: String,
    /// Number of physical cores of the current CPU.
    pub num_cores: int,
    /// Number of logical processors (may include HyperThreading or such).
    pub num_logical_cpus: int,
    /// Total number of logical processors.
    pub total_logical_cpus: int,
    /// L1 data cache size in kB. `Some(0)` if the CPU lacks cache, `None` if it couldn't be determined.
    pub l1_data_cache: Option<int>,
    /// L1 instruction cache size in kB. `Some(0)` if the CPU lacks cache, `None` if it couldn't be determined.
    pub l1_instruction_cache: Option<int>,
    /// L2 cache size in kB. `Some(0)` if the CPU lacks L2 cache, `None` if it couldn't be determined.
    pub l2_cache: Option<int>,
    /// L3 cache size in kB. `Some(0)` if the CPU lacks L3 cache, `None` if it couldn't be determined.
    pub l3_cache: Option<int>,
    flags: [u8, ..ffi::CPU_FLAGS_MAX],
}

/// CPU feature identifiers.
pub enum CpuFeature {
    FloatingPointUnit = 0,
    VirtualModeExtension,
    DebugingExtension,
    PageSizeExtension,
    TimestampCounter,
    ModelSpecificRegisters,
    PhysicalAddressExtension,
    MachineCheckException,
    CMPXCHG8B,
    APIC,
    MemoryTypeRangeRegisters,
    SysenterSysexit,
    PageGlobalEnable,
    MachineCheckArchitecture,
    CMOV,
    PageAttributeTable,
    PageAddressExtension36bit,
    ProcessorSerialNumber,
    CLFLUSH,
    DebugStore,
    ACPI,
    MMX,
    FXSAVE,
    SSE,
    SSE2,
    SelfSnoop,
    HyperThreading,
    ThermalMonitor,
    IA64,
    PendingBreakEnable,
    SSE3,
    PCLMULQDQ,
    DebugStore64,
    MONITOR,
    CplQualifiedDebugStore,
    VirtualisationTechnology,
    SaferModeExceptions,
    EnhancedSpeedStep,
    ThermalMonitor2,
    SSSE3,
    ContextId,
    CMPXCHG16B,
    SendTaskPriorityMessages,
    PerformanceCapabilitiesMSR,
    DirectCacheAccess,
    SSE41,
    SSE42,
    SyscallSysret,
    ExecuteDisableBit,
    MOVBE,
    POPCNT,
    AES,
    XSAVE,
    OSXSAVE,
    AdvancedVectorExtensions,
    MMXExtensions,
    AMD3DNow,
    AMD3DNowExtended,
    NoExecuteBit,
    FXSAVEOptimizations,
    RDTSCP,
    LongMode,
    LAHFLongMode,
    CoreMultiProcessingLegacyMode,
    AMDSecureVirtualMachine,
    LZCNT,
    MisalignedSSE,
    SSE4a,
    PREFETCH,
    OsVisibleWorkaround,
    InstructionBasedSampling,
    SSE5,
    SKINIT,
    WatchdogTimer,
    TemperatureSensor,
    FrequencyIDControl,
    VoltageIDControl,
    THERMTRIP,
    AMDThermalControl,
    SoftwareThermalControl,
    Multiplier100Mhz,
    HardwarePstateControl,
    ConstantTSCTicks,
    XOP,
    FMA3,
    FMA4,
    TrailingBitManipulation,
    FPConvert16Bit,
    RDRAND,
    X2APIC,
    CorePerformanceBoost,
    MPERF,
    ProcessorFeedbackInterface,
    ProcessorAccumulator,
    NumCpuFeatures,
}

impl CpuInfo {
    /// Checks if current CPU supports given feature.
    ///
    /// See `CpuFeature` for a list of available feature identifiers.
    pub fn has_feature(&self, feature: CpuFeature) -> bool {
        return self.flags[feature as uint] == 1u8
    }
}

/// Checks if the CPUID instruction is present.
pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

/// Returns libcpuid version string.
pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

/// Returns last libcpuid error string.
pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

/// Tries to identify the current CPU and its features.
///
/// In case of successful detection, a `CpuInfo` struct is returned (wrapped
/// with `Ok`) which contains all available data about the processor.
/// If libcpuid encounters an error, `identify` returns an `Err` with
/// the error message inside.
pub fn identify() -> Result<CpuInfo, String> {
    let mut raw: ffi::cpu_raw_data_t = unsafe { mem::uninitialized() };
    let raw_result = unsafe {
        ffi::cpuid_get_raw_data(&mut raw)
    };
    if raw_result != 0 {
        return Err(error());
    }
    let mut data: ffi::cpu_id_t = unsafe { mem::uninitialized() };
    let identify_result = unsafe {
        ffi::cpu_identify(&mut raw, &mut data)
    };
    if identify_result != 0 {
        Err(error())
    } else {
        Ok(CpuInfo {
            vendor: String::from_utf8(data.vendor_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid vendor string"),
            brand: String::from_utf8(data.brand_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid brand string"),
            codename: String::from_utf8(data.cpu_codename.iter().map(|&x| x as u8).collect()).ok().expect("Invalid codename string"),
            num_cores: data.num_cores as int,
            num_logical_cpus: data.num_logical_cpus as int,
            total_logical_cpus: data.total_logical_cpus as int,
            l1_data_cache: if data.l1_data_cache != -1 { Some(data.l1_data_cache as int) } else { None },
            l1_instruction_cache: if data.l1_instruction_cache != -1 { Some(data.l1_instruction_cache as int) } else { None },
            l2_cache: if data.l2_cache != -1 { Some(data.l2_cache as int) } else { None },
            l3_cache: if data.l3_cache != -1 { Some(data.l3_cache as int) } else { None },
            flags: data.flags,
        })
    }
}

/// Gets the CPU clock frequency in MHz.
///
/// The underlying implementation uses several methods to discover CPU
/// speed, including direct measurement. If all these methods fail, function
/// returns `None`.
pub fn clock_frequency() -> Option<int> {
    let frequency = unsafe {
        ffi::cpu_clock()
    };
    if frequency != -1 {
        Some(frequency as int)
    } else {
        None
    }
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<commit_msg>Updated dependency in the introductory docs.<commit_after>//! Rust bindings for [libpcuid](https://github.com/anrieff/libcpuid)
//! CPU detection and feature extraction library.
//!
//! `rust-cpuid` provides a high-level interface for getting information
//! about the features of the CPU that runs your code. All the essential
//! work is done by the `libcpuid` C library and exposed through Rust's
//! FFI mechanism as a simple and convenient API.
//!
//! # Available features
//!
//! * CPU vendor, brand and codename detection
//! * information about number of cores (both physical and logical)
//! * cache size
//! * clock frequency
//!
//! # Installation
//!
//! First - download, and build libcpuid as [described in the readme](https://github.com/anrieff/libcpuid). Install it by running `make install` (you may want to run `ldconfig` afterwards).
//!
//! Add to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! cpuid = "*"
//! ```
//!
//! # Example
//!
//! ```rust
//! extern crate cpuid;
//!
//! fn main () {
//!     match cpuid::identify() {
//!         Ok(info) => {
//!             println!("Found: {} CPU, model: {}", info.vendor, info.codename);
//!             println!("The full brand string is: {}", info.brand);
//!             println!("Hardware AES support: {}", if info.has_feature(cpuid::AES) { "yes" } else { "no" });
//!         },
//!         Err(err) => println!("cpuid error: {}", err),
//!     };
//!     match cpuid::clock_frequency() {
//!         Some(frequency) => println!("CPU speed: {} MHz", frequency),
//!         None => println!("Couldn't get CPU speed."),
//!     };
//! }
//! ```

extern crate libc;

use std::c_str::CString;
use std::mem;

mod ffi;

/// A struct holding information about CPU features.
///
/// This data structure is returned by `identify()`. You can consult
/// [libcpuid docs for cpu_id_t](http://libcpuid.sourceforge.net/doxy/structcpu__id__t.html)
/// for more detailed descriptions of these fields.
pub struct CpuInfo {
    /// CPU vendor string, for example *GenuineIntel*.
    pub vendor: String,
    /// Brand string, for example *Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz*.
    pub brand: String,
    /// Brief CPU codename, such as *Sandy Bridge (Core i5)*.
    pub codename: String,
    /// Number of physical cores of the current CPU.
    pub num_cores: int,
    /// Number of logical processors (may include HyperThreading or such).
    pub num_logical_cpus: int,
    /// Total number of logical processors.
    pub total_logical_cpus: int,
    /// L1 data cache size in kB. `Some(0)` if the CPU lacks cache, `None` if it couldn't be determined.
    pub l1_data_cache: Option<int>,
    /// L1 instruction cache size in kB. `Some(0)` if the CPU lacks cache, `None` if it couldn't be determined.
    pub l1_instruction_cache: Option<int>,
    /// L2 cache size in kB. `Some(0)` if the CPU lacks L2 cache, `None` if it couldn't be determined.
    pub l2_cache: Option<int>,
    /// L3 cache size in kB. `Some(0)` if the CPU lacks L3 cache, `None` if it couldn't be determined.
    pub l3_cache: Option<int>,
    flags: [u8, ..ffi::CPU_FLAGS_MAX],
}

/// CPU feature identifiers.
pub enum CpuFeature {
    FloatingPointUnit = 0,
    VirtualModeExtension,
    DebugingExtension,
    PageSizeExtension,
    TimestampCounter,
    ModelSpecificRegisters,
    PhysicalAddressExtension,
    MachineCheckException,
    CMPXCHG8B,
    APIC,
    MemoryTypeRangeRegisters,
    SysenterSysexit,
    PageGlobalEnable,
    MachineCheckArchitecture,
    CMOV,
    PageAttributeTable,
    PageAddressExtension36bit,
    ProcessorSerialNumber,
    CLFLUSH,
    DebugStore,
    ACPI,
    MMX,
    FXSAVE,
    SSE,
    SSE2,
    SelfSnoop,
    HyperThreading,
    ThermalMonitor,
    IA64,
    PendingBreakEnable,
    SSE3,
    PCLMULQDQ,
    DebugStore64,
    MONITOR,
    CplQualifiedDebugStore,
    VirtualisationTechnology,
    SaferModeExceptions,
    EnhancedSpeedStep,
    ThermalMonitor2,
    SSSE3,
    ContextId,
    CMPXCHG16B,
    SendTaskPriorityMessages,
    PerformanceCapabilitiesMSR,
    DirectCacheAccess,
    SSE41,
    SSE42,
    SyscallSysret,
    ExecuteDisableBit,
    MOVBE,
    POPCNT,
    AES,
    XSAVE,
    OSXSAVE,
    AdvancedVectorExtensions,
    MMXExtensions,
    AMD3DNow,
    AMD3DNowExtended,
    NoExecuteBit,
    FXSAVEOptimizations,
    RDTSCP,
    LongMode,
    LAHFLongMode,
    CoreMultiProcessingLegacyMode,
    AMDSecureVirtualMachine,
    LZCNT,
    MisalignedSSE,
    SSE4a,
    PREFETCH,
    OsVisibleWorkaround,
    InstructionBasedSampling,
    SSE5,
    SKINIT,
    WatchdogTimer,
    TemperatureSensor,
    FrequencyIDControl,
    VoltageIDControl,
    THERMTRIP,
    AMDThermalControl,
    SoftwareThermalControl,
    Multiplier100Mhz,
    HardwarePstateControl,
    ConstantTSCTicks,
    XOP,
    FMA3,
    FMA4,
    TrailingBitManipulation,
    FPConvert16Bit,
    RDRAND,
    X2APIC,
    CorePerformanceBoost,
    MPERF,
    ProcessorFeedbackInterface,
    ProcessorAccumulator,
    NumCpuFeatures,
}

impl CpuInfo {
    /// Checks if current CPU supports given feature.
    ///
    /// See `CpuFeature` for a list of available feature identifiers.
    pub fn has_feature(&self, feature: CpuFeature) -> bool {
        return self.flags[feature as uint] == 1u8
    }
}

/// Checks if the CPUID instruction is present.
pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

/// Returns libcpuid version string.
pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

/// Returns last libcpuid error string.
pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

/// Tries to identify the current CPU and its features.
///
/// In case of successful detection, a `CpuInfo` struct is returned (wrapped
/// with `Ok`) which contains all available data about the processor.
/// If libcpuid encounters an error, `identify` returns an `Err` with
/// the error message inside.
pub fn identify() -> Result<CpuInfo, String> {
    let mut raw: ffi::cpu_raw_data_t = unsafe { mem::uninitialized() };
    let raw_result = unsafe {
        ffi::cpuid_get_raw_data(&mut raw)
    };
    if raw_result != 0 {
        return Err(error());
    }
    let mut data: ffi::cpu_id_t = unsafe { mem::uninitialized() };
    let identify_result = unsafe {
        ffi::cpu_identify(&mut raw, &mut data)
    };
    if identify_result != 0 {
        Err(error())
    } else {
        Ok(CpuInfo {
            vendor: String::from_utf8(data.vendor_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid vendor string"),
            brand: String::from_utf8(data.brand_str.iter().map(|&x| x as u8).collect()).ok().expect("Invalid brand string"),
            codename: String::from_utf8(data.cpu_codename.iter().map(|&x| x as u8).collect()).ok().expect("Invalid codename string"),
            num_cores: data.num_cores as int,
            num_logical_cpus: data.num_logical_cpus as int,
            total_logical_cpus: data.total_logical_cpus as int,
            l1_data_cache: if data.l1_data_cache != -1 { Some(data.l1_data_cache as int) } else { None },
            l1_instruction_cache: if data.l1_instruction_cache != -1 { Some(data.l1_instruction_cache as int) } else { None },
            l2_cache: if data.l2_cache != -1 { Some(data.l2_cache as int) } else { None },
            l3_cache: if data.l3_cache != -1 { Some(data.l3_cache as int) } else { None },
            flags: data.flags,
        })
    }
}

/// Gets the CPU clock frequency in MHz.
///
/// The underlying implementation uses several methods to discover CPU
/// speed, including direct measurement. If all these methods fail, function
/// returns `None`.
pub fn clock_frequency() -> Option<int> {
    let frequency = unsafe {
        ffi::cpu_clock()
    };
    if frequency != -1 {
        Some(frequency as int)
    } else {
        None
    }
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<|endoftext|>