<commit_before>//! SHA-3 family (Secure Hash Algorithm)
//!
//! # General info
//!
//! | Name     | Digest size | Block size | Rounds | Structure        | Reference           |
//! | -------- | ----------: | ---------: | -----: | ---------------- | ------------------- |
//! | SHA3-224 |    224 bits |  1152 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-256 |    256 bits |  1088 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-384 |    384 bits |   832 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-512 |    512 bits |   576 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//!
//! [fips202]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions"
//! [sponge]: https://en.wikipedia.org/wiki/Sponge_function "Sponge function"

use core::ops::Div;
use core::ptr;

use byteorder::{ByteOrder, LittleEndian};
use typenum::consts::{U8, U72, U104, U136, U144, U224, U256, U384, U512};
use typenum::uint::Unsigned;
use static_buffer::{FixedBuf, FixedBuffer, StandardPadding};

use Digest;

#[derive(Copy)]
struct State {
    hash: [u64; 25],
    rest: usize,
    block_size: usize,
}

impl Clone for State {
    fn clone(&self) -> Self {
        State {
            hash: self.hash,
            rest: self.rest,
            block_size: self.block_size,
        }
    }
}

const ROUND_CONSTS: [u64; 24] = [0x0000000000000001,
                                 0x0000000000008082,
                                 0x800000000000808a,
                                 0x8000000080008000,
                                 0x000000000000808b,
                                 0x0000000080000001,
                                 0x8000000080008081,
                                 0x8000000000008009,
                                 0x000000000000008a,
                                 0x0000000000000088,
                                 0x0000000080008009,
                                 0x000000008000000a,
                                 0x000000008000808b,
                                 0x800000000000008b,
                                 0x8000000000008089,
                                 0x8000000000008003,
                                 0x8000000000008002,
                                 0x8000000000000080,
                                 0x000000000000800a,
                                 0x800000008000000a,
                                 0x8000000080008081,
                                 0x8000000000008080,
                                 0x0000000080000001,
                                 0x8000000080008008];

#[inline(always)]
fn round(rc: u64, a: &mut [u64; 25], c: &mut [u64; 5]) {
    let d0 = c[4] ^ c[1].rotate_left(1);
    let d1 = c[0] ^ c[2].rotate_left(1);
    let d2 = c[1] ^ c[3].rotate_left(1);
    let d3 = c[2] ^ c[4].rotate_left(1);
    let d4 = c[3] ^ c[0].rotate_left(1);

    let b0 = a[0] ^ d0;
    let b10 = (a[1] ^ d1).rotate_left(1);
    let b20 = (a[2] ^ d2).rotate_left(62);
    let b5 = (a[3] ^ d3).rotate_left(28);
    let b15 = (a[4] ^ d4).rotate_left(27);
    let b16 = (a[5] ^ d0).rotate_left(36);
    let b1 = (a[6] ^ d1).rotate_left(44);
    let b11 = (a[7] ^ d2).rotate_left(6);
    let b21 = (a[8] ^ d3).rotate_left(55);
    let b6 = (a[9] ^ d4).rotate_left(20);
    let b7 = (a[10] ^ d0).rotate_left(3);
    let b17 = (a[11] ^ d1).rotate_left(10);
    let b2 = (a[12] ^ d2).rotate_left(43);
    let b12 = (a[13] ^ d3).rotate_left(25);
    let b22 = (a[14] ^ d4).rotate_left(39);
    let b23 = (a[15] ^ d0).rotate_left(41);
    let b8 = (a[16] ^ d1).rotate_left(45);
    let b18 = (a[17] ^ d2).rotate_left(15);
    let b3 = (a[18] ^ d3).rotate_left(21);
    let b13 = (a[19] ^ d4).rotate_left(8);
    let b14 = (a[20] ^ d0).rotate_left(18);
    let b24 = (a[21] ^ d1).rotate_left(2);
    let b9 = (a[22] ^ d2).rotate_left(61);
    let b19 = (a[23] ^ d3).rotate_left(56);
    let b4 = (a[24] ^ d4).rotate_left(14);

    a[0] = (b0 ^ ((!b1) & b2)) ^ rc;
    c[0] = a[0];
    a[1] = b1 ^ ((!b2) & b3);
    c[1] = a[1];
    a[2] = b2 ^ ((!b3) & b4);
    c[2] = a[2];
    a[3] = b3 ^ ((!b4) & b0);
    c[3] = a[3];
    a[4] = b4 ^ ((!b0) & b1);
    c[4] = a[4];

    a[5] = b5 ^ ((!b6) & b7);
    c[0] ^= a[5];
    a[6] = b6 ^ ((!b7) & b8);
    c[1] ^= a[6];
    a[7] = b7 ^ ((!b8) & b9);
    c[2] ^= a[7];
    a[8] = b8 ^ ((!b9) & b5);
    c[3] ^= a[8];
    a[9] = b9 ^ ((!b5) & b6);
    c[4] ^= a[9];

    a[10] = b10 ^ ((!b11) & b12);
    c[0] ^= a[10];
    a[11] = b11 ^ ((!b12) & b13);
    c[1] ^= a[11];
    a[12] = b12 ^ ((!b13) & b14);
    c[2] ^= a[12];
    a[13] = b13 ^ ((!b14) & b10);
    c[3] ^= a[13];
    a[14] = b14 ^ ((!b10) & b11);
    c[4] ^= a[14];

    a[15] = b15 ^ ((!b16) & b17);
    c[0] ^= a[15];
    a[16] = b16 ^ ((!b17) & b18);
    c[1] ^= a[16];
    a[17] = b17 ^ ((!b18) & b19);
    c[2] ^= a[17];
    a[18] = b18 ^ ((!b19) & b15);
    c[3] ^= a[18];
    a[19] = b19 ^ ((!b15) & b16);
    c[4] ^= a[19];

    a[20] = b20 ^ ((!b21) & b22);
    c[0] ^= a[20];
    a[21] = b21 ^ ((!b22) & b23);
    c[1] ^= a[21];
    a[22] = b22 ^ ((!b23) & b24);
    c[2] ^= a[22];
    a[23] = b23 ^ ((!b24) & b20);
    c[3] ^= a[23];
    a[24] = b24 ^ ((!b20) & b21);
    c[4] ^= a[24];
}

impl State {
    fn init(bits: usize) -> Self {
        let rate = 1600 - bits * 2;
        assert!(rate <= 1600 && (rate % 64) == 0);
        State {
            hash: [0; 25],
            rest: 0,
            block_size: rate / 8,
        }
    }

    #[inline]
    fn permutation(&mut self) {
        let mut a = &mut self.hash;
        let mut c: [u64; 5] = [a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20],
                               a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21],
                               a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22],
                               a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23],
                               a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]];
        for &rc in &ROUND_CONSTS {
            round(rc, a, &mut c);
        }
    }

    #[inline]
    fn compress(&mut self, data: &[u8]) {
        let max = self.block_size / 8;
        for (h, c) in self.hash[0..max].iter_mut().zip(data.chunks(8)) {
            *h ^= LittleEndian::read_u64(c)
        }

        self.permutation();
    }
}

