<commit_before>/*
 * Copyright 2015 Jonathan Anderson
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

//!
//! `rshark`, the Rusty Shark library, is a library for deep inspection
//! of malicious packets.
//!
//! # Background
//!
//! [Wireshark](https://www.wireshark.org) is a very useful tool for network
//! debugging, but it's had its
//! [fair share of security vulnerabilities](https://www.wireshark.org/security).
//! It's generally accepted that, to succeed at Capture the Flag, one should fuzz
//! Wireshark for awhile before the competition to find a few new vulnerabilities
//! (don't worry, they're there, you'll find some) and use those offensively to
//! blind one's opponents.
//! This speaks to both the indispensability of packet capture/dissection tools
//! and the fundamental difficulty of ``just making Wireshark secure''.
//! Wireshark has a *lot* of dissectors, which are written using a
//! [complex C API](https://www.wireshark.org/docs/wsdg_html_chunked/ChDissectAdd.html)
//! (although some are now written in Lua).
//!
//! `rshark` uses the type safety of Rust to enable the dissection of
//! malicious packets without worry of buffer overflows or other common memory errors.
//! Rusty Shark dissectors can make mistakes, but those logical errors should only
//! affect the interpretation of the *current* data, rather than *all* data.
//! That is to say, Rusty Shark is compartmentalized to minimize the damage that
//! can be done by a successful adversary. The submarine metaphors write themselves.
//!
//! # Usage
//!
//! *note: for help on the `rshark` command-line client,
//! run `man rshark` or `rshark --help`.*
//!
//! The `rshark` library provides packet dissection functions such as
//! `rshark::ethernet::dissect()`. Every such dissection function, which should
//! conform to the `rshark::Dissector` function type, takes as input a slice of bytes
//! and returns an `rshark::Result` (which defaults to
//! `Result<rshark::Val, rshark::Error>`).
//! Usage is pretty simple:
//!
//! ```
//! let data = vec![];
//!
//! match rshark::ethernet::dissect(&data) {
//!     Err(e) => println!["Error: {}", e],
//!     Ok(val) => print!["{}", val.pretty_print(0)],
//! }
//! ```
//!
//! A `Val` can represent an arbitrary tree of structured data
//! (useful in graphical displays) and can be pretty-printed with indentation for
//! sub-objects.

#![doc(html_logo_url = "https://raw.githubusercontent.com/musec/rusty-shark/master/artwork/wordmark.png")]

extern crate byteorder;

use byteorder::ReadBytesExt;
use std::fmt::Display;
use std::fmt;
use std::io;

/// A value parsed from a packet.
///
/// # TODO
/// This value type isn't as expressive as would be required for a real
/// Wireshark replacement just yet. Additional needs include:
///
///  * tracking original bytes (by reference or by index?)
///  * supporting error metadata (e.g., "parsed ok but checksum doesn't match")
///  * supporting asynchronous sub-object parsing (some sort of promises?)
///
pub enum Val {
    /// A signed integer, in machine-native representation.
    Signed(i64),

    /// An unsigned integer, in machine-native representation.
    Unsigned(u64),

    /// A UTF-8–encoded string.
    String(String),

    /// A network address, which can have its own special encoding.
    Address { bytes: Vec<u8>, encoded: String },

    /// A sub-object is an ordered set of (name,value) tuples.
    Object(Vec<NamedValue>),

    /// Raw bytes, e.g., a checksum or just unparsed data.
    Bytes(Vec<u8>),
}

impl Val {
    pub fn pretty_print(&self, indent:usize) -> String {
        match self {
            &Val::Object(ref values) => {
                let mut s = "\n".to_string();
                let prefix =
                    ::std::iter::repeat(" ").take(2 * indent).collect::<String>();

                for &(ref k, ref v) in values {
                    s = s + &format!["{}{}: ", prefix, k];
                    s = s + &*(match v {
                        &Ok(ref value) => value.pretty_print(indent + 1),
                        &Err(ref e) => format!["<< Error: {} >>", e],
                    });
                    s = s + "\n";
                }

                s
            }

            _ => format!["{}", self]
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Val::Signed(ref i) => write![f, "{}", i],
            &Val::Unsigned(ref i) => write![f, "{}", i],
            &Val::String(ref s) => write![f, "{}", s],
            &Val::Address { ref encoded, .. } => write![f, "{}", encoded],

            &Val::Object(ref values) => {
                try![write![f, "{{ "]];

                for &(ref k, ref v) in values {
                    try![write![f, "{}: ", k]];

                    match v {
                        &Ok(ref value) => try![write![f, "{}", value]],
                        &Err(ref e) => try![write![f, "<<{}>>", e]],
                    }

                    try![write![f, ", "]];
                }

                write![f, "}}"]
            },

            &Val::Bytes(ref bytes) => {
                try![write![f, "{} B [", bytes.len()]];

                let to_print:&[u8] =
                    if bytes.len() < 16 { bytes }
                    else { &bytes[..16] }
                    ;

                for b in to_print {
                    try![write![f, " {:02x}", b]];
                }

                if bytes.len() > 16 {
                    try![write![f, " ..."]];
                }

                write![f, " ]"]
            }
        }
    }
}

/// An error related to packet dissection (underflow, bad value, etc.).
#[derive(Debug)]
pub enum Error {
    Underflow { expected: usize, have: usize, message: String, },
    InvalidData(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::Underflow { expected, have, ref message } =>
                write![f, "underflow (expected {}, have {}): {}",
                    expected, have, message],

            &Error::InvalidData(ref msg) => write![f, "invalid data: {}", msg],
        }
    }
}

/// The result of a dissection function.
pub type Result<T=Val> = ::std::result::Result<T,Error>;

/// A named value-or-error.
pub type NamedValue = (String,Result<Val>);

/// Type of dissection functions.
pub type Dissector = fn(&[u8]) -> Result<Val>;

/// Little- or big-endian integer representations.
pub enum Endianness {
    BigEndian,
    LittleEndian,
}

/// Parse a signed integer of a given endianness from a byte buffer.
///
/// The size of the buffer will be used to determine the size of the integer
/// that should be parsed (i8, i16, i32 or i64), but the result will be stored
/// in an i64.
pub fn signed(buffer: &[u8], endianness: Endianness) -> Result<i64> {
    let mut reader = io::Cursor::new(buffer);

    match endianness {
        Endianness::BigEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as i64),
                2 => Ok(reader.read_i16::<byteorder::BigEndian>().unwrap() as i64),
                4 => Ok(reader.read_i32::<byteorder::BigEndian>().unwrap() as i64),
                8 => Ok(reader.read_i64::<byteorder::BigEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }

        Endianness::LittleEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as i64),
                2 => Ok(reader.read_i16::<byteorder::LittleEndian>().unwrap() as i64),
                4 => Ok(reader.read_i32::<byteorder::LittleEndian>().unwrap() as i64),
                8 => Ok(reader.read_i64::<byteorder::LittleEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }
    }
}

/// Parse a signed integer of a given endianness from a byte buffer.
///
/// The size of the buffer will be used to determine the size of the integer
/// that should be parsed (u8, u16, u32 or u64), but the result will be stored
/// in a u64.
pub fn unsigned(buffer: &[u8], endianness: Endianness) -> Result<u64> {
    let mut reader = io::Cursor::new(buffer);

    match endianness {
        Endianness::BigEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as u64),
                2 => Ok(reader.read_u16::<byteorder::BigEndian>().unwrap() as u64),
                4 => Ok(reader.read_u32::<byteorder::BigEndian>().unwrap() as u64),
                8 => Ok(reader.read_u64::<byteorder::BigEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }

        Endianness::LittleEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as u64),
                2 => Ok(reader.read_u16::<byteorder::LittleEndian>().unwrap() as u64),
                4 => Ok(reader.read_u32::<byteorder::LittleEndian>().unwrap() as u64),
                8 => Ok(reader.read_u64::<byteorder::LittleEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }
    }
}

/// Dissector of last resort: store raw bytes without interpretation.
pub fn raw(data: &[u8]) -> Result {
    Ok(Val::Object(vec![
        ("raw data".to_string(), Ok(Val::Bytes(data.to_vec())))
    ]))
}

pub mod ethernet;
pub mod ip;
<commit_msg>Remove unused std::fmt::Display from src/lib.rs.<commit_after>/*
 * Copyright 2015 Jonathan Anderson
 *
 * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
 * http://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.
 */

