<commit_before>//! A Rust bindings library to Google Maps Web Services.
//!
//! The purpose of this crate is to provide an idomatic Rust bindings library
//! for Google Maps Web Services. It is a work in progress, and there will be
//! regular breaking changes prior to 0.1.0.
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde_urlencoded;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

/// Distance Matrix request and response
pub mod distance_matrix;
/// Common structs related to making a request
pub mod request_structs;
/// Common library wide types
pub mod types;

const BASE_URL: &'static str = "https://maps.googleapis.com/maps/api/";
<commit_msg>Fixed broken build in removing LatLng<commit_after>//! A Rust bindings library to Google Maps Web Services.
//!
//! The purpose of this crate is to provide an idomatic Rust bindings library
//! for Google Maps Web Services. It is a work in progress, and there will be
//! regular breaking changes prior to 0.1.0.
extern crate hyper;
extern crate hyper_native_tls;
extern crate serde_urlencoded;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

/// Distance Matrix request and response
pub mod distance_matrix;
/// Common library wide types
pub mod types;

const BASE_URL: &'static str = "https://maps.googleapis.com/maps/api/";
<|endoftext|>


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

pub mod xen;
pub mod arch;
pub mod utils;

extern {
    fn main(_: isize, _: *const *const u8) -> isize;
}

// 8KB
const STACK_SIZE: usize = 8192;

#[no_mangle]
#[allow(non_upper_case_globals)]
#[link_section=".stack"]
pub static rust_stack: [u8; STACK_SIZE] = [0; STACK_SIZE];

#[no_mangle]
pub fn uni_rust_entry() {
    unsafe {
        let _ = main(0, core::ptr::null());
    }
}

<commit_msg>uni: Entry function now calls an init function<commit_after>#![feature(no_std, lang_items, asm)]
#![no_std]

pub mod xen;
pub mod arch;
pub mod utils;

extern {
    fn main(_: isize, _: *const *const u8) -> isize;
}

// 8KB
const STACK_SIZE: usize = 8192;

#[no_mangle]
#[allow(non_upper_case_globals)]
#[link_section=".stack"]
pub static rust_stack: [u8; STACK_SIZE] = [0; STACK_SIZE];

fn init() {
    arch::init();
}

#[no_mangle]
pub fn uni_rust_entry() {
    init();

    unsafe {
        let _ = main(0, core::ptr::null());
    }
}

<|endoftext|>


<commit_before>#![crate_name = "jsonway"]
#![comment = "JSON builder for Rust"]
#![license = "MIT"]
#![crate_type = "rlib"]
// #![deny(warnings)]
// #![deny(bad_style)]
#![feature(macro_rules, phase, tuple_indexing)]

extern crate serialize;

use std::collections::TreeMap;
use std::to_string::ToString;
use serialize::json;
use serialize::json::{JsonList, Json, JsonObject, ToJson};

pub use mutable_json::MutableJson;

pub mod mutable_json;

pub struct ListBuilder {
    list: JsonList,
    null: bool,
    skip: bool
}

impl ListBuilder {

    pub fn new() -> ListBuilder {
        ListBuilder {
            list: vec![],
            null: false,
            skip: false
        }
    }

    pub fn from_json(list: Json) -> Option<ListBuilder> {
        match list {
            json::List(list) => Some(ListBuilder {
                list: list,
                null: false,
                skip: false
            }),
            _ => None
        }
    }

    pub fn build(builder: |&mut ListBuilder|) -> ListBuilder {
        let mut bldr = ListBuilder::new();
        builder(&mut bldr);

        bldr
    }

    pub fn move_to_json(self) -> Json {
        if self.null {
            json::Null
        } else {
            json::List(self.list)
        }
    }

    pub fn push_json(&mut self, value: Json) {
        self.list.push(value);
    }

    pub fn list(&mut self, builder: |&mut ListBuilder|) {
        self.push(ListBuilder::build(builder).move_to_json());
    }

    pub fn object(&mut self, builder: |&mut ObjectBuilder|) {
        self.push(ObjectBuilder::build(builder).move_to_json());
    }

    pub fn null(&mut self) {
        self.null = true;
    }

    pub fn skip(&mut self) {
        self.skip = true;
    }
}

impl<T: ToJson> ListBuilder {
    pub fn push(&mut self, value: T) {
        self.push_json(value.to_json());
    }
}

impl<A, T: Iterator<A>> ListBuilder {
    pub fn objects(&mut self, iter: &mut T, func: |A, &mut ObjectBuilder|) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                let mut bldr = ObjectBuilder::new();
                func(a.unwrap(), &mut bldr);
                if !bldr.skip {
                    self.push(bldr.move_to_json())
                }
            } else {
                stop = true;
            }
        }
    }

    pub fn lists(&mut self, iter: &mut T, func: |A, &mut ListBuilder|) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                let mut bldr = ListBuilder::new();
                func(a.unwrap(), &mut bldr);
                if !bldr.skip {
                    self.push(bldr.move_to_json())
                }
            } else {
                stop = true;
            }
        }
    }

    pub fn map(&mut self, iter: &mut T, func: |A| -> Json) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                self.push(func(a.unwrap()))
            } else {
                stop = true;
            }
        }
    }
}

impl ToJson for ListBuilder {
    fn to_json(&self) -> Json {
         if self.null { json::Null } else { self.list.to_json() }
    }
}

pub struct ObjectBuilder {
    object: JsonObject,
    null: bool,
    skip: bool
}

impl ObjectBuilder {
    pub fn new() -> ObjectBuilder {
        ObjectBuilder {
            object: TreeMap::new(),
            null: false,
            skip: false
        }
    }

    pub fn from_json(object: Json) -> Option<ObjectBuilder> {
        match object {
            json::Object(object) => Some(ObjectBuilder {
                object: object,
                null: false,
                skip: false
            }),
            _ => None
        }
    }

    pub fn build(builder: |&mut ObjectBuilder|) -> ObjectBuilder {
        let mut bldr = ObjectBuilder::new();
        builder(&mut bldr);

        bldr
    }

    pub fn move_to_json(self) -> Json {
        if self.null {
            json::Null
        } else {
            json::Object(self.object)
        }
    }

    pub fn null(&mut self) {
        self.null = true;
    }

    pub fn index(&mut self) -> bool {
        true
    }

    pub fn skip(&mut self) {
        self.skip = true;
    }
}

impl<V: ToJson, N: ToString> ObjectBuilder {
    pub fn set(&mut self, name: N, value: V) {
        self.set_json(name.to_string(), value.to_json());
    }

    pub fn call(&mut self, name: N, value: V) {
        self.set(name, value);
    }
}

impl<N: ToString> ObjectBuilder {
    pub fn set_json(&mut self, name: N, value: Json) {
        self.object.insert(name.to_string(), value);
    }

    pub fn list(&mut self, name: N, builder: |&mut ListBuilder|) {
        self.set(name, ListBuilder::build(builder).move_to_json());
    }

    pub fn object(&mut self, name: N, builder: |&mut ObjectBuilder|) {
        self.set(name, ObjectBuilder::build(builder).move_to_json());
    }
}

impl ToJson for ObjectBuilder {
    fn to_json(&self) -> Json {
        if self.null { json::Null } else { self.object.to_json() }
    }
}

pub struct JsonWay;

impl JsonWay {
    pub fn list(builder: |&mut ListBuilder|) -> ListBuilder {
        ListBuilder::build(builder)
    }

    pub fn object(builder: |&mut ObjectBuilder|) -> ObjectBuilder {
        ObjectBuilder::build(builder)
    }
}

#[test]
fn simple() {
    let object = JsonWay::object(|json| {
        json.set("first_name", "Luke".to_string());
        json.set("last_name", "Skywalker".to_string());

        json.object("info", |json| {
            json.set("homeworld", "Tatooine".to_string());
            json.set("born", "19 BBY".to_string());
            json.set("died", "Between 45 ABY and 137 ABY".to_string());
        });

        json.list("masters", |json| {
            json.push("Obi-Wan Kenobi".to_string());
            json.push("Yoda".to_string());
            json.push("Joruus C'baoth (Briefly)".to_string());
            json.push("Darth Sidious (Briefly)".to_string());
        });
    });

    println!("{}", object.move_to_json().to_pretty_str());

    // uncomment to dump
    // fail!("");

}

#[test]
fn iterations() {

    #[deriving(Show)]
    enum Side {
        Light,
        Dark
    }

    struct Jedi {
        name: String,
        side: Side
    }

    let jedi = vec![
        Jedi { name: "Saes Rrogon".to_string(), side: Dark },
        Jedi { name: "Qui-Gon Jinn".to_string(), side: Light },
        Jedi { name: "Obi-Wan Kenobi".to_string(), side: Light }
    ];

    let light_jedi_objects_list = JsonWay::list(|json| {
        json.objects(&mut jedi.iter(), |jedi, json| {
            match jedi.side {
                Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Dark => json.skip()
            }
        })
    });

    println!("{}", light_jedi_objects_list.move_to_json().to_pretty_str());

    let light_jedi_tuple_list = JsonWay::list(|json| {
        json.lists(&mut jedi.iter(), |jedi, json| {
            match jedi.side {
                Light => {
                    json.push(jedi.name.to_string());
                    json.push(jedi.side.to_string());
                },
                Dark => json.skip()
            }
        })
    });

    println!("{}", light_jedi_tuple_list.move_to_json().to_pretty_str());

    // uncomment to dump
    // fail!("");

}
<commit_msg>refactor: add some more docs and rename `move_to_json` to `unwrap`<commit_after>#![crate_name = "jsonway"]
#![comment = "JSON builder for Rust"]
#![license = "MIT"]
#![crate_type = "rlib"]
// #![deny(warnings)]
// #![deny(bad_style)]
#![feature(macro_rules, phase, tuple_indexing)]

extern crate serialize;

use std::collections::TreeMap;
use std::to_string::ToString;
use serialize::json;
use serialize::json::{JsonList, Json, JsonObject, ToJson};

pub use mutable_json::MutableJson;

pub mod mutable_json;

pub struct ListBuilder {
    list: JsonList,
    null: bool,
    skip: bool
}

/// Use ListBuilder to produce JSON arrays
impl ListBuilder {

    pub fn new() -> ListBuilder {
        ListBuilder {
            list: vec![],
            null: false,
            skip: false
        }
    }

    /// Initialize builder with initial value.
    pub fn from_json(list: Json) -> Option<ListBuilder> {
        match list {
            json::List(list) => Some(ListBuilder {
                list: list,
                null: false,
                skip: false
            }),
            _ => None
        }
    }

    /// Create new ListBuilder, pass it to closure as mutable ref and return.
    pub fn build(builder: |&mut ListBuilder|) -> ListBuilder {
        let mut bldr = ListBuilder::new();
        builder(&mut bldr);

        bldr
    }

    /// Move out internal JSON value.
    pub fn unwrap(self) -> Json {
        if self.null {
            json::Null
        } else {
            json::List(self.list)
        }
    }

    /// Push JSON value to list.
    pub fn push_json(&mut self, value: Json) {
        self.list.push(value);
    }