macro_rules! sha3_impl {
    ($(#[$attr:meta])* struct $name:ident -> $size:ty, $bsize:ty) => {
        #[derive(Clone)]
        $(#[$attr])*
        pub struct $name {
            state: State,
            buffer: FixedBuffer<$bsize>,
        }

        impl Default for $name {
            fn default() -> Self {
                $name {
                    state: State::init(<$size as Unsigned>::to_usize()),
                    buffer: FixedBuffer::new(),
                }
            }
        }

        impl Digest for $name {
            type OutputBits = $size;
            type OutputBytes = <$size as Div<U8>>::Output;

            type BlockSize = $bsize;

            fn update<T>(&mut self, data: T) where T: AsRef<[u8]> {
                let state = &mut self.state;
                self.buffer.input(data.as_ref(), |d| state.compress(d));
            }

            fn result<T>(mut self, mut out: T) where T: AsMut<[u8]> {
                let mut ret = out.as_mut();
                assert!(ret.len() >= Self::output_bytes());
                let state = &mut self.state;

                self.buffer.pad(0b00000110, 0, |d| state.compress(d));
                let buf = self.buffer.full_buffer();
                let last = buf.len() - 1;
                buf[last] |= 0b10000000;
                state.compress(buf);

                unsafe {
                    ptr::copy_nonoverlapping(
                        state.hash.as_ptr() as *const u8,
                        ret.as_mut_ptr(),
                        Self::output_bytes())
                };
            }
        }
    }
}

sha3_impl!(
/// SHA3-224 implementation
///
/// For more details check [module docs](index.html)
    struct Sha224 -> U224, U144);
sha3_impl!(
/// SHA3-256 implementation
///
/// For more details check [module docs](index.html)
    struct Sha256 -> U256, U136);
sha3_impl!(
/// SHA3-384 implementation
///
/// For more details check [module docs](index.html)
    struct Sha384 -> U384, U104);
sha3_impl!(
/// SHA3-512 implementation
///
/// For more details check [module docs](index.html)
    struct Sha512 -> U512, U72);
<commit_msg>style(digest::sha3): remove unneeded `mut`<commit_after>//! SHA-3 family (Secure Hash Algorithm)
//!
//! # General info
//!
//! | Name     | Digest size | Block size | Rounds | Structure        | Reference           |
//! | -------- | ----------: | ---------: | -----: | ---------------- | ------------------- |
//! | SHA3-224 |    224 bits |  1152 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-256 |    256 bits |  1088 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-384 |    384 bits |   832 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//! | SHA3-512 |    512 bits |   576 bits |     24 | [Sponge][sponge] | [FIPS 202][fips202] |
//!
//! [fips202]: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf "SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions"
//! [sponge]: https://en.wikipedia.org/wiki/Sponge_function "Sponge function"

use core::ops::Div;
use core::ptr;

use byteorder::{ByteOrder, LittleEndian};
use typenum::consts::{U8, U72, U104, U136, U144, U224, U256, U384, U512};
use typenum::uint::Unsigned;
use static_buffer::{FixedBuf, FixedBuffer, StandardPadding};

use Digest;

#[derive(Copy)]
struct State {
    hash: [u64; 25],
    rest: usize,
    block_size: usize,
}

impl Clone for State {
    fn clone(&self) -> Self {
        State {
            hash: self.hash,
            rest: self.rest,
            block_size: self.block_size,
        }
    }
}

const ROUND_CONSTS: [u64; 24] = [0x0000000000000001,
                                 0x0000000000008082,
                                 0x800000000000808a,
                                 0x8000000080008000,
                                 0x000000000000808b,
                                 0x0000000080000001,
                                 0x8000000080008081,
                                 0x8000000000008009,
                                 0x000000000000008a,
                                 0x0000000000000088,
                                 0x0000000080008009,
                                 0x000000008000000a,
                                 0x000000008000808b,
                                 0x800000000000008b,
                                 0x8000000000008089,
                                 0x8000000000008003,
                                 0x8000000000008002,
                                 0x8000000000000080,
                                 0x000000000000800a,
                                 0x800000008000000a,
                                 0x8000000080008081,
                                 0x8000000000008080,
                                 0x0000000080000001,
                                 0x8000000080008008];

#[inline(always)]
fn round(rc: u64, a: &mut [u64; 25], c: &mut [u64; 5]) {
    let d0 = c[4] ^ c[1].rotate_left(1);
    let d1 = c[0] ^ c[2].rotate_left(1);
    let d2 = c[1] ^ c[3].rotate_left(1);
    let d3 = c[2] ^ c[4].rotate_left(1);
    let d4 = c[3] ^ c[0].rotate_left(1);

    let b0 = a[0] ^ d0;
    let b10 = (a[1] ^ d1).rotate_left(1);
    let b20 = (a[2] ^ d2).rotate_left(62);
    let b5 = (a[3] ^ d3).rotate_left(28);
    let b15 = (a[4] ^ d4).rotate_left(27);
    let b16 = (a[5] ^ d0).rotate_left(36);
    let b1 = (a[6] ^ d1).rotate_left(44);
    let b11 = (a[7] ^ d2).rotate_left(6);
    let b21 = (a[8] ^ d3).rotate_left(55);
    let b6 = (a[9] ^ d4).rotate_left(20);
    let b7 = (a[10] ^ d0).rotate_left(3);
    let b17 = (a[11] ^ d1).rotate_left(10);
    let b2 = (a[12] ^ d2).rotate_left(43);
    let b12 = (a[13] ^ d3).rotate_left(25);
    let b22 = (a[14] ^ d4).rotate_left(39);
    let b23 = (a[15] ^ d0).rotate_left(41);
    let b8 = (a[16] ^ d1).rotate_left(45);
    let b18 = (a[17] ^ d2).rotate_left(15);
    let b3 = (a[18] ^ d3).rotate_left(21);
    let b13 = (a[19] ^ d4).rotate_left(8);
    let b14 = (a[20] ^ d0).rotate_left(18);
    let b24 = (a[21] ^ d1).rotate_left(2);
    let b9 = (a[22] ^ d2).rotate_left(61);
    let b19 = (a[23] ^ d3).rotate_left(56);
    let b4 = (a[24] ^ d4).rotate_left(14);

    a[0] = (b0 ^ ((!b1) & b2)) ^ rc;
    c[0] = a[0];
    a[1] = b1 ^ ((!b2) & b3);
    c[1] = a[1];
    a[2] = b2 ^ ((!b3) & b4);
    c[2] = a[2];
    a[3] = b3 ^ ((!b4) & b0);
    c[3] = a[3];
    a[4] = b4 ^ ((!b0) & b1);
    c[4] = a[4];

    a[5] = b5 ^ ((!b6) & b7);
    c[0] ^= a[5];
    a[6] = b6 ^ ((!b7) & b8);
    c[1] ^= a[6];
    a[7] = b7 ^ ((!b8) & b9);
    c[2] ^= a[7];
    a[8] = b8 ^ ((!b9) & b5);
    c[3] ^= a[8];
    a[9] = b9 ^ ((!b5) & b6);
    c[4] ^= a[9];

    a[10] = b10 ^ ((!b11) & b12);
    c[0] ^= a[10];
    a[11] = b11 ^ ((!b12) & b13);
    c[1] ^= a[11];
    a[12] = b12 ^ ((!b13) & b14);
    c[2] ^= a[12];
    a[13] = b13 ^ ((!b14) & b10);
    c[3] ^= a[13];
    a[14] = b14 ^ ((!b10) & b11);
    c[4] ^= a[14];

    a[15] = b15 ^ ((!b16) & b17);
    c[0] ^= a[15];
    a[16] = b16 ^ ((!b17) & b18);
    c[1] ^= a[16];
    a[17] = b17 ^ ((!b18) & b19);
    c[2] ^= a[17];
    a[18] = b18 ^ ((!b19) & b15);
    c[3] ^= a[18];
    a[19] = b19 ^ ((!b15) & b16);
    c[4] ^= a[19];

    a[20] = b20 ^ ((!b21) & b22);
    c[0] ^= a[20];
    a[21] = b21 ^ ((!b22) & b23);
    c[1] ^= a[21];
    a[22] = b22 ^ ((!b23) & b24);
    c[2] ^= a[22];
    a[23] = b23 ^ ((!b24) & b20);
    c[3] ^= a[23];
    a[24] = b24 ^ ((!b20) & b21);
    c[4] ^= a[24];
}

impl State {
    fn init(bits: usize) -> Self {
        let rate = 1600 - bits * 2;
        assert!(rate <= 1600 && (rate % 64) == 0);
        State {
            hash: [0; 25],
            rest: 0,
            block_size: rate / 8,
        }
    }

    #[inline]
    fn permutation(&mut self) {
        let a = &mut self.hash;
        let mut c: [u64; 5] = [a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20],
                               a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21],
                               a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22],
                               a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23],
                               a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]];
        for &rc in &ROUND_CONSTS {
            round(rc, a, &mut c);
        }
    }

    #[inline]
    fn compress(&mut self, data: &[u8]) {
        let max = self.block_size / 8;
        for (h, c) in self.hash[0..max].iter_mut().zip(data.chunks(8)) {
            *h ^= LittleEndian::read_u64(c)
        }

        self.permutation();
    }
}