//!
//! `rshark`, the Rusty Shark library, is a library for deep inspection
//! of malicious packets.
//!
//! # Background
//!
//! [Wireshark](https://www.wireshark.org) is a very useful tool for network
//! debugging, but it's had its
//! [fair share of security vulnerabilities](https://www.wireshark.org/security).
//! It's generally accepted that, to succeed at Capture the Flag, one should fuzz
//! Wireshark for awhile before the competition to find a few new vulnerabilities
//! (don't worry, they're there, you'll find some) and use those offensively to
//! blind one's opponents.
//! This speaks to both the indispensability of packet capture/dissection tools
//! and the fundamental difficulty of ``just making Wireshark secure''.
//! Wireshark has a *lot* of dissectors, which are written using a
//! [complex C API](https://www.wireshark.org/docs/wsdg_html_chunked/ChDissectAdd.html)
//! (although some are now written in Lua).
//!
//! `rshark` uses the type safety of Rust to enable the dissection of
//! malicious packets without worry of buffer overflows or other common memory errors.
//! Rusty Shark dissectors can make mistakes, but those logical errors should only
//! affect the interpretation of the *current* data, rather than *all* data.
//! That is to say, Rusty Shark is compartmentalized to minimize the damage that
//! can be done by a successful adversary. The submarine metaphors write themselves.
//!
//! # Usage
//!
//! *note: for help on the `rshark` command-line client,
//! run `man rshark` or `rshark --help`.*
//!
//! The `rshark` library provides packet dissection functions such as
//! `rshark::ethernet::dissect()`. Every such dissection function, which should
//! conform to the `rshark::Dissector` function type, takes as input a slice of bytes
//! and returns an `rshark::Result` (which defaults to
//! `Result<rshark::Val, rshark::Error>`).
//! Usage is pretty simple:
//!
//! ```
//! let data = vec![];
//!
//! match rshark::ethernet::dissect(&data) {
//!     Err(e) => println!["Error: {}", e],
//!     Ok(val) => print!["{}", val.pretty_print(0)],
//! }
//! ```
//!
//! A `Val` can represent an arbitrary tree of structured data
//! (useful in graphical displays) and can be pretty-printed with indentation for
//! sub-objects.

#![doc(html_logo_url = "https://raw.githubusercontent.com/musec/rusty-shark/master/artwork/wordmark.png")]

extern crate byteorder;

use byteorder::ReadBytesExt;
use std::fmt;
use std::io;

/// A value parsed from a packet.
///
/// # TODO
/// This value type isn't as expressive as would be required for a real
/// Wireshark replacement just yet. Additional needs include:
///
///  * tracking original bytes (by reference or by index?)
///  * supporting error metadata (e.g., "parsed ok but checksum doesn't match")
///  * supporting asynchronous sub-object parsing (some sort of promises?)
///
pub enum Val {
    /// A signed integer, in machine-native representation.
    Signed(i64),

    /// An unsigned integer, in machine-native representation.
    Unsigned(u64),

    /// A UTF-8–encoded string.
    String(String),

    /// A network address, which can have its own special encoding.
    Address { bytes: Vec<u8>, encoded: String },

    /// A sub-object is an ordered set of (name,value) tuples.
    Object(Vec<NamedValue>),

    /// Raw bytes, e.g., a checksum or just unparsed data.
    Bytes(Vec<u8>),
}

impl Val {
    pub fn pretty_print(&self, indent:usize) -> String {
        match self {
            &Val::Object(ref values) => {
                let mut s = "\n".to_string();
                let prefix =
                    ::std::iter::repeat(" ").take(2 * indent).collect::<String>();

                for &(ref k, ref v) in values {
                    s = s + &format!["{}{}: ", prefix, k];
                    s = s + &*(match v {
                        &Ok(ref value) => value.pretty_print(indent + 1),
                        &Err(ref e) => format!["<< Error: {} >>", e],
                    });
                    s = s + "\n";
                }

                s
            }

            _ => format!["{}", self]
        }
    }
}

impl fmt::Display for Val {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Val::Signed(ref i) => write![f, "{}", i],
            &Val::Unsigned(ref i) => write![f, "{}", i],
            &Val::String(ref s) => write![f, "{}", s],
            &Val::Address { ref encoded, .. } => write![f, "{}", encoded],

            &Val::Object(ref values) => {
                try![write![f, "{{ "]];

                for &(ref k, ref v) in values {
                    try![write![f, "{}: ", k]];

                    match v {
                        &Ok(ref value) => try![write![f, "{}", value]],
                        &Err(ref e) => try![write![f, "<<{}>>", e]],
                    }

                    try![write![f, ", "]];
                }

                write![f, "}}"]
            },

            &Val::Bytes(ref bytes) => {
                try![write![f, "{} B [", bytes.len()]];

                let to_print:&[u8] =
                    if bytes.len() < 16 { bytes }
                    else { &bytes[..16] }
                    ;

                for b in to_print {
                    try![write![f, " {:02x}", b]];
                }

                if bytes.len() > 16 {
                    try![write![f, " ..."]];
                }

                write![f, " ]"]
            }
        }
    }
}

/// An error related to packet dissection (underflow, bad value, etc.).
#[derive(Debug)]
pub enum Error {
    Underflow { expected: usize, have: usize, message: String, },
    InvalidData(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::Underflow { expected, have, ref message } =>
                write![f, "underflow (expected {}, have {}): {}",
                    expected, have, message],

            &Error::InvalidData(ref msg) => write![f, "invalid data: {}", msg],
        }
    }
}

/// The result of a dissection function.
pub type Result<T=Val> = ::std::result::Result<T,Error>;

/// A named value-or-error.
pub type NamedValue = (String,Result<Val>);

/// Type of dissection functions.
pub type Dissector = fn(&[u8]) -> Result<Val>;

/// Little- or big-endian integer representations.
pub enum Endianness {
    BigEndian,
    LittleEndian,
}

/// Parse a signed integer of a given endianness from a byte buffer.
///
/// The size of the buffer will be used to determine the size of the integer
/// that should be parsed (i8, i16, i32 or i64), but the result will be stored
/// in an i64.
pub fn signed(buffer: &[u8], endianness: Endianness) -> Result<i64> {
    let mut reader = io::Cursor::new(buffer);

    match endianness {
        Endianness::BigEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as i64),
                2 => Ok(reader.read_i16::<byteorder::BigEndian>().unwrap() as i64),
                4 => Ok(reader.read_i32::<byteorder::BigEndian>().unwrap() as i64),
                8 => Ok(reader.read_i64::<byteorder::BigEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }

        Endianness::LittleEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as i64),
                2 => Ok(reader.read_i16::<byteorder::LittleEndian>().unwrap() as i64),
                4 => Ok(reader.read_i32::<byteorder::LittleEndian>().unwrap() as i64),
                8 => Ok(reader.read_i64::<byteorder::LittleEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }
    }
}