    /// Create new list and push it.
    pub fn list(&mut self, builder: |&mut ListBuilder|) {
        self.push(ListBuilder::build(builder).unwrap());
    }

    /// Create new object and push it
    pub fn object(&mut self, builder: |&mut ObjectBuilder|) {
        self.push(ObjectBuilder::build(builder).unwrap());
    }

    /// It you call `null`, this list will be converted to null when converting
    /// to raw JSON value.
    pub fn null(&mut self) {
        self.null = true;
    }

    /// It you call `skip`, this list will be skipped.
    pub fn skip(&mut self) {
        self.skip = true;
    }
}

impl<T: ToJson> ListBuilder {
    /// Push to list something that can be converted to JSON.
    pub fn push(&mut self, value: T) {
        self.push_json(value.to_json());
    }
}

impl<A, T: Iterator<A>> ListBuilder {
    /// Fill this list by objects builded from iterator.
    pub fn objects(&mut self, iter: &mut T, func: |A, &mut ObjectBuilder|) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                let mut bldr = ObjectBuilder::new();
                func(a.unwrap(), &mut bldr);
                if !bldr.skip {
                    self.push(bldr.unwrap())
                }
            } else {
                stop = true;
            }
        }
    }

    // Fill this list by lists builded from iterator.
    pub fn lists(&mut self, iter: &mut T, func: |A, &mut ListBuilder|) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                let mut bldr = ListBuilder::new();
                func(a.unwrap(), &mut bldr);
                if !bldr.skip {
                    self.push(bldr.unwrap())
                }
            } else {
                stop = true;
            }
        }
    }

    /// Fill this list by JSON values builded from iterator.
    pub fn map(&mut self, iter: &mut T, func: |A| -> Json) {
        let mut stop = false;
        while !stop {
            let a = iter.next();
            if a.is_some() {
                self.push(func(a.unwrap()))
            } else {
                stop = true;
            }
        }
    }
}

impl ToJson for ListBuilder {
    /// Copy self to new JSON instance.
    fn to_json(&self) -> Json {
         if self.null { json::Null } else { self.list.to_json() }
    }
}

pub struct ObjectBuilder {
    object: JsonObject,
    null: bool,
    skip: bool
}

/// ListBuilder is used to produce JSON arrays
impl ObjectBuilder {
    pub fn new() -> ObjectBuilder {
        ObjectBuilder {
            object: TreeMap::new(),
            null: false,
            skip: false
        }
    }

    /// Initialize builder with initial value.
    pub fn from_json(object: Json) -> Option<ObjectBuilder> {
        match object {
            json::Object(object) => Some(ObjectBuilder {
                object: object,
                null: false,
                skip: false
            }),
            _ => None
        }
    }

    /// Create new builder, pass it to closure as mutable ref and return.
    pub fn build(builder: |&mut ObjectBuilder|) -> ObjectBuilder {
        let mut bldr = ObjectBuilder::new();
        builder(&mut bldr);

        bldr
    }

    /// Move out internal JSON value.
    pub fn unwrap(self) -> Json {
        if self.null {
            json::Null
        } else {
            json::Object(self.object)
        }
    }

    /// It you call `null`, this list will be converted to null.
    pub fn null(&mut self) {
        self.null = true;
    }

    /// It you call `skip`, this list will be skipped.
    pub fn skip(&mut self) {
        self.skip = true;
    }
}

impl<V: ToJson, N: ToString> ObjectBuilder {
    /// Set object's `name` field with something that can be
    /// converted to Json value.
    pub fn set(&mut self, name: N, value: V) {
        self.set_json(name.to_string(), value.to_json());
    }

    /// Stub for future use
    pub fn call(&mut self, name: N, value: V) {
        self.set(name, value);
    }
}

impl<N: ToString> ObjectBuilder {
    /// Set object's `name` field with raw Json value.
    pub fn set_json(&mut self, name: N, value: Json) {
        self.object.insert(name.to_string(), value);
    }

    /// Build new list and set object's `name` field with it.
    pub fn list(&mut self, name: N, builder: |&mut ListBuilder|) {
        self.set(name, ListBuilder::build(builder).unwrap());
    }

    /// Build new object and set object's `name` field with it.
    pub fn object(&mut self, name: N, builder: |&mut ObjectBuilder|) {
        self.set(name, ObjectBuilder::build(builder).unwrap());
    }
}

impl ToJson for ObjectBuilder {
    /// Copy self to new JSON instance.
    fn to_json(&self) -> Json {
        if self.null { json::Null } else { self.object.to_json() }
    }
}

pub struct JsonWay;

impl JsonWay {
    /// Create and return new ListBuilder
    pub fn list(builder: |&mut ListBuilder|) -> ListBuilder {
        ListBuilder::build(builder)
    }

    /// Create and return new ObjectBuilder
    pub fn object(builder: |&mut ObjectBuilder|) -> ObjectBuilder {
        ObjectBuilder::build(builder)
    }
}

#[test]
fn simple() {
    let object = JsonWay::object(|json| {
        json.set("first_name", "Luke".to_string());
        json.set("last_name", "Skywalker".to_string());

        json.object("info", |json| {
            json.set("homeworld", "Tatooine".to_string());
            json.set("born", "19 BBY".to_string());
            json.set("died", "Between 45 ABY and 137 ABY".to_string());
        });

        json.list("masters", |json| {
            json.push("Obi-Wan Kenobi".to_string());
            json.push("Yoda".to_string());
            json.push("Joruus C'baoth (Briefly)".to_string());
            json.push("Darth Sidious (Briefly)".to_string());
        });
    });

    println!("{}", object.unwrap().to_pretty_str());

    // uncomment to dump
    // fail!("");

}

#[test]
fn iterations() {

    #[deriving(Show)]
    enum Side {
        Light,
        Dark
    }

    struct Jedi {
        name: String,
        side: Side
    }

    let jedi = vec![
        Jedi { name: "Saes Rrogon".to_string(), side: Dark },
        Jedi { name: "Qui-Gon Jinn".to_string(), side: Light },
        Jedi { name: "Obi-Wan Kenobi".to_string(), side: Light }
    ];

    let light_jedi_objects_list = JsonWay::list(|json| {
        json.objects(&mut jedi.iter(), |jedi, json| {
            match jedi.side {
                Light => {
                    json.set("name".to_string(), jedi.name.to_string());
                    json.set("side".to_string(), jedi.side.to_string());
                },
                Dark => json.skip()
            }
        })
    });

    println!("{}", light_jedi_objects_list.unwrap().to_pretty_str());

    let light_jedi_tuple_list = JsonWay::list(|json| {
        json.lists(&mut jedi.iter(), |jedi, json| {
            match jedi.side {
                Light => {
                    json.push(jedi.name.to_string());
                    json.push(jedi.side.to_string());
                },
                Dark => json.skip()
            }
        })
    });

    println!("{}", light_jedi_tuple_list.unwrap().to_pretty_str());

    // uncomment to dump
    // fail!("");

}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/ipnet/2.3.1")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
//! [`Ipv6Subnets`] types for iterating over the subnets contained in
//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
//! addition, subtraction, bitwise-and, and bitwise-or operations that
//! are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These can be created
//!   using their constructors. They are also returned by the
//!   [`subnets()`] methods and used within the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
//!   iterators that generate IP addresses. These can be created using
//!   their constructors. They are also returned by the [`hosts()`]
//!   methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrRange.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.html
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but
//! it's not enabled by default. Use the `serde` [feature] to enable.
//!
//! ```toml
//! [dependencies]
//! ipnet = { version = "2", features = ["serde"] }
//! ```
//!
//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
//! `Ipv6Net` types will serialize to their `Display` strings.
//!
//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
//! consist of the network address octects followed by the prefix
//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
//! variant index prepending the above string of 5 or 17 bytes.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "serde")]
extern crate serde;

pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "serde")]
mod ipnet_serde;
<commit_msg>Update lib.rs<commit_after>#![doc(html_root_url = "https://docs.rs/ipnet/2.4.0")]
//! Types for IPv4 and IPv6 network addresses.
//!
//! This module provides types and useful methods for working with IPv4
//! and IPv6 network addresses, commonly called IP prefixes. The new
//! [`IpNet`], [`Ipv4Net`], and [`Ipv6Net`] types build on the existing
//! [`IpAddr`], [`Ipv4Addr`], and [`Ipv6Addr`] types already provided in
//! Rust's standard library and align to their design to stay
//! consistent.
//!
//! The module also provides the [`IpSubnets`], [`Ipv4Subnets`], and
//! [`Ipv6Subnets`] types for iterating over the subnets contained in
//! an IP address range. The [`IpAddrRange`], [`Ipv4AddrRange`], and
//! [`Ipv6AddrRange`] types for iterating over IP addresses in a range.
//! And traits that extend `Ipv4Addr` and `Ipv6Addr` with methods for
//! addition, subtraction, bitwise-and, and bitwise-or operations that
//! are missing in Rust's standard library.
//!
//! The module only uses stable features so it is guaranteed to compile
//! using the stable toolchain.
//!
//! # Organization
//!
//! * [`IpNet`] represents an IP network address, either IPv4 or IPv6.
//! * [`Ipv4Net`] and [`Ipv6Net`] are respectively IPv4 and IPv6 network
//!   addresses.
//! * [`IpSubnets`], [`Ipv4Subnets`], and [`Ipv6Subnets`] are iterators
//!   that generate the smallest set of IP network addresses bound by an
//!   IP address range and minimum prefix length. These can be created
//!   using their constructors. They are also returned by the
//!   [`subnets()`] methods and used within the [`aggregate()`] methods.
//! * [`IpAddrRange`], [`Ipv4AddrRange`], and [`Ipv6AddrRange`] are
//!   iterators that generate IP addresses. These can be created using
//!   their constructors. They are also returned by the [`hosts()`]
//!   methods.
//! * The [`IpAdd`], [`IpSub`], [`IpBitAnd`], [`IpBitOr`] traits extend
//!   the [`Ipv4Addr`] and [`Ipv6Addr`] types with methods to perform
//!   these operations.
//!
//! [`IpNet`]: enum.IpNet.html
//! [`Ipv4Net`]: struct.Ipv4Net.html
//! [`Ipv6Net`]: struct.Ipv6Net.html
//! [`IpAddr`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html
//! [`Ipv4Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv4Addr.html
//! [`Ipv6Addr`]: https://doc.rust-lang.org/std/net/struct.Ipv6Addr.html
//! [`IpSubnets`]: enum.IpSubnets.html
//! [`Ipv4Subnets`]: struct.Ipv4Subnets.html
//! [`Ipv6Subnets`]: struct.Ipv6Subnets.html
//! [`subnets()`]: enum.IpNet.html#method.subnets
//! [`aggregate()`]: enum.IpNet.html#method.aggregate
//! [`IpAddrRange`]: enum.IpAddrRange.html
//! [`Ipv4AddrRange`]: struct.Ipv4AddrRange.html
//! [`Ipv6AddrRange`]: struct.Ipv6AddrRange.html
//! [`hosts()`]: enum.IpNet.html#method.hosts
//! [`IpAdd`]: trait.IpAdd.html
//! [`IpSub`]: trait.IpSub.html
//! [`IpBitAnd`]: trait.IpBitAnd.html
//! [`IpBitOr`]: trait.IpBitOr.html
//!
//! # Serde support
//!
//! This library comes with support for [serde](https://serde.rs) but
//! it's not enabled by default. Use the `serde` [feature] to enable.
//!
//! ```toml
//! [dependencies]
//! ipnet = { version = "2", features = ["serde"] }
//! ```
//!
//! For human readable formats (e.g. JSON) the `IpNet`, `Ipv4Net`, and
//! `Ipv6Net` types will serialize to their `Display` strings.
//!
//! For compact binary formats (e.g. Bincode) the `Ipv4Net` and
//! `Ipv6Net` types will serialize to a string of 5 and 17 bytes that
//! consist of the network address octects followed by the prefix
//! length. The `IpNet` type will serialize to an Enum with the V4 or V6
//! variant index prepending the above string of 5 or 17 bytes.
//!
//! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section