macro_rules! sha3_impl {
    ($(#[$attr:meta])* struct $name:ident -> $size:ty, $bsize:ty) => {
        #[derive(Clone)]
        $(#[$attr])*
        pub struct $name {
            state: State,
            buffer: FixedBuffer<$bsize>,
        }

        impl Default for $name {
            fn default() -> Self {
                $name {
                    state: State::init(<$size as Unsigned>::to_usize()),
                    buffer: FixedBuffer::new(),
                }
            }
        }

        impl Digest for $name {
            type OutputBits = $size;
            type OutputBytes = <$size as Div<U8>>::Output;

            type BlockSize = $bsize;

            fn update<T>(&mut self, data: T) where T: AsRef<[u8]> {
                let state = &mut self.state;
                self.buffer.input(data.as_ref(), |d| state.compress(d));
            }

            fn result<T>(mut self, mut out: T) where T: AsMut<[u8]> {
                let mut ret = out.as_mut();
                assert!(ret.len() >= Self::output_bytes());
                let state = &mut self.state;

                self.buffer.pad(0b00000110, 0, |d| state.compress(d));
                let buf = self.buffer.full_buffer();
                let last = buf.len() - 1;
                buf[last] |= 0b10000000;
                state.compress(buf);

                unsafe {
                    ptr::copy_nonoverlapping(state.hash.as_ptr() as *const u8,
                                             ret.as_mut_ptr(),
                                             Self::output_bytes())
                };
            }
        }
    }
}

sha3_impl!(
/// SHA3-224 implementation
///
/// For more details check [module docs](index.html)
    struct Sha224 -> U224, U144);
sha3_impl!(
/// SHA3-256 implementation
///
/// For more details check [module docs](index.html)
    struct Sha256 -> U256, U136);
sha3_impl!(
/// SHA3-384 implementation
///
/// For more details check [module docs](index.html)
    struct Sha384 -> U384, U104);
sha3_impl!(
/// SHA3-512 implementation
///
/// For more details check [module docs](index.html)
    struct Sha512 -> U512, U72);
<|endoftext|>


<commit_before>extern crate futures;
extern crate tokio_core;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use futures::stream::Stream;
use tokio_core::reactor::Core;
use reql::{Client, Document, Run};

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 *
 */

#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Change {
    #[serde(rename(deserialize = "type"))]
    action: String,
    // new_val or old_val can be null, so we should use Options
    new_val: Option<TestItem>,
    old_val: Option<TestItem>,
}

fn main()
{
    // Create a new ReQL client
    let r = Client::new();

    // Create an even loop
    let core = Core::new().unwrap();

    // Create a connection pool
    let conn = r.connect(&core.handle()).unwrap();

    // Run the query
    let query =
        r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

        // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {
                // Extract the change type
                print!("{} action received\n\t=> ", change.action);

                // Match the change type
                match change.action.as_ref() {
                    "add" => println!("{:?}", change.new_val),
                    "remove" => println!("{:?}", change.old_val),
                    "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),

                    _ => println!("{:?}", change)
                }
            }
            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
        .or_else(|error| {
            println!("{:?}", error);
            Err(())
        });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<commit_msg>re-added missing comment<commit_after>extern crate futures;
extern crate tokio_core;

#[macro_use]
extern crate reql;
extern crate reql_types;

#[macro_use]
extern crate serde_derive;
extern crate serde;
extern crate serde_json;

use futures::stream::Stream;
use tokio_core::reactor::Core;
use reql::{Client, Document, Run};

/**
 * rethinkdb changelog example
 * After running, access your admin panel at localhost:8080
 *
 * setup a "test" database, with a "test" table, and run:
 *
 * // Insert an item
 * r.db('test').table('test').insert({ test: 1 });
 *
 * // Give the first item a random number
 * r.db('test').table('test').nth(0).update({ test: r.random(0, 100) }, { nonAtomic: true });
 *
 * // Remove the first item
 * r.db('test').table('test').nth(0).delete();
 *
 */

#[derive(Debug, Serialize, Deserialize)]
struct TestItem {
    test: i32,
    id: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Change {
    // Upon deserialisation:
    // We'll change the rethinkdb change "type" to avoid  naming issues
    #[serde(rename(deserialize = "type"))]
    action: String,
    // new_val or old_val can be null, so we should use Options
    new_val: Option<TestItem>,
    old_val: Option<TestItem>,
}

fn main()
{
    // Create a new ReQL client
    let r = Client::new();

    // Create an even loop
    let core = Core::new().unwrap();

    // Create a connection pool
    let conn = r.connect(&core.handle()).unwrap();

    // Run the query
    let query =
        r.db("test")
        .table("test")
        .filter(args!(|doc| {

            // Filter only documents which match our current TestItem trait
            doc.has_fields("test").and(doc.get_field("test").type_of().eq("NUMBER"))
        }))
        .changes()

    // We want rethinkdb to inform us of the change type
        .with_args(args!({
            include_types: true
        }))
        .run::<Change>(conn)
        .unwrap();

    // Process the results
    let stati = query.and_then(|change| {
        match change {
            // The server returned the response we were expecting,
            // and deserialized the data into our Change structure
            Some(Document::Expected(change)) => {
                // Extract the change type
                print!("{} action received\n\t=> ", change.action);

                // Match the change type
                match change.action.as_ref() {
                    "add" => println!("{:?}", change.new_val),
                    "remove" => println!("{:?}", change.old_val),
                    "change" => println!("from {:?} to {:?}", change.old_val, change.new_val),

                    _ => println!("{:?}", change)
                }
            }
            // We got a response alright, but it wasn't the one we were
            // expecting plus it's not an error either, otherwise it would
            // have been returned as such (This simply means that the response
            // we got couldn't be serialised into the type we were expecting)
            Some(Document::Unexpected(change)) => {
                println!("Got unexpected change: {}",change)
            }
            // This is impossible in this particular example since there
            // needs to be at least one server available to give this
            // response otherwise we would have run into an error for
            // failing to connect
            None => {
                println!("got no documents in the database");
            }
        }
        Ok(())
    })
    // Our query ran into an error
        .or_else(|error| {
            println!("{:?}", error);
            Err(())
        });

    // Wait for all the results to be processed
    for _ in stati.wait() {}
}
<|endoftext|>


<commit_before>//! An example of paragraph rendering
//! Controls
//!
//! * Resize window to adjust layout
//! * Scroll to modify font size
//! * Type to add/remove text
//! * Ctrl-Scroll to zoom in/out using a transform, this is cheap but notice how rusttype can't
//!   render at full quality without the correct pixel information.

extern crate cgmath;
extern crate gfx;
extern crate gfx_glyph;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate env_logger;
extern crate spin_sleep;

use cgmath::{Matrix4, Transform, Rad};
use glutin::GlContext;
use gfx::{format, Device};
use std::env;
use std::io;
use std::io::Write;
use std::f32::consts::PI as PI32;

fn main() {
    env_logger::init();

    // winit wayland is currently still wip
    if cfg!(target_os = "linux") && env::var("WINIT_UNIX_BACKEND").is_err() {
        env::set_var("WINIT_UNIX_BACKEND", "x11");
    }

    if cfg!(debug_assertions) && env::var("yes_i_really_want_debug_mode").is_err() {
        eprintln!(
            "Note: Release mode will improve performance greatly.\n    \
             e.g. use `cargo run --example paragraph --release`"
        );
    }

    let mut events_loop = glutin::EventsLoop::new();
    let title = "gfx_glyph example - scroll to size, type to modify, ctrl-scroll to gpu zoom, ctrl-shift-scroll to gpu rotate";
    let window_builder = glutin::WindowBuilder::new().with_title(title).with_dimensions(1024, 576);
    let context = glutin::ContextBuilder::new();
    let (window, mut device, mut factory, mut main_color, mut main_depth) =
        gfx_window_glutin::init::<format::Srgba8, format::DepthStencil>(
            window_builder,
            context,
            &events_loop,
        );

    let mut glyph_brush = gfx_glyph::GlyphBrushBuilder::using_font_bytes(
        include_bytes!("Arial Unicode.ttf") as &[u8],
    ).initial_cache_size((1024, 1024))
        .build(factory.clone());

    let mut text: String = include_str!("lipsum.txt").into();

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();

    let mut running = true;
    let mut font_size = gfx_glyph::Scale::uniform(18.0 * window.hidpi_factor());
    let mut zoom: f32 = 1.0;
    let mut angle = 0.0;
    let mut ctrl = false;
    let mut loop_helper = spin_sleep::LoopHelper::builder().build_without_target_rate();

    while running {
        loop_helper.loop_start();

        events_loop.poll_events(|event| {
            use glutin::*;

            if let Event::WindowEvent { event, .. } = event {
                match event {
                    WindowEvent::Closed => running = false,
                    WindowEvent::KeyboardInput {
                        input:
                            KeyboardInput {
                                state: ElementState::Pressed,
                                virtual_keycode: Some(keypress),
                                ..
                            },
                        ..
                    } => match keypress {
                        VirtualKeyCode::Escape => running = false,
                        VirtualKeyCode::Back => {
                            text.pop();
                        }
                        VirtualKeyCode::LControl | VirtualKeyCode::RControl => ctrl = true,
                        _ => (),
                    },
                    WindowEvent::KeyboardInput {
                        input: KeyboardInput { state: ElementState::Released, .. },
                        ..
                    } => ctrl = false,
                    WindowEvent::ReceivedCharacter(c) => if c != '\u{7f}' && c != '\u{8}' {
                        text.push(c);
                    },
                    WindowEvent::Resized(width, height) => {
                        window.resize(width, height);
                        gfx_window_glutin::update_views(&window, &mut main_color, &mut main_depth);
                    }
                    WindowEvent::MouseWheel {
                        delta: MouseScrollDelta::LineDelta(_, y),
                        modifiers: ModifiersState { ctrl, shift, .. },
                        ..
                    } => {
                        if ctrl && shift {
                            if y > 0.0 {
                                angle += 0.02 * PI32;
                            }
                            else {
                                angle -= 0.02 * PI32;
                            }
                            if (angle % (PI32 * 2.0)).abs() < 0.01 {
                                angle = 0.0;
                            }
                            print!("\r                            \r");
                            print!("transform-angle -> {:.2} * π", angle / PI32);
                            io::stdout().flush().ok().unwrap();
                        }
                        else if ctrl && !shift {
                            let old_zoom = zoom;
                            // increase/decrease zoom
                            if y > 0.0 {
                                zoom += 0.1;
                            }
                            else {
                                zoom -= 0.1;
                            }
                            zoom = zoom.min(1.0).max(0.1);
                            if (zoom - old_zoom).abs() > 1e-2 {
                                print!("\r                            \r");
                                print!("transform-zoom -> {:.1}", zoom);
                                io::stdout().flush().ok().unwrap();
                            }
                        }
                        else {
                            // increase/decrease font size
                            let old_size = font_size.x;
                            let mut size = font_size.x / window.hidpi_factor();
                            if y > 0.0 {
                                size += (size / 4.0).max(2.0)
                            }
                            else {
                                size *= 4.0 / 5.0
                            };
                            size = size.max(1.0);
                            font_size = gfx_glyph::Scale::uniform(size * window.hidpi_factor());
                            if (font_size.x - old_size).abs() > 1e-2 {
                                print!("\r                            \r");
                                print!("font-size -> {:.1}", font_size.x);
                                io::stdout().flush().ok().unwrap();
                            }
                        }
                    }
                    _ => {}
                }
            }
        });

        encoder.clear(&main_color, [0.02, 0.02, 0.02, 1.0]);

        let (width, height, ..) = main_color.get_dimensions();
        let (width, height) = (f32::from(width), f32::from(height));
        let scale = font_size;

        // The section is all the info needed for the glyph brush to render a 'section' of text.
        // Use `..Section::default()` to skip the bits you don't care about
        let section = gfx_glyph::Section {
            text: &text,
            scale,
            screen_position: (0.0, 0.0),
            bounds: (width / 3.15, height),
            color: [0.9, 0.3, 0.3, 1.0],
            ..Section::default()
        };

        // bounds of a section can be fetched with `pixel_bounds`
        let _bounds: Option<Rect<i32>> = glyph_brush.pixel_bounds(section);

        // Adds a section & layout to the queue for the next call to `draw_queued`, this
        // can be called multiple times for different sections that want to use the same
        // font and gpu cache
        // This step computes the glyph positions, this is cached to avoid unnecessary recalculation
        glyph_brush.queue(section);

        use gfx_glyph::*;
        glyph_brush.queue(Section {
            text: &text,
            scale,
            screen_position: (width / 2.0, 0.0),
            bounds: (width / 3.15, height),
            color: [0.3, 0.9, 0.3, 1.0],
            layout: Layout::default().h_align(HorizontalAlign::Center),
            ..Section::default()
        });

        glyph_brush.queue(Section {
            text: &text,
            scale,
            screen_position: (width, 0.0),
            bounds: (width / 3.15, height),
            color: [0.3, 0.3, 0.9, 1.0],
            layout: Layout::default().h_align(HorizontalAlign::Right),
            ..Section::default()
        });

        // Note: Can be drawn simply with the below, when transforms are not needed:
        // `glyph_brush.draw_queued(&mut encoder, &main_color, &main_depth).expect("draw");`

        // Here an example transform is used as a cheap zoom out (controlled with ctrl-scroll)
        let transform_zoom = Matrix4::from_scale(zoom);

        // Orthographic rotation transform
        let transform_rotate = {
            let aspect = width / height;
            let projection = cgmath::ortho(
                0.0 - 1.0 * aspect,
                0.0 + 1.0 * aspect,
                0.0 - 1.0,
                0.0 + 1.0,
                1.0,
                -1.0,
            );
            projection * Matrix4::from_angle_z(Rad(angle)) * projection.inverse_transform().unwrap()
        };

        let transform = transform_rotate * transform_zoom;

        // Finally once per frame you want to actually draw all the sections you've submitted
        // with `queue` calls.
        //
        // Note: Drawing in the case the text is unchanged from the previous frame (a common case)
        // is essentially free as the vertices are reused & gpu cache updating interaction
        // can be skipped.
        glyph_brush
            .draw_queued_with_transform(transform.into(), &mut encoder, &main_color, &main_depth)
            .expect("draw");

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();

        if let Some(rate) = loop_helper.report_rate() {
            window.set_title(&format!("{} - {:.0} FPS", title, rate));
        }
    }
    println!();
}
<commit_msg>Paragraph example: Remove some projection magic numbers<commit_after>//! An example of paragraph rendering
//! Controls
//!
//! * Resize window to adjust layout
//! * Scroll to modify font size
//! * Type to add/remove text
//! * Ctrl-Scroll to zoom in/out using a transform, this is cheap but notice how rusttype can't
//!   render at full quality without the correct pixel information.

extern crate cgmath;
extern crate gfx;
extern crate gfx_glyph;
extern crate gfx_window_glutin;
extern crate glutin;
extern crate env_logger;
extern crate spin_sleep;

use cgmath::{Matrix4, Transform, Rad};
use glutin::GlContext;
use gfx::{format, Device};
use std::env;
use std::io;
use std::io::Write;
use std::f32::consts::PI as PI32;

fn main() {
    env_logger::init();

    // winit wayland is currently still wip
    if cfg!(target_os = "linux") && env::var("WINIT_UNIX_BACKEND").is_err() {
        env::set_var("WINIT_UNIX_BACKEND", "x11");
    }

    if cfg!(debug_assertions) && env::var("yes_i_really_want_debug_mode").is_err() {
        eprintln!(
            "Note: Release mode will improve performance greatly.\n    \
             e.g. use `cargo run --example paragraph --release`"
        );
    }

    let mut events_loop = glutin::EventsLoop::new();
    let title = "gfx_glyph example - scroll to size, type to modify, ctrl-scroll to gpu zoom, ctrl-shift-scroll to gpu rotate";
    let window_builder = glutin::WindowBuilder::new().with_title(title).with_dimensions(1024, 576);
    let context = glutin::ContextBuilder::new();
    let (window, mut device, mut factory, mut main_color, mut main_depth) =
        gfx_window_glutin::init::<format::Srgba8, format::DepthStencil>(
            window_builder,
            context,
            &events_loop,
        );

    let mut glyph_brush = gfx_glyph::GlyphBrushBuilder::using_font_bytes(
        include_bytes!("Arial Unicode.ttf") as &[u8],
    ).initial_cache_size((1024, 1024))
        .build(factory.clone());

    let mut text: String = include_str!("lipsum.txt").into();

    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();

    let mut running = true;
    let mut font_size = gfx_glyph::Scale::uniform(18.0 * window.hidpi_factor());
    let mut zoom: f32 = 1.0;
    let mut angle = 0.0;
    let mut ctrl = false;
    let mut loop_helper = spin_sleep::LoopHelper::builder().build_without_target_rate();

    while running {
        loop_helper.loop_start();

        events_loop.poll_events(|event| {
            use glutin::*;

            if let Event::WindowEvent { event, .. } = event {
                match event {
                    WindowEvent::Closed => running = false,
                    WindowEvent::KeyboardInput {
                        input:
                            KeyboardInput {
                                state: ElementState::Pressed,
                                virtual_keycode: Some(keypress),
                                ..
                            },
                        ..
                    } => match keypress {
                        VirtualKeyCode::Escape => running = false,
                        VirtualKeyCode::Back => {
                            text.pop();
                        }
                        VirtualKeyCode::LControl | VirtualKeyCode::RControl => ctrl = true,
                        _ => (),
                    },
                    WindowEvent::KeyboardInput {
                        input: KeyboardInput { state: ElementState::Released, .. },
                        ..
                    } => ctrl = false,
                    WindowEvent::ReceivedCharacter(c) => if c != '\u{7f}' && c != '\u{8}' {
                        text.push(c);
                    },
                    WindowEvent::Resized(width, height) => {
                        window.resize(width, height);
                        gfx_window_glutin::update_views(&window, &mut main_color, &mut main_depth);
                    }
                    WindowEvent::MouseWheel {
                        delta: MouseScrollDelta::LineDelta(_, y),
                        modifiers: ModifiersState { ctrl, shift, .. },
                        ..
                    } => {
                        if ctrl && shift {
                            if y > 0.0 {
                                angle += 0.02 * PI32;
                            }
                            else {
                                angle -= 0.02 * PI32;
                            }
                            if (angle % (PI32 * 2.0)).abs() < 0.01 {
                                angle = 0.0;
                            }
                            print!("\r                            \r");
                            print!("transform-angle -> {:.2} * π", angle / PI32);
                            io::stdout().flush().ok().unwrap();
                        }
                        else if ctrl && !shift {
                            let old_zoom = zoom;
                            // increase/decrease zoom
                            if y > 0.0 {
                                zoom += 0.1;
                            }
                            else {
                                zoom -= 0.1;
                            }
                            zoom = zoom.min(1.0).max(0.1);
                            if (zoom - old_zoom).abs() > 1e-2 {
                                print!("\r                            \r");
                                print!("transform-zoom -> {:.1}", zoom);
                                io::stdout().flush().ok().unwrap();
                            }
                        }
                        else {
                            // increase/decrease font size
                            let old_size = font_size.x;
                            let mut size = font_size.x / window.hidpi_factor();
                            if y > 0.0 {
                                size += (size / 4.0).max(2.0)
                            }
                            else {
                                size *= 4.0 / 5.0
                            };
                            size = size.max(1.0);
                            font_size = gfx_glyph::Scale::uniform(size * window.hidpi_factor());
                            if (font_size.x - old_size).abs() > 1e-2 {
                                print!("\r                            \r");
                                print!("font-size -> {:.1}", font_size.x);
                                io::stdout().flush().ok().unwrap();
                            }
                        }
                    }
                    _ => {}
                }
            }
        });

        encoder.clear(&main_color, [0.02, 0.02, 0.02, 1.0]);

        let (width, height, ..) = main_color.get_dimensions();
        let (width, height) = (f32::from(width), f32::from(height));
        let scale = font_size;

        // The section is all the info needed for the glyph brush to render a 'section' of text.
        // Use `..Section::default()` to skip the bits you don't care about
        let section = gfx_glyph::Section {
            text: &text,
            scale,
            screen_position: (0.0, 0.0),
            bounds: (width / 3.15, height),
            color: [0.9, 0.3, 0.3, 1.0],
            ..Section::default()
        };

        // bounds of a section can be fetched with `pixel_bounds`
        let _bounds: Option<Rect<i32>> = glyph_brush.pixel_bounds(section);

        // Adds a section & layout to the queue for the next call to `draw_queued`, this
        // can be called multiple times for different sections that want to use the same
        // font and gpu cache
        // This step computes the glyph positions, this is cached to avoid unnecessary recalculation
        glyph_brush.queue(section);

        use gfx_glyph::*;
        glyph_brush.queue(Section {
            text: &text,
            scale,
            screen_position: (width / 2.0, 0.0),
            bounds: (width / 3.15, height),
            color: [0.3, 0.9, 0.3, 1.0],
            layout: Layout::default().h_align(HorizontalAlign::Center),
            ..Section::default()
        });

        glyph_brush.queue(Section {
            text: &text,
            scale,
            screen_position: (width, 0.0),
            bounds: (width / 3.15, height),
            color: [0.3, 0.3, 0.9, 1.0],
            layout: Layout::default().h_align(HorizontalAlign::Right),
            ..Section::default()
        });

        // Note: Can be drawn simply with the below, when transforms are not needed:
        // `glyph_brush.draw_queued(&mut encoder, &main_color, &main_depth).expect("draw");`

        // Here an example transform is used as a cheap zoom out (controlled with ctrl-scroll)
        let transform_zoom = Matrix4::from_scale(zoom);

        // Orthographic rotation transform
        let transform_rotate = {
            let aspect = width / height;
            let zoom = 1.0;
            let origin = (0.0, 0.0); // top-corner: `let origin = (1.0 * aspect, -1.0);`
            let projection = cgmath::ortho(
                origin.0 - zoom * aspect,
                origin.0 + zoom * aspect,
                origin.1 - zoom,
                origin.1 + zoom,
                1.0,
                -1.0,
            );
            projection * Matrix4::from_angle_z(Rad(angle)) * projection.inverse_transform().unwrap()
        };

        let transform = transform_rotate * transform_zoom;

        // Finally once per frame you want to actually draw all the sections you've submitted
        // with `queue` calls.
        //
        // Note: Drawing in the case the text is unchanged from the previous frame (a common case)
        // is essentially free as the vertices are reused & gpu cache updating interaction
        // can be skipped.
        glyph_brush
            .draw_queued_with_transform(transform.into(), &mut encoder, &main_color, &main_depth)
            .expect("draw");

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();

        if let Some(rate) = loop_helper.report_rate() {
            window.set_title(&format!("{} - {:.0} FPS", title, rate));
        }
    }
    println!();
}
<|endoftext|>


<commit_before>use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;

use events::Error as EventsError;
use crypto::{PublicKey, SecretKey, HexValue, FromHexError, Hash};
use serialize::ToHex;
use storage::{Result as StorageResult, Error as StorageError};

#[derive(Debug)]
pub enum ApiError {
    Service(Box<::std::error::Error + Send + Sync>),
    Storage(StorageError),
    Events(EventsError),
    FromHex(FromHexError),
    Io(::std::io::Error),
    FileNotFound(Hash),
    NotFound,
    FileTooBig,
    FileExists(Hash),
    IncorrectRequest(Box<::std::error::Error + Send + Sync>),
    Unauthorized,
}

impl ::std::fmt::Display for ApiError {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for ApiError {
    fn description(&self) -> &str {
        match *self {
            ApiError::Service(ref error) => error.description(),
            ApiError::Storage(ref error) => error.description(),
            ApiError::Events(ref error) => error.description(),
            ApiError::FromHex(ref error) => error.description(),
            ApiError::Io(ref error) => error.description(),
            ApiError::FileNotFound(_) => "FileNotFound",
            ApiError::NotFound => "NotFound",
            ApiError::FileTooBig => "FileToBig",
            ApiError::FileExists(_) => "FileExists",
            ApiError::IncorrectRequest(ref error) => error.description(),
            ApiError::Unauthorized => "Unauthorized",
        }
    }
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<StorageError> for ApiError {
    fn from(e: StorageError) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<EventsError> for ApiError {
    fn from(e: EventsError) -> ApiError {
        ApiError::Events(e)
    }
}

impl From<FromHexError> for ApiError {
    fn from(e: FromHexError) -> ApiError {
        ApiError::FromHex(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        use std::error::Error;

        let mut body = BTreeMap::new();
        let description = format!("{:?}; description: {:?}", e, e.description());
        body.insert("type", description);
        let code = match e {
            ApiError::FileExists(hash) |
            ApiError::FileNotFound(hash) => {
                body.insert("hash", ToHex::to_hex(&hash));
                status::Conflict
            }
            _ => status::Conflict,
        };
        IronError {
            error: Box::new(e),
            response: Response::with((code, ::serde_json::to_string_pretty(&body).unwrap())),
        }
    }
}

#[derive(Clone, Debug)]
pub struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
    where T: AsRef<[u8]> + Clone
{
    type Target = T;

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

impl<T> Serialize for HexField<T>
    where T: AsRef<[u8]> + Clone
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        ser.serialize_str(&self.0.as_ref().to_hex())
    }
}

struct HexVisitor<T>
    where T: AsRef<[u8]> + HexValue
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
    where T: AsRef<[u8]> + HexValue + Clone
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
        where E: de::Error
    {
        let v = T::from_hex(s)
            .map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
    where T: AsRef<[u8]> + HexValue + Clone
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

pub trait Api {
    fn load_hex_value_from_cookie<'a>(&self,
                                      request: &'a Request,
                                      key: &str)
                                      -> StorageResult<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = HexValue::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(StorageError::new(format!("Unable to find value with given key {}", key)))
    }

    fn load_keypair_from_cookies(&self,
                                 request: &Request)
                                 -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(self.load_hex_value_from_cookie(request,
                                                                               "public_key")?
                                                   .as_ref());
        let secret_key = SecretKey::from_slice(self.load_hex_value_from_cookie(request,
                                                                               "secret_key")?
                                                   .as_ref());

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    fn ok_response_with_cookies(&self,
                                json: &serde_json::Value,
                                cookies: Option<Vec<String>>)
                                -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }

    fn wire<'b>(&self, router: &'b mut Router);
}

#[cfg(test)]
mod tests {
    use router::Router;
    use serde_json;

    use blockchain::Block;
    use crypto::Hash;

    use super::*;

    #[test]
    fn test_json_response_for_complex_val() {
        let str_val = "sghdkgskgskldghshgsd";
        let complex_val = Block::new(24,
                                     2,
                                     &Hash::new([24; 32]),
                                     &Hash::new([34; 32]),
                                     &Hash::new([38; 32]));
        struct SampleAPI;
        impl Api for SampleAPI {
            fn wire<'b>(&self, _: &'b mut Router) {
                return;
            }
        }
        let stub = SampleAPI;
        let result = stub.ok_response(&serde_json::to_value(str_val).unwrap());
        assert!(result.is_ok());
        let result = stub.ok_response(&serde_json::to_value(&complex_val).unwrap());
        assert!(result.is_ok());
        print!("{:?}", result);
    }
}
<commit_msg>Fix clippy linted warning<commit_after>use iron::IronError;
use iron::prelude::*;
use iron::status;
use iron::headers::Cookie;
use hyper::header::{ContentType, SetCookie};
use cookie::Cookie as CookiePair;
use router::Router;
use serde_json;
use serde::{Serialize, Serializer};
use serde::de::{self, Visitor, Deserialize, Deserializer};

use std::ops::Deref;
use std::marker::PhantomData;
use std::io;
use std::collections::BTreeMap;
use std::fmt;

use events::Error as EventsError;
use crypto::{PublicKey, SecretKey, HexValue, FromHexError, Hash};
use serialize::ToHex;
use storage::{Result as StorageResult, Error as StorageError};

#[derive(Debug)]
pub enum ApiError {
    Service(Box<::std::error::Error + Send + Sync>),
    Storage(StorageError),
    Events(EventsError),
    FromHex(FromHexError),
    Io(::std::io::Error),
    FileNotFound(Hash),
    NotFound,
    FileTooBig,
    FileExists(Hash),
    IncorrectRequest(Box<::std::error::Error + Send + Sync>),
    Unauthorized,
}

impl ::std::fmt::Display for ApiError {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{:?}", self)
    }
}