/// Parse a signed integer of a given endianness from a byte buffer.
///
/// The size of the buffer will be used to determine the size of the integer
/// that should be parsed (u8, u16, u32 or u64), but the result will be stored
/// in a u64.
pub fn unsigned(buffer: &[u8], endianness: Endianness) -> Result<u64> {
    let mut reader = io::Cursor::new(buffer);

    match endianness {
        Endianness::BigEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as u64),
                2 => Ok(reader.read_u16::<byteorder::BigEndian>().unwrap() as u64),
                4 => Ok(reader.read_u32::<byteorder::BigEndian>().unwrap() as u64),
                8 => Ok(reader.read_u64::<byteorder::BigEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }

        Endianness::LittleEndian => {
            match buffer.len() {
                1 => Ok(buffer[0] as u64),
                2 => Ok(reader.read_u16::<byteorder::LittleEndian>().unwrap() as u64),
                4 => Ok(reader.read_u32::<byteorder::LittleEndian>().unwrap() as u64),
                8 => Ok(reader.read_u64::<byteorder::LittleEndian>().unwrap()),
                x => Err(Error::InvalidData(format!["Invalid integer size: {} B", x])),
            }
        }
    }
}

/// Dissector of last resort: store raw bytes without interpretation.
pub fn raw(data: &[u8]) -> Result {
    Ok(Val::Object(vec![
        ("raw data".to_string(), Ok(Val::Bytes(data.to_vec())))
    ]))
}

pub mod ethernet;
pub mod ip;
<|endoftext|>


<commit_before>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(into_cow)]

extern crate oauth_client as oauth;

use std::borrow::{Cow, IntoCow};
use std::collections::HashMap;
use oauth::Token;

mod api_twitter_oauth {
    pub const REQUEST_TOKEN: &'static str   = "https://api.twitter.com/oauth/request_token";
    pub const AUTHORIZE: &'static str       = "https://api.twitter.com/oauth/authorize";
    pub const ACCESS_TOKEN: &'static str    = "https://api.twitter.com/oauth/access_token";
}

mod api_twitter_soft {
    pub const UPDATE_STATUS: &'static str = "https://api.twitter.com/1.1/statuses/update.json";
}

fn split_query<'a>(query: &'a str) -> HashMap<Cow<'a, str>, Cow<'a, str>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

pub fn get_request_token(consumer: &Token) -> Token<'static> {
    let resp = oauth::get(api_twitter_oauth::REQUEST_TOKEN, consumer, None, None);
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

pub fn get_authorize_url(request: &Token) -> String {
    format!("{}?oauth_token={}", api_twitter_oauth::AUTHORIZE, request.key)
}

pub fn get_access_token(consumer: &Token, request: &Token, pin: &str) -> Token<'static> {
    let mut param = HashMap::new();
    let _ = param.insert("oauth_verifier".into_cow(), pin.into_cow());
    let resp = oauth::get(api_twitter_oauth::ACCESS_TOKEN, consumer, Some(request), Some(&param));
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

/// function to update the status
/// This function takes as arguments the consumer key, the access key, and the status (obviously)
pub fn update_status(consumer: &Token, access: &Token, status: &str) {
    let mut param = HashMap::new();
    let _ = param.insert("status".into_cow(), status.into_cow());
    let _ = oauth::post(api_twitter_soft::UPDATE_STATUS, consumer, Some(access), Some(&param));
}
}
<commit_msg>src/lib.rs : HOME_TIMELINE added (to get the home timeline in your terminal)<commit_after>#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]

#![feature(into_cow)]

extern crate oauth_client as oauth;

use std::borrow::{Cow, IntoCow};
use std::collections::HashMap;
use oauth::Token;

mod api_twitter_oauth {
    pub const REQUEST_TOKEN: &'static str   = "https://api.twitter.com/oauth/request_token";
    pub const AUTHORIZE: &'static str       = "https://api.twitter.com/oauth/authorize";
    pub const ACCESS_TOKEN: &'static str    = "https://api.twitter.com/oauth/access_token";
}

mod api_twitter_soft {
    pub const UPDATE_STATUS: &'static str = "https://api.twitter.com/1.1/statuses/update.json";
    pub const HOME_TIMELINE: &'static str = "https://api.twitter.com/1.1/statuses/home_timeline.json";
}

fn split_query<'a>(query: &'a str) -> HashMap<Cow<'a, str>, Cow<'a, str>> {
    let mut param = HashMap::new();
    for q in query.split('&') {
        let mut s = q.splitn(2, '=');
        let k = s.next().unwrap();
        let v = s.next().unwrap();
        let _ = param.insert(k.into_cow(), v.into_cow());
    }
    param
}

pub fn get_request_token(consumer: &Token) -> Token<'static> {
    let resp = oauth::get(api_twitter_oauth::REQUEST_TOKEN, consumer, None, None);
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

pub fn get_authorize_url(request: &Token) -> String {
    format!("{}?oauth_token={}", api_twitter_oauth::AUTHORIZE, request.key)
}

pub fn get_access_token(consumer: &Token, request: &Token, pin: &str) -> Token<'static> {
    let mut param = HashMap::new();
    let _ = param.insert("oauth_verifier".into_cow(), pin.into_cow());
    let resp = oauth::get(api_twitter_oauth::ACCESS_TOKEN, consumer, Some(request), Some(&param));
    let param = split_query(&resp);
    Token::new(param.get("oauth_token").unwrap().to_string(),
               param.get("oauth_token_secret").unwrap().to_string())
}

/// function to update the status
/// This function takes as arguments the consumer key, the access key, and the status (obviously)
pub fn update_status(consumer: &Token, access: &Token, status: &str) {
    let mut param = HashMap::new();
    let _ = param.insert("status".into_cow(), status.into_cow());
    let _ = oauth::post(api_twitter_soft::UPDATE_STATUS, consumer, Some(access), Some(&param));
}
}
<|endoftext|>