#[cfg(feature = "serde")]
extern crate serde;

pub use self::ipext::{IpAdd, IpSub, IpBitAnd, IpBitOr, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange};
pub use self::ipnet::{IpNet, Ipv4Net, Ipv6Net, PrefixLenError, IpSubnets, Ipv4Subnets, Ipv6Subnets};
pub use self::parser::AddrParseError;

mod ipext;
mod ipnet;
mod parser;
#[cfg(feature = "serde")]
mod ipnet_serde;
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(slicing_syntax)]

use std::slice::bytes::copy_memory;

pub static SBOX: [u8, ..256] = [
  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,
  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,
  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,
  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,
  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,
  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,
  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,
  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,
  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,
  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,
  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14
];

pub static SBOXI: [u8, ..256] = [
  0xdd, 0x07, 0x8f, 0x5f, 0x7e, 0x12, 0x0e, 0x46, 0xcb, 0xb7, 0xef, 0x4c, 0xcc, 0xb2, 0xe3, 0x9f,
  0x4a, 0xfd, 0x2f, 0x0f, 0xff, 0x44, 0x27, 0x2d, 0x2b, 0x61, 0xf7, 0x90, 0x98, 0xde, 0x20, 0xf6,
  0x87, 0x4f, 0x4d, 0xa3, 0xc8, 0x92, 0xaf, 0x57, 0xb5, 0x00, 0x6b, 0x1a, 0xb0, 0x8d, 0x01, 0x3d,
  0x62, 0xf0, 0x56, 0xfb, 0x9c, 0x58, 0x09, 0xc2, 0x72, 0xdf, 0xa7, 0xdc, 0x23, 0x08, 0x59, 0x47,
  0x9d, 0xbc, 0x29, 0x02, 0xf1, 0x80, 0x99, 0xa1, 0x64, 0x37, 0xcf, 0xee, 0x1d, 0xbe, 0x31, 0x70,
  0xf2, 0xa5, 0xbf, 0xb1, 0x0a, 0xa0, 0x6d, 0x22, 0xe5, 0x83, 0x54, 0x89, 0xa9, 0x52, 0x69, 0x4e,
  0x91, 0x9a, 0x10, 0xd5, 0x84, 0x8b, 0xe4, 0x28, 0x41, 0x9b, 0xc0, 0x7a, 0xc4, 0xd7, 0xb3, 0x2a,
  0x82, 0x85, 0xea, 0x16, 0x7d, 0xed, 0x78, 0xe9, 0xd0, 0x42, 0x3f, 0xca, 0x06, 0x76, 0x9e, 0x51,
  0x50, 0xbd, 0x1e, 0xfe, 0xb6, 0xb4, 0x88, 0x86, 0xd1, 0x4b, 0x2c, 0xd3, 0x17, 0xfa, 0x3b, 0xf4,
  0x55, 0x43, 0x6a, 0x19, 0x48, 0xd2, 0x74, 0x5e, 0x18, 0xf9, 0x53, 0x21, 0x7c, 0x81, 0x35, 0xfc,
  0x38, 0x0b, 0x04, 0xa2, 0x75, 0x65, 0xe8, 0x11, 0x8e, 0x40, 0x6e, 0xc6, 0x6c, 0x93, 0x94, 0xa6,
  0x95, 0xce, 0x45, 0x63, 0xf3, 0x66, 0x77, 0xe2, 0x71, 0x96, 0xac, 0x3c, 0x1c, 0xcd, 0x30, 0x5c,
  0x14, 0xc5, 0x49, 0xa8, 0x32, 0xad, 0x6f, 0x15, 0xc3, 0x03, 0x1f, 0xd9, 0x5a, 0xba, 0xab, 0x8a,
  0xe6, 0x67, 0x73, 0xb8, 0x25, 0xda, 0x33, 0x68, 0x05, 0x1b, 0x34, 0xf8, 0xc1, 0xa4, 0x36, 0xb9,
  0x26, 0xc9, 0x7b, 0xd4, 0xe7, 0x2e, 0x8c, 0x5b, 0xd6, 0xd8, 0xae, 0xec, 0x0c, 0xf5, 0x3e, 0xe1,
  0x0d, 0x7f, 0xe0, 0x13, 0xbb, 0x3a, 0x97, 0x5d, 0xeb, 0xaa, 0xc7, 0x39, 0x79, 0x24, 0xdb, 0x60
];

fn pad(msg: &[u8]) -> Vec<u8> {
  let mut msg = msg.to_vec();
  let pad = 16 - msg.len() % 16;
  msg.grow_fn(pad, |_| pad as u8);
  msg
}

fn checksum(msg: &[u8]) -> [u8, ..16] {
  // Message must be padded.
  assert!(msg.len() % 16 == 0);

  let mut checksum = [0u8, ..16];
  let mut last = 0u8;

  for chunk in msg.chunks(16) {
    for (mbyte, cbyte) in chunk.iter().zip(checksum.iter_mut()) {
      *cbyte ^= SBOX[(*mbyte ^ last) as uint];
      last = *cbyte;
    }
  }

  checksum
}

pub fn compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
  // Two 128 bit blocks in.
  assert!(state.len() == 16 && msg.len() == 16);

  let mut x = [0u8, ..48];
  let mut result = [0u8, ..16];

  // Copy over the previous state.
  copy_memory(x[mut ..16], state);

  // Copy over the message block.
  copy_memory(x[mut 16..32], msg);

  // XOR the previous state and the message block.
  for (i, byte) in msg.iter().enumerate() {
    x[32 + i] = *byte ^ x[i];
  }

  // Encrypt block (18 rounds).
  let mut t = 0u8;
  for i in range(0, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += i;
  }

  // Copy the new state.
  copy_memory(&mut result, x[..16]);
  result
}

pub fn digest(msg: &[u8]) -> [u8, ..16] {
  // Pad the message to be a multiple of 16 bytes long.
  let msg = pad(msg);

  // Compress all message blocks.
  let state = msg.chunks(16).fold([0u8, ..16], |s, m| compress(&s, m));

  // Compute the checksum.
  let checksum = checksum(msg[]);

  // Compress checksum and return.
  compress(&state, &checksum)
}

#[cfg(test)]
mod test {
  use digest;