impl ::std::error::Error for ApiError {
    fn description(&self) -> &str {
        match *self {
            ApiError::Service(ref error) |
            ApiError::IncorrectRequest(ref error) => error.description(),
            ApiError::Storage(ref error) => error.description(),
            ApiError::Events(ref error) => error.description(),
            ApiError::FromHex(ref error) => error.description(),
            ApiError::Io(ref error) => error.description(),
            ApiError::FileNotFound(_) => "FileNotFound",
            ApiError::NotFound => "NotFound",
            ApiError::FileTooBig => "FileToBig",
            ApiError::FileExists(_) => "FileExists",
            ApiError::Unauthorized => "Unauthorized",
        }
    }
}

impl From<io::Error> for ApiError {
    fn from(e: io::Error) -> ApiError {
        ApiError::Io(e)
    }
}

impl From<StorageError> for ApiError {
    fn from(e: StorageError) -> ApiError {
        ApiError::Storage(e)
    }
}

impl From<EventsError> for ApiError {
    fn from(e: EventsError) -> ApiError {
        ApiError::Events(e)
    }
}

impl From<FromHexError> for ApiError {
    fn from(e: FromHexError) -> ApiError {
        ApiError::FromHex(e)
    }
}

impl From<ApiError> for IronError {
    fn from(e: ApiError) -> IronError {
        use std::error::Error;

        let mut body = BTreeMap::new();
        let description = format!("{:?}; description: {:?}", e, e.description());
        body.insert("type", description);
        let code = match e {
            ApiError::FileExists(hash) |
            ApiError::FileNotFound(hash) => {
                body.insert("hash", ToHex::to_hex(&hash));
                status::Conflict
            }
            _ => status::Conflict,
        };
        IronError {
            error: Box::new(e),
            response: Response::with((code, ::serde_json::to_string_pretty(&body).unwrap())),
        }
    }
}

