<commit_before>#![feature(test)]

extern crate test;
extern crate typedb;

use typedb::{Value, KV};

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

    macro_rules! bench_teardown {
        ($p:ident) => {
            use std::{thread, time};

            thread::sleep(time::Duration::from_secs(2));
            let _ = std::fs::remove_file($p);
        };
    }

    #[bench]
    fn bench_get_int(b: &mut Bencher) {
        let test_cab_path = "./bench_get_many.cab";
        let mut test_store = KV::<String, Value>::new(test_cab_path).unwrap();

        let _ = test_store.insert("test".to_string(), Value::Int(1));

        let test_as_string = "test".to_string();
        b.iter(|| {
            let _ = test_store.get(&test_as_string);
        });

        bench_teardown!(test_cab_path);
    }

    #[bench]
    fn bench_insert_int(b: &mut Bencher) {
        let test_cab_path = "./bench_insert_many.cab";
        let mut test_store = KV::<String, Value>::new(test_cab_path).unwrap();

        b.iter(|| {
            let _ = test_store.insert("test".to_string(), Value::Int(1));
        });

        bench_teardown!(test_cab_path);
    }
}
<commit_msg>Add benchmark for insert+get<commit_after>#![feature(test)]

extern crate test;
extern crate typedb;

use typedb::{Value, KV};

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

    macro_rules! bench_teardown {
        ($p:ident) => {
            use std::{thread, time};

            thread::sleep(time::Duration::from_secs(2));
            let _ = std::fs::remove_file($p);
        };
    }

    #[bench]
    fn bench_get_int(b: &mut Bencher) {
        let test_cab_path = "./bench_get_many.cab";
        let mut test_store = KV::<String, Value>::new(test_cab_path).unwrap();

        let _ = test_store.insert("test".to_string(), Value::Int(1));

        let test_as_string = "test".to_string();
        b.iter(|| {
            let _ = test_store.get(&test_as_string);
        });

        bench_teardown!(test_cab_path);
    }

    #[bench]
    fn bench_insert_int(b: &mut Bencher) {
        let test_cab_path = "./bench_insert_many.cab";
        let mut test_store = KV::<String, Value>::new(test_cab_path).unwrap();

        b.iter(|| {
            let _ = test_store.insert("test".to_string(), Value::Int(1));
        });

        bench_teardown!(test_cab_path);
    }

    #[bench]
    fn bench_insert_get_int(b: &mut Bencher) {
        let test_cab_path = "./bench_insert_get_many.cab";
        let mut test_store = KV::<String, Value>::new(test_cab_path).unwrap();
        let test_as_string = "test".to_string();

        b.iter(|| {
            let _ = test_store.insert(test_as_string.clone(), Value::Int(1));
            let _ = test_store.get(&test_as_string);
        });

        bench_teardown!(test_cab_path);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use criterion::{
    AxisScale, Bencher, Criterion, ParameterizedBenchmark, PlotConfiguration, Throughput,
};
use rand::{Rng, RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
use tempfile::TempDir;

use exonum_crypto::Hash;
use exonum_merkledb::{
    proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE, Database, DbOptions, ProofListIndex,
    ProofMapIndex, RocksDB,
};

const NAME: &str = "name";
const SAMPLE_SIZE: usize = 20;
const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];
const ITEM_COUNTS: [usize; 3] = [1_000, 10_000, 100_000];

fn generate_random_kv(len: usize) -> Vec<(Hash, Vec<u8>)> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut exists_keys = HashSet::new();
    let mut base = [0; KEY_SIZE];
    rng.fill_bytes(&mut base);
    let base = base;

    let kv_generator = |_| {
        let mut v = vec![0; CHUNK_SIZE];
        // Generate only unique keys.
        let mut k = base;
        let byte: usize = rng.gen_range(0, 31);
        k[byte] = rng.gen::<u8>();

        rng.fill_bytes(&mut v);
        while exists_keys.contains(&k) {
            rng.fill_bytes(&mut k);
        }
        exists_keys.insert(k);
        (Hash::new(k), v)
    };

    (0..len).map(kv_generator).collect::<Vec<_>>()
}

fn proof_list_append(b: &mut Bencher, db: &dyn Database, len: usize) {
    let mut rng = XorShiftRng::from_seed(SEED);
    let data = (0..len)
        .map(|_| {
            let mut chunk = vec![0; CHUNK_SIZE];
            rng.fill_bytes(&mut chunk);
            chunk
        })
        .collect::<Vec<_>>();

    b.iter_with_setup(
        || db.fork(),
        |mut storage| {
            let mut table = ProofListIndex::new(NAME, &mut storage);
            assert!(table.is_empty());
            for item in &data {
                table.push(item.clone());
            }
        },
    );
}

fn proof_map_insert_without_merge(b: &mut Bencher, db: &dyn Database, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || db.fork(),
        |mut storage| {
            let mut table = ProofMapIndex::new(NAME, &mut storage);
            assert!(table.keys().next().is_none());
            for item in &data {
                table.put(&item.0, item.1.clone());
            }
        },
    );
}

fn proof_map_insert_with_merge(b: &mut Bencher, db: &dyn Database, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || {
            let mut fork = db.fork();
            {
                let mut table: ProofMapIndex<_, Hash, Vec<u8>> =
                    ProofMapIndex::new(NAME, &mut fork);
                table.clear();
            }
            db.merge(fork.into_patch()).unwrap();
        },
        |_| {
            let mut fork = db.fork();
            {
                let mut table = ProofMapIndex::new(NAME, &mut fork);
                assert!(table.keys().next().is_none());
                for item in &data {
                    table.put(&item.0, item.1.clone());
                }
            }
            db.merge(fork.into_patch()).unwrap();
        },
    );
}

fn proof_map_index_build_proofs(b: &mut Bencher, db: &dyn Database, len: usize) {
    let data = generate_random_kv(len);
    let mut storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &mut storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let mut proofs = Vec::with_capacity(data.len());

    b.iter(|| {
        proofs.clear();
        proofs.extend(data.iter().map(|item| table.get_proof(item.0)));
    });

    for (i, proof) in proofs.into_iter().enumerate() {
        let checked_proof = proof.check().unwrap();
        assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
        assert_eq!(checked_proof.merkle_root(), table_merkle_root);
    }
}

fn proof_map_index_verify_proofs(b: &mut Bencher, db: &dyn Database, len: usize) {
    let data = generate_random_kv(len);
    let mut storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &mut storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let proofs: Vec<_> = data.iter().map(|item| table.get_proof(item.0)).collect();

    b.iter(|| {
        for (i, proof) in proofs.iter().enumerate() {
            let checked_proof = proof.clone().check().unwrap();
            assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
            assert_eq!(checked_proof.merkle_root(), table_merkle_root);
        }
    });
}

fn bench_fn_rocksdb<F>(c: &mut Criterion, name: &str, benchmark: F)
where
    F: Fn(&mut Bencher, &dyn Database, usize) + 'static,
{
    let item_counts = ITEM_COUNTS.iter().cloned();
    c.bench(
        name,
        ParameterizedBenchmark::new(
            "items",
            move |b: &mut Bencher, &len: &usize| {
                let tempdir = TempDir::new().unwrap();
                let options = DbOptions::default();
                let db = RocksDB::open(tempdir.path(), &options).unwrap();
                benchmark(b, &db, len)
            },
            item_counts,
        )
        .throughput(|s| Throughput::Elements(*s as u32))
        .plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic))
        .sample_size(SAMPLE_SIZE),
    );
}

pub fn bench_storage(c: &mut Criterion) {
    exonum_crypto::init();

    bench_fn_rocksdb(c, "proof_list/append", proof_list_append);
    bench_fn_rocksdb(
        c,
        "proof_map/insert/no_merge",
        proof_map_insert_without_merge,
    );
    bench_fn_rocksdb(c, "proof_map/insert/merge", proof_map_insert_with_merge);
    bench_fn_rocksdb(c, "proof_map/proofs/build", proof_map_index_build_proofs);
    bench_fn_rocksdb(
        c,
        "proof_map/proofs/validate",
        proof_map_index_verify_proofs,
    );
}
<commit_msg>Improve setup perfomance<commit_after>// Copyright 2018 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashSet;

use criterion::{
    AxisScale, Bencher, Criterion, ParameterizedBenchmark, PlotConfiguration, Throughput,
};
use rand::{Rng, RngCore, SeedableRng};
use rand_xorshift::XorShiftRng;
use tempfile::TempDir;

use exonum_crypto::Hash;
use exonum_merkledb::{
    proof_map_index::PROOF_MAP_KEY_SIZE as KEY_SIZE, Database, DbOptions, ProofListIndex,
    ProofMapIndex, RocksDB,
};

const NAME: &str = "name";
const SAMPLE_SIZE: usize = 10;
const CHUNK_SIZE: usize = 64;
const SEED: [u8; 16] = [100; 16];
const ITEM_COUNTS: [usize; 3] = [1_000, 10_000, 100_000];

trait DatabaseFactory: Sized {
    fn create(&mut self) -> Box<dyn Database>;
}

struct RocksdbDatabaseFactory(Option<TempDir>);

impl Default for RocksdbDatabaseFactory {
    fn default() -> Self {
        RocksdbDatabaseFactory(None)
    }
}

impl DatabaseFactory for RocksdbDatabaseFactory {
    fn create(&mut self) -> Box<dyn Database> {
        if let Some(dir) = self.0.take() {
            dir.close().unwrap();
        }

        let dir = TempDir::new().unwrap();
        let options = DbOptions::default();
        let db = RocksDB::open(dir.path(), &options).unwrap();
        self.0 = Some(dir);
        Box::new(db)
    }
}