  fn check(exp: &str, msg: &str) {
    let hash = digest(msg.as_bytes());
    let hex = hash.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b));
    assert_eq!(exp.to_string(), hex);
  }

  #[test]
  fn test() {
    check("8350e5a3e24c153df2275c9f80692773", "");
    check("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
    check("da853b0d3f88d99b30283a69e6ded6bb", "abc");
    check("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
    check("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
    check("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
    check("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
  }
}
<commit_msg>small clean ups<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(slicing_syntax)]

use std::slice::bytes::copy_memory;

pub static SBOX: [u8, ..256] = [
  0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1, 0xec, 0xf0, 0x06, 0x13,
  0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c, 0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca,
  0x1e, 0x9b, 0x57, 0x3c, 0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
  0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e, 0xbb, 0x2f, 0xee, 0x7a,
  0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f, 0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21,
  0x80, 0x7f, 0x5d, 0x9a, 0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
  0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a, 0xac, 0x56, 0xaa, 0xc6,
  0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6, 0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1,
  0x45, 0x9d, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
  0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7e, 0x0f,
  0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a, 0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26,
  0x2c, 0x53, 0x0d, 0x6e, 0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
  0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08, 0x0c, 0xbd, 0xb1, 0x4a,
  0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d, 0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39,
  0xf2, 0xef, 0xb7, 0x0e, 0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
  0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33, 0x9f, 0x11, 0x83, 0x14
];

pub static SBOXI: [u8, ..256] = [
  0xdd, 0x07, 0x8f, 0x5f, 0x7e, 0x12, 0x0e, 0x46, 0xcb, 0xb7, 0xef, 0x4c, 0xcc, 0xb2, 0xe3, 0x9f,
  0x4a, 0xfd, 0x2f, 0x0f, 0xff, 0x44, 0x27, 0x2d, 0x2b, 0x61, 0xf7, 0x90, 0x98, 0xde, 0x20, 0xf6,
  0x87, 0x4f, 0x4d, 0xa3, 0xc8, 0x92, 0xaf, 0x57, 0xb5, 0x00, 0x6b, 0x1a, 0xb0, 0x8d, 0x01, 0x3d,
  0x62, 0xf0, 0x56, 0xfb, 0x9c, 0x58, 0x09, 0xc2, 0x72, 0xdf, 0xa7, 0xdc, 0x23, 0x08, 0x59, 0x47,
  0x9d, 0xbc, 0x29, 0x02, 0xf1, 0x80, 0x99, 0xa1, 0x64, 0x37, 0xcf, 0xee, 0x1d, 0xbe, 0x31, 0x70,
  0xf2, 0xa5, 0xbf, 0xb1, 0x0a, 0xa0, 0x6d, 0x22, 0xe5, 0x83, 0x54, 0x89, 0xa9, 0x52, 0x69, 0x4e,
  0x91, 0x9a, 0x10, 0xd5, 0x84, 0x8b, 0xe4, 0x28, 0x41, 0x9b, 0xc0, 0x7a, 0xc4, 0xd7, 0xb3, 0x2a,
  0x82, 0x85, 0xea, 0x16, 0x7d, 0xed, 0x78, 0xe9, 0xd0, 0x42, 0x3f, 0xca, 0x06, 0x76, 0x9e, 0x51,
  0x50, 0xbd, 0x1e, 0xfe, 0xb6, 0xb4, 0x88, 0x86, 0xd1, 0x4b, 0x2c, 0xd3, 0x17, 0xfa, 0x3b, 0xf4,
  0x55, 0x43, 0x6a, 0x19, 0x48, 0xd2, 0x74, 0x5e, 0x18, 0xf9, 0x53, 0x21, 0x7c, 0x81, 0x35, 0xfc,
  0x38, 0x0b, 0x04, 0xa2, 0x75, 0x65, 0xe8, 0x11, 0x8e, 0x40, 0x6e, 0xc6, 0x6c, 0x93, 0x94, 0xa6,
  0x95, 0xce, 0x45, 0x63, 0xf3, 0x66, 0x77, 0xe2, 0x71, 0x96, 0xac, 0x3c, 0x1c, 0xcd, 0x30, 0x5c,
  0x14, 0xc5, 0x49, 0xa8, 0x32, 0xad, 0x6f, 0x15, 0xc3, 0x03, 0x1f, 0xd9, 0x5a, 0xba, 0xab, 0x8a,
  0xe6, 0x67, 0x73, 0xb8, 0x25, 0xda, 0x33, 0x68, 0x05, 0x1b, 0x34, 0xf8, 0xc1, 0xa4, 0x36, 0xb9,
  0x26, 0xc9, 0x7b, 0xd4, 0xe7, 0x2e, 0x8c, 0x5b, 0xd6, 0xd8, 0xae, 0xec, 0x0c, 0xf5, 0x3e, 0xe1,
  0x0d, 0x7f, 0xe0, 0x13, 0xbb, 0x3a, 0x97, 0x5d, 0xeb, 0xaa, 0xc7, 0x39, 0x79, 0x24, 0xdb, 0x60
];

fn pad(msg: &[u8]) -> Vec<u8> {
  let mut msg = msg.to_vec();
  let pad = 16 - msg.len() % 16;
  msg.grow_fn(pad, |_| pad as u8);
  msg
}

fn checksum(msg: &[u8]) -> [u8, ..16] {
  // Message must be padded.
  assert!(msg.len() % 16 == 0);

  let mut checksum = [0u8, ..16];
  let mut last = 0u8;

  for chunk in msg.chunks(16) {
    for (mbyte, cbyte) in chunk.iter().zip(checksum.iter_mut()) {
      *cbyte ^= SBOX[(*mbyte ^ last) as uint];
      last = *cbyte;
    }
  }

  checksum
}

pub fn compress(state: &[u8], msg: &[u8]) -> [u8, ..16] {
  // Two 128 bit blocks in.
  assert!(state.len() == 16 && msg.len() == 16);

  // Copy over the current state and the message block.
  let mut x = [0u8, ..48];
  copy_memory(x[mut ..16], state);
  copy_memory(x[mut 16..32], msg);

  // XOR the previous state and the message block.
  for (i, byte) in msg.iter().enumerate() {
    x[32 + i] = *byte ^ x[i];
  }

  // Encrypt block (18 rounds).
  let mut t = 0u8;
  for i in range(0, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += i;
  }

  // Extract the result.
  let mut result = [0u8, ..16];
  copy_memory(&mut result, x[..16]);
  result
}

pub fn digest(msg: &[u8]) -> [u8, ..16] {
  // Pad the message to be a multiple of 16 bytes long.
  let msg = pad(msg);

  // Compress all message blocks.
  let state = msg.chunks(16).fold([0u8, ..16], |s, m| compress(&s, m));

  // Compute the checksum and merge it into the state.
  compress(&state, &checksum(msg[]))
}

#[cfg(test)]
mod test {
  use digest;

  fn check(exp: &str, msg: &str) {
    let hash = digest(msg.as_bytes());
    let hex = hash.iter().fold(String::new(), |a, &b| format!("{}{:02x}", a, b));
    assert_eq!(exp.to_string(), hex);
  }

  #[test]
  fn test() {
    check("8350e5a3e24c153df2275c9f80692773", "");
    check("32ec01ec4a6dac72c0ab96fb34c0b5d1", "a");
    check("da853b0d3f88d99b30283a69e6ded6bb", "abc");
    check("ab4f496bfb2a530b219ff33031fe06b0", "message digest");
    check("4e8ddff3650292ab5a4108c3aa47940b", "abcdefghijklmnopqrstuvwxyz");
    check("da33def2a42df13975352846c30338cd", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
    check("d5976f79d83d3a0dc9806c3c66f3efd8", "12345678901234567890123456789012345678901234567890123456789012345678901234567890");
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(slicing_syntax)]

extern crate "rust-md2" as md2;

use md2::{SBOX, SBOXI};
use std::iter::range_inclusive;
use std::slice::bytes::{copy_memory, MutableByteVector};

struct ByteRange {
  current: Vec<u8>,
  first: bool
}

impl ByteRange {
  fn new(num_bytes: uint) -> ByteRange {
    ByteRange { current: Vec::from_elem(num_bytes, 0u8), first: true }
  }
}

impl Iterator<Vec<u8>> for ByteRange {
  fn next(&mut self) -> Option<Vec<u8>> {
    // TODO make nicer
    if self.first {
      self.first = false;
      return Some(self.current.clone());
    }

    for i in range(0, self.current.len()).rev() {
      if self.current[i] == 255 {
        continue;
      }

      // Increase.
      self.current[i] += 1;

      // Zero all bytes right of the current index.
      self.current[mut i+1..].set_memory(0);

      return Some(self.current.clone());
    }

    None
  }
}

pub struct Candidates {
  range: ByteRange,
  state: Vec<u8>,
  row: uint
}

impl Iterator<(Vec<u8>, Vec<u8>)> for Candidates {
  fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>)> {
    let next = self.range.next();

    // Bail out if we tried all possible combinations.
    if next.is_none() {
      return None;
    }

    // Set bytes for current candidate.
    let bytes = next.unwrap();
    copy_memory(self.state[mut 16..18], bytes[]);
    copy_memory(self.state[mut 32..34], bytes[]);

    // TODO rename variables

    // Compute the final compression value.
    let key = compress(self.state[], self.row);

    // Compute the original message leading to this state.
    let msg = decompress(self.state[], self.row);

    Some((key, msg))
  }
}

pub fn candidates(state: &[u8], row: uint) -> Candidates {
  // Test 2^16 combinations.
  let range = ByteRange::new(2);

  Candidates { range: range, state: state.to_vec(), row: row }
}

// TODO rename function
pub fn create_initial_state(num_rows: uint) -> Vec<u8> {
  let mut state = [[0u8, ..49], ..19];

  for row in range_inclusive(1, num_rows) {
    // Fill row of T1.
    for i in range(1, 17) {
      state[row][i] = SBOX[state[row][i - 1] as uint] ^ state[row - 1][i];
    }

    // Last bytes are equal.
    state[row][32] = state[row][16];
    state[row][48] = state[row][16];

    // Next t value.
    state[row + 1][0] = state[row][48] + (row as u8) - 1;
  }

  // Compute triangles.
  for col in range(0, num_rows) {
    for row in range_inclusive(2 + col, num_rows).rev() {
      // TODO make nicer
      let byte = SBOXI[(state[row][32 - col] ^ state[row - 1][32 - col]) as uint];
      state[row][32 - col - 1] = byte;
      state[row][48 - col - 1] = byte;
    }
  }

  // TODO explain
  state[num_rows][1..].to_vec()
}

fn compress(state: &[u8], iteration: uint) -> Vec<u8> {
  let mut t = state[47] + iteration as u8 - 1;
  let mut x = state.to_vec();

  // TODO explain
  for row in range(iteration, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += row as u8;
  }

  x[..16].to_vec()
}

fn decompress(state: &[u8], iteration: uint) -> Vec<u8> {
  let mut x = state.to_vec();

  // TODO explain
  for row in range(0, iteration).rev() {
    for col in range(1, 48).rev() {
      x[col] ^= SBOX[x[col - 1] as uint];
    }

    let t = x[47] + (row as u8) - 1;
    x[0] ^= SBOX[t as uint];
  }

  x[16..32].to_vec()
}

#[cfg(test)]
mod test {
  use candidates;
  use create_initial_state;

  use md2::compress;
  use std::collections::HashMap;
  use std::collections::hash_map::Entry::{Occupied, Vacant};
  use std::sync::TaskPool;

  // Count the number of map entries that have more than a single message.
  // Those will compress to the same final value and thus represent collisions.
  fn count(map: &HashMap<Vec<u8>,Vec<Vec<u8>>>) -> uint {
    map.values().fold(0u, |count, msgs| count + msgs.len() - 1)
  }

  // Validate all colliding entries in the given map to ensure that those
  // messages do indeed collide when computing their compressed values.
  fn validate(map: &HashMap<Vec<u8>,Vec<Vec<u8>>>) -> bool {
    map.values().filter(|msgs| msgs.len() > 1).all(|msgs| {
      let empty = [0u8, ..16];
      // TODO rename "hash" variables
      let mut first_hash: Option<[u8, ..16]> = None;
      let hashes = msgs.iter().map(|msg| compress(&empty, msg[]));

      hashes.all(|md2| { // TODO rename |md2|
        first_hash.map_or_else(|| { first_hash = Some(md2); true }, |v| v == md2)
      })
    })
  }

  #[test]
  fn test_k2() {
    let state = create_initial_state(14);

    // There will be ~2^16 entries (minus collisions).
    let mut map = HashMap::with_capacity(256u * 256u);

    // TODO rename variables
    for (key, msg) in candidates(state[], 14) {
      match map.entry(key) {
        Vacant(entry) => { entry.set(vec!(msg)); },
        Occupied(mut entry) => { entry.get_mut().push(msg); }
      }
    }

    assert!(validate(&map));
    assert_eq!(count(&map), 141);
  }

  #[test]
  fn test_k3() {
    let pool = TaskPool::new(8u);
    let (tx, rx) = channel();
    let state = create_initial_state(13);

    for byte in range(0u, 256u) {
      let txc = tx.clone();
      let mut state = state.clone();

      pool.execute(move || {
        // TODO explain
        state[18] = byte as u8;
        state[34] = byte as u8;

        for (key, msg) in candidates(state[], 13) {
          txc.send((key, msg));
        }
      });
    }

    // There will be ~2^24 entries (minus collisions).
    let total = 256u * 256u * 256u;
    let mut map = HashMap::with_capacity(total);

    // Merge partial results.
    let mut c = 0u;
    let mut last_percent = 0;
    for (key, msg) in rx.iter().take(total) {
      match map.entry(key) {
        Vacant(entry) => { entry.set(vec!(msg)); },
        Occupied(mut entry) => { entry.get_mut().push(msg); }
      }

      let percent = c / (total / 100);
      if last_percent != percent {
        last_percent = percent;
        println!("count = {} / {} ({}%)", c, total, percent);
      }
      c += 1;
    }

    assert!(validate(&map));
    assert_eq!(count(&map), 32784);
  }
}
<commit_msg>more refactoring<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(slicing_syntax)]

extern crate "rust-md2" as md2;

use md2::{SBOX, SBOXI};
use std::iter::range_inclusive;
use std::slice::bytes::{copy_memory, MutableByteVector};

struct ByteRange {
  current: Vec<u8>,
  first: bool
}

impl ByteRange {
  fn new(num_bytes: uint) -> ByteRange {
    ByteRange { current: Vec::from_elem(num_bytes, 0u8), first: true }
  }
}

impl Iterator<Vec<u8>> for ByteRange {
  fn next(&mut self) -> Option<Vec<u8>> {
    // TODO make nicer
    if self.first {
      self.first = false;
      return Some(self.current.clone());
    }

    for i in range(0, self.current.len()).rev() {
      if self.current[i] == 255 {
        continue;
      }

      // Increase.
      self.current[i] += 1;

      // Zero all bytes right of the current index.
      self.current[mut i+1..].set_memory(0);

      return Some(self.current.clone());
    }

    None
  }
}

pub struct Candidates {
  range: ByteRange,
  state: Vec<u8>,
  row: uint
}

impl Iterator<(Vec<u8>, Vec<u8>)> for Candidates {
  fn next(&mut self) -> Option<(Vec<u8>, Vec<u8>)> {
    let next = self.range.next();

    // Bail out if we tried all possible combinations.
    if next.is_none() {
      return None;
    }

    // Set bytes for current candidate.
    let bytes = next.unwrap();
    copy_memory(self.state[mut 16..18], bytes[]);
    copy_memory(self.state[mut 32..34], bytes[]);

    // Compute the final compression value.
    let cmp = compress(self.state[], self.row);

    // Compute the original message leading to this state.
    let msg = decompress(self.state[], self.row);

    Some((cmp, msg))
  }
}

pub fn candidates(state: &[u8], row: uint) -> Candidates {
  // Test 2^16 combinations.
  Candidates { range: ByteRange::new(2), state: state.to_vec(), row: row }
}

pub fn prefill_row(num_rows: uint) -> Vec<u8> {
  let mut state = [[0u8, ..49], ..19];

  for row in range_inclusive(1, num_rows) {
    // Fill row of T1.
    for i in range(1, 17) {
      state[row][i] = SBOX[state[row][i - 1] as uint] ^ state[row - 1][i];
    }

    // Last bytes are equal.
    state[row][32] = state[row][16];
    state[row][48] = state[row][16];

    // Next t value.
    state[row + 1][0] = state[row][48] + (row as u8) - 1;
  }

  // Compute triangles.
  for col in range(0, num_rows) {
    for row in range_inclusive(2 + col, num_rows).rev() {
      // TODO make nicer
      let byte = SBOXI[(state[row][32 - col] ^ state[row - 1][32 - col]) as uint];
      state[row][32 - col - 1] = byte;
      state[row][48 - col - 1] = byte;
    }
  }

  // TODO explain
  state[num_rows][1..].to_vec()
}

fn compress(state: &[u8], iteration: uint) -> Vec<u8> {
  let mut t = state[47] + iteration as u8 - 1;
  let mut x = state.to_vec();

  // TODO explain
  for row in range(iteration, 18) {
    for byte in x.iter_mut() {
      *byte ^= SBOX[t as uint];
      t = *byte;
    }
    t += row as u8;
  }

  x[..16].to_vec()
}

fn decompress(state: &[u8], iteration: uint) -> Vec<u8> {
  let mut x = state.to_vec();

  // TODO explain
  for row in range(0, iteration).rev() {
    for col in range(1, 48).rev() {
      x[col] ^= SBOX[x[col - 1] as uint];
    }

    let t = x[47] + (row as u8) - 1;
    x[0] ^= SBOX[t as uint];
  }

  x[16..32].to_vec()
}

#[cfg(test)]
mod test {
  use candidates;
  use prefill_row;

  use md2::compress;
  use std::collections::HashMap;
  use std::collections::hash_map::Entry::{Occupied, Vacant};
  use std::sync::TaskPool;

  // Insert the given candidate pair, consisting of the compressed and the
  // original message, into the given hash map.
  fn insert(map: &mut HashMap<Vec<u8>,Vec<Vec<u8>>>, cmp: Vec<u8>, msg: Vec<u8>) {
    match map.entry(cmp) {
      Vacant(entry) => { entry.set(vec!(msg)); }
      Occupied(mut entry) => { entry.get_mut().push(msg); }
    }
  }

  // Validate all colliding entries in the given map to ensure that those
  // messages do indeed collide when computing their compressed values.
  fn validate(map: &HashMap<Vec<u8>,Vec<Vec<u8>>>) -> bool {
    let empty = [0u8, ..16];

    // Ignore compressed values with only a single message (no collisions).
    let collisions = map.iter().filter(|&(_, msgs)| msgs.len() > 1);

    collisions.all(|(cmp, msgs)| {
      msgs.iter().all(|msg| compress(&empty, msg[]) == *cmp)
    })
  }

  // Count the number of map entries that have more than a single message.
  // Those will compress to the same final value and thus represent collisions.
  fn count(map: &HashMap<Vec<u8>,Vec<Vec<u8>>>) -> uint {
    map.values().fold(0u, |count, msgs| count + msgs.len() - 1)
  }

  #[test]
  fn test_k2() {
    let state = prefill_row(14);

    // There will be ~2^16 entries (minus collisions).
    let mut map = HashMap::with_capacity(256u * 256u);

    // Iterate and record all candidate pairs.
    for (cmp, msg) in candidates(state[], 14) {
      insert(&mut map, cmp, msg);
    }

    assert!(validate(&map));
    assert_eq!(count(&map), 141);
  }

  #[test]
  fn test_k3() {
    let pool = TaskPool::new(8u);
    let (tx, rx) = channel();
    let state = prefill_row(13);

    for byte in range(0u, 256u) {
      let txc = tx.clone();
      let mut state = state.clone();

      pool.execute(move || {
        // TODO explain
        state[18] = byte as u8;
        state[34] = byte as u8;

        for candidate in candidates(state[], 13) {
          txc.send(candidate);
        }
      });
    }

    // There will be ~2^24 entries (minus collisions).
    let total = 256u * 256u * 256u;
    let mut map = HashMap::with_capacity(total);

    // Merge partial results.
    for (key, msg) in rx.iter().take(total) {
      insert(&mut map, key, msg);
    }

    assert!(validate(&map));
    assert_eq!(count(&map), 32784);
  }
}
<|endoftext|>


<commit_before>//! A DEFLATE-based stream compression/decompression library
//!
//! This library is meant to supplement/replace the standard distributon's
//! libflate library by providing a streaming encoder/decoder rather than purely
//! in in-memory encoder/decoder.
//!
//! Like with libflate, flate2 is based on [`miniz.c`][1]
//!
//! [1]: https://code.google.com/p/miniz/

#![deny(missing_doc)]
#![feature(unsafe_destructor)]

extern crate libc;

use std::io;
use std::io::IoResult;
use std::mem;

pub use DeflateEncoder = deflate::Encoder;
pub use DeflateDecoder = deflate::Decoder;
pub use ZlibEncoder = zlib::Encoder;
pub use ZlibDecoder = zlib::Decoder;
pub use GzEncoder = gz::Encoder;
pub use GzDecoder = gz::Decoder;

mod ffi;
pub mod deflate;
pub mod zlib;
pub mod gz;

struct Encoder<W> {
    inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

struct Decoder<R> {
    inner: R,
    stream: Stream,
    pos: uint,
    buf: Vec<u8>,
}

enum Flavor { Deflate, Inflate }

struct Stream(ffi::mz_stream, Flavor);

/// When compressing data, the compression level can be specified by a value in
/// this enum.
pub enum CompressionLevel {
    /// No compression is to be performed, this may actually inflate data
    /// slightly when encoding.
    NoCompression = 0,
    /// Optimize for the best speed of encoding.
    BestSpeed = 1,
    /// Optimize for the size of data being encoded.
    BestCompression = 9,
    /// Choose the default compression, a balance between speed and size.
    Default = 6,
}

impl<W: Writer> Encoder<W> {
    fn new(w: W, level: CompressionLevel, raw: bool,
           buf: Vec<u8>) -> Encoder<W> {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = unsafe {
            ffi::mz_deflateInit2(&mut state,
                                 level as libc::c_int,
                                 ffi::MZ_DEFLATED,
                                 if raw {
                                     -ffi::MZ_DEFAULT_WINDOW_BITS
                                 } else {
                                     ffi::MZ_DEFAULT_WINDOW_BITS
                                 },
                                 9,
                                 ffi::MZ_DEFAULT_STRATEGY)
        };
        assert_eq!(ret, 0);

        Encoder {
            inner: Some(w),
            stream: Stream(state, Deflate),
            buf: buf,
        }
    }

    fn do_finish(&mut self) -> IoResult<()> {
        try!(self.deflate([], ffi::MZ_FINISH));
        self.inner.get_mut_ref().write(self.buf.as_slice())
    }

    fn deflate(&mut self, mut buf: &[u8], flush: libc::c_int) -> IoResult<()> {
        let cap = self.buf.capacity();
        loop {
            self.stream.next_in = buf.as_ptr();
            self.stream.avail_in = buf.len() as libc::c_uint;
            let cur_len = self.buf.len();
            self.stream.next_out = self.buf.mut_slice_from(cur_len).as_mut_ptr();
            self.stream.avail_out = (cap - cur_len) as libc::c_uint;

            let before_out = self.stream.total_out;
            let before_in = self.stream.total_in;

            let ret = unsafe {
                let ret = ffi::mz_deflate(&mut *self.stream, flush);
                self.buf.set_len(cur_len + (self.stream.total_out - before_out) as uint);
                ret
            };
            buf = buf.slice_from((self.stream.total_in - before_in) as uint);

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END => return Ok(()),
                ffi::MZ_BUF_ERROR => {
                    try!(self.inner.get_mut_ref().write(self.buf.as_slice()));
                    self.buf.truncate(0);
                }
                n => fail!("unexpected return {}", n),
            }
            if buf.len() == 0 { return Ok(()) }
        }
    }
}

impl<W: Writer> Writer for Encoder<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.deflate(buf, ffi::MZ_NO_FLUSH)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.deflate([], ffi::MZ_SYNC_FLUSH).and_then(|_| {
            self.inner.get_mut_ref().flush()
        })
    }
}

#[unsafe_destructor]
impl<W: Writer> Drop for Encoder<W> {
    fn drop(&mut self) {
        match self.inner {
            Some(..) => { let _ = self.do_finish(); }
            None => {}
        }
    }
}

impl<R: Reader> Decoder<R> {
    /// Same as `new`, but the intermediate buffer for data is specified.
    ///
    /// Note that the capacity of the intermediate buffer is never increased,
    /// and it is recommended for it to be large.
    fn new(r: R, raw: bool, buf: Vec<u8>) -> Decoder<R> {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = unsafe {
            ffi::mz_inflateInit2(&mut state,
                                 if raw {
                                     -ffi::MZ_DEFAULT_WINDOW_BITS
                                 } else {
                                     ffi::MZ_DEFAULT_WINDOW_BITS
                                 })
        };
        assert_eq!(ret, 0);

        Decoder {
            inner: r,
            stream: Stream(state, Inflate),
            pos: 0,
            buf: buf,
        }
    }
}

impl<R: Reader> Reader for Decoder<R> {
    fn read(&mut self, into: &mut [u8]) -> IoResult<uint> {
        let cap = self.buf.capacity();
        let mut read = 0;
        while read < into.len() {
            if self.pos == self.buf.len() {
                self.buf.truncate(0);
                try!(self.inner.push(cap, &mut self.buf));
                self.pos = 0;
            }

            self.stream.next_in = self.buf.slice_from(self.pos).as_ptr();
            self.stream.avail_in = (self.buf.len() - self.pos) as libc::c_uint;
            self.stream.next_out = into.mut_slice_from(read).as_mut_ptr();
            self.stream.avail_out = (into.len() - read) as libc::c_uint;

            let before_out = self.stream.total_out;
            let before_in = self.stream.total_in;

            let ret = unsafe {
                ffi::mz_inflate(&mut *self.stream, ffi::MZ_NO_FLUSH)
            };
            read += (self.stream.total_out - before_out) as uint;
            self.pos += (self.stream.total_in - before_in) as uint;

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END if read > 0 => break,
                ffi::MZ_STREAM_END => {
                    return Err(io::standard_error(io::EndOfFile))
                }
                ffi::MZ_BUF_ERROR => break,
                ffi::MZ_DATA_ERROR => {
                    return Err(io::standard_error(io::InvalidInput))
                }
                n => fail!("unexpected return {}", n),
            }
        }

        Ok(read)
    }
}