#[derive(Clone, Debug)]
pub struct HexField<T: AsRef<[u8]> + Clone>(pub T);

impl<T> Deref for HexField<T>
    where T: AsRef<[u8]> + Clone
{
    type Target = T;

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

impl<T> Serialize for HexField<T>
    where T: AsRef<[u8]> + Clone
{
    fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        ser.serialize_str(&self.0.as_ref().to_hex())
    }
}

struct HexVisitor<T>
    where T: AsRef<[u8]> + HexValue
{
    _p: PhantomData<T>,
}

impl<'v, T> Visitor<'v> for HexVisitor<T>
    where T: AsRef<[u8]> + HexValue + Clone
{
    type Value = HexField<T>;

    fn expecting(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(fmt, "expected hex represented string")
    }

    fn visit_str<E>(self, s: &str) -> Result<HexField<T>, E>
        where E: de::Error
    {
        let v = T::from_hex(s)
            .map_err(|_| de::Error::custom("Invalid hex"))?;
        Ok(HexField(v))
    }
}

impl<'de, T> Deserialize<'de> for HexField<T>
    where T: AsRef<[u8]> + HexValue + Clone
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where D: Deserializer<'de>
    {
        deserializer.deserialize_str(HexVisitor { _p: PhantomData })
    }
}