<commit_before>// Copyright (C) 2015  Jonas Pollok <jonas.p@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! # Exprssion Rewriting System
//!
//! The Expression Rewriting System provides the tools
//! to create and transform expressions based on patterns
//! and rewriting rules.
//!
//!
//! ## Expressions
//!
//! An [`Expression`](enum.Expression.html) is the fundamental
//! object wich will be created and transformed. The string representation
//! of an [`Expression`](enum.Expression.html) is an S-Expression.
//!
//! We have several types of expressions where most of them are needed for
//! matching. But we have two fundamental basic blocks one is an `Atom`
//! and the other one is a `List`.  An `Atom` represents a string entry while
//! a `List` contains a list of expressions. Denoted as S-Expressions we have
//! for example `(x (y z))` which is a list of two expressions. The first is
//! an `Atom` with the value `x`. The second is another `List` which itself
//! contains two `Atom` expressions representing `y` and `z`.
//!
//! ```
//! use ers::Expression;
//!
//! let x = Expression::Atom("x".to_string());
//! let y = Expression::Atom("y".to_string());
//! let z = Expression::Atom("z".to_string());
//!
//! let ls = Expression::List(vec![y, z]);
//! format!("{:?}", ls); // => "(y z)"
//!
//! let ers = Expression::List(vec![x, ls]);
//! format!("{:?}", ers); // => "(x (y z))"
//! ```
//!
//! ### Parsing
//!
//! We can also build an `Expression` by parsing an S-Expression string.
//!
//! ```
//! use ers::Expression;
//!
//! let ls = "(x (y z))".parse::<Expression>();
//!
//! assert_eq!(format!("{:?}", ls.unwrap()), "(x (y z))");
//! ```
//!
//!
//! ## Matching
//!
//! The other types of expressions are `Blank` and `Pattern` together with
//! their derivatives `BlankSeq`, `BlankNullSeq` as well as `PatternSeq`
//! and `PatternNullSeq`. These expressions are used when we want to match
//! another expression and create bindings which can be used to rewrite
//! expressions. The difference between a `Pattern` and `Blank` is
//! that `Blank` is unnamed while `Pattern` does carry a name. The S-Expression
//! representation is `_` for a `Blank` and `x_` for a `Pattern` with the name
//! `x`. `BlankSeq` and `PatternSeq` are sequence patterns and are denoted
//! `__` as well as `x__`. Finally `BlankNullSeq` and `PatternNullSeq` use
//! three underscores `___` and `x___`.
//!
//! ```
//! use ers::{Expression, Match};
//!
//! let expr = "(x (y z))".parse::<Expression>().unwrap();
//! let pattern = "(_ a_)".parse::<Expression>().unwrap();
//!
//! // create bindings mapping `a` to `(y z)`
//! let bindings = expr.match_pattern(&pattern);
//! ```
//!
//! ## Binding
//!
//! Once we successfully matched an expression and generated bindings we can use
//! these to bind them to a template. A template is an expression where the
//! variable contained in the bindings are an `Atom` expression within the
//! template.
//!
//! ```
//! use ers::{Expression, Match, Bind};
//!
//! let expr = "(x (y z))".parse::<Expression>().unwrap();
//! let pattern = "(_ a_)".parse::<Expression>().unwrap();
//!
//! // create bindings mapping `a` to `(y z)`
//! let bindings =  expr.match_pattern(&pattern).unwrap();
//!
//! let template = "(a b)".parse::<Expression>().unwrap();
//!
//! // replace the atom `a` in the template with the expression `(y z)`
//! // according to the bindings
//! let replaced = template.bind(&bindings);
//!
//! assert_eq!(format!("{:?}", replaced), "((y z) b)");
//! ```

#![feature(staged_api)]
#![staged_api]
#![unstable(feature = "ers1")]

#![feature(collections)]

#![deny(missing_docs)]

#![crate_type = "rlib"]
#![crate_type = "dylib"]

pub use expression::Expression;
pub use matching::Match;
pub use binding::Binding;
pub use binding::Bind;

mod expression;
mod matching;
mod binding;
<commit_msg>feature collections is not needed anymore<commit_after>// Copyright (C) 2015  Jonas Pollok <jonas.p@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.

// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! # Exprssion Rewriting System
//!
//! The Expression Rewriting System provides the tools
//! to create and transform expressions based on patterns
//! and rewriting rules.
//!
//!
//! ## Expressions
//!
//! An [`Expression`](enum.Expression.html) is the fundamental
//! object wich will be created and transformed. The string representation
//! of an [`Expression`](enum.Expression.html) is an S-Expression.
//!
//! We have several types of expressions where most of them are needed for
//! matching. But we have two fundamental basic blocks one is an `Atom`
//! and the other one is a `List`.  An `Atom` represents a string entry while
//! a `List` contains a list of expressions. Denoted as S-Expressions we have
//! for example `(x (y z))` which is a list of two expressions. The first is
//! an `Atom` with the value `x`. The second is another `List` which itself
//! contains two `Atom` expressions representing `y` and `z`.
//!
//! ```
//! use ers::Expression;
//!
//! let x = Expression::Atom("x".to_string());
//! let y = Expression::Atom("y".to_string());
//! let z = Expression::Atom("z".to_string());
//!
//! let ls = Expression::List(vec![y, z]);
//! format!("{:?}", ls); // => "(y z)"
//!
//! let ers = Expression::List(vec![x, ls]);
//! format!("{:?}", ers); // => "(x (y z))"
//! ```
//!
//! ### Parsing
//!
//! We can also build an `Expression` by parsing an S-Expression string.
//!
//! ```
//! use ers::Expression;
//!
//! let ls = "(x (y z))".parse::<Expression>();
//!
//! assert_eq!(format!("{:?}", ls.unwrap()), "(x (y z))");
//! ```
//!
//!
//! ## Matching
//!
//! The other types of expressions are `Blank` and `Pattern` together with
//! their derivatives `BlankSeq`, `BlankNullSeq` as well as `PatternSeq`
//! and `PatternNullSeq`. These expressions are used when we want to match
//! another expression and create bindings which can be used to rewrite
//! expressions. The difference between a `Pattern` and `Blank` is
//! that `Blank` is unnamed while `Pattern` does carry a name. The S-Expression
//! representation is `_` for a `Blank` and `x_` for a `Pattern` with the name
//! `x`. `BlankSeq` and `PatternSeq` are sequence patterns and are denoted
//! `__` as well as `x__`. Finally `BlankNullSeq` and `PatternNullSeq` use
//! three underscores `___` and `x___`.
//!
//! ```
//! use ers::{Expression, Match};
//!
//! let expr = "(x (y z))".parse::<Expression>().unwrap();
//! let pattern = "(_ a_)".parse::<Expression>().unwrap();
//!
//! // create bindings mapping `a` to `(y z)`
//! let bindings = expr.match_pattern(&pattern);
//! ```
//!
//! ## Binding
//!
//! Once we successfully matched an expression and generated bindings we can use
//! these to bind them to a template. A template is an expression where the
//! variable contained in the bindings are an `Atom` expression within the
//! template.
//!
//! ```
//! use ers::{Expression, Match, Bind};
//!
//! let expr = "(x (y z))".parse::<Expression>().unwrap();
//! let pattern = "(_ a_)".parse::<Expression>().unwrap();
//!
//! // create bindings mapping `a` to `(y z)`
//! let bindings =  expr.match_pattern(&pattern).unwrap();
//!
//! let template = "(a b)".parse::<Expression>().unwrap();
//!
//! // replace the atom `a` in the template with the expression `(y z)`
//! // according to the bindings
//! let replaced = template.bind(&bindings);
//!
//! assert_eq!(format!("{:?}", replaced), "((y z) b)");
//! ```

#![feature(staged_api)]
#![staged_api]
#![unstable(feature = "ers1")]

#![deny(missing_docs)]

#![crate_type = "rlib"]
#![crate_type = "dylib"]

pub use expression::Expression;
pub use matching::Match;
pub use binding::Binding;
pub use binding::Bind;

mod expression;
mod matching;
mod binding;
<|endoftext|>


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