fn generate_random_kv(len: usize) -> Vec<(Hash, Vec<u8>)> {
    let mut rng = XorShiftRng::from_seed(SEED);
    let mut exists_keys = HashSet::new();
    let mut base = [0; KEY_SIZE];
    rng.fill_bytes(&mut base);
    let base = base;

    let kv_generator = |_| {
        let mut v = vec![0; CHUNK_SIZE];
        // Generate only unique keys.
        let mut k = base;
        let byte: usize = rng.gen_range(0, 31);
        k[byte] = rng.gen::<u8>();

        rng.fill_bytes(&mut v);
        while exists_keys.contains(&k) {
            rng.fill_bytes(&mut k);
        }
        exists_keys.insert(k);
        (Hash::new(k), v)
    };

    (0..len).map(kv_generator).collect::<Vec<_>>()
}

fn proof_list_append(b: &mut Bencher, mut factory: impl DatabaseFactory, len: usize) {
    let mut rng = XorShiftRng::from_seed(SEED);
    let data = (0..len)
        .map(|_| {
            let mut chunk = vec![0; CHUNK_SIZE];
            rng.fill_bytes(&mut chunk);
            chunk
        })
        .collect::<Vec<_>>();

    let db = factory.create();
    b.iter_with_setup(
        || db.fork(),
        |mut storage| {
            let mut table = ProofListIndex::new(NAME, &mut storage);
            assert!(table.is_empty());
            for item in &data {
                table.push(item.clone());
            }
        },
    );
}

fn proof_map_insert_without_merge(b: &mut Bencher, mut factory: impl DatabaseFactory, len: usize) {
    let data = generate_random_kv(len);
    let db = factory.create();
    b.iter_with_setup(
        || db.fork(),
        |mut storage| {
            let mut table = ProofMapIndex::new(NAME, &mut storage);
            assert!(table.keys().next().is_none());
            for item in &data {
                table.put(&item.0, item.1.clone());
            }
        },
    );
}

fn proof_map_insert_with_merge(b: &mut Bencher, mut factory: impl DatabaseFactory, len: usize) {
    let data = generate_random_kv(len);
    b.iter_with_setup(
        || factory.create(),
        |db| {
            let mut fork = db.fork();
            {
                let mut table = ProofMapIndex::new(NAME, &mut fork);
                assert!(table.keys().next().is_none());
                for item in &data {
                    table.put(&item.0, item.1.clone());
                }
            }
            db.merge(fork.into_patch()).unwrap();
        },
    );
}

fn proof_map_index_build_proofs(b: &mut Bencher, mut factory: impl DatabaseFactory, len: usize) {
    let data = generate_random_kv(len);
    let db = factory.create();
    let mut storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &mut storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let mut proofs = Vec::with_capacity(data.len());

    b.iter(|| {
        proofs.clear();
        proofs.extend(data.iter().map(|item| table.get_proof(item.0)));
    });

    for (i, proof) in proofs.into_iter().enumerate() {
        let checked_proof = proof.check().unwrap();
        assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
        assert_eq!(checked_proof.merkle_root(), table_merkle_root);
    }
}

fn proof_map_index_verify_proofs(b: &mut Bencher, mut factory: impl DatabaseFactory, len: usize) {
    let data = generate_random_kv(len);
    let db = factory.create();
    let mut storage = db.fork();
    let mut table = ProofMapIndex::new(NAME, &mut storage);

    for item in &data {
        table.put(&item.0, item.1.clone());
    }
    let table_merkle_root = table.merkle_root();
    let proofs: Vec<_> = data.iter().map(|item| table.get_proof(item.0)).collect();

    b.iter(|| {
        for (i, proof) in proofs.iter().enumerate() {
            let checked_proof = proof.clone().check().unwrap();
            assert_eq!(*checked_proof.entries().next().unwrap().1, data[i].1);
            assert_eq!(checked_proof.merkle_root(), table_merkle_root);
        }
    });
}

fn bench_fn_rocksdb<F>(c: &mut Criterion, name: &str, benchmark: F)
where
    F: Fn(&mut Bencher, RocksdbDatabaseFactory, usize) + 'static,
{
    let item_counts = ITEM_COUNTS.iter().cloned();
    c.bench(
        name,
        ParameterizedBenchmark::new(
            "items",
            move |b: &mut Bencher, &len: &usize| {
                benchmark(b, RocksdbDatabaseFactory::default(), len)
            },
            item_counts,
        )
        .throughput(|s| Throughput::Elements(*s as u32))
        .plot_config(PlotConfiguration::default().summary_scale(AxisScale::Logarithmic))
        .sample_size(SAMPLE_SIZE),
    );
}

pub fn bench_storage(c: &mut Criterion) {
    exonum_crypto::init();

    bench_fn_rocksdb(c, "proof_list/append", proof_list_append);
    bench_fn_rocksdb(
        c,
        "proof_map/insert/no_merge",
        proof_map_insert_without_merge,
    );
    bench_fn_rocksdb(c, "proof_map/insert/merge", proof_map_insert_with_merge);
    bench_fn_rocksdb(c, "proof_map/proofs/build", proof_map_index_build_proofs);
    bench_fn_rocksdb(
        c,
        "proof_map/proofs/validate",
        proof_map_index_verify_proofs,
    );
}
<|endoftext|>


<commit_before>
extern crate ndarray;
extern crate ndarray_odeint;
extern crate ndarray_numtest;
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::prelude::*;
use ndarray_numtest::prelude::*;

use ndarray_odeint::prelude::*;
use ndarray_odeint::lyapunov::*;

#[test]
fn jacobian_linearity() {
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, 0.01);
    let x0 = rcarr1(&[1.0, 0.0, 0.0]);
    let j = teo.jacobian(x0, 1e-7);
    let v = Array1::real_normal_init(3, 1.0, 1.0);
    let w = Array1::real_normal_init(3, 1.0, 1.0);
    all_close_l2(&(j.dot(&v) + j.dot(&w)), &j.dot(&(v + w)), 1e-5).unwrap();
}

#[test]
fn jacobian_matrix_shape() {
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, 0.01);
    let x0 = rcarr1(&[1.0, 0.0, 0.0]);
    let j = teo.jacobian(x0, 1e-7);
    let v = Array2::real_normal_init((3, 2), 1.0, 1.0);
    let jv = j.dot(&v);
    assert!(jv.shape() == v.shape());
}

#[test]
fn exponents_l63() {
    let dt = 0.01;
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let l = exponents(&teo, rcarr1(&[1.0, 0.0, 0.0]), 1e-7, 100000);
    all_close_max(&l, &arr1(&[0.906, 0.0, -14.572]), 1e-3).unwrap();
    // value from http://sprott.physics.wisc.edu/chaos/lorenzle.htm
}
<commit_msg>Loosen test bound<commit_after>
extern crate ndarray;
extern crate ndarray_odeint;
extern crate ndarray_numtest;
extern crate ndarray_linalg;

use ndarray::*;
use ndarray_linalg::prelude::*;
use ndarray_numtest::prelude::*;

use ndarray_odeint::prelude::*;
use ndarray_odeint::lyapunov::*;

#[test]
fn jacobian_linearity() {
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, 0.01);
    let x0 = rcarr1(&[1.0, 0.0, 0.0]);
    let j = teo.jacobian(x0, 1e-7);
    let v = Array1::real_normal_init(3, 1.0, 1.0);
    let w = Array1::real_normal_init(3, 1.0, 1.0);
    all_close_l2(&(j.dot(&v) + j.dot(&w)), &j.dot(&(v + w)), 1e-5).unwrap();
}

#[test]
fn jacobian_matrix_shape() {
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, 0.01);
    let x0 = rcarr1(&[1.0, 0.0, 0.0]);
    let j = teo.jacobian(x0, 1e-7);
    let v = Array2::real_normal_init((3, 2), 1.0, 1.0);
    let jv = j.dot(&v);
    assert!(jv.shape() == v.shape());
}

#[test]
fn exponents_l63() {
    let dt = 0.01;
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let l = exponents(&teo, rcarr1(&[1.0, 0.0, 0.0]), 1e-7, 100000);
    all_close_max(&l, &arr1(&[0.906, 0.0, -14.572]), 1e-2).unwrap();
    // value from http://sprott.physics.wisc.edu/chaos/lorenzle.htm
}
<|endoftext|>


<commit_before>#![allow(warnings)]

extern crate libc;

pub const MZ_NO_FLUSH: libc::c_int = 0;
pub const MZ_SYNC_FLUSH: libc::c_int = 2;
pub const MZ_FINISH: libc::c_int = 4;

pub const MZ_OK: libc::c_int = 0;
pub const MZ_STREAM_END: libc::c_int = 1;
pub const MZ_NEED_DICT: libc::c_int = 2;
pub const MZ_ERRNO: libc::c_int = -1;
pub const MZ_STREAM_ERROR: libc::c_int = -2;
pub const MZ_DATA_ERROR: libc::c_int = -3;
pub const MZ_MEM_ERROR: libc::c_int = -4;
pub const MZ_BUF_ERROR: libc::c_int = -5;
pub const MZ_VERSION_ERROR: libc::c_int = -6;
pub const MZ_PARAM_ERROR: libc::c_int = -10000;

pub const MZ_DEFLATED: libc::c_int = 8;
pub const MZ_DEFAULT_WINDOW_BITS: libc::c_int = 15;
pub const MZ_DEFAULT_STRATEGY: libc::c_int = 0;

#[repr(C)]
pub struct mz_stream {
    pub next_in: *const u8,
    pub avail_in: libc::c_uint,
    pub total_in: libc::c_ulong,

    pub next_out: *mut u8,
    pub avail_out: libc::c_uint,
    pub total_out: libc::c_ulong,

    pub msg: *const libc::c_char,
    pub state: *mut mz_internal_state,

    pub zalloc: Option<mz_alloc_func>,
    pub zfree: Option<mz_free_func>,
    pub opaque: *mut libc::c_void,