pub trait Api {
    fn load_hex_value_from_cookie<'a>(&self,
                                      request: &'a Request,
                                      key: &str)
                                      -> StorageResult<Vec<u8>> {
        if let Some(&Cookie(ref cookies)) = request.headers.get() {
            for cookie in cookies.iter() {
                if let Ok(c) = CookiePair::parse(cookie.as_str()) {
                    if c.name() == key {
                        if let Ok(value) = HexValue::from_hex(c.value()) {
                            return Ok(value);
                        }
                    }
                }
            }
        }
        Err(StorageError::new(format!("Unable to find value with given key {}", key)))
    }

    fn load_keypair_from_cookies(&self,
                                 request: &Request)
                                 -> Result<(PublicKey, SecretKey), ApiError> {
        let public_key = PublicKey::from_slice(self.load_hex_value_from_cookie(request,
                                                                               "public_key")?
                                                   .as_ref());
        let secret_key = SecretKey::from_slice(self.load_hex_value_from_cookie(request,
                                                                               "secret_key")?
                                                   .as_ref());

        let public_key = public_key.ok_or(ApiError::Unauthorized)?;
        let secret_key = secret_key.ok_or(ApiError::Unauthorized)?;
        Ok((public_key, secret_key))
    }

    fn ok_response_with_cookies(&self,
                                json: &serde_json::Value,
                                cookies: Option<Vec<String>>)
                                -> IronResult<Response> {
        let mut resp = Response::with((status::Ok, serde_json::to_string_pretty(json).unwrap()));
        resp.headers.set(ContentType::json());
        if let Some(cookies) = cookies {
            resp.headers.set(SetCookie(cookies));
        }
        Ok(resp)
    }

    fn ok_response(&self, json: &serde_json::Value) -> IronResult<Response> {
        self.ok_response_with_cookies(json, None)
    }

    fn wire<'b>(&self, router: &'b mut Router);
}

#[cfg(test)]
mod tests {
    use router::Router;
    use serde_json;

    use blockchain::Block;
    use crypto::Hash;

    use super::*;

    #[test]
    fn test_json_response_for_complex_val() {
        let str_val = "sghdkgskgskldghshgsd";
        let complex_val = Block::new(24,
                                     2,
                                     &Hash::new([24; 32]),
                                     &Hash::new([34; 32]),
                                     &Hash::new([38; 32]));
        struct SampleAPI;
        impl Api for SampleAPI {
            fn wire<'b>(&self, _: &'b mut Router) {
                return;
            }
        }
        let stub = SampleAPI;
        let result = stub.ok_response(&serde_json::to_value(str_val).unwrap());
        assert!(result.is_ok());
        let result = stub.ok_response(&serde_json::to_value(&complex_val).unwrap());
        assert!(result.is_ok());
        print!("{:?}", result);
    }
}
<|endoftext|>


<commit_before>fn main() {
    let input = include_str!("day5.txt");

    let mut total = 0;

    for line in input.lines() {
        if two_letters_twice(line) && two_with_one_between(line) {
            total += 1;
        }
    }

    println!("{}", total);
}

fn two_letters_twice(line: &str) -> bool {
    let chars: Vec<_> = line.chars().collect();
    let chars2: Vec<_> = line.chars().skip(1).collect();

    let size = chars.len();

    let mut i = 0;
    for (c1, c2) in chars.iter().zip(chars2.iter()) {
        let j = i + 2;

        if j > size - 1 {
            break;
        }

        for n in j..(size - 1) {
            if &chars[n] == c1 && &chars[n + 1] == c2 {
                return true
            }
        }

        i += 1;
    }

    false
}

fn two_with_one_between(line: &str) -> bool {
    let chars1: Vec<_> = line.chars().collect();
    let chars2: Vec<_> = line.chars().skip(2).collect();

    for (c1, c2) in chars1.iter().zip(chars2.iter()) {
        if c1 == c2 {
            return true
        }
    }

    false
}
<commit_msg>add comments on day5-2.rs<commit_after>fn main() {
    let input = include_str!("day5.txt");

    let mut total = 0;

    for line in input.lines() {
        if two_letters_twice(line) && two_with_one_between(line) {
            total += 1;
        }
    }

    println!("{}", total);
}

fn two_letters_twice(line: &str) -> bool {
    let chars: Vec<_> = line.chars().collect();
    let chars2: Vec<_> = line.chars().skip(1).collect();

    let size = chars.len();

    let mut i = 0;
    for (c1, c2) in chars.iter().zip(chars2.iter()) {
        // start inner loop two position ahead of outer loop
        let j = i + 2;

        // break if out of bounds
        if j > size - 1 {
            break;
        }

        for n in j..(size - 1) {
            if &chars[n] == c1 && &chars[n + 1] == c2 {
                return true
            }
        }

        i += 1;
    }

    false
}

fn two_with_one_between(line: &str) -> bool {
    let chars1: Vec<_> = line.chars().collect();
    let chars2: Vec<_> = line.chars().skip(2).collect();

    for (c1, c2) in chars1.iter().zip(chars2.iter()) {
        if c1 == c2 {
            return true
        }
    }

    false
}
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate hashids;

use hashids::HashIds;

#[test]
fn it_works_1() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![12345];
  let encode = ids.encode(&numbers);
  let longs = ids.decode(encode.clone());

  assert_eq!(numbers, longs);
}

#[test]
fn it_works_2() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![12345];
  let encode = ids.encode(&numbers);

  let ids_some2 = HashIds::new_with_salt("this is my pepper".to_string());
  let ids2 = match ids_some2 {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let longs = ids2.decode(encode.clone());

  assert_eq!(longs.len(), 0);
}

#[test]
fn it_works_3() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![683, 94108, 123, 5];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "aBMswoO2UB3Sj");
}

#[test]
fn it_works_4() {
  let ids_some = HashIds::new_with_salt_and_min_length("this is my salt".to_string(), 8);
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "gB0NV05e");
}

#[test]
fn it_works_5() {
  let ids_some = HashIds::new("this is my salt".to_string(), 0, "0123456789abcdef".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1234567];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "b332db5");
}

#[test]
fn it_works_6() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![5, 5, 5, 5];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "1Wc8cwcE");
}

#[test]
fn it_works_7() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "kRHnurhptKcjIDTWC3sx");
}

#[test]
fn it_works_8() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(e) => {
      println!("error");
      return;
    }
  };

  let numbers_1: Vec<i64> = vec![1];
  let encode_1 = ids.encode(&numbers_1);
  let numbers_2: Vec<i64> = vec![2];
  let encode_2 = ids.encode(&numbers_2);
  let numbers_3: Vec<i64> = vec![3];
  let encode_3 = ids.encode(&numbers_3);
  let numbers_4: Vec<i64> = vec![4];
  let encode_4 = ids.encode(&numbers_4);
  let numbers_5: Vec<i64> = vec![5];
  let encode_5 = ids.encode(&numbers_5);

  assert_eq!(encode_1, "NV");
  assert_eq!(encode_2, "6m");
  assert_eq!(encode_3, "yD");
  assert_eq!(encode_4, "2l");
  assert_eq!(encode_5, "rD");
}
<commit_msg>Fix warnings in unit test<commit_after>extern crate hashids;

use hashids::HashIds;

#[test]
fn it_works_1() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![12345];
  let encode = ids.encode(&numbers);
  let longs = ids.decode(encode.clone());

  assert_eq!(numbers, longs);
}

#[test]
fn it_works_2() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![12345];
  let encode = ids.encode(&numbers);

  let ids_some2 = HashIds::new_with_salt("this is my pepper".to_string());
  let ids2 = match ids_some2 {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let longs = ids2.decode(encode.clone());

  assert_eq!(longs.len(), 0);
}

#[test]
fn it_works_3() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![683, 94108, 123, 5];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "aBMswoO2UB3Sj");
}

#[test]
fn it_works_4() {
  let ids_some = HashIds::new_with_salt_and_min_length("this is my salt".to_string(), 8);
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "gB0NV05e");
}

#[test]
fn it_works_5() {
  let ids_some = HashIds::new("this is my salt".to_string(), 0, "0123456789abcdef".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1234567];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "b332db5");
}

#[test]
fn it_works_6() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![5, 5, 5, 5];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "1Wc8cwcE");
}

#[test]
fn it_works_7() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers: Vec<i64> = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  let encode = ids.encode(&numbers);

  assert_eq!(encode, "kRHnurhptKcjIDTWC3sx");
}

#[test]
fn it_works_8() {
  let ids_some = HashIds::new_with_salt("this is my salt".to_string());
  let ids = match ids_some {
    Ok(v) => { v }
    Err(_) => {
      println!("error");
      return;
    }
  };

  let numbers_1: Vec<i64> = vec![1];
  let encode_1 = ids.encode(&numbers_1);
  let numbers_2: Vec<i64> = vec![2];
  let encode_2 = ids.encode(&numbers_2);
  let numbers_3: Vec<i64> = vec![3];
  let encode_3 = ids.encode(&numbers_3);
  let numbers_4: Vec<i64> = vec![4];
  let encode_4 = ids.encode(&numbers_4);
  let numbers_5: Vec<i64> = vec![5];
  let encode_5 = ids.encode(&numbers_5);

  assert_eq!(encode_1, "NV");
  assert_eq!(encode_2, "6m");
  assert_eq!(encode_3, "yD");
  assert_eq!(encode_4, "2l");
  assert_eq!(encode_5, "rD");
}
<|endoftext|>


<commit_before>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn query_result() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    Connection::with_parent(&env).warning_as_error().unwrap();
}