//! Hound, a WAV encoding library.
//!
//! TODO: Add some introductory text here.
//!
//! The following example renders a 440 Hz sine wave, and stores it as as a
//! mono wav file with a sample rate of 44.1 kHz and 16 bits per sample.
//!
//! ```
//! #![feature(core)]
//!
//! use std::fs;
//! use std::f32::consts::PI;
//! use std::iter::IntoIterator;
//! use std::num;
//! use hound;
//!
//! let spec = hound::WavSpec {
//!     channels: 1,
//!     sample_rate: 44100,
//!     bits_per_sample: hound::BitDepth::Bps16
//! };
//! // TODO: ensure that the type can be inferred.
//! let mut writer = hound::WavWriter::<fs::File>::create("sine.wav", spec);
//! let mut writer = writer.ok().unwrap();
//! for t in (0 .. 44100).into_iter().map(|x| x as f32 / 44100.0) {
//!     let sample = (t * 440.0 * 2.0 * PI).sin();
//!     let amplitude: i16 = num::Int::max_value();
//!     writer.write_sample((sample * amplitude as f32) as i16).ok().unwrap();
//! }
//! writer.finalize().ok().unwrap();
//! ```

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

use std::fs;
use std::io;
use std::io::{Seek, Write};
use std::num;
use std::path;

/// Extends the functionality of `io::Write` with additional methods.
///
/// The methods may be used on any type that implements `io::Write`.
trait WriteExt: io::Write {
    /// Writes an unsigned 16-bit integer in little endian format.
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;

    /// Writes an unsigned 32-bit integer in little endian format.
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

/// A type that can be used to represent audio samples.
pub trait Sample {
    /// Writes the audio sample to the WAVE data section.
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()>;
}

impl Sample for u16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()> {
        writer.write_le_u16(self)
        // TODO: take bits into account
    }
}

impl Sample for i16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()> {
        writer.write_le_u16(self as u16)
        // TODO: take bits into account
    }
}

/// The number of bits per sample, as a multiple of 8.
#[derive(Clone, Copy)]
pub enum BitDepth {
    /// 8 bits per sample.
    Bps8,

    /// 16 bits per sample.
    Bps16,

    /// 24 bits per sample.
    Bps24,

    /// 32 bits per sample.
    Bps32
}

impl BitDepth {
    /// Returns the number of bits per sample as an integer.
    pub fn into_u32(self) -> u32 {
        match self {
            BitDepth::Bps8 => 8,
            BitDepth::Bps16 => 16,
            BitDepth::Bps24 => 24,
            BitDepth::Bps32 => 32
        }
    }
}

impl num::FromPrimitive for BitDepth {
    fn from_u64(n: u64) -> Option<BitDepth> {
        match n {
            8 => Some(BitDepth::Bps8),
            16 => Some(BitDepth::Bps16),
            24 => Some(BitDepth::Bps24),
            32 => Some(BitDepth::Bps32),
            _ => None
        }
    }

    fn from_i64(n: i64) -> Option<BitDepth> { num::from_u8(n as u8) }
}

impl num::ToPrimitive for BitDepth {
    fn to_u64(&self) -> Option<u64> { Some(self.into_u32() as u64) }
    fn to_i64(&self) -> Option<i64> { Some(self.into_u32() as i64) }
}

impl num::NumCast for BitDepth {
    fn from<T>(n: T) -> Option<BitDepth> where T: num::ToPrimitive {
        n.to_u8().and_then(num::FromPrimitive::from_u8)
    }
}

/// Specifies properties of the audio data.
#[derive(Clone, Copy)]
pub struct WavSpec {
    /// The number of channels.
    pub channels: u16,

    /// The number of samples per second.
    ///
    /// A common value is 44100, this is 44.1 kHz which is used for CD audio.
    pub sample_rate: u32,

    /// The number of bits per sample.
    ///
    /// A common value is 16 bits per sample, which is used for CD audio.
    pub bits_per_sample: BitDepth
}

/// A writer that accepts samples and writes the WAVE format.
///
/// TODO: add example.
///
/// After all samples have been written, the file must be finalized. This can
/// be done by calling `finalize`. If `finalize` is not called, the file will
/// be finalized upon drop. However, finalization involves IO that may fail,
/// and without calling `finalize`, such a failure cannot be observed.
pub struct WavWriter<W> where W: io::Write + io::Seek {
    /// Specifies properties of the audio data.
    spec: WavSpec,

    /// Whether the header has been written already.
    wrote_header: bool,

    /// The writer that will be written to.
    writer: io::BufWriter<W>,

    /// The number of bytes written to the data section.
    ///
    /// This is an `u32` because WAVE cannot accomodate more data.
    data_bytes_written: u32,

    /// Whether `finalize_internal` has been called.
    finalized: bool
}

impl<W> WavWriter<W> where W: io::Write + io::Seek {
    /// Creates a writer that writes the WAVE format to the underlying writer.
    ///
    /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
    /// buffering internally to avoid too many `write` calls to the underlying
    /// writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W> {
        WavWriter {
            spec: spec,
            wrote_header: false,
            writer: io::BufWriter::new(writer),
            data_bytes_written: 0,
            finalized: false
        }
    }

    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// The file will be overwritten if it exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        let mut header = [0u8; 44];
        let spec = &self.spec;
        let bps = spec.bits_per_sample.into_u32();

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            try!(buffer.seek(io::SeekFrom::Current(4)));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt\0".as_bytes()));
            try!(buffer.write_le_u32(16)); // Size of the WAVE header
            try!(buffer.write_le_u16(1));  // PCM encoded audio
            try!(buffer.write_le_u16(spec.channels));
            try!(buffer.write_le_u32(spec.sample_rate));
            let bytes_per_sec = spec.sample_rate
                              * bps
                              * spec.channels as u32 / 8;
            try!(buffer.write_le_u32(bytes_per_sec));
            try!(buffer.write_le_u16(16)); // TODO: block align
            try!(buffer.write_le_u32(bps));

            // TODO: data section header
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    /// Writes a single sample for one channel.
    ///
    /// WAVE interleaves channel data, so the channel that this writes the
    /// sample to depends on previous writes.
    pub fn write_sample<S: Sample>(&mut self, sample: S) -> io::Result<()> {
        if !self.wrote_header {
            try!(self.write_header());
        }

        let bps = self.spec.bits_per_sample.into_u32();
        try!(sample.write(&mut self.writer, bps));
        self.data_bytes_written += bps / 8;
        Ok(())
    }

    /// Performs finalization. After calling this, the writer should be destructed.
    fn finalize_internal(&mut self) -> io::Result<()> {
        self.finalized = true;

        // Flush remaining samples via the BufWriter.
        try!(self.writer.flush());

        // Extract the underlying writer and rewind it to the start, to update
        // the header fields of which we now know the value.
        let mut writer = self.writer.get_mut();
        try!(writer.seek(io::SeekFrom::Start(0)));

        // TODO: update size fields
        Ok(())
    }

    /// Writes the parts of the WAVE format that require knowing all samples.
    ///
    /// This method must be called after all samples have been written. If it
    /// is not called, the destructor will finalize the file, but any IO errors
    /// that occur in the process cannot be observed in that manner.
    pub fn finalize(mut self) -> io::Result<()> {
        self.finalize_internal()
    }
}