    pub data_type: libc::c_int,
    pub adler: libc::c_ulong,
    pub reserved: libc::c_ulong,
}

pub enum mz_internal_state {}

pub type mz_alloc_func = extern fn(*mut libc::c_void,
                                   libc::size_t,
                                   libc::size_t) -> *mut libc::c_void;
pub type mz_free_func = extern fn(*mut libc::c_void, *mut libc::c_void);

#[link(name = "miniz", kind = "static")]
extern {
    pub fn mz_deflateInit2(stream: *mut mz_stream,
                           level: libc::c_int,
                           method: libc::c_int,
                           window_bits: libc::c_int,
                           mem_level: libc::c_int,
                           strategy: libc::c_int) -> libc::c_int;
    pub fn mz_deflate(stream: *mut mz_stream, flush: libc::c_int) -> libc::c_int;
    pub fn mz_deflateEnd(stream: *mut mz_stream) -> libc::c_int;

    pub fn mz_inflateInit2(stream: *mut mz_stream,
                           window_bits: libc::c_int) -> libc::c_int;
    pub fn mz_inflate(stream: *mut mz_stream, flush: libc::c_int) -> libc::c_int;
    pub fn mz_inflateEnd(stream: *mut mz_stream) -> libc::c_int;

    pub fn mz_crc32(crc: libc::c_ulong, ptr: *const u8,
                    len: libc::size_t) -> libc::c_ulong;
}

<commit_msg>Remove an explicit link annotation<commit_after>#![allow(warnings)]

extern crate libc;

pub const MZ_NO_FLUSH: libc::c_int = 0;
pub const MZ_SYNC_FLUSH: libc::c_int = 2;
pub const MZ_FINISH: libc::c_int = 4;

pub const MZ_OK: libc::c_int = 0;
pub const MZ_STREAM_END: libc::c_int = 1;
pub const MZ_NEED_DICT: libc::c_int = 2;
pub const MZ_ERRNO: libc::c_int = -1;
pub const MZ_STREAM_ERROR: libc::c_int = -2;
pub const MZ_DATA_ERROR: libc::c_int = -3;
pub const MZ_MEM_ERROR: libc::c_int = -4;
pub const MZ_BUF_ERROR: libc::c_int = -5;
pub const MZ_VERSION_ERROR: libc::c_int = -6;
pub const MZ_PARAM_ERROR: libc::c_int = -10000;

pub const MZ_DEFLATED: libc::c_int = 8;
pub const MZ_DEFAULT_WINDOW_BITS: libc::c_int = 15;
pub const MZ_DEFAULT_STRATEGY: libc::c_int = 0;

#[repr(C)]
pub struct mz_stream {
    pub next_in: *const u8,
    pub avail_in: libc::c_uint,
    pub total_in: libc::c_ulong,

    pub next_out: *mut u8,
    pub avail_out: libc::c_uint,
    pub total_out: libc::c_ulong,

    pub msg: *const libc::c_char,
    pub state: *mut mz_internal_state,

    pub zalloc: Option<mz_alloc_func>,
    pub zfree: Option<mz_free_func>,
    pub opaque: *mut libc::c_void,

    pub data_type: libc::c_int,
    pub adler: libc::c_ulong,
    pub reserved: libc::c_ulong,
}

pub enum mz_internal_state {}

pub type mz_alloc_func = extern fn(*mut libc::c_void,
                                   libc::size_t,
                                   libc::size_t) -> *mut libc::c_void;
pub type mz_free_func = extern fn(*mut libc::c_void, *mut libc::c_void);

extern {
    pub fn mz_deflateInit2(stream: *mut mz_stream,
                           level: libc::c_int,
                           method: libc::c_int,
                           window_bits: libc::c_int,
                           mem_level: libc::c_int,
                           strategy: libc::c_int) -> libc::c_int;
    pub fn mz_deflate(stream: *mut mz_stream, flush: libc::c_int) -> libc::c_int;
    pub fn mz_deflateEnd(stream: *mut mz_stream) -> libc::c_int;

    pub fn mz_inflateInit2(stream: *mut mz_stream,
                           window_bits: libc::c_int) -> libc::c_int;
    pub fn mz_inflate(stream: *mut mz_stream, flush: libc::c_int) -> libc::c_int;
    pub fn mz_inflateEnd(stream: *mut mz_stream) -> libc::c_int;

    pub fn mz_crc32(crc: libc::c_ulong, ptr: *const u8,
                    len: libc::size_t) -> libc::c_ulong;
}

<|endoftext|>


<commit_before>#![feature(rustc_private)]

extern crate getopts;
extern crate miri;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_trans_utils;
extern crate env_logger;
extern crate log_settings;
extern crate syntax;
extern crate log;

use rustc::session::Session;
use rustc::middle::cstore::CrateStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc::ty::TyCtxt;
use rustc_trans_utils::trans_crate::TransCrate;
use syntax::ast;
use std::path::PathBuf;

struct MiriCompilerCalls {
    default: RustcDefaultCalls,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default.early_callback(
            matches,
            sopts,
            cfg,
            descriptions,
            output,
        )
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(
            matches,
            sopts,
            cfg,
            odir,
            ofile,
            descriptions,
        )
    }
    fn late_callback(
        &mut self,
        trans: &TransCrate,
        matches: &getopts::Matches,
        sess: &Session,
        cstore: &CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
    }
    fn build_controller(
        &mut self,
        sess: &Session,
        matches: &getopts::Matches,
    ) -> CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if sess.target.target != sess.host {
            // only fully compile targets on the host. linking will fail for cross-compilation.
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (
        String::from("miri"),
        syntax::feature_gate::AttributeType::Whitelisted,
    );
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(
            TyCtxt<'a, 'tcx, 'tcx>,
            &'a CompileState<'a, 'tcx>
        );
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::Item_::ItemFn(_, _, _, _, _, body_id) = i.node {
                    if i.attrs.iter().any(|attr| {
                        attr.name().map_or(false, |n| n == "test")
                    })
                    {
                        let did = self.0.hir.body_owner_def_id(body_id);
                        println!(
                            "running test: {}",
                            self.0.def_path_debug_str(did),
                        );
                        miri::eval_main(self.0, did, None);
                        self.1.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(
            &mut Visitor(tcx, state),
        );
    } else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn| {
            if tcx.is_mir_available(start_fn) {
                Some(start_fn)
            } else {
                None
            }
        });
        miri::eval_main(tcx, entry_def_id, start_wrapper);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn init_logger() {
    let format = |formatter: &mut env_logger::fmt::Formatter, record: &log::Record| {
        use std::io::Write;
        if record.level() == log::Level::Trace {
            // prepend frame number
            let indentation = log_settings::settings().indentation;
            writeln!(
                formatter,
                "{indentation}:{lvl}:{module}: {text}",
                lvl = record.level(),
                module = record.module_path().unwrap_or("<unknown module>"),
                indentation = indentation,
                text = record.args(),
            )
        } else {
            writeln!(
                formatter,
                "{lvl}:{module}: {text}",
                lvl = record.level(),
                module = record.module_path().unwrap_or("<unknown_module>"),
                text = record.args(),
            )
        }
    };

    let mut builder = env_logger::Builder::new();
    builder.format(format).filter(
        None,
        log::LevelFilter::Info,
    );

    if std::env::var("MIRI_LOG").is_ok() {
        builder.parse(&std::env::var("MIRI_LOG").unwrap());
    }

    builder.init();
}

fn find_sysroot() -> String {
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        return sysroot;
    }

    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => {
            option_env!("RUST_SYSROOT")
                .expect(
                    "need to specify RUST_SYSROOT env var or use rustup or multirust",
                )
                .to_owned()
        }
    }
}

fn main() {
    rustc_driver::init_rustc_env_logger();
    init_logger();
    let mut args: Vec<String> = std::env::args().collect();

    let sysroot_flag = String::from("--sysroot");
    if !args.contains(&sysroot_flag) {
        args.push(sysroot_flag);
        args.push(find_sysroot());
    }

    // Make sure we always have all the MIR (e.g. for auxilary builds in unit tests).
    args.push("-Zalways-encode-mir".to_owned());

    rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
        default: RustcDefaultCalls,
    }, None, None);
}
<commit_msg>Minor fix to get build working<commit_after>#![feature(rustc_private)]

extern crate getopts;
extern crate miri;
extern crate rustc;
extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_trans_utils;
extern crate env_logger;
extern crate log_settings;
extern crate syntax;
extern crate log;

use rustc::session::Session;
use rustc::middle::cstore::CrateStore;
use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls};
use rustc_driver::driver::{CompileState, CompileController};
use rustc::session::config::{self, Input, ErrorOutputType};
use rustc::hir::{self, itemlikevisit};
use rustc::ty::TyCtxt;
use rustc_trans_utils::trans_crate::TransCrate;
use syntax::ast;
use std::path::PathBuf;

struct MiriCompilerCalls {
    default: RustcDefaultCalls,
}

impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
    fn early_callback(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        descriptions: &rustc_errors::registry::Registry,
        output: ErrorOutputType,
    ) -> Compilation {
        self.default.early_callback(
            matches,
            sopts,
            cfg,
            descriptions,
            output,
        )
    }
    fn no_input(
        &mut self,
        matches: &getopts::Matches,
        sopts: &config::Options,
        cfg: &ast::CrateConfig,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
        descriptions: &rustc_errors::registry::Registry,
    ) -> Option<(Input, Option<PathBuf>)> {
        self.default.no_input(
            matches,
            sopts,
            cfg,
            odir,
            ofile,
            descriptions,
        )
    }
    fn late_callback(
        &mut self,
        trans: &TransCrate,
        matches: &getopts::Matches,
        sess: &Session,
        cstore: &CrateStore,
        input: &Input,
        odir: &Option<PathBuf>,
        ofile: &Option<PathBuf>,
    ) -> Compilation {
        self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile)
    }
    fn build_controller(
        &mut self,
        sess: &Session,
        matches: &getopts::Matches,
    ) -> CompileController<'a> {
        let mut control = self.default.build_controller(sess, matches);
        control.after_hir_lowering.callback = Box::new(after_hir_lowering);
        control.after_analysis.callback = Box::new(after_analysis);
        if sess.target.target != sess.host {
            // only fully compile targets on the host. linking will fail for cross-compilation.
            control.after_analysis.stop = Compilation::Stop;
        }
        control
    }
}