impl Deref<ffi::mz_stream> for Stream {
    fn deref<'a>(&'a self) -> &'a ffi::mz_stream {
        let Stream(ref inner, _) = *self; inner
    }
}

impl DerefMut<ffi::mz_stream> for Stream {
    fn deref_mut<'a>(&'a mut self) -> &'a mut ffi::mz_stream {
        let Stream(ref mut inner, _) = *self; inner
    }
}

impl Drop for Stream {
    fn drop(&mut self) {
        unsafe {
            match *self {
                Stream(ref mut s, Deflate) => ffi::mz_deflateEnd(s),
                Stream(ref mut s, Inflate) => ffi::mz_inflateEnd(s),
            };
        }
    }
}
<commit_msg>Finish looping when flusing the stream<commit_after>//! A DEFLATE-based stream compression/decompression library
//!
//! This library is meant to supplement/replace the standard distributon's
//! libflate library by providing a streaming encoder/decoder rather than purely
//! in in-memory encoder/decoder.
//!
//! Like with libflate, flate2 is based on [`miniz.c`][1]
//!
//! [1]: https://code.google.com/p/miniz/

#![deny(missing_doc)]
#![feature(unsafe_destructor)]

extern crate libc;

use std::io;
use std::io::IoResult;
use std::mem;