impl<W> Drop for WavWriter<W> where W: io::Write + io::Seek {
    fn drop(&mut self) {
        // `finalize_internal` must be called only once. If that is done via
        // `finalize`, then this method is a no-op. If the user did not
        // finalize explicitly, then we should do it now. This can fail, but
        // drop should not panic, so a failure is ignored silently here.
        if !self.finalized {
            let _r = self.finalize_internal();
        }
    }
}
<commit_msg>implement writing the WAVEFORMATEXTENSIBLE struct<commit_after>// Hound -- A WAV encoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 3 of the License only.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Hound, a WAV encoding library.
//!
//! TODO: Add some introductory text here.
//!
//! The following example renders a 440 Hz sine wave, and stores it as as a
//! mono wav file with a sample rate of 44.1 kHz and 16 bits per sample.
//!
//! ```
//! #![feature(core)]
//!
//! use std::fs;
//! use std::f32::consts::PI;
//! use std::iter::IntoIterator;
//! use std::num;
//! use hound;
//!
//! let spec = hound::WavSpec {
//!     channels: 1,
//!     sample_rate: 44100,
//!     bits_per_sample: 16
//! };
//! // TODO: ensure that the type can be inferred.
//! let mut writer = hound::WavWriter::<fs::File>::create("sine.wav", spec);
//! let mut writer = writer.ok().unwrap();
//! for t in (0 .. 44100).into_iter().map(|x| x as f32 / 44100.0) {
//!     let sample = (t * 440.0 * 2.0 * PI).sin();
//!     let amplitude: i16 = num::Int::max_value();
//!     writer.write_sample((sample * amplitude as f32) as i16).ok().unwrap();
//! }
//! writer.finalize().ok().unwrap();
//! ```

#![warn(missing_docs)]
#![allow(dead_code)] // TODO: Remove for v0.1
#![feature(convert, io)]

use std::fs;
use std::io;
use std::io::{Seek, Write};
use std::path;

/// Extends the functionality of `io::Write` with additional methods.
///
/// The methods may be used on any type that implements `io::Write`.
trait WriteExt: io::Write {
    /// Writes an unsigned 16-bit integer in little endian format.
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;

    /// Writes an unsigned 32-bit integer in little endian format.
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

/// A type that can be used to represent audio samples.
pub trait Sample {
    /// Writes the audio sample to the WAVE data section.
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()>;
}

impl Sample for u16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()> {
        writer.write_le_u16(self)
        // TODO: take bits into account
    }
}

impl Sample for i16 {
    fn write<W: io::Write>(self, writer: &mut W, bits: u32) -> io::Result<()> {
        writer.write_le_u16(self as u16)
        // TODO: take bits into account
    }
}

/// Specifies properties of the audio data.
#[derive(Clone, Copy)]
pub struct WavSpec {
    /// The number of channels.
    pub channels: u16,

    /// The number of samples per second.
    ///
    /// A common value is 44100, this is 44.1 kHz which is used for CD audio.
    pub sample_rate: u32,

    /// The number of bits per sample.
    ///
    /// A common value is 16 bits per sample, which is used for CD audio.
    pub bits_per_sample: u32
}

/// A writer that accepts samples and writes the WAVE format.
///
/// TODO: add example.
///
/// After all samples have been written, the file must be finalized. This can
/// be done by calling `finalize`. If `finalize` is not called, the file will
/// be finalized upon drop. However, finalization involves IO that may fail,
/// and without calling `finalize`, such a failure cannot be observed.
pub struct WavWriter<W> where W: io::Write + io::Seek {
    /// Specifies properties of the audio data.
    spec: WavSpec,

    /// The (container) bytes per sample. This is the bit rate / 8 rounded up.
    bytes_per_sample: u32,

    /// Whether the header has been written already.
    wrote_header: bool,

    /// The writer that will be written to.
    writer: io::BufWriter<W>,

    /// The number of bytes written to the data section.
    ///
    /// This is an `u32` because WAVE cannot accomodate more data.
    data_bytes_written: u32,

    /// Whether `finalize_internal` has been called.
    finalized: bool
}

impl<W> WavWriter<W> where W: io::Write + io::Seek {
    /// Creates a writer that writes the WAVE format to the underlying writer.
    ///
    /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
    /// buffering internally to avoid too many `write` calls to the underlying
    /// writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W> {
        WavWriter {
            spec: spec,
            bytes_per_sample: (spec.bits_per_sample as f32 / 8.0).ceil() as u32,
            wrote_header: false,
            writer: io::BufWriter::new(writer),
            data_bytes_written: 0,
            finalized: false
        }
    }

    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// The file will be overwritten if it exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        // Useful links:
        // https://msdn.microsoft.com/en-us/library/ms713462.aspx
        // https://msdn.microsoft.com/en-us/library/ms713497.aspx

        let mut header = [0u8; 70];
        let spec = &self.spec;

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            try!(buffer.write_le_u32(0));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt ".as_bytes()));
            try!(buffer.write_le_u32(16)); // Size of the WAVE header chunk.

            // The following is based on the WAVEFORMATEXTENSIBLE struct as
            // documented on MSDN.

            // The field wFormatTag, value 1 means WAVE_FORMAT_PCM, but we use
            // the slightly more sophisticated WAVE_FORMAT_EXTENSIBLE.
            try!(buffer.write_le_u16(0xfffe));
            // The field nChannels.
            try!(buffer.write_le_u16(spec.channels));
            // The field nSamplesPerSec.
            try!(buffer.write_le_u32(spec.sample_rate));
            let bytes_per_sec = spec.sample_rate
                              * self.bytes_per_sample
                              * spec.channels as u32;
            // The field nAvgBytesPerSec;
            try!(buffer.write_le_u32(bytes_per_sec));
            // The field nBlockAlign. Block align * sample rate = bytes per sec.
            try!(buffer.write_le_u16((bytes_per_sec / spec.sample_rate) as u16));
            // The field wBitsPerSample. This is actually the size of the
            // container, so this is a multiple of 8.
            try!(buffer.write_le_u32(self.bytes_per_sample * 8));
            // The field cbSize, the number of remaining bytes in the struct.
            try!(buffer.write_le_u16(22));
            // The field wValidBitsPerSample, the real number of bits per sample.
            try!(buffer.write_le_u16(self.spec.bits_per_sample as u16));
            // The field dwChannelMask.
            // TODO: add the option to specify the channel mask. For now, write
            // the stereo mask, even though it is wrong.
            try!(buffer.write_le_u32(0x1 | 0x2));
            // The field SubFormat. We use KSDATAFORMAT_SUBTYPE_PCM. The
            // following UUIDS are defined:
            // - PCM:        00000001-0000-0010-8000-00aa00389b71
            // - IEEE_FLOAT: 00000003-0000-0010-8000-00aa00389b71
            try!(buffer.write_all(&[0x00, 0x00, 0x00, 0x01,
                                    0x00, 0x00, 0x00, 0x01,
                                    0x80, 0x00, 0x00, 0xaa,
                                    0x00, 0x38, 0x9b, 0x71]));

            // So far the "fmt " section, now comes the "data" section. We will
            // only write the header here, actual data are the samples. The
            // number of bytes that this will take is not known at this point.
            // The 0 will be overwritten later.
            try!(buffer.write_all("data".as_bytes()));
            try!(buffer.write_le_u32(0));
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    /// Writes a single sample for one channel.
    ///
    /// WAVE interleaves channel data, so the channel that this writes the
    /// sample to depends on previous writes.
    pub fn write_sample<S: Sample>(&mut self, sample: S) -> io::Result<()> {
        if !self.wrote_header {
            try!(self.write_header());
        }

        // TODO: do we need bits per sample? Is the padding at the obvious side?
        try!(sample.write(&mut self.writer, self.bytes_per_sample));
        self.data_bytes_written += self.bytes_per_sample;
        Ok(())
    }

    /// Performs finalization. After calling this, the writer should be destructed.
    fn finalize_internal(&mut self) -> io::Result<()> {
        self.finalized = true;

        // Flush remaining samples via the BufWriter.
        try!(self.writer.flush());

        // Extract the underlying writer and rewind it to the start, to update
        // the header fields of which we now know the value.
        let mut writer = self.writer.get_mut();
        try!(writer.seek(io::SeekFrom::Start(0)));

        // TODO: update size fields
        Ok(())
    }

    /// Writes the parts of the WAVE format that require knowing all samples.
    ///
    /// This method must be called after all samples have been written. If it
    /// is not called, the destructor will finalize the file, but any IO errors
    /// that occur in the process cannot be observed in that manner.
    pub fn finalize(mut self) -> io::Result<()> {
        self.finalize_internal()
    }
}