fn after_hir_lowering(state: &mut CompileState) {
    let attr = (
        String::from("miri"),
        syntax::feature_gate::AttributeType::Whitelisted,
    );
    state.session.plugin_attributes.borrow_mut().push(attr);
}

fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
    state.session.abort_if_errors();

    let tcx = state.tcx.unwrap();

    if std::env::args().any(|arg| arg == "--test") {
        struct Visitor<'a, 'tcx: 'a>(
            TyCtxt<'a, 'tcx, 'tcx>,
            &'a CompileState<'a, 'tcx>
        );
        impl<'a, 'tcx: 'a, 'hir> itemlikevisit::ItemLikeVisitor<'hir> for Visitor<'a, 'tcx> {
            fn visit_item(&mut self, i: &'hir hir::Item) {
                if let hir::Item_::ItemFn(_, _, _, _, _, body_id) = i.node {
                    if i.attrs.iter().any(|attr| {
                        attr.name() == "test"
                    })
                    {
                        let did = self.0.hir.body_owner_def_id(body_id);
                        println!(
                            "running test: {}",
                            self.0.def_path_debug_str(did),
                        );
                        miri::eval_main(self.0, did, None);
                        self.1.session.abort_if_errors();
                    }
                }
            }
            fn visit_trait_item(&mut self, _trait_item: &'hir hir::TraitItem) {}
            fn visit_impl_item(&mut self, _impl_item: &'hir hir::ImplItem) {}
        }
        state.hir_crate.unwrap().visit_all_item_likes(
            &mut Visitor(tcx, state),
        );
    } else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
        let entry_def_id = tcx.hir.local_def_id(entry_node_id);
        let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn| {
            if tcx.is_mir_available(start_fn) {
                Some(start_fn)
            } else {
                None
            }
        });
        miri::eval_main(tcx, entry_def_id, start_wrapper);

        state.session.abort_if_errors();
    } else {
        println!("no main function found, assuming auxiliary build");
    }
}

fn init_logger() {
    let format = |formatter: &mut env_logger::fmt::Formatter, record: &log::Record| {
        use std::io::Write;
        if record.level() == log::Level::Trace {
            // prepend frame number
            let indentation = log_settings::settings().indentation;
            writeln!(
                formatter,
                "{indentation}:{lvl}:{module}: {text}",
                lvl = record.level(),
                module = record.module_path().unwrap_or("<unknown module>"),
                indentation = indentation,
                text = record.args(),
            )
        } else {
            writeln!(
                formatter,
                "{lvl}:{module}: {text}",
                lvl = record.level(),
                module = record.module_path().unwrap_or("<unknown_module>"),
                text = record.args(),
            )
        }
    };

    let mut builder = env_logger::Builder::new();
    builder.format(format).filter(
        None,
        log::LevelFilter::Info,
    );

    if std::env::var("MIRI_LOG").is_ok() {
        builder.parse(&std::env::var("MIRI_LOG").unwrap());
    }

    builder.init();
}

fn find_sysroot() -> String {
    if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
        return sysroot;
    }

    // Taken from https://github.com/Manishearth/rust-clippy/pull/911.
    let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME"));
    let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN"));
    match (home, toolchain) {
        (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain),
        _ => {
            option_env!("RUST_SYSROOT")
                .expect(
                    "need to specify RUST_SYSROOT env var or use rustup or multirust",
                )
                .to_owned()
        }
    }
}

fn main() {
    rustc_driver::init_rustc_env_logger();
    init_logger();
    let mut args: Vec<String> = std::env::args().collect();

    let sysroot_flag = String::from("--sysroot");
    if !args.contains(&sysroot_flag) {
        args.push(sysroot_flag);
        args.push(find_sysroot());
    }

    // Make sure we always have all the MIR (e.g. for auxilary builds in unit tests).
    args.push("-Zalways-encode-mir".to_owned());

    rustc_driver::run_compiler(&args, &mut MiriCompilerCalls {
        default: RustcDefaultCalls,
    }, None, None);
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io::BufReader;
use std::str;

//1 group = 512 bits = 16 * 32 bits
//512 bits = 64 bytes = 16 * 4 bytes
//448 bits = 56 bytes
//32 bits = 4 bytes
//MD5 give Hex chars out
/*
fn read_group<R>(reader: R) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];

    let mut chunk = reader.take(64);
    // Do appropriate error handling for your situation
    let n = chunk.read_to_end(&mut buf).expect("Read issue error:");

    if n < 64 {
        if n < 56 {
            buf.push(0x10u8);
            for _ in 0..(55 - n) {
                buf.push(0x00u8)
            }
        } else if n > 56 {
            buf.push(0x10u8);
            for _ in 0..(63 - n) {
                buf.push(0x00u8)
            }
            for _ in 0..56 {
                buf.push(0x00u8)
            }
        }
        return buf;
    }

    buf
}*/

fn read_group<R>(reader: R) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];
    let bytes = reader.bytes();
    let mut time = 0;

    for byte in bytes {
        time += 1;
        buf.push(byte.unwrap());
        if time == 64 {
            time = 0;
        }
    }

    if time < 64 {
        if time < 56 {
            buf.push(0x10u8);
            for _ in 0..(55 - time) {
                buf.push(0x00u8)
            }
        } else if time > 56 {
            buf.push(0x10u8);
            for _ in 0..(63 - time) {
                buf.push(0x00u8)
            }
            for _ in 0..56 {
                buf.push(0x00u8)
            }
        }
        return buf;
    }

    buf
}

fn main() {
    let input_data = b"123456789A123456789B123456789C123456789D123456789E123456789F";
    let mut reader = BufReader::new(&input_data[..]);

    let word = read_group(&mut reader);
    println!("{}", word.len());
    println!("{:?}", str::from_utf8(&word));
}
<commit_msg>a bit<commit_after>use std::io::prelude::*;
use std::io::BufReader;
use std::str;

//1 group = 512 bits = 16 * 32 bits
//512 bits = 64 bytes = 16 * 4 bytes
//448 bits = 56 bytes
//32 bits = 4 bytes
//MD5 give Hex chars out
/*
fn read_group<R>(reader: R) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];

    let mut chunk = reader.take(64);
    // Do appropriate error handling for your situation
    let n = chunk.read_to_end(&mut buf).expect("Read issue error:");

    if n < 64 {
        if n < 56 {
            buf.push(0x10u8);
            for _ in 0..(55 - n) {
                buf.push(0x00u8)
            }
        } else if n > 56 {
            buf.push(0x10u8);
            for _ in 0..(63 - n) {
                buf.push(0x00u8)
            }
            for _ in 0..56 {
                buf.push(0x00u8)
            }
        }
        return buf;
    }

    buf
}*/

fn read_group<R>(reader: R) -> Vec<u8>
where
    R: Read,
{
    let mut buf = vec![];
    let bytes = reader.bytes();
    let mut time = 0;

    let mut origin_len = 0;
    for byte in bytes {
        time += 1;
        origin_len += 1
        buf.push(byte.unwrap());
        if time == 64 {
            time = 0;
        }
    }

    if time < 64 {
        if time < 56 {
            buf.push(0x10u8);
            for _ in 0..(55 - time) {
                buf.push(0x00u8)
            }
        } else if time > 56 {
            buf.push(0x10u8);
            for _ in 0..(63 - time) {
                buf.push(0x00u8)
            }
            for _ in 0..56 {
                buf.push(0x00u8)
            }
        }
    }

    origin_len * 8

    buf
}

fn main() {
    let input_data = b"123456789A123456789B123456789C123456789D123456789E123456789F";
    let mut reader = BufReader::new(&input_data[..]);

    let word = read_group(&mut reader);
    println!("{}", word.len());
    println!("{:?}", str::from_utf8(&word));
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "collections_range",
            reason = "waiting for dust to settle on inclusive ranges",
            issue = "30877")]

//! Range syntax.

use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
use Bound::{self, Excluded, Included, Unbounded};

/// **RangeArgument** is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
pub trait RangeArgument<T> {
    /// Start index (inclusive)
    ///
    /// Return start value if present, else `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    ///
    /// assert_eq!((..10).start(), None);
    /// assert_eq!((3..10).start(), Some(&3));
    /// # }
    /// ```
    fn start(&self) -> Bound<&T> {
        Unbounded
    }

    /// End index (exclusive)
    ///
    /// Return end value if present, else `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    ///
    /// assert_eq!((3..).end(), None);
    /// assert_eq!((3..10).end(), Some(&10));
    /// # }
    /// ```
    fn end(&self) -> Bound<&T> {
        Unbounded
    }
}

// FIXME add inclusive ranges to RangeArgument

impl<T> RangeArgument<T> for RangeFull {}

impl<T> RangeArgument<T> for RangeFrom<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
}

impl<T> RangeArgument<T> for RangeTo<T> {
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for Range<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}
<commit_msg>impl RangeArgument for (Bound<T>, Bound<T>)<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "collections_range",
            reason = "waiting for dust to settle on inclusive ranges",
            issue = "30877")]

//! Range syntax.

use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
use Bound::{self, Excluded, Included, Unbounded};