#[test]
fn wrong_datasource() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"DoesntExist".as_ref(), b"".as_ref(), b"".as_ref())
        .map_error(|_| ())
        .warning_as_error()
        .unwrap_err();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();

    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"DoesntExist".as_ref(), b"".as_ref(), b"".as_ref());
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics Diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres_u() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"travis_ci_test".as_ref(),
                 b"postgres".as_ref(),
                 b"".as_ref())
        .map_error(|_| ())
        .warning_as_error()
        .unwrap();
}
<commit_msg>add helper function to test suite<commit_after>extern crate odbc_sys;
extern crate odbc_safe;

use odbc_safe::*;

#[test]
fn query_result() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    Connection::with_parent(&env).warning_as_error().unwrap();
}

#[test]
fn wrong_datasource() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"DoesntExist".as_ref(), b"".as_ref(), b"".as_ref())
        .map_error(|_| ())
        .warning_as_error()
        .unwrap_err();
}

#[test]
fn diagnostics() {

    let expected = if cfg!(target_os = "windows") {
        "[Microsoft][ODBC Driver Manager] Data source name not found and no default driver \
         specified"
    } else {
        "[unixODBC][Driver Manager]Data source name not found, and no default driver specified"
    };

    use std::str;

    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();

    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"DoesntExist".as_ref(), b"".as_ref(), b"".as_ref());
    if let Error(d) = dbc {
        let mut message = [0; 512];
        match d.diagnostics(1, &mut message) {
            DiagReturn::Success(rec) => {
                let message = str::from_utf8(&mut message[..(rec.text_length as usize)]).unwrap();
                assert_eq!(expected, message);
            }
            _ => panic!("Error retriving diagnostics Diagnostics"),
        }
    }
}

#[cfg_attr(not(feature = "travis"), ignore)]
#[test]
fn connect_to_postgres_u() {
    let env = Environment::allocate().warning_as_error().unwrap();
    let env: Environment<Odbc3> = env.declare_version().warning_as_error().unwrap();
    let dbc = Connection::with_parent(&env).warning_as_error().unwrap();
    let dbc = dbc.connect(b"travis_ci_test".as_ref(),
                 b"postgres".as_ref(),
                 b"".as_ref())
        .map_error(|_| ())
        .warning_as_error()
        .unwrap();
}

/// Checks for a diagnstic record. Should one be present this function pancis printing the contents
/// of said record.
fn panic_with_diagnostic(diag: &Diagnostics){
    use std::str;
    let mut buffer = [0;512];
    match diag.diagnostics(0, &mut buffer){
        DiagReturn::Success(dr) | DiagReturn::Info(dr) =>{
            panic!("{}", str::from_utf8(&buffer[0..(dr.text_length as usize)]).unwrap())
        },
        DiagReturn::Error => panic!("Error during fetching diagnostic record"),
        DiagReturn::NoData => (),
    }
}<|endoftext|>


<commit_before>#![feature(rustc_private, custom_derive, plugin)]
#![plugin(derive_more)]

extern crate syntax;
use syntax::codemap;

#[derive(Eq, PartialEq, Debug)]
#[derive(Add, Mul)]
struct MyInt(u32, u32);

#[derive(Eq, PartialEq, Debug)]
#[derive(Add, Mul)]
struct MyStruct{x:u32, y:u32}

#[test]
fn main() {
    assert_eq!(MyInt(5, 6) * 10, MyInt(50, 60));
    assert_eq!(MyStruct{x:5, y:6} * 10, MyStruct{x:50, y:60});
}
<commit_msg>Add old tests again<commit_after>#![feature(rustc_private, custom_derive, plugin)]
#![plugin(derive_more)]

extern crate syntax;
use syntax::codemap;

#[derive(From)]
#[derive(Eq, PartialEq, Debug)]
#[derive(Add)]
struct MyInt(i32);

#[derive(Add)]
#[derive(Eq, PartialEq, Debug)]
struct MyUInt(u64, u64);

#[derive(Add, Sub, Mul, Div, Rem, BitAnd, BitOr, BitXor)]
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
struct NormalStruct{int1: u64, int2: u64}

#[derive(From)]
//#[derive(Eq, PartialEq, Debug)]
struct NestedInt(MyInt);

#[derive(From)]
//#[derive(Eq, PartialEq, Debug)]
struct MySpan(codemap::Span);

#[derive(From)]
//#[derive(Eq, PartialEq, Debug)]
struct MySpan2(::syntax::codemap::Span);

#[derive(Eq, PartialEq, Debug)]
#[derive(From)]
#[derive(Add,Sub)]
enum SimpleMyIntEnum{
    Int(i32),
    UnsignedOne(u32),
    UnsignedTwo(u32),
}

#[derive(Eq, PartialEq, Debug)]
#[derive(From)]
#[derive(Add)]
enum SimpleEnum{
    Int(i32),
    Ints(i32, i32),
    LabeledInts{a: i32, b: i32},
    SomeUnit,
}

#[derive(Eq, PartialEq, Debug)]
#[derive(From, Add)]
enum MyIntEnum{
    SmallInt(i32),
    BigInt(i64),
    TwoInts(i32, i32),
    UnsignedOne(u32),
    UnsignedTwo(u32),
    Nothing,
}

#[derive(Eq, PartialEq, Debug)]
#[derive(Add, Mul)]
struct DoubleUInt(u32, u32);

#[derive(Eq, PartialEq, Debug)]
#[derive(Add, Mul)]
struct DoubleUIntStruct{x:u32, y:u32}

#[test]
fn main() {
    assert_eq!(MyInt(5), 5.into());
    assert_eq!(MyIntEnum::SmallInt(5), 5.into());

    assert_eq!(MyInt(4) + MyInt(1), 5.into());
    assert_eq!(MyUInt(4, 5) + MyUInt(1, 2), MyUInt(5, 7));
    let s1 = NormalStruct{int1: 1, int2: 2};
    let s2 = NormalStruct{int1: 2, int2: 3};
    let s3 = NormalStruct{int1: 3, int2: 5};
    assert_eq!(s1 + s2, s3);
    assert_eq!(s3 - s2, s1);
    assert_eq!((SimpleMyIntEnum::Int(6) + 5.into()).unwrap(), 11.into());
    assert_eq!((SimpleMyIntEnum::Int(6) - 5.into()).unwrap(), 1.into());
    assert_eq!((SimpleEnum::Ints(6, 5) + SimpleEnum::Ints(1, 4)).unwrap(), SimpleEnum::Ints(7, 9));
    assert_eq!((SimpleEnum::LabeledInts{a: 6, b: 5} + SimpleEnum::LabeledInts{a: 1, b: 4}).unwrap(),
               SimpleEnum::LabeledInts{a: 7, b: 9});

    let my_enum_val = (MyIntEnum::SmallInt(5) + 6.into()).unwrap();

    assert_eq!(DoubleUInt(5, 6) * 10, DoubleUInt(50, 60));
    assert_eq!(DoubleUIntStruct{x:5, y:6} * 10, DoubleUIntStruct{x:50, y:60});
}
<|endoftext|>


<commit_before>extern crate cron;
extern crate chrono;

#[cfg(test)]
mod tests {
    use cron::Schedule;
    use std::str::FromStr;
    use chrono::*;

    #[test]
    fn test_readme() {
        let expression = "0   30   9,12,15     1,15       May-Aug  Mon,Wed,Fri  2018/2";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("README: Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(10) {
            println!("README: -> {}", datetime);
        }
    }

    #[test]
    fn test_anything_goes() {
        let expression = "* * * * * * *";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("All stars: Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(10) {
            println!("All stars: -> {}", datetime);
        }
    }

    #[test]
    fn test_parse_with_year() {
        let expression = "1 2 3 4 5 6 2015";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_with_seconds_list() {
        let expression = "1,30,40 2 3 4 5 Mon-Fri";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_with_lists() {
        let expression = "1 2,17,51 1-3,6,9-11 4,29 2,3,7 Tues";
        let schedule = Schedule::from_str(expression).unwrap();
        let mut date = UTC::now();
        println!("Fire times for {}:", expression);
        for _ in 0..20 {
            date = schedule.after(&date).next().expect("No further dates!");
            println!("-> {}", date);
        }
        assert!(true);
    }

    #[test]
    fn test_upcoming_iterator() {
        let expression = "0 2,17,51 1-3,6,9-11 4,29 2,3,7 Wed";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(12) {
            println!("-> {}", datetime);
        }
        assert!(true);
    }

    #[test]
    fn test_parse_without_year() {
        let expression = "1 2 3 4 5 6";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_too_many_fields() {
        let expression = "1 2 3 4 5 6 7 8 9 2019";
        assert!(Schedule::from_str(expression).is_err());
    }

    #[test]
    fn test_not_enough_fields() {
        let expression = "1 2 3 2019";
        assert!(Schedule::from_str(expression).is_err());
    }

    #[test]
    fn test_next_utc() {
        let expression = "1 2 3 4 10 Fri";
        let schedule = Schedule::from_str(expression).unwrap();
        let next = schedule.upcoming(UTC).next().expect("There was no upcoming fire time.");
        println!("Next fire time: {}", next.to_rfc3339());
    }

    #[test]
    fn test_yearly() {
        let expression = "@yearly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @yearly.");
        let starting_date = UTC.ymd(2017, 6, 15).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2019, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_monthly() {
        let expression = "@monthly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @monthly.");
        let starting_date = UTC.ymd(2017, 10, 15).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2017, 11, 1).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 12, 1).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_weekly() {
        let expression = "@weekly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @weekly.");
        let starting_date = UTC.ymd(2016, 12, 23).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2016, 12, 25).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 8).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_daily() {
        let expression = "@daily";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @daily.");
        let starting_date = UTC.ymd(2016, 12, 29).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2016, 12, 30).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2016, 12, 31).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_hourly() {
        let expression = "@hourly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @hourly.");
        let starting_date = UTC.ymd(2017, 2, 25).and_hms(22, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2017, 2, 25).and_hms(23, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 2, 26).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 2, 26).and_hms(1, 0, 0),
                   events.next().unwrap());
    }
}
<commit_msg>Additional test.<commit_after>extern crate cron;
extern crate chrono;