pub use DeflateEncoder = deflate::Encoder;
pub use DeflateDecoder = deflate::Decoder;
pub use ZlibEncoder = zlib::Encoder;
pub use ZlibDecoder = zlib::Decoder;
pub use GzEncoder = gz::Encoder;
pub use GzDecoder = gz::Decoder;

mod ffi;
pub mod deflate;
pub mod zlib;
pub mod gz;

struct Encoder<W> {
    inner: Option<W>,
    stream: Stream,
    buf: Vec<u8>,
}

struct Decoder<R> {
    inner: R,
    stream: Stream,
    pos: uint,
    buf: Vec<u8>,
}

enum Flavor { Deflate, Inflate }

struct Stream(ffi::mz_stream, Flavor);

/// When compressing data, the compression level can be specified by a value in
/// this enum.
pub enum CompressionLevel {
    /// No compression is to be performed, this may actually inflate data
    /// slightly when encoding.
    NoCompression = 0,
    /// Optimize for the best speed of encoding.
    BestSpeed = 1,
    /// Optimize for the size of data being encoded.
    BestCompression = 9,
    /// Choose the default compression, a balance between speed and size.
    Default = 6,
}

impl<W: Writer> Encoder<W> {
    fn new(w: W, level: CompressionLevel, raw: bool,
           buf: Vec<u8>) -> Encoder<W> {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = unsafe {
            ffi::mz_deflateInit2(&mut state,
                                 level as libc::c_int,
                                 ffi::MZ_DEFLATED,
                                 if raw {
                                     -ffi::MZ_DEFAULT_WINDOW_BITS
                                 } else {
                                     ffi::MZ_DEFAULT_WINDOW_BITS
                                 },
                                 9,
                                 ffi::MZ_DEFAULT_STRATEGY)
        };
        assert_eq!(ret, 0);

        Encoder {
            inner: Some(w),
            stream: Stream(state, Deflate),
            buf: buf,
        }
    }

    fn do_finish(&mut self) -> IoResult<()> {
        try!(self.deflate([], ffi::MZ_FINISH));
        try!(self.inner.get_mut_ref().write(self.buf.as_slice()));
        self.buf.truncate(0);
        Ok(())
    }

    fn deflate(&mut self, mut buf: &[u8], flush: libc::c_int) -> IoResult<()> {
        let cap = self.buf.capacity();
        while buf.len() > 0 || flush == ffi::MZ_FINISH {
            self.stream.next_in = buf.as_ptr();
            self.stream.avail_in = buf.len() as libc::c_uint;
            let cur_len = self.buf.len();
            self.stream.next_out = self.buf.mut_slice_from(cur_len).as_mut_ptr();
            self.stream.avail_out = (cap - cur_len) as libc::c_uint;

            let before_out = self.stream.total_out;
            let before_in = self.stream.total_in;

            let ret = unsafe {
                let ret = ffi::mz_deflate(&mut *self.stream, flush);
                self.buf.set_len(cur_len + (self.stream.total_out - before_out) as uint);
                ret
            };
            buf = buf.slice_from((self.stream.total_in - before_in) as uint);

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END => return Ok(()),
                ffi::MZ_BUF_ERROR => {
                    try!(self.inner.get_mut_ref().write(self.buf.as_slice()));
                    self.buf.truncate(0);
                }
                n => fail!("unexpected return {}", n),
            }
        }

        Ok(())
    }
}

impl<W: Writer> Writer for Encoder<W> {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.deflate(buf, ffi::MZ_NO_FLUSH)
    }

    fn flush(&mut self) -> IoResult<()> {
        self.deflate([], ffi::MZ_SYNC_FLUSH).and_then(|_| {
            self.inner.get_mut_ref().flush()
        })
    }
}

#[unsafe_destructor]
impl<W: Writer> Drop for Encoder<W> {
    fn drop(&mut self) {
        match self.inner {
            Some(..) => { let _ = self.do_finish(); }
            None => {}
        }
    }
}

impl<R: Reader> Decoder<R> {
    /// Same as `new`, but the intermediate buffer for data is specified.
    ///
    /// Note that the capacity of the intermediate buffer is never increased,
    /// and it is recommended for it to be large.
    fn new(r: R, raw: bool, buf: Vec<u8>) -> Decoder<R> {
        let mut state: ffi::mz_stream = unsafe { mem::zeroed() };
        let ret = unsafe {
            ffi::mz_inflateInit2(&mut state,
                                 if raw {
                                     -ffi::MZ_DEFAULT_WINDOW_BITS
                                 } else {
                                     ffi::MZ_DEFAULT_WINDOW_BITS
                                 })
        };
        assert_eq!(ret, 0);

        Decoder {
            inner: r,
            stream: Stream(state, Inflate),
            pos: 0,
            buf: buf,
        }
    }
}

impl<R: Reader> Reader for Decoder<R> {
    fn read(&mut self, into: &mut [u8]) -> IoResult<uint> {
        let cap = self.buf.capacity();
        let mut read = 0;
        while read < into.len() {
            if self.pos == self.buf.len() {
                self.buf.truncate(0);
                try!(self.inner.push(cap, &mut self.buf));
                self.pos = 0;
            }

            self.stream.next_in = self.buf.slice_from(self.pos).as_ptr();
            self.stream.avail_in = (self.buf.len() - self.pos) as libc::c_uint;
            self.stream.next_out = into.mut_slice_from(read).as_mut_ptr();
            self.stream.avail_out = (into.len() - read) as libc::c_uint;

            let before_out = self.stream.total_out;
            let before_in = self.stream.total_in;

            let ret = unsafe {
                ffi::mz_inflate(&mut *self.stream, ffi::MZ_NO_FLUSH)
            };
            read += (self.stream.total_out - before_out) as uint;
            self.pos += (self.stream.total_in - before_in) as uint;

            match ret {
                ffi::MZ_OK => {}
                ffi::MZ_STREAM_END if read > 0 => break,
                ffi::MZ_STREAM_END => {
                    return Err(io::standard_error(io::EndOfFile))
                }
                ffi::MZ_BUF_ERROR => break,
                ffi::MZ_DATA_ERROR => {
                    return Err(io::standard_error(io::InvalidInput))
                }
                n => fail!("unexpected return {}", n),
            }
        }

        Ok(read)
    }
}

impl Deref<ffi::mz_stream> for Stream {
    fn deref<'a>(&'a self) -> &'a ffi::mz_stream {
        let Stream(ref inner, _) = *self; inner
    }
}

impl DerefMut<ffi::mz_stream> for Stream {
    fn deref_mut<'a>(&'a mut self) -> &'a mut ffi::mz_stream {
        let Stream(ref mut inner, _) = *self; inner
    }
}

impl Drop for Stream {
    fn drop(&mut self) {
        unsafe {
            match *self {
                Stream(ref mut s, Deflate) => ffi::mz_deflateEnd(s),
                Stream(ref mut s, Inflate) => ffi::mz_inflateEnd(s),
            };
        }
    }
}
<|endoftext|>


<commit_before>//! The fast sweeping method for the computation of the signed distance function in 2D in 3D.
//!
//! Based on [1].
//!
//! ## References
//!
//! [1] Zhao, Hongkai A fast sweeping method for eikonal equations. Math. Comp. 74 (2005), no. 250,
//! 603–627.

mod level_set;
mod eikonal;

/// Computes the signed distance from the _zero_ level set of the function given by the values of
/// `u` on a regular 3D grid of dimensions `dim` and stores the result in a preallocated array `d`.
///
/// The zero level set is reconstructed by splitting each cube of the grid into 6 tetrahedra whose
/// vertices have coordinates `(0, 0, 0)`, ..., ..., `(1, 1, 1)` (relative to the cube), and the
/// following vertex in the sequence flips exactly one coordinate from `0` to `1`. The level set
/// function is then assumed to be linear on the tetrahedron.
///
/// `h` is the distance between neighboring nodes.
///
/// `u` is assumed to be in the _row-major_ order (C order).
///
/// Returns `std::f64::MAX` if all `u` are positive and `-std::f64::MAX` if all `u` are negative.
pub fn signed_distance_3d(d: &mut [f64], u: &[f64], dim: (usize, usize, usize), h: f64) {
    assert_eq!(dim.0 * dim.1 * dim.2, u.len());
    assert_eq!(dim.0 * dim.1 * dim.2, d.len());
    level_set::init_dist_3d(d, u, dim);
    eikonal::fast_sweep_dist_3d(d, dim);

    // compute the signed distance function from the solution of the eikonal equation
    for i in 0..d.len() {
        if u[i] < 0. {
            d[i] = -d[i] * h;
        } else {
            d[i] *= h;
        }
    }
}