/// **RangeArgument** is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
pub trait RangeArgument<T> {
    /// Start index (inclusive)
    ///
    /// Return start value if present, else `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    ///
    /// assert_eq!((..10).start(), None);
    /// assert_eq!((3..10).start(), Some(&3));
    /// # }
    /// ```
    fn start(&self) -> Bound<&T> {
        Unbounded
    }

    /// End index (exclusive)
    ///
    /// Return end value if present, else `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(collections)]
    /// #![feature(collections_range)]
    ///
    /// extern crate collections;
    ///
    /// # fn main() {
    /// use collections::range::RangeArgument;
    ///
    /// assert_eq!((3..).end(), None);
    /// assert_eq!((3..10).end(), Some(&10));
    /// # }
    /// ```
    fn end(&self) -> Bound<&T> {
        Unbounded
    }
}

// FIXME add inclusive ranges to RangeArgument

impl<T> RangeArgument<T> for RangeFull {}

impl<T> RangeArgument<T> for RangeFrom<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
}

impl<T> RangeArgument<T> for RangeTo<T> {
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for Range<T> {
    fn start(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

impl<T> RangeArgument<T> for (Bound<T>, Bound<T>) {
    fn start(&self) -> Bound<&T> {
        match *self {
            (Included(ref start), _) => Included(start),
            (Excluded(ref start), _) => Excluded(start),
            (Unbounded, _)           => Unbounded,
        }
    }

    fn end(&self) -> Bound<&T> {
        match *self {
            (_, Included(ref end)) => Included(end),
            (_, Excluded(ref end)) => Excluded(end),
            (_, Unbounded)         => Unbounded,
        }
    }
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/reader.rs                                           *
 *                                                        *
 * hprose reader for Rust.                                *
 *                                                        *
 * LastModified: Sep 25, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

extern crate test;

use super::*;
use super::tags::*;
use super::util::*;
use super::decoders::*;
use super::reader_refer::ReaderRefer;

use std::convert::From;
use std::{fmt, f64, str};

use time::{Tm, empty_tm};

/// A set of errors that can occur decoding byte slice
#[derive(Clone, PartialEq, Debug)]
pub enum DecoderError {
    ParserError(ParserError),
    CastError(&'static str, &'static str),
    UnexpectedTag(u8, Option<Bytes>),
    ReferenceError
}

impl From<ParserError> for DecoderError {
    fn from(e: ParserError) -> Self {
        DecoderError::ParserError(e)
    }
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DecoderError::CastError(src_type, dst_type) => write!(f, "can't convert {} to {}", src_type, dst_type),
            DecoderError::UnexpectedTag(tag, ref expect_tags_option) => {
                match *expect_tags_option {
                    // todo: format tag as 'c'(0xdd)
                    Some(ref expect_tags) => write!(f, "Tag '{:?}' expected, but '{}' found in stream", expect_tags, tag),
                    None => write!(f, "Unexpected serialize tag '{}' in stream", tag)
                }
            },
            _ => fmt::Debug::fmt(self, f)
        }
    }
}

pub type DecodeResult<T> = Result<T, DecoderError>;

/// Reader is a fine-grained operation struct for Hprose unserialization
pub struct Reader<'a> {
    pub byte_reader: ByteReader<'a>,
    refer: Option<ReaderRefer<'a>>
}

impl<'a> Reader<'a> {
    #[inline]
    pub fn new(buf: &'a [u8], simple: bool) -> Reader<'a> {
        Reader {
            byte_reader: ByteReader::new(buf),
            refer: if simple { None } else { Some(ReaderRefer::new()) }
        }
    }

    #[inline]
    pub fn unserialize<T: Decodable>(&mut self) -> DecodeResult<T> {
        self.read()
    }

    #[inline]
    pub fn read<T: Decodable>(&mut self) -> DecodeResult<T> {
        Decodable::decode(self)
    }
}

impl<'a> Decoder for Reader<'a> {
    type Error = DecoderError;

    fn read_nil(&mut self) -> DecodeResult<()> {
        unimplemented!()
    }

    fn read_bool(&mut self) -> DecodeResult<bool> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| bool_decode(self, t))
    }

    fn read_i64(&mut self) -> DecodeResult<i64> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| i64_decode(self, t))
    }

    fn read_u64(&mut self) -> DecodeResult<u64> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| u64_decode(self, t))
    }

    fn read_f32(&mut self) -> DecodeResult<f32> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| f32_decode(self, t))
    }

    fn read_f64(&mut self) -> DecodeResult<f64> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| f64_decode(self, t))
    }

    fn read_char(&mut self) -> DecodeResult<char> {
        unimplemented!()
    }

    fn read_string_without_tag(&mut self) -> DecodeResult<String> {
        let start = self.byte_reader.off - 1;
        let result = self.byte_reader.read_string().map_err(|e| DecoderError::ParserError(e));
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        result
    }

    fn read_string(&mut self) -> DecodeResult<String> {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| string_decode(self, t))
    }

    fn read_bytes(&mut self) -> DecodeResult<Bytes> {
        unimplemented!()
    }

    fn read_datetime_without_tag(&mut self) -> DecodeResult<Tm> {
        let start = self.byte_reader.off - 1;
        let mut tm = empty_tm();
        let mut tag = 0;
        {
            let bytes = try!(self.byte_reader.next(9));
            tm.tm_year = bytes_to_diget4(&bytes[..4]) - 1900;
            tm.tm_mon = bytes_to_diget2(&bytes[4..6]) - 1;
            tm.tm_mday = bytes_to_diget2(&bytes[6..8]);
            tag = bytes[8];
        }
        if tag == TAG_TIME {
            {
                let bytes = try!(self.byte_reader.next(7));
                tm.tm_hour = bytes_to_diget2(&bytes[..2]);
                tm.tm_min = bytes_to_diget2(&bytes[2..4]);
                tm.tm_sec = bytes_to_diget2(&bytes[4..6]);
                tag = bytes[6];
            }
            if tag == TAG_POINT {
                {
                    let bytes = try!(self.byte_reader.next(4));
                    tm.tm_nsec = bytes_to_diget3(&bytes[..3]);
                    tag = bytes[3];
                }
                if (tag >= b'0') && (tag <= b'9') {
                    {
                        let bytes = try!(self.byte_reader.next(3));
                        tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                        tag = bytes[2];
                    }
                    if (tag >= b'0') && (tag <= b'9') {
                        let bytes = try!(self.byte_reader.next(3));
                        tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                        tag = bytes[2];
                    }
                }
            }
        };
        if tag != TAG_UTC {
            tm.tm_utcoff = get_utcoff();
        }
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        Ok(tm)
    }

    fn read_time_without_tag(&mut self) -> Result<Tm, Self::Error> {
        let start = self.byte_reader.off - 1;
        let mut tm = empty_tm();
        let mut tag = 0;
        tm.tm_year = 70;
        tm.tm_mday = 1;
        {
            let bytes = try!(self.byte_reader.next(7));
            tm.tm_hour = bytes_to_diget2(&bytes[..2]);
            tm.tm_min = bytes_to_diget2(&bytes[2..4]);
            tm.tm_sec = bytes_to_diget2(&bytes[4..6]);
            tag = bytes[6];
        }
        if tag == TAG_POINT {
            {
                let bytes = try!(self.byte_reader.next(4));
                tm.tm_nsec = bytes_to_diget3(&bytes[..3]);
                tag = bytes[3];
            }
            if (tag >= b'0') && (tag <= b'9') {
                {
                    let bytes = try!(self.byte_reader.next(3));
                    tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                    tag = bytes[2];
                }
                if (tag >= b'0') && (tag <= b'9') {
                    let bytes = try!(self.byte_reader.next(3));
                    tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                    tag = bytes[2];
                }
            }
        }
        if tag != TAG_UTC {
            tm.tm_utcoff = get_utcoff();
        }
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        Ok(tm)
    }

    fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnMut(&mut Reader<'a>, bool) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnOnce(&mut Reader<'a>, usize) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
        where T: Decodable, F: FnOnce(&mut Reader<'a>, usize) -> DecodeResult<T>
    {
        self.byte_reader.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| map_decode(self, t, |d, len| f(d, len)))
    }

    fn read_ref<T: Decodable>(&mut self) -> Result<T, DecoderError> {
        let i = try!(self.byte_reader.read_i64());
        match self.refer {
            Some(ref mut r) => Reader::new(r.read(i as usize), true).unserialize::<T>(),
            None => Err(DecoderError::ReferenceError)
        }
    }
}

fn tag_to_str(tag: u8) -> Result<&'static str, DecoderError> {
    match tag {
        b'0'...b'9' | TAG_INTEGER => Ok("i32"),
        TAG_LONG => Ok("big int"),
        TAG_DOUBLE => Ok("f64"),
        TAG_NULL => Ok("nil"),
        TAG_EMPTY => Ok("empty string"),
        TAG_TRUE => Ok("true"),
        TAG_FALSE => Ok("false"),
        TAG_NAN => Ok("NaN"),
        TAG_INFINITY => Ok("Infinity"),
        TAG_DATE | TAG_TIME => Ok("time"),
        TAG_BYTES => Ok("bytes"),
        TAG_UTF8_CHAR | TAG_STRING => Ok("string"),
        TAG_GUID => Ok("GUID"),
        TAG_LIST => Ok("slice"),
        TAG_MAP => Ok("map"),
        TAG_CLASS | TAG_OBJECT => Ok("struct"),
        TAG_REF => Ok("reference"),
        _ => Err(DecoderError::UnexpectedTag(tag, None))
    }
}