#[cfg(test)]
mod tests {
    use cron::Schedule;
    use std::str::FromStr;
    use chrono::*;

    #[test]
    fn test_readme() {
        let expression = "0   30   9,12,15     1,15       May-Aug  Mon,Wed,Fri  2018/2";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("README: Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(10) {
            println!("README: -> {}", datetime);
        }
    }

    #[test]
    fn test_anything_goes() {
        let expression = "* * * * * * *";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("All stars: Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(10) {
            println!("All stars: -> {}", datetime);
        }
    }

    #[test]
    fn test_parse_with_year() {
        let expression = "1 2 3 4 5 6 2015";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_with_seconds_list() {
        let expression = "1,30,40 2 3 4 5 Mon-Fri";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_with_lists() {
        let expression = "1 2,17,51 1-3,6,9-11 4,29 2,3,7 Tues";
        let schedule = Schedule::from_str(expression).unwrap();
        let mut date = UTC::now();
        println!("Fire times for {}:", expression);
        for _ in 0..20 {
            date = schedule.after(&date).next().expect("No further dates!");
            println!("-> {}", date);
        }
        assert!(true);
    }

    #[test]
    fn test_upcoming_iterator() {
        let expression = "0 2,17,51 1-3,6,9-11 4,29 2,3,7 Wed";
        let schedule = Schedule::from_str(expression).unwrap();
        println!("Upcoming fire times for '{}':", expression);
        for datetime in schedule.upcoming(UTC).take(12) {
            println!("-> {}", datetime);
        }
        assert!(true);
    }

    #[test]
    fn test_parse_without_year() {
        let expression = "1 2 3 4 5 6";
        assert!(Schedule::from_str(expression).is_ok());
    }

    #[test]
    fn test_parse_too_many_fields() {
        let expression = "1 2 3 4 5 6 7 8 9 2019";
        assert!(Schedule::from_str(expression).is_err());
    }

    #[test]
    fn test_not_enough_fields() {
        let expression = "1 2 3 2019";
        assert!(Schedule::from_str(expression).is_err());
    }

    #[test]
    fn test_next_utc() {
        let expression = "1 2 3 4 10 Fri";
        let schedule = Schedule::from_str(expression).unwrap();
        let next = schedule.upcoming(UTC).next().expect("There was no upcoming fire time.");
        println!("Next fire time: {}", next.to_rfc3339());
    }

    #[test]
    fn test_yearly() {
        let expression = "@yearly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @yearly.");
        let starting_date = UTC.ymd(2017, 6, 15).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2019, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2020, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_monthly() {
        let expression = "@monthly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @monthly.");
        let starting_date = UTC.ymd(2017, 10, 15).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2017, 11, 1).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 12, 1).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_weekly() {
        let expression = "@weekly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @weekly.");
        let starting_date = UTC.ymd(2016, 12, 23).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2016, 12, 25).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 8).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_daily() {
        let expression = "@daily";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @daily.");
        let starting_date = UTC.ymd(2016, 12, 29).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2016, 12, 30).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2016, 12, 31).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
    }

    #[test]
    fn test_hourly() {
        let expression = "@hourly";
        let schedule = Schedule::from_str(expression).expect("Failed to parse @hourly.");
        let starting_date = UTC.ymd(2017, 2, 25).and_hms(22, 29, 36);
        let mut events = schedule.after(&starting_date);
        assert_eq!(UTC.ymd(2017, 2, 25).and_hms(23, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 2, 26).and_hms(0, 0, 0),
                   events.next().unwrap());
        assert_eq!(UTC.ymd(2017, 2, 26).and_hms(1, 0, 0),
                   events.next().unwrap());
    }

    #[test]
    fn test_step_schedule() {
        let expression = "0/20 0/5 0 1 1 * *";
        let schedule = Schedule::from_str(expression).expect("Failed to parse expression.");
        let starting_date = UTC.ymd(2017, 6, 15).and_hms(14, 29, 36);
        let mut events = schedule.after(&starting_date);

        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 20), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 0, 40), events.next().unwrap());

        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 5, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 5, 20), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 5, 40), events.next().unwrap());

        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 10, 0), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 10, 20), events.next().unwrap());
        assert_eq!(UTC.ymd(2018, 1, 1).and_hms(0, 10, 40), events.next().unwrap());
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      let mut i = 0;
      for chunk in self.chunks(chunk_size) {
        let s = format!("{:08x}", i);
        let s2: &str = &s;
        for &ch in s.as_bytes().iter() {
          v.push(ch);
        }
        v.push('\t' as u8);

        i = i + chunk_size;

        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

take!(offset_parser 4);
fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      println!("size: {:08x}", offset);
      let sz: usize = offset as usize;
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Error(42)//Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}
take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8],&str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], FileType> {
  //FIXME: flat_map should work here
  //mp4_box(input).flat_map(filetype)
  match mp4_box(input) {
    Done(i, o) => {
      match filetype(o) {
        Done(i2, o2) => {
          Done(i, o2)
        },
        a => a
      }
    },
    a => Error(0)
  }
}

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 100).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        println!("bytes:\n{}", bytes.to_hex(8));
        match filetype_box(bytes) {
          Done(i, o) => {
            println!("parsed: {:?}\n{}", o, i.to_hex(8))
          },
          a => println!("error: {:?}", a)
        }
      },
      _ => println!("got error")
    }
    /*//p.push(|par| {println!("parsed file: {}", par); par});
    //p.push(|par| par.flat_map(print));
    fn pr<'a,'b,'c>(data: &[u8]) -> IResult<'b,&[u8], &[u8]> {
      println!("bytes: {:?}", &data[0..20]);
      //Done("".as_bytes(), data).map_res(str::from_utf8);
      Done("".as_bytes(),"".as_bytes())
    }
    pusher!(ps, pr);
    ps(&mut p);
    */
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>prepare for parsing multiple boxes<commit_after>#[macro_use]
extern crate nom;
//extern crate serialize;

use nom::{IResult,FlatMapper,Mapper,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;
use std::collections::HashMap;
//use serialize::hex::ToHex;

pub trait HexDisplay {
      /// Converts the value of `self` to a hex value, returning the owned
      ///     /// string.
  fn to_hex(&self, chunk_size: usize) -> String;
}

static CHARS: &'static[u8] = b"0123456789abcdef";

impl HexDisplay for [u8] {
    fn to_hex(&self, chunk_size: usize) -> String {
      let mut v = Vec::with_capacity(self.len() * 3);
      let mut i = 0;
      for chunk in self.chunks(chunk_size) {
        let s = format!("{:08x}", i);
        let s2: &str = &s;
        for &ch in s.as_bytes().iter() {
          v.push(ch);
        }
        v.push('\t' as u8);

        i = i + chunk_size;

        for &byte in chunk {
          v.push(CHARS[(byte >> 4) as usize]);
          v.push(CHARS[(byte & 0xf) as usize]);
          v.push(' ' as u8);
        }
        if chunk_size > chunk.len() {
          for i in 0..(chunk_size - chunk.len()) {
            v.push(' ' as u8);
            v.push(' ' as u8);
            v.push(' ' as u8);
          }
        }
        v.push('\t' as u8);

        for &byte in chunk {
          if (byte >=32 && byte <= 126) || byte >= 128 {
            v.push(byte);
          } else {
            v.push('.' as u8);
          }
        }
        v.push('\n' as u8);
      }

      unsafe {
        String::from_utf8_unchecked(v)
      }
    }
}

take!(offset_parser 4);
fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      if i.len() >= sz {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Error(42)//Incomplete(0)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov,
  Free
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8],&str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input, ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}},
    m: brand_name,
    v: major_brand_version,
    c: compatible_brands,)
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  //FIXME: flat_map should work here
  //mp4_box(input).flat_map(filetype)
  match mp4_box(input) {
    Done(i, o) => {
      match filetype(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Ftyp(o2))
        },
        a => Error(0)
      }
    },
    a => Error(0)
  }
}

tag!(free    "ftyp".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match mp4_box(input) {
    Done(i, o) => {
      match free(o) {
        Done(i2, o2) => {
          Done(i, MP4Box::Free)
        },
        a => Error(0)
      }
    },
    a => Error(0)
  }
}

alt!(box_parser<&[u8], MP4Box>, filetype_box | free_box);

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 100).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        println!("bytes:\n{}", bytes.to_hex(8));
        match filetype_box(bytes) {
          Done(i, o) => {
            match o {
              MP4Box::Ftyp(f) => println!("parsed ftyp: {:?}", f),
              MP4Box::Moov    => println!("found moov box"),
              MP4Box::Free    => println!("found free box")
            }
            println!("remaining:\n{}", i.to_hex(8))
          },
          a => println!("error: {:?}", a)
        }
      },
      _ => println!("got error")
    }
    /*//p.push(|par| {println!("parsed file: {}", par); par});
    //p.push(|par| par.flat_map(print));
    fn pr<'a,'b,'c>(data: &[u8]) -> IResult<'b,&[u8], &[u8]> {
      println!("bytes: {:?}", &data[0..20]);
      //Done("".as_bytes(), data).map_res(str::from_utf8);
      Done("".as_bytes(),"".as_bytes())
    }
    pusher!(ps, pr);
    ps(&mut p);
    */
    assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<|endoftext|>