/// Computes the signed distance from the _zero_ level set of the function given by the values of
/// `u` on a regular 2D grid of dimensions `dim` and stores the result in a preallocated array `d`.
///
/// The zero level set is reconstructed by splitting each square of the grid into 2 triangles whose
/// vertices have coordinates `(0, 0)`, ..., `(1, 1)` (relative to the square), and the
/// following vertex in the sequence flips exactly one coordinate from `0` to `1`. The level set
/// function is then assumed to be linear on the triangle.
///
/// ```text,ignore
///   0,1 *----* 1,1
///       |   /|
///       |  / |
///       | /  |
///       |/   |
///   0,0 *----* 1,0
/// ```
///
/// `h` is the distance between neighboring nodes.
///
/// `u` is assumed to be in the _row-major_ order (C order).
///
/// Returns `std::f64::MAX` if all `u` are nonnegative (`-std::f64::MAX` if all `u` are negative).
pub fn signed_distance_2d(d: &mut [f64], u: &[f64], dim: (usize, usize), h: f64) {
    assert_eq!(dim.0 * dim.1, u.len());
    assert_eq!(dim.0 * dim.1, d.len());
    level_set::init_dist_2d(d, u, dim);
    eikonal::fast_sweep_dist_2d(d, dim);

    // compute the signed distance function from the solution of the eikonal equation
    for i in 0..d.len() {
        if u[i] < 0. {
            d[i] = -d[i] * h;
        } else {
            d[i] *= h;
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    extern crate quickcheck;
    extern crate ndarray;
    use self::quickcheck::quickcheck;
    use self::ndarray::prelude::*;
    use self::ndarray::Si;

    fn check_line(gx: f64, gy: f64, c: f64, dim: (usize, usize), tol: f64, print: bool) -> bool {
        let (nx, ny) = dim;
        let xs = Array::linspace(0., 1., nx);
        let ys = Array::linspace(0., (ny - 1) as f64 / (nx - 1) as f64, ny);
        let u_array = {
            let mut u_array = Array::zeros(dim);
            for ((i, j), u) in u_array.indexed_iter_mut() {
                let (x, y) = (xs[i], ys[j]);
                *u = x * gx + y * gy + c;
            }
            u_array
        };
        let u = u_array.as_slice().unwrap();

        let d = {
            let mut d = vec![0f64; nx * ny];
            signed_distance_2d(&mut d, &u, dim, 1. / (nx - 1) as f64);
            Array::from_shape_vec(dim, d).unwrap()
        };
        if print {
            println!("{}", u_array);
            println!("{}", d);
        }
        d.all_close(&u_array, tol)
    }

    #[test]
    fn it_works_for_x_axis_line() {
        fn prop(y: f64) -> bool {
            check_line(0., 1., -((y - y.floor()) * 0.9 + 0.05), (9, 17), 0.00001, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_y_axis_line() {
        fn prop(x: f64) -> bool {
            check_line(1., 0., -((x - x.floor()) * 0.9 + 0.05), (16, 9), 0.00001, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_diagonal() {
        assert!(check_line((0.5f64).sqrt(),
                           (0.5f64).sqrt(),
                           -(0.5f64).sqrt(),
                           (9, 9),
                           1e-6,
                           false));
        assert!(check_line(-(0.5f64).sqrt(), (0.5f64).sqrt(), 0., (9, 9), 1e-6, false));
    }

    #[test]
    fn it_preserves_lines() {
        fn prop(ta: f64) -> bool {
            let n = 17;
            let ta = (ta - ta.floor()) * 2. * ::std::f64::consts::PI;
            let (gy, gx) = ta.sin_cos();
            let c = -(gx + gy) * 0.5;

            let xs = Array::linspace(0., 1., n);
            let ys = Array::linspace(0., 1., n);
            let u_array = {
                let mut u_array = xs.broadcast((n, n)).unwrap().to_owned();
                u_array.zip_mut_with(&ys.broadcast((n, n)).unwrap().t(),
                                     |x, y| *x = *x * gx + *y * gy + c);
                u_array
            };
            let u = u_array.as_slice().unwrap();

            let d = {
                let mut d = vec![0f64; n * n];
                signed_distance_2d(&mut d, &u, (n, n), 1. / (n - 1) as f64);
                Array::from_shape_vec((n, n), d).unwrap()
            };
            let d2 = {
                let mut d2 = vec![0f64; n * n];
                signed_distance_2d(&mut d2, d.as_slice().unwrap(), (n, n), 1. / (n - 1) as f64);
                Array::from_shape_vec((n, n), d2).unwrap()
            };
            // check only elements away from the boundary
            let s = &[Si(2, Some(-2), 1), Si(2, Some(-2), 1)];
            d.slice(s).all_close(&d2.slice(s), 0.001)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

}
<commit_msg>Add tests for 3d case<commit_after>//! The fast sweeping method for the computation of the signed distance function in 2D in 3D.
//!
//! Based on [1].
//!
//! ## References
//!
//! [1] Zhao, Hongkai A fast sweeping method for eikonal equations. Math. Comp. 74 (2005), no. 250,
//! 603–627.

mod level_set;
mod eikonal;

/// Computes the signed distance from the _zero_ level set of the function given by the values of
/// `u` on a regular 3D grid of dimensions `dim` and stores the result in a preallocated array `d`.
///
/// The zero level set is reconstructed by splitting each cube of the grid into 6 tetrahedra whose
/// vertices have coordinates `(0, 0, 0)`, ..., ..., `(1, 1, 1)` (relative to the cube), and the
/// following vertex in the sequence flips exactly one coordinate from `0` to `1`. The level set
/// function is then assumed to be linear on the tetrahedron.
///
/// `h` is the distance between neighboring nodes.
///
/// `u` is assumed to be in the _row-major_ order (C order).
///
/// Returns `std::f64::MAX` if all `u` are positive and `-std::f64::MAX` if all `u` are negative.
pub fn signed_distance_3d(d: &mut [f64], u: &[f64], dim: (usize, usize, usize), h: f64) {
    assert_eq!(dim.0 * dim.1 * dim.2, u.len());
    assert_eq!(dim.0 * dim.1 * dim.2, d.len());
    level_set::init_dist_3d(d, u, dim);
    eikonal::fast_sweep_dist_3d(d, dim);

    // compute the signed distance function from the solution of the eikonal equation
    for i in 0..d.len() {
        if u[i] < 0. {
            d[i] = -d[i] * h;
        } else {
            d[i] *= h;
        }
    }
}

/// Computes the signed distance from the _zero_ level set of the function given by the values of
/// `u` on a regular 2D grid of dimensions `dim` and stores the result in a preallocated array `d`.
///
/// The zero level set is reconstructed by splitting each square of the grid into 2 triangles whose
/// vertices have coordinates `(0, 0)`, ..., `(1, 1)` (relative to the square), and the
/// following vertex in the sequence flips exactly one coordinate from `0` to `1`. The level set
/// function is then assumed to be linear on the triangle.
///
/// ```text,ignore
///   0,1 *----* 1,1
///       |   /|
///       |  / |
///       | /  |
///       |/   |
///   0,0 *----* 1,0
/// ```
///
/// `h` is the distance between neighboring nodes.
///
/// `u` is assumed to be in the _row-major_ order (C order).
///
/// Returns `std::f64::MAX` if all `u` are nonnegative (`-std::f64::MAX` if all `u` are negative).
pub fn signed_distance_2d(d: &mut [f64], u: &[f64], dim: (usize, usize), h: f64) {
    assert_eq!(dim.0 * dim.1, u.len());
    assert_eq!(dim.0 * dim.1, d.len());
    level_set::init_dist_2d(d, u, dim);
    eikonal::fast_sweep_dist_2d(d, dim);

    // compute the signed distance function from the solution of the eikonal equation
    for i in 0..d.len() {
        if u[i] < 0. {
            d[i] = -d[i] * h;
        } else {
            d[i] *= h;
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    extern crate quickcheck;
    extern crate ndarray;
    use self::quickcheck::quickcheck;
    use self::ndarray::prelude::*;
    use self::ndarray::Si;

    fn check_line(gx: f64, gy: f64, c: f64, dim: (usize, usize), tol: f64, print: bool) -> bool {
        let (nx, ny) = dim;
        let xs = Array::linspace(0., 1., nx);
        let ys = Array::linspace(0., (ny - 1) as f64 / (nx - 1) as f64, ny);
        let u_array = {
            let mut u_array = Array::zeros(dim);
            for ((i, j), u) in u_array.indexed_iter_mut() {
                let (x, y) = (xs[i], ys[j]);
                *u = x * gx + y * gy + c;
            }
            u_array
        };
        let u = u_array.as_slice().unwrap();

        let d = {
            let mut d = vec![0f64; nx * ny];
            signed_distance_2d(&mut d, &u, dim, 1. / (nx - 1) as f64);
            Array::from_shape_vec(dim, d).unwrap()
        };
        if print {
            println!("{}", u_array);
            println!("{}", d);
        }
        d.all_close(&u_array, tol)
    }

    #[test]
    fn it_works_for_x_axis_line() {
        fn prop(y: f64) -> bool {
            check_line(0., 1., -((y - y.floor()) * 0.9 + 0.05), (9, 17), 0.00001, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_y_axis_line() {
        fn prop(x: f64) -> bool {
            check_line(1., 0., -((x - x.floor()) * 0.9 + 0.05), (16, 9), 0.00001, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_diagonal() {
        assert!(check_line((0.5f64).sqrt(),
                           (0.5f64).sqrt(),
                           -(0.5f64).sqrt(),
                           (9, 9),
                           1e-6,
                           false));
        assert!(check_line(-(0.5f64).sqrt(), (0.5f64).sqrt(), 0., (9, 9), 1e-6, false));
    }

    #[test]
    fn it_preserves_lines() {
        fn prop(ta: f64) -> bool {
            let n = 17;
            let ta = (ta - ta.floor()) * 2. * ::std::f64::consts::PI;
            let (gy, gx) = ta.sin_cos();
            let c = -(gx + gy) * 0.5;

            let xs = Array::linspace(0., 1., n);
            let ys = Array::linspace(0., 1., n);
            let u_array = {
                let mut u_array = xs.broadcast((n, n)).unwrap().to_owned();
                u_array.zip_mut_with(&ys.broadcast((n, n)).unwrap().t(),
                                     |x, y| *x = *x * gx + *y * gy + c);
                u_array
            };
            let u = u_array.as_slice().unwrap();

            let d = {
                let mut d = vec![0f64; n * n];
                signed_distance_2d(&mut d, &u, (n, n), 1. / (n - 1) as f64);
                Array::from_shape_vec((n, n), d).unwrap()
            };
            let d2 = {
                let mut d2 = vec![0f64; n * n];
                signed_distance_2d(&mut d2, d.as_slice().unwrap(), (n, n), 1. / (n - 1) as f64);
                Array::from_shape_vec((n, n), d2).unwrap()
            };
            // check only elements away from the boundary
            let s = &[Si(2, Some(-2), 1), Si(2, Some(-2), 1)];
            d.slice(s).all_close(&d2.slice(s), 0.001)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    fn check_plane(gx: f64, gy: f64, gz: f64, c: f64, dim: (usize, usize, usize), tol: f64, print: bool) -> bool {
        let (nx, ny, nz) = dim;
        let xs = Array::linspace(0., 1., nx);
        let ys = Array::linspace(0., (ny - 1) as f64 / (nx - 1) as f64, ny);
        let zs = Array::linspace(0., (nz - 1) as f64 / (nx - 1) as f64, nz);
        let u_array = {
            let mut u_array = Array::zeros(dim);
            for ((i, j, k), u) in u_array.indexed_iter_mut() {
                let (x, y, z) = (xs[i], ys[j], zs[k]);
                *u = x * gx + y * gy + z * gz + c;
            }
            u_array
        };
        let u = u_array.as_slice().unwrap();

        let d = {
            let mut d = vec![0f64; nx * ny * nz];
            signed_distance_3d(&mut d, &u, dim, 1. / (nx - 1) as f64);
            Array::from_shape_vec(dim, d).unwrap()
        };
        if print {
            println!("{}", u_array);
            println!("{}", d);
        }
        d.all_close(&u_array, tol)
    }

    #[test]
    fn it_works_for_x_axis_plane() {
        fn prop(x: f64) -> bool {
            check_plane(1., 0., 0., -((x - x.floor()) * 0.9 + 0.05), (9, 14, 18), 1e-6, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_y_axis_plane() {
        fn prop(x: f64) -> bool {
            check_plane(0., 1., 0., -((x - x.floor()) * 0.9 + 0.05), (9, 14, 18), 1e-6, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }

    #[test]
    fn it_works_for_z_axis_plane() {
        fn prop(x: f64) -> bool {
            check_plane(0., 0., 1., -((x - x.floor()) * 0.9 + 0.05), (9, 14, 18), 1e-6, false)
        }
        quickcheck(prop as fn(f64) -> bool);
    }
}
<|endoftext|>


<commit_before>extern crate reqwest;

pub use self::paster::Paster;
pub use self::objects::PastebinMessage;
pub use self::paster::expiration::Expiration;
pub use self::paster::access::Access;
pub use self::paster::format::Format;
pub use self::error::Error;

mod paster;
pub mod objects;
mod error;

/// # Examples
///
/// Simple usage of `Paster`:
///
/// ```
/// /// I recommend to put your dev key into an environment variable called `PASTEBIN_DEVELOPER_TOKEN`.
/// let parser = Paster::new(Some("<YOUR DEV KEY>".to_owned()));
/// let response = parser.paste("<html></html>",
///                             &Access::Private,
///                             "TestHtml",
///                             &Expiration::TenMinutes,
///                             &Format::HTML5,
///                             None);
/// if response.is_ok() {
///     if let Some(paste) = response.ok() {
///         /// If everything is OK, you can get the url to your code here.
///         println!("{}", paste.url);
///     }
/// }
///
/// ```
///

/// method for constructing the api url for pastebin.
fn construct_api_url(path: &[&str]) -> String {
    format!("https://pastebin.com/api/{}", path.join("/"))
}
<commit_msg>updated documentation<commit_after>
//! # Pastebin Rust Api
//!
//! Wrapper for the [Pastebin Api](https://pastebin.com/api)
//!
//! ## Getting started
//!
//! Simple usage of `Paster`:
//!
//! ```
//! // I recommend to put your dev key into an environment variable called `PASTEBIN_DEVELOPER_TOKEN`.
//! let parser = Paster::new(Some("<YOUR DEV KEY>".to_owned()));
//! let response = parser.paste("<html></html>",
//!                             &Access::Private,
//!                             "TestHtml",
//!                             &Expiration::TenMinutes,
//!                             &Format::HTML5,
//!                             None);
//! if response.is_ok() {
//!     if let Some(paste) = response.ok() {
//!         // If everything is OK, you can get the url to your code here.
//!         println!("{}", paste.url);
//!     }
//! }
//!
//! ```
//!

extern crate reqwest;

pub use self::paster::Paster;
pub use self::paster::expiration::Expiration;
pub use self::paster::access::Access;
pub use self::paster::format::Format;
pub use self::error::Error;

mod paster;
mod objects;
mod error;

/// method for constructing the api url for pastebin.
fn construct_api_url(path: &[&str]) -> String {
    format!("https://pastebin.com/api/{}", path.join("/"))
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate base64;
extern crate rand;
extern crate test;

use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
             encode_config_slice, Base64Encoder, Config, MIME, STANDARD};
use base64::display;

use std::io::Write;
use test::Bencher;
use rand::Rng;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3, STANDARD)
}

#[bench]
fn encode_3b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3, STANDARD)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_display(b: &mut Bencher) {
    do_encode_bench_display(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50, STANDARD)
}

#[bench]
fn encode_50b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 50, STANDARD)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100, STANDARD)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, STANDARD)
}

#[bench]
fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, MIME)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
}

#[bench]
fn encode_3kib_reuse_buf_stream(b: &mut Bencher) {
    do_encode_bench_stream(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_3mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_3b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_50b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3kib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = encoded.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_buf(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_decode_bench_slice(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    buf.resize(size, 0);
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_slice(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_display(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = format!("{}", display::Base64Display::standard(&v));
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        encode_config_buf(&v, config, &mut buf);
        buf.clear();
    });
}

fn do_encode_bench_slice(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);
    b.iter(|| {
        encode_config_slice(&v, config, &mut buf);
    });
}

fn do_encode_bench_stream(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);

    b.iter(|| {
        let mut stream_enc = Base64Encoder::new(&mut buf, config);
        stream_enc.write(&v).unwrap();
        stream_enc.flush().unwrap();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<commit_msg>Make the stream benchmark clear its buffer each run so timing isn't dominated by resize...<commit_after>#![feature(test)]

extern crate base64;
extern crate rand;
extern crate test;

use base64::{decode, decode_config_buf, decode_config_slice, encode, encode_config_buf,
             encode_config_slice, Base64Encoder, Config, MIME, STANDARD};
use base64::display;

use std::io::Write;
use test::Bencher;
use rand::Rng;

#[bench]
fn encode_3b(b: &mut Bencher) {
    do_encode_bench(b, 3)
}

#[bench]
fn encode_3b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3, STANDARD)
}

#[bench]
fn encode_3b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3, STANDARD)
}

#[bench]
fn encode_50b(b: &mut Bencher) {
    do_encode_bench(b, 50)
}

#[bench]
fn encode_50b_display(b: &mut Bencher) {
    do_encode_bench_display(b, 50)
}

#[bench]
fn encode_50b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 50, STANDARD)
}

#[bench]
fn encode_50b_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 50, STANDARD)
}

#[bench]
fn encode_100b(b: &mut Bencher) {
    do_encode_bench(b, 100)
}

#[bench]
fn encode_100b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 100, STANDARD)
}

#[bench]
fn encode_500b(b: &mut Bencher) {
    do_encode_bench(b, 500)
}

#[bench]
fn encode_500b_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, STANDARD)
}

#[bench]
fn encode_500b_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 500, MIME)
}

#[bench]
fn encode_3kib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024)
}

#[bench]
fn encode_3kib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024)
}

#[bench]
fn encode_3kib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3kib_reuse_buf_mime(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024, MIME)
}

#[bench]
fn encode_3kib_reuse_buf_stream(b: &mut Bencher) {
    do_encode_bench_stream(b, 3 * 1024, STANDARD)
}

#[bench]
fn encode_3mib(b: &mut Bencher) {
    do_encode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_display(b: &mut Bencher) {
    do_encode_bench_display(b, 3 * 1024 * 1024)
}

#[bench]
fn encode_3mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_3mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 3 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_10mib(b: &mut Bencher) {
    do_encode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn encode_10mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 10 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib(b: &mut Bencher) {
    do_encode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn encode_30mib_reuse_buf(b: &mut Bencher) {
    do_encode_bench_reuse_buf(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn encode_30mib_slice(b: &mut Bencher) {
    do_encode_bench_slice(b, 30 * 1024 * 1024, STANDARD)
}

#[bench]
fn decode_3b(b: &mut Bencher) {
    do_decode_bench(b, 3)
}

#[bench]
fn decode_3b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3)
}

#[bench]
fn decode_3b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3)
}

#[bench]
fn decode_50b(b: &mut Bencher) {
    do_decode_bench(b, 50)
}

#[bench]
fn decode_50b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 50)
}