impl<W> Drop for WavWriter<W> where W: io::Write + io::Seek {
    fn drop(&mut self) {
        // `finalize_internal` must be called only once. If that is done via
        // `finalize`, then this method is a no-op. If the user did not
        // finalize explicitly, then we should do it now. This can fail, but
        // drop should not panic, so a failure is ignored silently here.
        if !self.finalized {
            let _r = self.finalize_internal();
        }
    }
}
<|endoftext|>


<commit_before>// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

// TODO:
// Collection trait
// convert this to Key/Value K/V

use Direction::{Left, Middle, Right, Leaf};
use InsertResult::{Fit, Split};

/// Four
enum SplitNode<V: Ord> {
    Four(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> SplitNode<V> {
    fn to_two(self) -> Two<V> {
        match self {
            SplitNode::LeafFour(v1, v2, v3) =>
                Two(v2,
                    box Node::LeafTwo(LeafTwo(v1)),
                    box Node::LeafTwo(LeafTwo(v3))),
            SplitNode::Four(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    box Node::Two(Two(v1, n1, n2)),
                    box Node::Two(Two(v3, n3, n4))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(SplitNode<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn as_node(self) -> Node<V> { Node::Two(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn as_node(self) -> Node<V> { Node::Three(self) }

    fn to_four(self, other_value: V, other_node: Box<Node<V>>) -> SplitNode<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            SplitNode::Four(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            SplitNode::Four(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

impl <V: Ord> LeafTwo<V> {
    fn to_three(self, other_value: V) -> LeafThree<V> {
        let LeafTwo(self_value) = self;
        if self_value > other_value {
            LeafThree(other_value, self_value)
        } else {
            LeafThree(self_value, other_value)
        }
    }
}

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn as_node(self) -> Node<V> { Node::LeafThree(self) }

    fn to_four(self, value: V) -> SplitNode<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { SplitNode::LeafFour(value1, value2, value) }
        else if value < value1 { SplitNode::LeafFour(value, value1, value2) }
        else                   { SplitNode::LeafFour(value1, value, value2) }
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwo(LeafTwo<V>),
    LeafThree(LeafThree<V>),
    Two(Two<V>),
    Three(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match self {
            &Node::Two(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            &Node::Three(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &Node::Two(Two(ref v, _, _)) |
                &Node::LeafTwo(LeafTwo(ref v)) if to_check == v => true,

            &Node::Three(Three(ref v1, ref v2, _, _, _)) |
                &Node::LeafThree(LeafThree(ref v1, ref v2)) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            Node::LeafTwo(leaf_two) => {
                let three_node = leaf_two.to_three(to_insert);
                Fit(three_node.as_node())
            },

            // Split if leaf ThreeNode
            Node::LeafThree(leaf_three) => {
                let four_node = leaf_three.to_four(to_insert);
                Split(four_node)
            },

            // Recurse down if internal Node and handle results
            Node::Two(Two(value, box left, box middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => panic!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, box returned_node, box other_node),
                            Middle => Two(value, box other_node, box returned_node),
                            _ => panic!(""),
                        }.as_node(),
                    Split(four_node) => four_node.to_two().to_three(value, box other_node).as_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            Node::Three(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => panic!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, box returned_node, other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, box returned_node),
                            _ => panic!(""),
                        };
                        Fit(three.as_node())
                    },
                    Split(four_node) => {
                        let two = four_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_four(value1, other_node1),
                            _ => panic!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => Node::LeafTwo(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(four_node) => four_node.to_two().as_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}
<commit_msg>Rename method to be more consistent<commit_after>// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

// TODO:
// Collection trait
// convert this to Key/Value K/V

use Direction::{Left, Middle, Right, Leaf};
use InsertResult::{Fit, Split};

/// Four
enum SplitNode<V: Ord> {
    Four(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> SplitNode<V> {
    fn to_two(self) -> Two<V> {
        match self {
            SplitNode::LeafFour(v1, v2, v3) =>
                Two(v2,
                    box Node::LeafTwo(LeafTwo(v1)),
                    box Node::LeafTwo(LeafTwo(v3))),
            SplitNode::Four(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    box Node::Two(Two(v1, n1, n2)),
                    box Node::Two(Two(v3, n3, n4))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(SplitNode<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn as_node(self) -> Node<V> { Node::Two(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn as_node(self) -> Node<V> { Node::Three(self) }

    fn to_split_node(self, other_value: V, other_node: Box<Node<V>>) -> SplitNode<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            SplitNode::Four(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            SplitNode::Four(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

impl <V: Ord> LeafTwo<V> {
    fn to_three(self, other_value: V) -> LeafThree<V> {
        let LeafTwo(self_value) = self;
        if self_value > other_value {
            LeafThree(other_value, self_value)
        } else {
            LeafThree(self_value, other_value)
        }
    }
}

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn as_node(self) -> Node<V> { Node::LeafThree(self) }

    fn to_split_node(self, value: V) -> SplitNode<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { SplitNode::LeafFour(value1, value2, value) }
        else if value < value1 { SplitNode::LeafFour(value, value1, value2) }
        else                   { SplitNode::LeafFour(value1, value, value2) }
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwo(LeafTwo<V>),
    LeafThree(LeafThree<V>),
    Two(Two<V>),
    Three(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match self {
            &Node::Two(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            &Node::Three(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &Node::Two(Two(ref v, _, _)) |
                &Node::LeafTwo(LeafTwo(ref v)) if to_check == v => true,

            &Node::Three(Three(ref v1, ref v2, _, _, _)) |
                &Node::LeafThree(LeafThree(ref v1, ref v2)) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            Node::LeafTwo(leaf_two) => {
                let three_node = leaf_two.to_three(to_insert);
                Fit(three_node.as_node())
            },

            // Split if leaf ThreeNode
            Node::LeafThree(leaf_three) => {
                let four_node = leaf_three.to_split_node(to_insert);
                Split(four_node)
            },

            // Recurse down if internal Node and handle results
            Node::Two(Two(value, box left, box middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => panic!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, box returned_node, box other_node),
                            Middle => Two(value, box other_node, box returned_node),
                            _ => panic!(""),
                        }.as_node(),
                    Split(four_node) => four_node.to_two().to_three(value, box other_node).as_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            Node::Three(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => panic!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, box returned_node, other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, box returned_node),
                            _ => panic!(""),
                        };
                        Fit(three.as_node())
                    },
                    Split(four_node) => {
                        let two = four_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_split_node(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_split_node(value1, other_node1),
                            _ => panic!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => Node::LeafTwo(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(four_node) => four_node.to_two().as_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}
<|endoftext|>


<commit_before>extern crate redis;
use redis::{Connection, Commands};

extern crate threadpool;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;

pub trait Task : Sync {
  fn get_name(&self) -> &str;
  fn perform(&self, params: Result<String, ()>) -> bool;
}

pub struct Worker {
  pool: ThreadPool,
  prefix: String,
  conn: redis::Connection,
  tasks: Vec<Box<Task>>
}

impl Worker {

  pub fn new(n : usize) -> Worker {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let prefix = "workers".to_string();

    Worker {
      pool: ThreadPool::new(n),
      prefix: prefix,
      conn: client.get_connection().unwrap(),
      tasks: Vec::new()
    }
  }

  pub fn register(&mut self, t: Box<Task>) {
    self.tasks.push(t);
  }

  pub fn enqueue(&self, task_name: &str, arguments: &str) {
    let key = format!("{}:tasks", self.prefix);
    let val = format!("{}:{}", task_name, arguments);
    redis::cmd("RPUSH").arg(key).arg(val).execute(&self.conn);
  }

  pub fn work(&self) {
    let next = self.next_task();

    if next.is_ok() {
      let (task, args) = next.unwrap();

      // self.pool.execute(move|| {
      //   println!("Execute task in a thread... {}", task.get_name());
      // });
      task.perform(args);

    } else {
      println!("Nothing more!");
    }
  }

  fn next_task(&self) -> Result<(&Box<Task>, Result<String, ()>), &'static str> {
    let next : redis::RedisResult<String> = self.conn.rpop(format!("{}:tasks", self.prefix));

    // TODO: it should be a better way to write this
    if next.is_ok() {
      let next_payload = next.unwrap();
      let r = self.get_task_by_name(&next_payload);
      let args : Result<String, ()>;

      if r.is_ok() {
        let task : &Box<Task> = r.unwrap();
        if next_payload.len() > task.get_name().len() {
          args = Ok(next_payload[task.get_name().len()+1 .. next_payload.len()].to_string());
        } else {
          args = Err(());
        }

        Ok((task, args))

      } else {
        Err("Error")
      }

    } else {
      Err("No more")
    }
  }

  fn get_task_by_name(&self, name: &str) -> Result<&Box<Task>, &'static str> {
    for task in &self.tasks {
      if name.starts_with(task.get_name()) {
        return Ok(task)
      }
    }
    Err("Task not found!")
  }

}

#[test]
fn it_works() {
}
<commit_msg>use Box instead of &Box in order to move it for the thread.<commit_after>// use core::clone::Clone;

extern crate redis;
use redis::{Connection, Commands};

extern crate threadpool;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
use std::sync::Mutex;

pub trait Task : Sync + Send {
  fn get_name(&self) -> &str;
  fn perform(&self, params: Result<String, ()>) -> bool;
}

pub struct Worker {
  pool: ThreadPool,
  prefix: String,
  conn: redis::Connection,
  tasks: Mutex<Vec<Box<Task>>>
}

impl Worker {

  pub fn new(n : usize) -> Worker {
    let client = redis::Client::open("redis://127.0.0.1/").unwrap();
    let prefix = "workers".to_string();

    Worker {
      pool: ThreadPool::new(n),
      prefix: prefix,
      conn: client.get_connection().unwrap(),
      tasks: Mutex::new(Vec::new())
    }
  }

  pub fn register(&mut self, t: Box<Task>) {
    self.tasks.lock().unwrap().push(t);
  }

  pub fn enqueue(&self, task_name: &str, arguments: &str) {
    let key = format!("{}:tasks", self.prefix);
    let val = format!("{}:{}", task_name, arguments);
    redis::cmd("RPUSH").arg(key).arg(val).execute(&self.conn);
  }

  pub fn work(&self) {
    let next = self.next_task();

    if next.is_ok() {
      let (task, args) = next.unwrap();

      self.pool.execute(move|| {
        println!("Execute task in a thread... {}", task.get_name());
        task.perform(args);
      });

    } else {
      println!("Nothing more!");
    }
  }

  fn next_task(&self) -> Result<(Box<Task>, Result<String, ()>), &'static str> {
    let next : redis::RedisResult<String> = self.conn.rpop(format!("{}:tasks", self.prefix));

    // TODO: it should be a better way to write this
    if next.is_ok() {
      let next_payload = next.unwrap();
      let r = self.get_task_by_name(&next_payload);
      let args : Result<String, ()>;

      if r.is_ok() {
        let task : Box<Task> = r.unwrap();
        if next_payload.len() > task.get_name().len() {
          args = Ok(next_payload[task.get_name().len()+1 .. next_payload.len()].to_string());
        } else {
          args = Err(());
        }

        Ok((task, args))

      } else {
        Err("Error")
      }

    } else {
      Err("No more")
    }
  }

  fn get_task_by_name(&self, name: &str) -> Result<Box<Task>, &'static str> {
    let mut tasks = self.tasks.lock().unwrap();

    let pos = tasks.iter().position(|t| {
      name.starts_with(t.get_name())
    });

    match pos {
      Some(p) => Ok(tasks.remove(p)),
      None => Err("Task not found!")
    }
  }

}

#[test]
fn it_works() {
}
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate serde;
#[macro_use] extern crate serde_derive;

mod error;
mod errorcode;
mod response;

use std::io::Read;
use std::collections::HashSet;
use std::net::Ipv4Addr;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&Ipv4Addr>) -> Result<(), RecaptchaError> {
    use reqwest::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.query_pairs_mut().extend_pairs(&[
        ("secret", key),
        ("response", response),
    ]);

    if let Some(user_ip) = user_ip {
        url.query_pairs_mut().append_pair("remoteip", &user_ip);
    }

    let client = Client::new();

    let mut response = try!(client.get(url).send());
    let recaptcha_response = response.json::<RecaptchaResponse>()?;

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<commit_msg>Use IpAddr instead of Ipv4Addr<commit_after>extern crate reqwest;
extern crate serde;
#[macro_use] extern crate serde_derive;

mod error;
mod errorcode;
mod response;

use std::collections::HashSet;
use std::net::IpAddr;

pub use error::RecaptchaError;
pub use errorcode::RecaptchaErrorCode;

use response::RecaptchaResponse;

/// Verify a recaptcha user response
pub fn verify(key: &str, response: &str, user_ip: Option<&IpAddr>) -> Result<(), RecaptchaError> {
    use reqwest::{Client, Url};

    let user_ip = user_ip.map(ToString::to_string);

    let mut url = Url::parse("https://www.google.com/recaptcha/api/siteverify").unwrap();

    url.query_pairs_mut().extend_pairs(&[
        ("secret", key),
        ("response", response),
    ]);

    if let Some(user_ip) = user_ip {
        url.query_pairs_mut().append_pair("remoteip", &user_ip);
    }

    let client = Client::new();

    let mut response = try!(client.get(url).send());
    let recaptcha_response = response.json::<RecaptchaResponse>()?;

    match (recaptcha_response.success, recaptcha_response.error_codes) {
        (true, _) => Ok(()),
        (false, Some(errors)) => Err(RecaptchaError::Codes(errors)),
        (false, _) => Err(RecaptchaError::Codes(HashSet::new()))
    }
}

#[test]
fn test_invalid_secret_missing_response() {
    use RecaptchaError::*;
    use RecaptchaErrorCode::*;
    let resp = verify("", "", None);

    match resp {
        Ok(()) => panic!("unexpected response: Ok(())"),
        Err(Codes(ref errors)) => {
            assert!(errors.contains(&InvalidSecret));
            assert!(errors.contains(&MissingResponse));
        }
        Err(e) => panic!("unexpected error: {}", e),
    };

    println!("{:?}", resp);
}
<|endoftext|>