pub fn cast_error(tag: u8, dst_type: &'static str) -> DecoderError {
    tag_to_str(tag)
        .map(|src_type| DecoderError::CastError(src_type, dst_type))
        .unwrap_or_else(|e| e)
}

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

    use std::{i32, i64, u32, u64};
    use std::collections::HashMap;
    use std::mem::transmute;

    use time::{Timespec, at_utc};

    macro_rules! test {
        ($ty:ty, $writer:expr, $($value:expr, $result:expr),+) => (
            $(
                $writer.serialize(&$value);
            )+
            let bytes = $writer.bytes();
            let mut r = Reader::new(&bytes, false);
            $(
                assert_eq!(r.unserialize::<$ty>(), Ok($result));
            )+
        )
    }

    #[test]
    fn test_unserialize_bool() {
        let true_value = String::from("true");
        let mut w = Writer::new(false);
        w.serialize(&true)
            .serialize(&false)
            .serialize(&())
            .serialize(&"")
            .serialize(&0)
            .serialize(&1)
            .serialize(&9)
            .serialize(&100)
            .serialize(&100000000000000i64)
            .serialize(&0.0)
            .serialize(&"t")
            .serialize(&"f")
            .serialize(&true_value)
            .serialize(&"false")
            .serialize(&true_value);
        let results = [true, false, false, false, false, true, true, true, true, false, true, false, true, false, true];
        let bytes = w.bytes();
        let mut r = Reader::new(&bytes, false);
        for result in &results {
            assert_eq!(r.unserialize::<bool>(), Ok(*result));
        }
    }

    #[bench]
    fn benchmark_unserialize_bool(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&true).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<bool>().unwrap();
        });
    }

    #[test]
    fn test_unserialize_i64() {
        let int_value = String::from("1234567");
        let mut w = Writer::new(false);
        test! { i64, w,
            true, 1,
            false, 0,
            (), 0,
		    "", 0,
            0, 0,
            1, 1,
            9, 9,
            100, 100,
            -100, -100,
            i32::MIN, i32::MIN as i64,
            i64::MAX, i64::MAX,
            i64::MIN, i64::MIN,
            u64::MAX, u64::MAX as i64,
            0.0, 0,
            "1", 1,
            "9", 9,
            int_value, 1234567,
            at_utc(Timespec::new(123, 456)), 123000000456,
            at_utc(Timespec::new(1234567890, 123456789)), 1234567890123456789,
            int_value, 1234567
        }
    }

    #[bench]
    fn benchmark_unserialize_i64(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&12345).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<i64>().unwrap();
        });
    }

    #[bench]
    fn benchmark_unserialize_str(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize("你好，🇨🇳").bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<String>().unwrap();
        });
    }

    #[bench]
    fn benchmark_unserialize_map(b: &mut Bencher) {
        let mut map = HashMap::new();
        map.insert("name", "Tom");
        map.insert("国家", "🇨🇳");
        let bytes = Writer::new(true).serialize(&map).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<HashMap<String, String>>().unwrap();
        });
    }
}
<commit_msg>use try! macro simplify code.<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/reader.rs                                           *
 *                                                        *
 * hprose reader for Rust.                                *
 *                                                        *
 * LastModified: Sep 25, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

extern crate test;

use super::*;
use super::tags::*;
use super::util::*;
use super::decoders::*;
use super::reader_refer::ReaderRefer;

use std::convert::From;
use std::{fmt, f64, str};

use time::{Tm, empty_tm};

/// A set of errors that can occur decoding byte slice
#[derive(Clone, PartialEq, Debug)]
pub enum DecoderError {
    ParserError(ParserError),
    CastError(&'static str, &'static str),
    UnexpectedTag(u8, Option<Bytes>),
    ReferenceError
}

impl From<ParserError> for DecoderError {
    fn from(e: ParserError) -> Self {
        DecoderError::ParserError(e)
    }
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DecoderError::CastError(src_type, dst_type) => write!(f, "can't convert {} to {}", src_type, dst_type),
            DecoderError::UnexpectedTag(tag, ref expect_tags_option) => {
                match *expect_tags_option {
                    // todo: format tag as 'c'(0xdd)
                    Some(ref expect_tags) => write!(f, "Tag '{:?}' expected, but '{}' found in stream", expect_tags, tag),
                    None => write!(f, "Unexpected serialize tag '{}' in stream", tag)
                }
            },
            _ => fmt::Debug::fmt(self, f)
        }
    }
}

pub type DecodeResult<T> = Result<T, DecoderError>;

/// Reader is a fine-grained operation struct for Hprose unserialization
pub struct Reader<'a> {
    pub byte_reader: ByteReader<'a>,
    refer: Option<ReaderRefer<'a>>
}

impl<'a> Reader<'a> {
    #[inline]
    pub fn new(buf: &'a [u8], simple: bool) -> Reader<'a> {
        Reader {
            byte_reader: ByteReader::new(buf),
            refer: if simple { None } else { Some(ReaderRefer::new()) }
        }
    }

    #[inline]
    pub fn unserialize<T: Decodable>(&mut self) -> DecodeResult<T> {
        self.read()
    }

    #[inline]
    pub fn read<T: Decodable>(&mut self) -> DecodeResult<T> {
        Decodable::decode(self)
    }
}

impl<'a> Decoder for Reader<'a> {
    type Error = DecoderError;

    fn read_nil(&mut self) -> DecodeResult<()> {
        unimplemented!()
    }

    fn read_bool(&mut self) -> DecodeResult<bool> {
        let b = try!(self.byte_reader.read_byte());
        bool_decode(self, b)
    }

    fn read_i64(&mut self) -> DecodeResult<i64> {
        let b = try!(self.byte_reader.read_byte());
        i64_decode(self, b)
    }

    fn read_u64(&mut self) -> DecodeResult<u64> {
        let b = try!(self.byte_reader.read_byte());
        u64_decode(self, b)
    }

    fn read_f32(&mut self) -> DecodeResult<f32> {
        let b = try!(self.byte_reader.read_byte());
        f32_decode(self, b)
    }

    fn read_f64(&mut self) -> DecodeResult<f64> {
        let b = try!(self.byte_reader.read_byte());
        f64_decode(self, b)
    }

    fn read_char(&mut self) -> DecodeResult<char> {
        unimplemented!()
    }

    fn read_string_without_tag(&mut self) -> DecodeResult<String> {
        let start = self.byte_reader.off - 1;
        let s = try!(self.byte_reader.read_string());
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        Ok(s)
    }

    fn read_string(&mut self) -> DecodeResult<String> {
        let b = try!(self.byte_reader.read_byte());
        string_decode(self, b)
    }

    fn read_bytes(&mut self) -> DecodeResult<Bytes> {
        unimplemented!()
    }

    fn read_datetime_without_tag(&mut self) -> DecodeResult<Tm> {
        let start = self.byte_reader.off - 1;
        let mut tm = empty_tm();
        let mut tag = 0;
        {
            let bytes = try!(self.byte_reader.next(9));
            tm.tm_year = bytes_to_diget4(&bytes[..4]) - 1900;
            tm.tm_mon = bytes_to_diget2(&bytes[4..6]) - 1;
            tm.tm_mday = bytes_to_diget2(&bytes[6..8]);
            tag = bytes[8];
        }
        if tag == TAG_TIME {
            {
                let bytes = try!(self.byte_reader.next(7));
                tm.tm_hour = bytes_to_diget2(&bytes[..2]);
                tm.tm_min = bytes_to_diget2(&bytes[2..4]);
                tm.tm_sec = bytes_to_diget2(&bytes[4..6]);
                tag = bytes[6];
            }
            if tag == TAG_POINT {
                {
                    let bytes = try!(self.byte_reader.next(4));
                    tm.tm_nsec = bytes_to_diget3(&bytes[..3]);
                    tag = bytes[3];
                }
                if (tag >= b'0') && (tag <= b'9') {
                    {
                        let bytes = try!(self.byte_reader.next(3));
                        tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                        tag = bytes[2];
                    }
                    if (tag >= b'0') && (tag <= b'9') {
                        let bytes = try!(self.byte_reader.next(3));
                        tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                        tag = bytes[2];
                    }
                }
            }
        };
        if tag != TAG_UTC {
            tm.tm_utcoff = get_utcoff();
        }
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        Ok(tm)
    }

    fn read_time_without_tag(&mut self) -> Result<Tm, Self::Error> {
        let start = self.byte_reader.off - 1;
        let mut tm = empty_tm();
        let mut tag = 0;
        tm.tm_year = 70;
        tm.tm_mday = 1;
        {
            let bytes = try!(self.byte_reader.next(7));
            tm.tm_hour = bytes_to_diget2(&bytes[..2]);
            tm.tm_min = bytes_to_diget2(&bytes[2..4]);
            tm.tm_sec = bytes_to_diget2(&bytes[4..6]);
            tag = bytes[6];
        }
        if tag == TAG_POINT {
            {
                let bytes = try!(self.byte_reader.next(4));
                tm.tm_nsec = bytes_to_diget3(&bytes[..3]);
                tag = bytes[3];
            }
            if (tag >= b'0') && (tag <= b'9') {
                {
                    let bytes = try!(self.byte_reader.next(3));
                    tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                    tag = bytes[2];
                }
                if (tag >= b'0') && (tag <= b'9') {
                    let bytes = try!(self.byte_reader.next(3));
                    tm.tm_nsec = tm.tm_nsec * 1000 + (tag - b'0') as i32 * 100 + bytes_to_diget2(&bytes[..2]);
                    tag = bytes[2];
                }
            }
        }
        if tag != TAG_UTC {
            tm.tm_utcoff = get_utcoff();
        }
        let reference = &self.byte_reader.buf[start..self.byte_reader.off];
        self.refer.as_mut().map(|mut r| r.set(reference));
        Ok(tm)
    }

    fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnMut(&mut Reader<'a>, bool) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnOnce(&mut Reader<'a>, usize) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_map<T, F>(&mut self, f: F) -> DecodeResult<T>
        where T: Decodable, F: FnOnce(&mut Reader<'a>, usize) -> DecodeResult<T>
    {
        let b = try!(self.byte_reader.read_byte());
        map_decode(self, b, |d, len| f(d, len))
    }

    fn read_ref<T: Decodable>(&mut self) -> Result<T, DecoderError> {
        let i = try!(self.byte_reader.read_i64());
        match self.refer {
            Some(ref mut r) => Reader::new(r.read(i as usize), true).unserialize::<T>(),
            None => Err(DecoderError::ReferenceError)
        }
    }
}

fn tag_to_str(tag: u8) -> Result<&'static str, DecoderError> {
    match tag {
        b'0'...b'9' | TAG_INTEGER => Ok("i32"),
        TAG_LONG => Ok("big int"),
        TAG_DOUBLE => Ok("f64"),
        TAG_NULL => Ok("nil"),
        TAG_EMPTY => Ok("empty string"),
        TAG_TRUE => Ok("true"),
        TAG_FALSE => Ok("false"),
        TAG_NAN => Ok("NaN"),
        TAG_INFINITY => Ok("Infinity"),
        TAG_DATE | TAG_TIME => Ok("time"),
        TAG_BYTES => Ok("bytes"),
        TAG_UTF8_CHAR | TAG_STRING => Ok("string"),
        TAG_GUID => Ok("GUID"),
        TAG_LIST => Ok("slice"),
        TAG_MAP => Ok("map"),
        TAG_CLASS | TAG_OBJECT => Ok("struct"),
        TAG_REF => Ok("reference"),
        _ => Err(DecoderError::UnexpectedTag(tag, None))
    }
}

pub fn cast_error(tag: u8, dst_type: &'static str) -> DecoderError {
    tag_to_str(tag)
        .map(|src_type| DecoderError::CastError(src_type, dst_type))
        .unwrap_or_else(|e| e)
}

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

    use std::{i32, i64, u32, u64};
    use std::collections::HashMap;
    use std::mem::transmute;

    use time::{Timespec, at_utc};

    macro_rules! test {
        ($ty:ty, $writer:expr, $($value:expr, $result:expr),+) => (
            $(
                $writer.serialize(&$value);
            )+
            let bytes = $writer.bytes();
            let mut r = Reader::new(&bytes, false);
            $(
                assert_eq!(r.unserialize::<$ty>(), Ok($result));
            )+
        )
    }

    #[test]
    fn test_unserialize_bool() {
        let true_value = String::from("true");
        let mut w = Writer::new(false);
        w.serialize(&true)
            .serialize(&false)
            .serialize(&())
            .serialize(&"")
            .serialize(&0)
            .serialize(&1)
            .serialize(&9)
            .serialize(&100)
            .serialize(&100000000000000i64)
            .serialize(&0.0)
            .serialize(&"t")
            .serialize(&"f")
            .serialize(&true_value)
            .serialize(&"false")
            .serialize(&true_value);
        let results = [true, false, false, false, false, true, true, true, true, false, true, false, true, false, true];
        let bytes = w.bytes();
        let mut r = Reader::new(&bytes, false);
        for result in &results {
            assert_eq!(r.unserialize::<bool>(), Ok(*result));
        }
    }

    #[bench]
    fn benchmark_unserialize_bool(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&true).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<bool>().unwrap();
        });
    }

    #[test]
    fn test_unserialize_i64() {
        let int_value = String::from("1234567");
        let mut w = Writer::new(false);
        test! { i64, w,
            true, 1,
            false, 0,
            (), 0,
		    "", 0,
            0, 0,
            1, 1,
            9, 9,
            100, 100,
            -100, -100,
            i32::MIN, i32::MIN as i64,
            i64::MAX, i64::MAX,
            i64::MIN, i64::MIN,
            u64::MAX, u64::MAX as i64,
            0.0, 0,
            "1", 1,
            "9", 9,
            int_value, 1234567,
            at_utc(Timespec::new(123, 456)), 123000000456,
            at_utc(Timespec::new(1234567890, 123456789)), 1234567890123456789,
            int_value, 1234567
        }
    }

    #[bench]
    fn benchmark_unserialize_i64(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&12345).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<i64>().unwrap();
        });
    }

    #[bench]
    fn benchmark_unserialize_str(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize("你好，🇨🇳").bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<String>().unwrap();
        });
    }

    #[bench]
    fn benchmark_unserialize_map(b: &mut Bencher) {
        let mut map = HashMap::new();
        map.insert("name", "Tom");
        map.insert("国家", "🇨🇳");
        let bytes = Writer::new(true).serialize(&map).bytes();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            Reader::new(&bytes, true).unserialize::<HashMap<String, String>>().unwrap();
        });
    }
}
<|endoftext|>


<commit_before>mod progress;