#[bench]
fn decode_50b_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 50)
}

#[bench]
fn decode_100b(b: &mut Bencher) {
    do_decode_bench(b, 100)
}

#[bench]
fn decode_100b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 100)
}

#[bench]
fn decode_500b(b: &mut Bencher) {
    do_decode_bench(b, 500)
}

#[bench]
fn decode_500b_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 500)
}

#[bench]
fn decode_3kib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024)
}

#[bench]
fn decode_3kib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024)
}

#[bench]
fn decode_3kib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024)
}

#[bench]
fn decode_3mib(b: &mut Bencher) {
    do_decode_bench(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_3mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 3 * 1024 * 1024)
}

#[bench]
fn decode_10mib(b: &mut Bencher) {
    do_decode_bench(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_10mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 10 * 1024 * 1024)
}

#[bench]
fn decode_30mib(b: &mut Bencher) {
    do_decode_bench(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_reuse_buf(b: &mut Bencher) {
    do_decode_bench_reuse_buf(b, 30 * 1024 * 1024)
}

#[bench]
fn decode_30mib_slice(b: &mut Bencher) {
    do_decode_bench_slice(b, 30 * 1024 * 1024)
}

fn do_decode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    b.bytes = encoded.len() as u64;
    b.iter(|| {
        let orig = decode(&encoded);
        test::black_box(&orig);
    });
}

fn do_decode_bench_reuse_buf(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_buf(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
        buf.clear();
    });
}

fn do_decode_bench_slice(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size * 3 / 4);
    fill(&mut v);
    let encoded = encode(&v);

    let mut buf = Vec::new();
    buf.resize(size, 0);
    b.bytes = encoded.len() as u64;
    b.iter(|| {
        decode_config_slice(&encoded, STANDARD, &mut buf).unwrap();
        test::black_box(&buf);
    });
}

fn do_encode_bench(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = encode(&v);
        test::black_box(&e);
    });
}

fn do_encode_bench_display(b: &mut Bencher, size: usize) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    b.bytes = v.len() as u64;
    b.iter(|| {
        let e = format!("{}", display::Base64Display::standard(&v));
        test::black_box(&e);
    });
}

fn do_encode_bench_reuse_buf(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = String::new();

    b.bytes = v.len() as u64;
    b.iter(|| {
        encode_config_buf(&v, config, &mut buf);
        buf.clear();
    });
}

fn do_encode_bench_slice(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;
    // conservative estimate of encoded size
    buf.resize(size * 2, 0);
    b.iter(|| {
        encode_config_slice(&v, config, &mut buf);
    });
}

fn do_encode_bench_stream(b: &mut Bencher, size: usize, config: Config) {
    let mut v: Vec<u8> = Vec::with_capacity(size);
    fill(&mut v);

    let mut buf = Vec::new();

    b.bytes = v.len() as u64;

    buf.reserve(size * 2);
    b.iter(|| {
        buf.clear();
        let mut stream_enc = Base64Encoder::new(&mut buf, config);
        stream_enc.write(&v).unwrap();
        stream_enc.flush().unwrap();
    });
}

fn fill(v: &mut Vec<u8>) {
    let cap = v.capacity();
    // weak randomness is plenty; we just want to not be completely friendly to the branch predictor
    let mut r = rand::weak_rng();
    while v.len() < cap {
        v.push(r.gen::<u8>());
    }
}
<|endoftext|>