use self::progress::Progress;
use crate::common;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "5e8897b7b51636f157630e6639b711d698e1d101";

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    assert!(path_string.starts_with("tests/rust/src/"));
    let path = &path_string["tests/rust/src/".len()..];

    // TODO assert that parsing fails on the parse-fail cases
    if path.starts_with("test/parse-fail")
        || path.starts_with("test/compile-fail")
        || path.starts_with("test/rustfix")
    {
        return false;
    }

    if path.starts_with("test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path {
        // Deprecated placement syntax
        "test/ui/obsolete-in-place/bad.rs" |
        // Deprecated anonymous parameter syntax in traits
        "test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs" |
        "test/ui/issues/issue-13105.rs" |
        "test/ui/issues/issue-13775.rs" |
        "test/ui/issues/issue-34074.rs" |
        // 2015-style dyn that libsyntax rejects
        "test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs" |
        // TODO: const trait impls and bounds
        "test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs" |
        "test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs" |
        "test/ui/rfc-2632-const-trait-impl/feature-gate.rs" |
        "test/ui/rfc-2632-const-trait-impl/syntax.rs" |
        // not actually test cases
        "test/rustdoc-ui/test-compile-fail2.rs" |
        "test/rustdoc-ui/test-compile-fail3.rs" |
        "test/ui/include-single-expr-helper.rs" |
        "test/ui/include-single-expr-helper-1.rs" |
        "test/ui/issues/auxiliary/issue-21146-inc.rs" |
        "test/ui/macros/auxiliary/macro-comma-support.rs" |
        "test/ui/macros/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
        if common::travis_ci() {
            // Something about this makes the travis build not deadlock...
            errorf!(".");
        }
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Update rust repo revision to nightly-2020-02-21<commit_after>mod progress;

use self::progress::Progress;
use crate::common;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "2c462a2f776b899d46743b1b44eda976e846e61d";

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    assert!(path_string.starts_with("tests/rust/src/"));
    let path = &path_string["tests/rust/src/".len()..];

    // TODO assert that parsing fails on the parse-fail cases
    if path.starts_with("test/parse-fail")
        || path.starts_with("test/compile-fail")
        || path.starts_with("test/rustfix")
    {
        return false;
    }

    if path.starts_with("test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    match path {
        // TODO
        "test/mir-opt/exponential-or.rs" |
        "test/pretty/trait-inner-attr.rs" |
        "test/ui/or-patterns/basic-switch.rs" |
        "test/ui/or-patterns/basic-switchint.rs" |
        "test/ui/or-patterns/bindings-runpass-1.rs" |
        "test/ui/or-patterns/bindings-runpass-2.rs" |
        "test/ui/or-patterns/consistent-bindings.rs" |
        "test/ui/or-patterns/exhaustiveness-pass.rs" |
        "test/ui/or-patterns/for-loop.rs" |
        "test/ui/or-patterns/if-let-while-let.rs" |
        "test/ui/or-patterns/issue-67514-irrefutable-param.rs" |
        "test/ui/or-patterns/issue-68785-irrefutable-param-with-at.rs" |
        "test/ui/or-patterns/let-pattern.rs" |
        "test/ui/or-patterns/mix-with-wild.rs" |
        "test/ui/or-patterns/or-patterns-default-binding-modes.rs" |
        "test/ui/or-patterns/or-patterns-syntactic-pass.rs" |
        "test/ui/or-patterns/search-via-bindings.rs" |
        "test/ui/or-patterns/struct-like.rs" |
        "test/ui/parser/assoc-const-underscore-syntactic-pass.rs" |
        "test/ui/parser/fn-body-optional-syntactic-pass.rs" |
        "test/ui/parser/fn-header-syntactic-pass.rs" |
        "test/ui/parser/foreign-static-syntactic-pass.rs" |
        "test/ui/parser/foreign-ty-syntactic-pass.rs" |
        "test/ui/parser/inner-attr-in-trait-def.rs" |
        "test/ui/parser/item-free-const-no-body-syntactic-pass.rs" |
        "test/ui/parser/item-free-static-no-body-syntactic-pass.rs" |
        "test/ui/parser/self-param-syntactic-pass.rs" |
        "test/ui/rfc-2632-const-trait-impl/assoc-type.rs" |
        "test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs" |
        "test/ui/rfc-2632-const-trait-impl/generic-bound.rs" |
        // Deprecated placement syntax
        "test/ui/obsolete-in-place/bad.rs" |
        // Deprecated anonymous parameter syntax in traits
        "test/ui/error-codes/e0119/auxiliary/issue-23563-a.rs" |
        "test/ui/issues/issue-13105.rs" |
        "test/ui/issues/issue-13775.rs" |
        "test/ui/issues/issue-34074.rs" |
        // 2015-style dyn that libsyntax rejects
        "test/ui/dyn-keyword/dyn-2015-no-warnings-without-lints.rs" |
        // TODO: const trait impls and bounds
        "test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/feature-gate.rs" |
        "test/ui/rfc-2632-const-trait-impl/const-trait-bound-opt-out/syntax.rs" |
        "test/ui/rfc-2632-const-trait-impl/feature-gate.rs" |
        "test/ui/rfc-2632-const-trait-impl/syntax.rs" |
        // not actually test cases
        "test/rustdoc-ui/test-compile-fail2.rs" |
        "test/rustdoc-ui/test-compile-fail3.rs" |
        "test/ui/include-single-expr-helper.rs" |
        "test/ui/include-single-expr-helper-1.rs" |
        "test/ui/issues/auxiliary/issue-21146-inc.rs" |
        "test/ui/macros/auxiliary/macro-comma-support.rs" |
        "test/ui/macros/auxiliary/macro-include-items-expr.rs" => false,
        _ => true,
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
        if common::travis_ci() {
            // Something about this makes the travis build not deadlock...
            errorf!(".");
        }
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before>extern crate libc;

#[macro_use]
extern crate apache2;

use apache2::{Request, Status, get_server_description, get_server_built, show_mpm,
   apr_version_string, apu_version_string};

apache2_module!(info_rs_module, info_rs_handler, c_info_rs_handler, b"mod_info_rs\0");

fn info_rs_handler(r: &Request) -> Status {
   if r.handler().unwrap() != "server-info-rs" {
      return Status::DECLINED
   }

   let conn = r.connection().unwrap();

   r.set_content_type("text/html");

   r.write("<!doctype html><meta charset=\"utf-8\"><title>Apache Info</title>");

   r.write("
Apache Server Information
");

   let server_name = r.escape_html(r.server_name().unwrap()).unwrap();
   let server_port = r.server_port();
   let local_ip = conn.local_ip().unwrap();
   r.write(format!("
Server: {}:{} (via {})
", server_name, server_port, local_ip));

   let server_description = get_server_description().unwrap();
   r.write(format!("
Server Version: {}
", server_description));

   let mmp = show_mpm().unwrap();
   r.write(format!("
Server MPM: {}
", mmp));

   let server_built = get_server_built().unwrap();
   r.write(format!("
Server Built: {}
", server_built));

   let apr_version = apr_version_string().unwrap();
   r.write(format!("
Server loaded APR Version: {}
", apr_version));

   let apu_version = apu_version_string().unwrap();
   r.write(format!("
Server loaded APU Version: {}
", apu_version));

   let client_ip = conn.client_ip().unwrap();
   r.write(format!("
Client IP: {}
", client_ip));

   let args = match r.args() {
      Some(args) => args,
      None => "None"
   };
   r.write(format!("
Request Args: {}
", args));

   r.write("");

   Status::OK
}
<commit_msg>Horizontal divider in the info page.<commit_after>extern crate libc;

#[macro_use]
extern crate apache2;

use apache2::{Request, Status, get_server_description, get_server_built, show_mpm,
   apr_version_string, apu_version_string};

apache2_module!(info_rs_module, info_rs_handler, c_info_rs_handler, b"mod_info_rs\0");

fn info_rs_handler(r: &Request) -> Status {
   if r.handler().unwrap() != "server-info-rs" {
      return Status::DECLINED
   }

   let conn = r.connection().unwrap();

   r.set_content_type("text/html");

   r.write("<!doctype html><meta charset=\"utf-8\"><title>Apache Info</title>");

   r.write("
Apache Server Information
");

   let server_name = r.escape_html(r.server_name().unwrap()).unwrap();
   let server_port = r.server_port();
   let local_ip = conn.local_ip().unwrap();
   r.write(format!("
Server: {}:{} (via {})
", server_name, server_port, local_ip));

   let server_description = get_server_description().unwrap();
   r.write(format!("
Server Version: {}
", server_description));

   let mmp = show_mpm().unwrap();
   r.write(format!("
Server MPM: {}
", mmp));

   let server_built = get_server_built().unwrap();
   r.write(format!("
Server Built: {}
", server_built));

   let apr_version = apr_version_string().unwrap();
   r.write(format!("
Server loaded APR Version: {}
", apr_version));

   let apu_version = apu_version_string().unwrap();
   r.write(format!("
Server loaded APU Version: {}
", apu_version));

   r.write("
");

   let client_ip = conn.client_ip().unwrap();
   r.write(format!("
Client IP: {}
", client_ip));

   let args = match r.args() {
      Some(args) => args,
      None => "None"
   };
   r.write(format!("
Request Args: {}
", args));

   r.write("");

   Status::OK
}
<|endoftext|>


<commit_before>use parse::IrcMsg;

fn byte_length_sum(items: &[&str]) -> usize {
    use std::iter::AdditiveIterator;
    items.iter().map(|x| x.as_bytes().len()).sum()
}

macro_rules! msg_wrapper_common {
    ($t:ident) => {
        impl $t {
            pub fn into_bytes(self) -> Vec<u8> {
                self.into_irc_msg().into_bytes()
            }

            pub fn into_irc_msg(self) -> IrcMsg {
                let $t(msg) = self;
                msg
            }

            pub fn to_irc_msg<'a>(&'a self) -> &'a IrcMsg {
                let $t(ref msg) = *self;
                msg
            }
        }
    }
}

#[derive(Clone, Show)]
pub struct Join(IrcMsg);
msg_wrapper_common!(Join);

impl Join {
    pub fn new(channel: &str) -> Join {
        let output_length = byte_length_sum(&[channel]) + 5;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_with_key(channel: &str, key: &str) -> Join {
        let output_length = byte_length_sum(&[channel, key]) + 6;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());
        msg.push_all(b" ");
        msg.push_all(key.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Nick(IrcMsg);
msg_wrapper_common!(Nick);

impl Nick {
    pub fn new(argument: &str) -> Nick {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"NICK ");
        msg.push_all(argument.as_bytes());
        Nick(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Pong(IrcMsg);
msg_wrapper_common!(Pong);

impl Pong {
    pub fn new(argument: &str) -> Pong {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"PONG ");
        msg.push_all(argument.as_bytes());
        Pong(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Privmsg(IrcMsg);
msg_wrapper_common!(Privmsg);

impl Privmsg {
    pub fn new(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" :");
        msg.push_all(argument);

        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_ctcp(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" \x01");
        msg.push_all(argument);
        msg.push_all(b"\x01");
        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct User(IrcMsg);
msg_wrapper_common!(User);

impl User {
    //  <user> <mode> <unused> <realname>
    pub fn new(user: &str, mode: &str, unused: &str, realname: &str) -> User {

        let output_length = byte_length_sum(&[user, mode, unused, realname]) + 8;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"USER ");
        msg.push_all(mode.as_bytes());
        msg.push_all(b" ");
        msg.push_all(unused.as_bytes());
        msg.push_all(b" :");
        msg.push_all(realname.as_bytes());

        User(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Who(IrcMsg);
msg_wrapper_common!(Who);

impl Who {
    pub fn new(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_opers(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" o");

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}
<commit_msg>Fix USER command<commit_after>use parse::IrcMsg;

fn byte_length_sum(items: &[&str]) -> usize {
    use std::iter::AdditiveIterator;
    items.iter().map(|x| x.as_bytes().len()).sum()
}

macro_rules! msg_wrapper_common {
    ($t:ident) => {
        impl $t {
            pub fn into_bytes(self) -> Vec<u8> {
                self.into_irc_msg().into_bytes()
            }

            pub fn into_irc_msg(self) -> IrcMsg {
                let $t(msg) = self;
                msg
            }

            pub fn to_irc_msg<'a>(&'a self) -> &'a IrcMsg {
                let $t(ref msg) = *self;
                msg
            }
        }
    }
}

#[derive(Clone, Show)]
pub struct Join(IrcMsg);
msg_wrapper_common!(Join);

impl Join {
    pub fn new(channel: &str) -> Join {
        let output_length = byte_length_sum(&[channel]) + 5;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_with_key(channel: &str, key: &str) -> Join {
        let output_length = byte_length_sum(&[channel, key]) + 6;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"JOIN ");
        msg.push_all(channel.as_bytes());
        msg.push_all(b" ");
        msg.push_all(key.as_bytes());

        Join(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Nick(IrcMsg);
msg_wrapper_common!(Nick);

impl Nick {
    pub fn new(argument: &str) -> Nick {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"NICK ");
        msg.push_all(argument.as_bytes());
        Nick(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Pong(IrcMsg);
msg_wrapper_common!(Pong);

impl Pong {
    pub fn new(argument: &str) -> Pong {
        let mut msg = Vec::with_capacity(5 + argument.as_bytes().len());
        msg.push_all(b"PONG ");
        msg.push_all(argument.as_bytes());
        Pong(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Privmsg(IrcMsg);
msg_wrapper_common!(Privmsg);

impl Privmsg {
    pub fn new(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" :");
        msg.push_all(argument);

        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_ctcp(target: &str, argument: &[u8]) -> Privmsg {
        let mut msg = Vec::new();
        msg.push_all(b"PRIVMSG ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" \x01");
        msg.push_all(argument);
        msg.push_all(b"\x01");
        Privmsg(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct User(IrcMsg);
msg_wrapper_common!(User);

impl User {
    //  <user> <mode> <unused> <realname>
    pub fn new(user: &str, mode: &str, unused: &str, realname: &str) -> User {

        let output_length = byte_length_sum(&[user, mode, unused, realname]) + 8;

        let mut msg = Vec::with_capacity(output_length);
        msg.push_all(b"USER ");
        msg.push_all(user.as_bytes());
        msg.push_all(b" ");
        msg.push_all(mode.as_bytes());
        msg.push_all(b" ");
        msg.push_all(unused.as_bytes());
        msg.push_all(b" :");
        msg.push_all(realname.as_bytes());

        User(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}

#[derive(Clone, Show)]
pub struct Who(IrcMsg);
msg_wrapper_common!(Who);

impl Who {
    pub fn new(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }

    pub fn new_opers(target: &str) -> Who {
        let mut msg = Vec::new();
        msg.push_all(b"WHO ");
        msg.push_all(target.as_bytes());
        msg.push_all(b" o");

        Who(IrcMsg::new(msg).ok().expect("Generated invalid message"))
    }
}
<|endoftext|>