<commit_before>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! Public/Private keys

use std::intrinsics::copy_nonoverlapping_memory;
use std::fmt;
use std::rand::Rng;
use constants;
use ffi;

use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey};

/// Secret 256-bit nonce used as `k` in an ECDSA signature
pub struct Nonce([u8, ..constants::NONCE_SIZE]);

/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);

/// Public key
#[deriving(PartialEq, Eq, Show)]
pub struct PublicKey(PublicKeyData);

enum PublicKeyData {
    Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
    Uncompressed([u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
}

fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8, ..32] {
    [rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen(),
     rng.gen(), rng.gen(), rng.gen(), rng.gen()]
}

impl Nonce {
    /// Creates a new random nonce
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> Nonce {
        Nonce(random_32_bytes(rng))
    }

    /// Converts a `NONCE_SIZE`-byte slice to a nonce
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<Nonce> {
        match data.len() {
            constants::NONCE_SIZE => {
                let mut ret = [0, ..constants::NONCE_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(Nonce(ret))
            }
            _ => Err(InvalidNonce)
        }
    }

    /// Converts the nonce into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &Nonce(ref data) = self;
        data.as_slice()
    }

    /// Converts the nonce to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &Nonce(ref data) = self;
        data.as_ptr()
    }
}

impl SecretKey {
    /// Creates a new random secret key
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> SecretKey {
        SecretKey(random_32_bytes(rng))
    }

    /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<SecretKey> {
        match data.len() {
            constants::SECRET_KEY_SIZE => {
                let mut ret = [0, ..constants::SECRET_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(SecretKey(ret))
            }
            _ => Err(InvalidSecretKey)
        }
    }

    /// Converts the secret key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &SecretKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the secret key to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &SecretKey(ref data) = self;
        data.as_ptr()
    }
}

impl PublicKey {
    /// Creates a new zeroed out public key
    #[inline]
    pub fn new(compressed: bool) -> PublicKey {
        PublicKey(
            if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
            else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
        )
    }

    /// Creates a new public key from a secret key. Marked `unsafe` since you must
    /// call `init()` (or construct a `Secp256k1`, which does this for you) before
    /// using this function
    #[inline]
    pub unsafe fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey {
        let mut pk = PublicKey::new(compressed);
        let compressed = if compressed {1} else {0};
        let mut len = 0;

        while ffi::secp256k1_ecdsa_pubkey_create(
            pk.as_mut_ptr(), &mut len,
            sk.as_ptr(), compressed) != 1 {
            // loop
        }
        assert_eq!(len as uint, pk.len());

        pk
    }

    /// Creates a public key directly from a slice
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
        match data.len() {
            constants::COMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Compressed(ret)))
            }
            constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Uncompressed(ret)))
            }
            _ => Err(InvalidPublicKey)
        }
    }

    /// Returns whether the public key is compressed or uncompressed
    #[inline]
    pub fn is_compressed(&self) -> bool {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(_) => true,
            Uncompressed(_) => false
        }
    }

    /// Returns the length of the public key
    #[inline]
    pub fn len(&self) -> uint {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.len(),
            Uncompressed(ref x) => x.len()
        }
    }

    /// Converts the public key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &PublicKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the public key to a raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.as_ptr(),
            Uncompressed(ref x) => x.as_ptr()
        }
    }

    /// Converts the public key to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &PublicKey(ref mut data) = self;
        match *data {
            Compressed(ref mut x) => x.as_mut_ptr(),
            Uncompressed(ref mut x) => x.as_mut_ptr()
        }
    }
}

impl PublicKeyData {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            Compressed(ref x) => x.as_slice(),
            Uncompressed(ref x) => x.as_slice()
        }
    }
}

// We have to do all these impls ourselves as Rust can't derive
// them for arrays
impl PartialEq for Nonce {
    fn eq(&self, other: &Nonce) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for Nonce {}

impl fmt::Show for Nonce {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl PartialEq for PublicKeyData {
    fn eq(&self, other: &PublicKeyData) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for PublicKeyData {}

impl fmt::Show for PublicKeyData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl PartialEq for SecretKey {
    fn eq(&self, other: &SecretKey) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for SecretKey {}

impl fmt::Show for SecretKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

#[cfg(test)]
mod test {
    use std::rand::task_rng;

    use super::super::{Secp256k1, InvalidNonce, InvalidPublicKey, InvalidSecretKey};
    use super::*;

    #[test]
    fn nonce_from_slice() {
        let n = Nonce::from_slice([1, ..31]);
        assert_eq!(n, Err(InvalidNonce));

        let n = SecretKey::from_slice([1, ..32]);
        assert!(n.is_ok());
    }

    #[test]
    fn skey_from_slice() {
        let sk = SecretKey::from_slice([1, ..31]);
        assert_eq!(sk, Err(InvalidSecretKey));

        let sk = SecretKey::from_slice([1, ..32]);
        assert!(sk.is_ok());
    }

    #[test]
    fn pubkey_from_slice() {
        assert_eq!(PublicKey::from_slice([]), Err(InvalidPublicKey));
        assert_eq!(PublicKey::from_slice([1, 2, 3]), Err(InvalidPublicKey));

        let uncompressed = PublicKey::from_slice([1, ..65]);
        assert!(uncompressed.is_ok());
        assert!(!uncompressed.unwrap().is_compressed());

        let compressed = PublicKey::from_slice([1, ..33]);
        assert!(compressed.is_ok());
        assert!(compressed.unwrap().is_compressed());
    }

    #[test]
    fn keypair_slice_round_trip() {
        let mut s = Secp256k1::new();

        let (sk1, pk1) = s.generate_keypair(true).unwrap();
        assert_eq!(SecretKey::from_slice(sk1.as_slice()), Ok(sk1));
        assert_eq!(PublicKey::from_slice(pk1.as_slice()), Ok(pk1));

        let (sk2, pk2) = s.generate_keypair(false).unwrap();
        assert_eq!(SecretKey::from_slice(sk2.as_slice()), Ok(sk2));
        assert_eq!(PublicKey::from_slice(pk2.as_slice()), Ok(pk2));
    }

    #[test]
    fn nonce_slice_round_trip() {
        let mut rng = task_rng();
        let nonce = Nonce::new(&mut rng);
        assert_eq!(Nonce::from_slice(nonce.as_slice()), Ok(nonce));
    }
}

<commit_msg>Simpler `random_32_bytes`.<commit_after>// Bitcoin secp256k1 bindings
// Written in 2014 by
//   Dawid Ciężarkiewicz
//   Andrew Poelstra
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! Public/Private keys

use std::intrinsics::copy_nonoverlapping_memory;
use std::fmt;
use std::rand::Rng;
use constants;
use ffi;

use super::{Result, InvalidNonce, InvalidPublicKey, InvalidSecretKey};

/// Secret 256-bit nonce used as `k` in an ECDSA signature
pub struct Nonce([u8, ..constants::NONCE_SIZE]);

/// Secret 256-bit key used as `x` in an ECDSA signature
pub struct SecretKey([u8, ..constants::SECRET_KEY_SIZE]);

/// Public key
#[deriving(PartialEq, Eq, Show)]
pub struct PublicKey(PublicKeyData);

enum PublicKeyData {
    Compressed([u8, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]),
    Uncompressed([u8, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]),
}

fn random_32_bytes<R:Rng>(rng: &mut R) -> [u8, ..32] {
    let mut ret = [0u8, ..32];
    rng.fill_bytes(ret);
    ret
}

impl Nonce {
    /// Creates a new random nonce
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> Nonce {
        Nonce(random_32_bytes(rng))
    }

    /// Converts a `NONCE_SIZE`-byte slice to a nonce
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<Nonce> {
        match data.len() {
            constants::NONCE_SIZE => {
                let mut ret = [0, ..constants::NONCE_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(Nonce(ret))
            }
            _ => Err(InvalidNonce)
        }
    }

    /// Converts the nonce into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &Nonce(ref data) = self;
        data.as_slice()
    }

    /// Converts the nonce to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &Nonce(ref data) = self;
        data.as_ptr()
    }
}

impl SecretKey {
    /// Creates a new random secret key
    #[inline]
    pub fn new<R:Rng>(rng: &mut R) -> SecretKey {
        SecretKey(random_32_bytes(rng))
    }

    /// Converts a `SECRET_KEY_SIZE`-byte slice to a secret key
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<SecretKey> {
        match data.len() {
            constants::SECRET_KEY_SIZE => {
                let mut ret = [0, ..constants::SECRET_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(SecretKey(ret))
            }
            _ => Err(InvalidSecretKey)
        }
    }

    /// Converts the secret key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &SecretKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the secret key to a raw pointer suitable for use with
    /// the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &SecretKey(ref data) = self;
        data.as_ptr()
    }
}

impl PublicKey {
    /// Creates a new zeroed out public key
    #[inline]
    pub fn new(compressed: bool) -> PublicKey {
        PublicKey(
            if compressed { Compressed([0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE]) }
            else { Uncompressed([0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE]) }
        )
    }

    /// Creates a new public key from a secret key. Marked `unsafe` since you must
    /// call `init()` (or construct a `Secp256k1`, which does this for you) before
    /// using this function
    #[inline]
    pub unsafe fn from_secret_key(sk: &SecretKey, compressed: bool) -> PublicKey {
        let mut pk = PublicKey::new(compressed);
        let compressed = if compressed {1} else {0};
        let mut len = 0;

        while ffi::secp256k1_ecdsa_pubkey_create(
            pk.as_mut_ptr(), &mut len,
            sk.as_ptr(), compressed) != 1 {
            // loop
        }
        assert_eq!(len as uint, pk.len());

        pk
    }

    /// Creates a public key directly from a slice
    #[inline]
    pub fn from_slice(data: &[u8]) -> Result<PublicKey> {
        match data.len() {
            constants::COMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::COMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Compressed(ret)))
            }
            constants::UNCOMPRESSED_PUBLIC_KEY_SIZE => {
                let mut ret = [0, ..constants::UNCOMPRESSED_PUBLIC_KEY_SIZE];
                unsafe {
                    copy_nonoverlapping_memory(ret.as_mut_ptr(),
                                               data.as_ptr(),
                                               data.len());
                }
                Ok(PublicKey(Uncompressed(ret)))
            }
            _ => Err(InvalidPublicKey)
        }
    }

    /// Returns whether the public key is compressed or uncompressed
    #[inline]
    pub fn is_compressed(&self) -> bool {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(_) => true,
            Uncompressed(_) => false
        }
    }

    /// Returns the length of the public key
    #[inline]
    pub fn len(&self) -> uint {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.len(),
            Uncompressed(ref x) => x.len()
        }
    }

    /// Converts the public key into a byte slice
    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        let &PublicKey(ref data) = self;
        data.as_slice()
    }

    /// Converts the public key to a raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_ptr(&self) -> *const u8 {
        let &PublicKey(ref data) = self;
        match *data {
            Compressed(ref x) => x.as_ptr(),
            Uncompressed(ref x) => x.as_ptr()
        }
    }

    /// Converts the public key to a mutable raw pointer suitable for use
    /// with the FFI functions
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut u8 {
        let &PublicKey(ref mut data) = self;
        match *data {
            Compressed(ref mut x) => x.as_mut_ptr(),
            Uncompressed(ref mut x) => x.as_mut_ptr()
        }
    }
}

impl PublicKeyData {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            Compressed(ref x) => x.as_slice(),
            Uncompressed(ref x) => x.as_slice()
        }
    }
}

// We have to do all these impls ourselves as Rust can't derive
// them for arrays
impl PartialEq for Nonce {
    fn eq(&self, other: &Nonce) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for Nonce {}

impl fmt::Show for Nonce {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl PartialEq for PublicKeyData {
    fn eq(&self, other: &PublicKeyData) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for PublicKeyData {}

impl fmt::Show for PublicKeyData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

impl PartialEq for SecretKey {
    fn eq(&self, other: &SecretKey) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl Eq for SecretKey {}

impl fmt::Show for SecretKey {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}

#[cfg(test)]
mod test {
    use std::rand::task_rng;

    use super::super::{Secp256k1, InvalidNonce, InvalidPublicKey, InvalidSecretKey};
    use super::*;

    #[test]
    fn nonce_from_slice() {
        let n = Nonce::from_slice([1, ..31]);
        assert_eq!(n, Err(InvalidNonce));

        let n = SecretKey::from_slice([1, ..32]);
        assert!(n.is_ok());
    }

    #[test]
    fn skey_from_slice() {
        let sk = SecretKey::from_slice([1, ..31]);
        assert_eq!(sk, Err(InvalidSecretKey));

        let sk = SecretKey::from_slice([1, ..32]);
        assert!(sk.is_ok());
    }

    #[test]
    fn pubkey_from_slice() {
        assert_eq!(PublicKey::from_slice([]), Err(InvalidPublicKey));
        assert_eq!(PublicKey::from_slice([1, 2, 3]), Err(InvalidPublicKey));

        let uncompressed = PublicKey::from_slice([1, ..65]);
        assert!(uncompressed.is_ok());
        assert!(!uncompressed.unwrap().is_compressed());

        let compressed = PublicKey::from_slice([1, ..33]);
        assert!(compressed.is_ok());
        assert!(compressed.unwrap().is_compressed());
    }

    #[test]
    fn keypair_slice_round_trip() {
        let mut s = Secp256k1::new();

        let (sk1, pk1) = s.generate_keypair(true).unwrap();
        assert_eq!(SecretKey::from_slice(sk1.as_slice()), Ok(sk1));
        assert_eq!(PublicKey::from_slice(pk1.as_slice()), Ok(pk1));

        let (sk2, pk2) = s.generate_keypair(false).unwrap();
        assert_eq!(SecretKey::from_slice(sk2.as_slice()), Ok(sk2));
        assert_eq!(PublicKey::from_slice(pk2.as_slice()), Ok(pk2));
    }

    #[test]
    fn nonce_slice_round_trip() {
        let mut rng = task_rng();
        let nonce = Nonce::new(&mut rng);
        assert_eq!(Nonce::from_slice(nonce.as_slice()), Ok(nonce));
    }
}

<|endoftext|>


<commit_before>use std::fmt::Debug;

pub trait Key: Copy + PartialEq + Ord + Default + Debug {
    type Bytes: AsRef<[u8]>;
    const SIZE: usize;
    fn into_bytes(self) -> Self::Bytes;
    fn from_bytes(bytes: Self::Bytes) -> Self;
}

macro_rules! impl_key {
    ($type:ident, $size:expr) => {
        impl Key for $type {
            type Bytes = [u8; $size];
            const SIZE: usize = $size;
            fn into_bytes(self) -> Self::Bytes {
                unsafe {
                    ::std::mem::transmute(self.to_be())
                }
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                let integer = unsafe {
                    ::std::mem::transmute(bytes)
                };
                $type::from_be(integer)
            }
        }
    }
}

impl_key!(u8, 1);
impl_key!(u16, 2);
impl_key!(u32, 4);
impl_key!(u64, 8);
#[cfg(feature = "i128")]
impl_key!(u128, 16);
#[cfg(target_pointer_width = "32")]
impl_key!(usize, 4);
#[cfg(target_pointer_width = "64")]
impl_key!(usize, 8);
<commit_msg>Remove unneeded associated const<commit_after>use std::fmt::Debug;

pub trait Key: Copy + PartialEq + Ord + Default + Debug {
    type Bytes: AsRef<[u8]>;
    fn into_bytes(self) -> Self::Bytes;
    fn from_bytes(bytes: Self::Bytes) -> Self;
}

macro_rules! impl_key {
    ($type:ident, $size:expr) => {
        impl Key for $type {
            type Bytes = [u8; $size];
            fn into_bytes(self) -> Self::Bytes {
                unsafe {
                    ::std::mem::transmute(self.to_be())
                }
            }

            fn from_bytes(bytes: Self::Bytes) -> Self {
                let integer = unsafe {
                    ::std::mem::transmute(bytes)
                };
                $type::from_be(integer)
            }
        }
    }
}

impl_key!(u8, 1);
impl_key!(u16, 2);
impl_key!(u32, 4);
impl_key!(u64, 8);
#[cfg(feature = "i128")]
impl_key!(u128, 16);
#[cfg(target_pointer_width = "32")]
impl_key!(usize, 4);
#[cfg(target_pointer_width = "64")]
impl_key!(usize, 8);
<|endoftext|>


<commit_before>use std::cmp::max;

// strsplit is like `s.split(split)`, except that if `split` is "", it
// trims the leading and trailing empty elements, since the `lcs`
// logic won't handle those properly.
fn strsplit<'a>(s: &'a str, split: &str) -> Vec<&'a str> {
    let mut si = s.split(split);
    if split == "" {
        si.next();
    }
    let mut v: Vec<&str> = si.collect();
    if split == "" {
        v.pop();
    }
    v
}

// finds the longest common subsequences
// outputs the edit distance and a string containing
// all chars both inputs have in common
#[allow(non_snake_case)]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
pub fn lcs(orig: &str, edit: &str, split: &str) -> (i32, String) {
    // make list by custom splits
    let a = strsplit(orig, split);
    let b = strsplit(edit, split);

    let N = a.len();
    let M = b.len();

    let mut idx: Vec<usize> = Vec::with_capacity(N * M);
    idx.resize(N * M, 0);

    for i in 0..N {
        for j in 0..M {
            if b[j] == a[i] {
                if i == 0 || j == 0 {
                    idx[i * M + j] = 1;
                } else {
                    idx[i * M + j] = idx[(i - 1) * M + j - 1] + 1;
                }
            } else if i == 0 {
                if j == 0 {
                    idx[i * M + j] = 0;
                } else {
                    idx[i * M + j] = idx[i * M + j - 1];
                }
            } else if j == 0 {
                idx[i * M + j] = idx[(i - 1) * M + j];
            } else {
                idx[i * M + j] = max(idx[i * M + j - 1], idx[(i - 1) * M + j]);
            }
        }
    }

    let mut i = (N as isize) - 1;
    let mut j = (M as isize) - 1;
    let mut lcs = Vec::new();
    while i >= 0 && j >= 0 {
        let ui = i as usize;
        let uj = j as usize;
        if a[ui] == b[uj] {
            lcs.push(a[ui]);
            i -= 1;
            j -= 1;
        } else if j == 0 && i == 0 {
            break;
        } else if i == 0 || idx[ui * M + uj - 1] > idx[(ui - 1) * M + uj] {
            j -= 1;
        } else {
            i -= 1;
        }
    }

    lcs.reverse();
    ((N + M - 2 * lcs.len()) as i32, lcs.join(split))
}

#[test]
fn test_lcs() {
    assert_eq!(lcs("test", "tost", ""), (2, "tst".to_string()));
    assert_eq!(lcs("test", "test", ""), (0, "test".to_string()));

    assert_eq!(lcs("test", "test", " "), (0, "test".to_string()));

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "",
        ),
        (16, "The quick brown o ps over the lazy ".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            " ",
        ),
        (6, "The quick brown over the lazy".to_string())
    );

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "\n",
        ),
        (2, "".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown fox jumps over the lazy dog",
            "\n",
        ),
        (0, "The quick brown fox jumps over the lazy dog".to_string())
    );

    assert_eq!(
        lcs("a b : c", "b a : b : c", " "),
        (2, "a b : c".to_string())
    );

    assert_eq!(lcs("", "a b c", ""), (5, "".to_string()));

    assert_eq!(lcs("", " a", " "), (1, "".to_string()));
}
<commit_msg>Comment attributing algorithm to wikipedia article.<commit_after>use std::cmp::max;

// strsplit is like `s.split(split)`, except that if `split` is "", it
// trims the leading and trailing empty elements, since the `lcs`
// logic won't handle those properly.
fn strsplit<'a>(s: &'a str, split: &str) -> Vec<&'a str> {
    let mut si = s.split(split);
    if split == "" {
        si.next();
    }
    let mut v: Vec<&str> = si.collect();
    if split == "" {
        v.pop();
    }
    v
}

// finds the longest common subsequences
// outputs the edit distance and a string containing
// all chars both inputs have in common
//
// This algorithm is based on
// https://en.wikipedia.org/wiki/Longest_common_subsequence_problem#Code_for_the_dynamic_programming_solution
#[allow(non_snake_case)]
#[cfg_attr(feature = "cargo-clippy", allow(many_single_char_names))]
pub fn lcs(orig: &str, edit: &str, split: &str) -> (i32, String) {
    // make list by custom splits
    let a = strsplit(orig, split);
    let b = strsplit(edit, split);

    let N = a.len();
    let M = b.len();

    let mut idx: Vec<usize> = Vec::with_capacity(N * M);
    idx.resize(N * M, 0);

    for i in 0..N {
        for j in 0..M {
            if b[j] == a[i] {
                if i == 0 || j == 0 {
                    idx[i * M + j] = 1;
                } else {
                    idx[i * M + j] = idx[(i - 1) * M + j - 1] + 1;
                }
            } else if i == 0 {
                if j == 0 {
                    idx[i * M + j] = 0;
                } else {
                    idx[i * M + j] = idx[i * M + j - 1];
                }
            } else if j == 0 {
                idx[i * M + j] = idx[(i - 1) * M + j];
            } else {
                idx[i * M + j] = max(idx[i * M + j - 1], idx[(i - 1) * M + j]);
            }
        }
    }

    let mut i = (N as isize) - 1;
    let mut j = (M as isize) - 1;
    let mut lcs = Vec::new();
    while i >= 0 && j >= 0 {
        let ui = i as usize;
        let uj = j as usize;
        if a[ui] == b[uj] {
            lcs.push(a[ui]);
            i -= 1;
            j -= 1;
        } else if j == 0 && i == 0 {
            break;
        } else if i == 0 || idx[ui * M + uj - 1] > idx[(ui - 1) * M + uj] {
            j -= 1;
        } else {
            i -= 1;
        }
    }

    lcs.reverse();
    ((N + M - 2 * lcs.len()) as i32, lcs.join(split))
}

#[test]
fn test_lcs() {
    assert_eq!(lcs("test", "tost", ""), (2, "tst".to_string()));
    assert_eq!(lcs("test", "test", ""), (0, "test".to_string()));

    assert_eq!(lcs("test", "test", " "), (0, "test".to_string()));

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "",
        ),
        (16, "The quick brown o ps over the lazy ".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            " ",
        ),
        (6, "The quick brown over the lazy".to_string())
    );

    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown dog leaps over the lazy cat",
            "\n",
        ),
        (2, "".to_string())
    );
    assert_eq!(
        lcs(
            "The quick brown fox jumps over the lazy dog",
            "The quick brown fox jumps over the lazy dog",
            "\n",
        ),
        (0, "The quick brown fox jumps over the lazy dog".to_string())
    );

    assert_eq!(
        lcs("a b : c", "b a : b : c", " "),
        (2, "a b : c".to_string())
    );

    assert_eq!(lcs("", "a b c", ""), (5, "".to_string()));

    assert_eq!(lcs("", " a", " "), (1, "".to_string()));
}
<|endoftext|>


<commit_before>//! Iterator zippers
//!
//! This crate provides "zippers" as tuple structs: `Zip2`, `Zip3`, etc. These structs accept
//! iterators as fields, and provides iteration over the "zipped" elements.
//!
//! The functionality is similar to the `Iterator::zip` method. The difference is that the `zip`
//! method always produces an iterator that yields *two-element* tuples. If you want to zip 3
//! iterators, you'll write `xs.zip(ys).zip(zs)` which returns an iterator that yields elements of
//! type `((X, Y), Z)`. On the other hand, with this library you can write `Zip3(xs, ys, zs)` which
//! is an iterator that yields elements of type `(X, Y, Z)`.
//!
//! ```
//! use zip::Zip3;
//!
//! let chars = &['a', 'b', 'c'];
//! let mut v = vec![0u, 1, 2];
//! for (&c, i, &mut j) in Zip3(chars.iter(), range(0u, 5), v.iter_mut()) {
//!     assert!(i < 3);
//!     assert_eq!(i, j);
//! }
//! ```

#![deny(missing_docs, warnings)]

/// This macro emulates an "any-arity" free function that zips iterators
///
/// **Note** This macro calls `into_iter()` on the inputs. For this reason, this macro won't work
/// until `IntoIterator` lands in stdlib, or unless you provide your own `IntoIterator` trait.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate zip;
///
/// # use std::slice;
/// # trait IntoIterator {
/// #     type Iter: Iterator;
/// #     fn into_iter(self) -> Self::Iter;
/// # }
/// # impl<I> IntoIterator for I where I: Iterator {
/// #     type Iter = I;
/// #     fn into_iter(self) -> I { self }
/// # }
/// # impl<'a, T> IntoIterator for &'a [T] {
/// #     type Iter = slice::Iter<'a, T>;
/// #     fn into_iter(self) -> slice::Iter<'a, T> { self.iter() }
/// # }
/// # impl<'a, T> IntoIterator for &'a mut Vec<T> {
/// #     type Iter = slice::IterMut<'a, T>;
/// #     fn into_iter(self) -> slice::IterMut<'a, T> { self.iter_mut() }
/// # }
/// # fn main() {
/// let chars = &['a', 'b', 'c'];
/// let mut v = vec![0u, 1, 2];
///
/// for (&c, i, &mut j) in zip!(chars, range(0u, 5), &mut v) {
///     assert!(i < 3);
///     assert_eq!(i, j);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! zip {
    ($a:expr, $b:expr) => {
        $crate::Zip2(($a).into_iter(), ($b).into_iter())
    };
    ($a:expr, $b:expr, $c:expr) => {
        $crate::Zip3(($a).into_iter(), ($b).into_iter(), ($c).into_iter())
    };
    ($a:expr, $b:expr, $c:expr, $d:expr) => {
        $crate::Zip4(($a).into_iter(), ($b).into_iter(), ($c).into_iter(), ($d).into_iter())
    };
    ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr) => {
        $crate::Zip5(
            ($a).into_iter(),
            ($b).into_iter(),
            ($c).into_iter(),
            ($d).into_iter(),
            ($e).into_iter(),
        )
    };
    ($($x:expr),+,) => { zip!($($x),+) }
}

macro_rules! min {
    ($x:expr) => { $x };
    ($x:expr, $($y:expr),+) => { ::std::cmp::min($x, min!($($y),+)) };
    ($($x:expr),+,) => { min!($($x),+) };
}

/// Two-iterator zipper
pub struct Zip2<A, B>(pub A, pub B);

impl<A, B, AI, BI> Iterator for Zip2<AI, BI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
{
    type Item = (A, B);

    fn next(&mut self) -> Option<(A, B)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                return Some((a, b));
            }
        }

        None
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
        }, None)
    }
}

/// Three-iterator zipper
pub struct Zip3<A, B, C>(pub A, pub B, pub C);

impl<A, B, C, AI, BI, CI> Iterator for Zip3<AI, BI, CI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
{
    type Item = (A, B, C);

    fn next(&mut self) -> Option<(A, B, C)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    return Some((a, b, c));
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
        }, None)
    }
}

/// Four-iterator zipper
pub struct Zip4<A, B, C, D>(pub A, pub B, pub C, pub D);

impl<A, B, C, D, AI, BI, CI, DI> Iterator for Zip4<AI, BI, CI, DI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
    DI: Iterator<Item=D>,
{
    type Item = (A, B, C, D);

    fn next(&mut self) -> Option<(A, B, C, D)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    if let Some(d) = self.3.next() {
                        return Some((a, b, c, d))
                    }
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
            self.3.size_hint().0,
        }, None)
    }
}

/// Five-iterator zipper
pub struct Zip5<A, B, C, D, E>(pub A, pub B, pub C, pub D, pub E);

impl<A, B, C, D, E, AI, BI, CI, DI, EI> Iterator for Zip5<AI, BI, CI, DI, EI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
    DI: Iterator<Item=D>,
    EI: Iterator<Item=E>,
{
    type Item = (A, B, C, D, E);

    fn next(&mut self) -> Option<(A, B, C, D, E)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    if let Some(d) = self.3.next() {
                        if let Some(e) = self.4.next() {
                            return Some((a, b, c, d, e))
                        }
                    }
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
            self.3.size_hint().0,
            self.4.size_hint().0,
        }, None)
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use self::test::Bencher;

    const SIZE: uint = 1024;

    #[bench]
    fn collect2(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            ::Zip2(a.iter(), b.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect2_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            a.iter().zip(b.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count2(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            ::Zip2(a.iter(), b.iter()).count()
        })
    }

    #[bench]
    fn count2_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            a.iter().zip(b.iter()).count()
        })
    }

    #[bench]
    fn collect3(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            ::Zip3(a.iter(), b.iter(), c.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect3_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count3(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            ::Zip3(a.iter(), b.iter(), c.iter()).count()
        })
    }

    #[bench]
    fn count3_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).count()
        })
    }

    #[bench]
    fn collect4(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            ::Zip4(a.iter(), b.iter(), c.iter(), d.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect4_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count4(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            ::Zip4(a.iter(), b.iter(), c.iter(), d.iter()).count()
        })
    }

    #[bench]
    fn count4_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).count()
        })
    }

    #[bench]
    fn collect5(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            ::Zip5(a.iter(), b.iter(), c.iter(), d.iter(), e.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect5_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).zip(e.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count5(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            ::Zip5(a.iter(), b.iter(), c.iter(), d.iter(), e.iter()).count()
        })
    }

    #[bench]
    fn count5_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).zip(e.iter()).count()
        })
    }
}
<commit_msg>fix: update to rust nightly<commit_after>//! Iterator zippers
//!
//! This crate provides "zippers" as tuple structs: `Zip2`, `Zip3`, etc. These structs accept
//! iterators as fields, and provides iteration over the "zipped" elements.
//!
//! The functionality is similar to the `Iterator::zip` method. The difference is that the `zip`
//! method always produces an iterator that yields *two-element* tuples. If you want to zip 3
//! iterators, you'll write `xs.zip(ys).zip(zs)` which returns an iterator that yields elements of
//! type `((X, Y), Z)`. On the other hand, with this library you can write `Zip3(xs, ys, zs)` which
//! is an iterator that yields elements of type `(X, Y, Z)`.
//!
//! ```
//! use zip::Zip3;
//!
//! let chars = &['a', 'b', 'c'];
//! let mut v = vec![0, 1, 2];
//! for (&c, i, &mut j) in Zip3(chars.iter(), 0..5, v.iter_mut()) {
//!     assert!(i < 3);
//!     assert_eq!(i, j);
//! }
//! ```

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

/// This macro emulates an "any-arity" free function that zips iterators
///
/// **Note** This macro calls `into_iter()` on the inputs. For this reason, this macro won't work
/// until `IntoIterator` lands in stdlib, or unless you provide your own `IntoIterator` trait.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate zip;
///
/// # use std::slice;
/// # trait IntoIterator {
/// #     type Iter: Iterator;
/// #     fn into_iter(self) -> Self::Iter;
/// # }
/// # impl<I> IntoIterator for I where I: Iterator {
/// #     type Iter = I;
/// #     fn into_iter(self) -> I { self }
/// # }
/// # impl<'a, T> IntoIterator for &'a [T] {
/// #     type Iter = slice::Iter<'a, T>;
/// #     fn into_iter(self) -> slice::Iter<'a, T> { self.iter() }
/// # }
/// # impl<'a, T> IntoIterator for &'a mut Vec<T> {
/// #     type Iter = slice::IterMut<'a, T>;
/// #     fn into_iter(self) -> slice::IterMut<'a, T> { self.iter_mut() }
/// # }
/// # fn main() {
/// let chars = &['a', 'b', 'c'];
/// let mut v = vec![0, 1, 2];
///
/// for (&c, i, &mut j) in zip!(chars, 0..5, &mut v) {
///     assert!(i < 3);
///     assert_eq!(i, j);
/// }
/// # }
/// ```
#[macro_export]
macro_rules! zip {
    ($a:expr, $b:expr) => {
        $crate::Zip2(($a).into_iter(), ($b).into_iter())
    };
    ($a:expr, $b:expr, $c:expr) => {
        $crate::Zip3(($a).into_iter(), ($b).into_iter(), ($c).into_iter())
    };
    ($a:expr, $b:expr, $c:expr, $d:expr) => {
        $crate::Zip4(($a).into_iter(), ($b).into_iter(), ($c).into_iter(), ($d).into_iter())
    };
    ($a:expr, $b:expr, $c:expr, $d:expr, $e:expr) => {
        $crate::Zip5(
            ($a).into_iter(),
            ($b).into_iter(),
            ($c).into_iter(),
            ($d).into_iter(),
            ($e).into_iter(),
        )
    };
    ($($x:expr),+,) => { zip!($($x),+) }
}

macro_rules! min {
    ($x:expr) => { $x };
    ($x:expr, $($y:expr),+) => { ::std::cmp::min($x, min!($($y),+)) };
    ($($x:expr),+,) => { min!($($x),+) };
}

/// Two-iterator zipper
pub struct Zip2<A, B>(pub A, pub B);

impl<A, B, AI, BI> Iterator for Zip2<AI, BI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
{
    type Item = (A, B);

    fn next(&mut self) -> Option<(A, B)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                return Some((a, b));
            }
        }

        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
        }, None)
    }
}

/// Three-iterator zipper
pub struct Zip3<A, B, C>(pub A, pub B, pub C);

impl<A, B, C, AI, BI, CI> Iterator for Zip3<AI, BI, CI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
{
    type Item = (A, B, C);

    fn next(&mut self) -> Option<(A, B, C)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    return Some((a, b, c));
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
        }, None)
    }
}

/// Four-iterator zipper
pub struct Zip4<A, B, C, D>(pub A, pub B, pub C, pub D);

impl<A, B, C, D, AI, BI, CI, DI> Iterator for Zip4<AI, BI, CI, DI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
    DI: Iterator<Item=D>,
{
    type Item = (A, B, C, D);

    fn next(&mut self) -> Option<(A, B, C, D)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    if let Some(d) = self.3.next() {
                        return Some((a, b, c, d))
                    }
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
            self.3.size_hint().0,
        }, None)
    }
}

/// Five-iterator zipper
pub struct Zip5<A, B, C, D, E>(pub A, pub B, pub C, pub D, pub E);

impl<A, B, C, D, E, AI, BI, CI, DI, EI> Iterator for Zip5<AI, BI, CI, DI, EI> where
    AI: Iterator<Item=A>,
    BI: Iterator<Item=B>,
    CI: Iterator<Item=C>,
    DI: Iterator<Item=D>,
    EI: Iterator<Item=E>,
{
    type Item = (A, B, C, D, E);

    fn next(&mut self) -> Option<(A, B, C, D, E)> {
        if let Some(a) = self.0.next() {
            if let Some(b) = self.1.next() {
                if let Some(c) = self.2.next() {
                    if let Some(d) = self.3.next() {
                        if let Some(e) = self.4.next() {
                            return Some((a, b, c, d, e))
                        }
                    }
                }
            }
        }

        None
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (min!{
            self.0.size_hint().0,
            self.1.size_hint().0,
            self.2.size_hint().0,
            self.3.size_hint().0,
            self.4.size_hint().0,
        }, None)
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use self::test::Bencher;

    const SIZE: usize = 1024;

    #[bench]
    fn collect2(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            ::Zip2(a.iter(), b.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect2_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            a.iter().zip(b.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count2(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            ::Zip2(a.iter(), b.iter()).count()
        })
    }

    #[bench]
    fn count2_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let b = a;

        z.iter(|| {
            a.iter().zip(b.iter()).count()
        })
    }

    #[bench]
    fn collect3(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            ::Zip3(a.iter(), b.iter(), c.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect3_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count3(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            ::Zip3(a.iter(), b.iter(), c.iter()).count()
        })
    }

    #[bench]
    fn count3_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c) = (a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).count()
        })
    }

    #[bench]
    fn collect4(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            ::Zip4(a.iter(), b.iter(), c.iter(), d.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect4_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count4(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            ::Zip4(a.iter(), b.iter(), c.iter(), d.iter()).count()
        })
    }

    #[bench]
    fn count4_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d) = (a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).count()
        })
    }

    #[bench]
    fn collect5(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            ::Zip5(a.iter(), b.iter(), c.iter(), d.iter(), e.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn collect5_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).zip(e.iter()).collect::<Vec<_>>()
        })
    }

    #[bench]
    fn count5(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            ::Zip5(a.iter(), b.iter(), c.iter(), d.iter(), e.iter()).count()
        })
    }

    #[bench]
    fn count5_(z: &mut Bencher) {
        let a = [0u8; SIZE];
        let (b, c, d, e) = (a, a, a, a);

        z.iter(|| {
            a.iter().zip(b.iter()).zip(c.iter()).zip(d.iter()).zip(e.iter()).count()
        })
    }
}
<|endoftext|>


<commit_before>//! proxer api library
#[macro_use]
extern crate serde_derive;
extern crate chrono;
extern crate reqwest;
extern crate serde_json;
extern crate serde;
extern crate serde_urlencoded;
#[macro_use]
extern crate log;
#[macro_use]
extern crate hyper;

pub mod error;
pub mod response;
pub mod api;
pub mod prelude;
pub mod client;
pub mod tests;

pub use client::Client;
pub use prelude::*;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::fmt;

/// Every struct that is an endpoint, implements this trait.
pub trait Endpoint: Serialize {
	type ResponseType: std::fmt::Debug + Clone + DeserializeOwned;
	const URL: &'static str;
}

pub trait PageableEndpoint
where
	Self: Endpoint + std::marker::Sized,
	<Self as Endpoint>::ResponseType: IntoIterator + Clone,
	<<Self as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	fn pager(self, client: Client) -> Pager<Self>;

	fn page_mut(&mut self) -> &mut Option<usize>;
	fn limit_mut(&mut self) -> &mut Option<usize>;
}

#[derive(Clone, Debug)]
pub struct Pager<T>
where
	T: Endpoint,
	<T as Endpoint>::ResponseType: IntoIterator + Clone + std::fmt::Debug,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	client: Client,
	shifted: usize,
	endpoint: T,
	data: Vec<<<T as Endpoint>::ResponseType as IntoIterator>::Item>,
}

impl<T> Pager<T>
where
	T: Endpoint + PageableEndpoint,
	T: Clone + fmt::Debug,
	<T as Endpoint>::ResponseType: IntoIterator + Clone + fmt::Debug,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	pub fn new(client: Client, mut endpoint: T, start: Option<usize>, limit: Option<usize>)
		-> Self
	{
		match (endpoint.page_mut(), start)
		{
			(&mut None, None) => *endpoint.page_mut() = Some(0),
			(&mut None, Some(_)) => *endpoint.page_mut() = start,
			_ => {}
		}

		match (endpoint.limit_mut(), limit)
		{
			(&mut None, None) => *endpoint.limit_mut() = Some(750),
			(&mut None, Some(_)) => *endpoint.limit_mut() = limit,
			_ => {}
		}

		debug!(
			"initialize new pager: page: {}, limit {}",
			endpoint.page_mut().unwrap(),
			endpoint.limit_mut().unwrap(),
		);

		Self {
			client: client,
			data: Vec::new(),
			shifted: 0,
			endpoint: endpoint,
		}
	}

	fn page_mut(&mut self) -> usize
	{
		self.endpoint.page_mut().unwrap()
	}

	fn limit_mut(&mut self) -> usize
	{
		self.endpoint.limit_mut().unwrap()
	}

	fn next_page(&mut self) {
		*self.endpoint.page_mut() = Some(self.page_mut() + 1);
	}
}

impl<T> Iterator for Pager<T>
where
	T: Endpoint,
	T: PageableEndpoint + Clone + std::fmt::Debug,
	<T as Endpoint>::ResponseType: IntoIterator,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	type Item = Result<<<T as Endpoint>::ResponseType as IntoIterator>::Item, error::Error>;

	fn next(&mut self) -> Option<Self::Item>
	{
		match self.data.pop()
		{
			Some(i) => {
				debug!("returning from buffer");
				self.shifted += 1;

				debug!("buffer: remaining/shifted: {}/{}",
					self.data.len(),
					self.shifted,
				);
				Some(Ok(i))
			}
			None => {
				debug!("expected shifted: {}", self.page_mut() * self.limit_mut());
				debug!("actually shifted: {}", self.shifted);

				if self.page_mut() * self.limit_mut() > self.shifted {
					debug!("reached the last page");
					return None;
				}

				debug!("fetching new data");
				let res = self.client
					.execute(self.endpoint.clone());

				self.next_page();

				match res {
					Ok(res) => {
						for var in res.into_iter() {
							self.data.push(var);
						}
						debug!("filled buffer with {} entries", self.data.len());

						self.next()
					},
					Err(e) => {
						Some(Err(e))
					}
				}
			}
		}
	}
}
<commit_msg>reexport error:Error<commit_after>//! proxer api library
#[macro_use]
extern crate serde_derive;
extern crate chrono;
extern crate reqwest;
extern crate serde_json;
extern crate serde;
extern crate serde_urlencoded;
#[macro_use]
extern crate log;
#[macro_use]
extern crate hyper;

pub mod error;
pub mod response;
pub mod api;
pub mod prelude;
pub mod client;
pub mod tests;

pub use client::Client;
pub use prelude::*;
pub use error::Error;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::fmt;

/// Every struct that is an endpoint, implements this trait.
pub trait Endpoint: Serialize {
	type ResponseType: std::fmt::Debug + Clone + DeserializeOwned;
	const URL: &'static str;
}

pub trait PageableEndpoint
where
	Self: Endpoint + std::marker::Sized,
	<Self as Endpoint>::ResponseType: IntoIterator + Clone,
	<<Self as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	fn pager(self, client: Client) -> Pager<Self>;

	fn page_mut(&mut self) -> &mut Option<usize>;
	fn limit_mut(&mut self) -> &mut Option<usize>;
}

#[derive(Clone, Debug)]
pub struct Pager<T>
where
	T: Endpoint,
	<T as Endpoint>::ResponseType: IntoIterator + Clone + std::fmt::Debug,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	client: Client,
	shifted: usize,
	endpoint: T,
	data: Vec<<<T as Endpoint>::ResponseType as IntoIterator>::Item>,
}

impl<T> Pager<T>
where
	T: Endpoint + PageableEndpoint,
	T: Clone + fmt::Debug,
	<T as Endpoint>::ResponseType: IntoIterator + Clone + fmt::Debug,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	pub fn new(client: Client, mut endpoint: T, start: Option<usize>, limit: Option<usize>)
		-> Self
	{
		match (endpoint.page_mut(), start)
		{
			(&mut None, None) => *endpoint.page_mut() = Some(0),
			(&mut None, Some(_)) => *endpoint.page_mut() = start,
			_ => {}
		}

		match (endpoint.limit_mut(), limit)
		{
			(&mut None, None) => *endpoint.limit_mut() = Some(750),
			(&mut None, Some(_)) => *endpoint.limit_mut() = limit,
			_ => {}
		}

		debug!(
			"initialize new pager: page: {}, limit {}",
			endpoint.page_mut().unwrap(),
			endpoint.limit_mut().unwrap(),
		);

		Self {
			client: client,
			data: Vec::new(),
			shifted: 0,
			endpoint: endpoint,
		}
	}

	fn page_mut(&mut self) -> usize
	{
		self.endpoint.page_mut().unwrap()
	}

	fn limit_mut(&mut self) -> usize
	{
		self.endpoint.limit_mut().unwrap()
	}

	fn next_page(&mut self) {
		*self.endpoint.page_mut() = Some(self.page_mut() + 1);
	}
}

impl<T> Iterator for Pager<T>
where
	T: Endpoint,
	T: PageableEndpoint + Clone + std::fmt::Debug,
	<T as Endpoint>::ResponseType: IntoIterator,
	<<T as Endpoint>::ResponseType as std::iter::IntoIterator>::Item: Clone + fmt::Debug,
{
	type Item = Result<<<T as Endpoint>::ResponseType as IntoIterator>::Item, error::Error>;

	fn next(&mut self) -> Option<Self::Item>
	{
		match self.data.pop()
		{
			Some(i) => {
				debug!("returning from buffer");
				self.shifted += 1;

				debug!("buffer: remaining/shifted: {}/{}",
					self.data.len(),
					self.shifted,
				);
				Some(Ok(i))
			}
			None => {
				debug!("expected shifted: {}", self.page_mut() * self.limit_mut());
				debug!("actually shifted: {}", self.shifted);

				if self.page_mut() * self.limit_mut() > self.shifted {
					debug!("reached the last page");
					return None;
				}

				debug!("fetching new data");
				let res = self.client
					.execute(self.endpoint.clone());

				self.next_page();

				match res {
					Ok(res) => {
						for var in res.into_iter() {
							self.data.push(var);
						}
						debug!("filled buffer with {} entries", self.data.len());

						self.next()
					},
					Err(e) => {
						Some(Err(e))
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>#![feature(core)]
#![cfg_attr(test, feature(test))]

mod number_streams;

use number_streams::NumberStreams;

const CHUNK_SIZE: usize = 32;

const PRIME64_1: u64 = 11400714785074694791;
const PRIME64_2: u64 = 14029467366897019727;
const PRIME64_3: u64 = 1609587929392839161;
const PRIME64_4: u64 = 9650029242287828579;
const PRIME64_5: u64 = 2870177450012600261;

#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

#[derive(Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn from_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME64_1).wrapping_add(PRIME64_2),
            v2: seed.wrapping_add(PRIME64_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME64_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u64>
    {
        // TODO: The original code pulls out local vars for
        // v[1234], presumably for performance
        // reasons. Investigate.

        #[inline(always)]
        fn ingest_one_number(mut current_value: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME64_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(31);
            current_value.wrapping_mul(PRIME64_1)
        };

        let mut values = values.peekable();

        while values.peek().is_some() {
            self.v1 = ingest_one_number(self.v1, values.next().unwrap());
            self.v2 = ingest_one_number(self.v2, values.next().unwrap());
            self.v3 = ingest_one_number(self.v3, values.next().unwrap());
            self.v4 = ingest_one_number(self.v4, values.next().unwrap());
        }
    }

    #[inline(always)]
    fn finish(&self) -> u64 {
        // TODO: The original code pulls out local vars for
        // v[1234], presumably for performance
        // reasons. Investigate.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        #[inline(always)]
        fn mix_one(mut hash: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME64_2);
            value = value.rotate_left(31);
            value = value.wrapping_mul(PRIME64_1);
            hash ^= value;
            hash = hash.wrapping_mul(PRIME64_1);
            hash.wrapping_add(PRIME64_4)
        }

        hash = mix_one(hash, self.v1);
        hash = mix_one(hash, self.v2);
        hash = mix_one(hash, self.v3);
        hash = mix_one(hash, self.v4);

        hash
    }
}

impl std::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    pub fn from_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::from_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

impl XxHash {
    pub fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u64_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        if bytes.len() >= CHUNK_SIZE {
            let (iter, leftover) = bytes.u64_stream();
            self.core.ingest_chunks(iter);
            bytes = leftover;
        }

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    pub fn finish(&self) -> u64 {
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u64 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME64_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u64s, buffered) = buffered.u64_stream();

        for mut k1 in buffered_u64s {
            k1 = k1.wrapping_mul(PRIME64_2);
            k1 = k1.rotate_left(31);
            k1 = k1.wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(27);
            hash = hash.wrapping_mul(PRIME64_1);
            hash = hash.wrapping_add(PRIME64_4);
        }

        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = (k1 as u64).wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(23);
            hash = hash.wrapping_mul(PRIME64_2);
            hash = hash.wrapping_add(PRIME64_3);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u64).wrapping_mul(PRIME64_5);
            hash ^= k1;
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME64_1);
        }

        // The final intermixing
        hash ^= hash.wrapping_shr(33);
        hash = hash.wrapping_mul(PRIME64_2);
        hash ^= hash.wrapping_shr(29);
        hash = hash.wrapping_mul(PRIME64_3);
        hash ^= hash.wrapping_shr(32);

        hash
    }
}

#[cfg(test)]
mod test {
    use super::XxHash;

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::from_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::from_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xef46db3751d8e999);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0x0a9edecebeb03ae4);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x7b06c531ea43e89f);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6ac1e58032166597);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x4b6a04fcdf7a4672);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x567e355e0682e1f1);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::XxHash;

    #[inline(always)]
    fn straight_line_slice_bench(b: &mut test::Bencher, len: usize) {
        let bytes: Vec<_> = (0..100).cycle().take(len).collect();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            let mut hasher = XxHash::from_seed(0);
            hasher.write(&bytes);
            hasher.finish()
        });
    }

    #[bench]
    fn straight_line_megabyte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1024*1024);
    }

    #[bench]
    fn straight_line_1024_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1024);
    }

    #[bench]
    fn straight_line_512_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 512);
    }

    #[bench]
    fn straight_line_256_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 256);
    }

    #[bench]
    fn straight_line_128_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 128);
    }

    #[bench]
    fn straight_line_32_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 32);
    }

    #[bench]
    fn straight_line_16_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 16);
    }

    #[bench]
    fn straight_line_4_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 4);
    }

    #[bench]
    fn straight_line_1_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1);
    }

    #[bench]
    fn straight_line_0_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 0);
    }
}
<commit_msg>Improve performance by avoiding memory access contention<commit_after>#![feature(core)]
#![cfg_attr(test, feature(test))]

mod number_streams;

use number_streams::NumberStreams;

const CHUNK_SIZE: usize = 32;

const PRIME64_1: u64 = 11400714785074694791;
const PRIME64_2: u64 = 14029467366897019727;
const PRIME64_3: u64 = 1609587929392839161;
const PRIME64_4: u64 = 9650029242287828579;
const PRIME64_5: u64 = 2870177450012600261;

#[derive(Copy,Clone,PartialEq)]
struct XxCore {
    v1: u64,
    v2: u64,
    v3: u64,
    v4: u64,
}

#[derive(Debug,Copy,Clone)]
pub struct XxHash {
    total_len: u64,
    seed: u64,
    core: XxCore,
    buffer: [u8; CHUNK_SIZE],
    buffer_usage: usize,
}

impl XxCore {
    fn from_seed(seed: u64) -> XxCore {
        XxCore {
            v1: seed.wrapping_add(PRIME64_1).wrapping_add(PRIME64_2),
            v2: seed.wrapping_add(PRIME64_2),
            v3: seed,
            v4: seed.wrapping_sub(PRIME64_1),
        }
    }

    #[inline(always)]
    fn ingest_chunks<I>(&mut self, values: I)
        where I: Iterator<Item=u64>
    {
        #[inline(always)]
        fn ingest_one_number(mut current_value: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME64_2);
            current_value = current_value.wrapping_add(value);
            current_value = current_value.rotate_left(31);
            current_value.wrapping_mul(PRIME64_1)
        };

        // By drawing these out, we can avoid going back and forth to
        // memory. It only really helps for large files, when we need
        // to iterate multiple times here.

        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;
        let mut v4 = self.v4;

        let mut values = values.peekable();

        while values.peek().is_some() {
            v1 = ingest_one_number(v1, values.next().unwrap());
            v2 = ingest_one_number(v2, values.next().unwrap());
            v3 = ingest_one_number(v3, values.next().unwrap());
            v4 = ingest_one_number(v4, values.next().unwrap());
        }

        self.v1 = v1;
        self.v2 = v2;
        self.v3 = v3;
        self.v4 = v4;
    }

    #[inline(always)]
    fn finish(&self) -> u64 {
        // TODO: The original code pulls out local vars for
        // v[1234], presumably for performance
        // reasons. Investigate.

        let mut hash;

        hash =                   self.v1.rotate_left( 1);
        hash = hash.wrapping_add(self.v2.rotate_left( 7));
        hash = hash.wrapping_add(self.v3.rotate_left(12));
        hash = hash.wrapping_add(self.v4.rotate_left(18));

        #[inline(always)]
        fn mix_one(mut hash: u64, mut value: u64) -> u64 {
            value = value.wrapping_mul(PRIME64_2);
            value = value.rotate_left(31);
            value = value.wrapping_mul(PRIME64_1);
            hash ^= value;
            hash = hash.wrapping_mul(PRIME64_1);
            hash.wrapping_add(PRIME64_4)
        }

        hash = mix_one(hash, self.v1);
        hash = mix_one(hash, self.v2);
        hash = mix_one(hash, self.v3);
        hash = mix_one(hash, self.v4);

        hash
    }
}

impl std::fmt::Debug for XxCore {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(
            f, "XxCore {{ {:016x} {:016x} {:016x} {:016x} }}",
            self.v1, self.v2, self.v3, self.v4
        )
    }
}

impl XxHash {
    pub fn from_seed(seed: u64) -> XxHash {
        XxHash {
            total_len: 0,
            seed: seed,
            core: XxCore::from_seed(seed),
            buffer: [0; CHUNK_SIZE],
            buffer_usage: 0,
        }
    }
}

impl XxHash {
    pub fn write(&mut self, bytes: &[u8]) {
        let mut bytes = bytes;

        self.total_len += bytes.len() as u64;

        // Even with new data, we still don't have a full buffer. Wait
        // until we have a full buffer.
        if self.buffer_usage + bytes.len() < self.buffer.len() {
            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), tail, bytes.len());
            }
            self.buffer_usage += bytes.len();
            return;
        }

        // Some data left from previous update. Fill the buffer and
        // consume it first.
        if self.buffer_usage > 0 {
            let bytes_to_use = self.buffer.len() - self.buffer_usage;
            let (to_use, leftover) = bytes.split_at(bytes_to_use);

            unsafe {
                let tail = self.buffer.as_mut_ptr().offset(self.buffer_usage as isize);
                std::ptr::copy_nonoverlapping(to_use.as_ptr(), tail, bytes_to_use);
            }

            let (iter, _) = self.buffer.u64_stream();

            self.core.ingest_chunks(iter);

            bytes = leftover;
            self.buffer_usage = 0;
        }

        // Consume the input data in large chunks
        if bytes.len() >= CHUNK_SIZE {
            let (iter, leftover) = bytes.u64_stream();
            self.core.ingest_chunks(iter);
            bytes = leftover;
        }

        // Save any leftover data for the next call
        if bytes.len() > 0 {
            unsafe {
                std::ptr::copy_nonoverlapping(bytes.as_ptr(), self.buffer.as_mut_ptr(), bytes.len());
            }
            self.buffer_usage = bytes.len();
        }
    }

    pub fn finish(&self) -> u64 {
        let mut hash;

        // We have processed at least one full chunk
        if self.total_len >= CHUNK_SIZE as u64 {
            hash = self.core.finish();
        } else {
            hash = self.seed.wrapping_add(PRIME64_5);
        }

        hash = hash.wrapping_add(self.total_len);

        let buffered = &self.buffer[..self.buffer_usage];
        let (buffered_u64s, buffered) = buffered.u64_stream();

        for mut k1 in buffered_u64s {
            k1 = k1.wrapping_mul(PRIME64_2);
            k1 = k1.rotate_left(31);
            k1 = k1.wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(27);
            hash = hash.wrapping_mul(PRIME64_1);
            hash = hash.wrapping_add(PRIME64_4);
        }

        let (buffered_u32s, buffered) = buffered.u32_stream();

        for k1 in buffered_u32s {
            let k1 = (k1 as u64).wrapping_mul(PRIME64_1);
            hash ^= k1;
            hash = hash.rotate_left(23);
            hash = hash.wrapping_mul(PRIME64_2);
            hash = hash.wrapping_add(PRIME64_3);
        }

        for buffered_u8 in buffered {
            let k1 = (*buffered_u8 as u64).wrapping_mul(PRIME64_5);
            hash ^= k1;
            hash = hash.rotate_left(11);
            hash = hash.wrapping_mul(PRIME64_1);
        }

        // The final intermixing
        hash ^= hash.wrapping_shr(33);
        hash = hash.wrapping_mul(PRIME64_2);
        hash ^= hash.wrapping_shr(29);
        hash = hash.wrapping_mul(PRIME64_3);
        hash ^= hash.wrapping_shr(32);

        hash
    }
}

#[cfg(test)]
mod test {
    use super::XxHash;

    #[test]
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
        let bytes: Vec<_> = (0..32).map(|_| 0).collect();

        let mut byte_by_byte = XxHash::from_seed(0);
        for byte in bytes.chunks(1) {
            byte_by_byte.write(byte);
        }

        let mut one_chunk = XxHash::from_seed(0);
        one_chunk.write(&bytes);

        assert_eq!(byte_by_byte.core, one_chunk.core);
    }

    #[test]
    fn hash_of_nothing_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0xef46db3751d8e999);
    }

    #[test]
    fn hash_of_single_byte_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&[42]);
        assert_eq!(hasher.finish(), 0x0a9edecebeb03ae4);
    }

    #[test]
    fn hash_of_multiple_bytes_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0);
        hasher.write(b"Hello, world!\0");
        assert_eq!(hasher.finish(), 0x7b06c531ea43e89f);
    }

    #[test]
    fn hash_of_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x6ac1e58032166597);
    }

    #[test]
    fn hash_with_different_seed_matches_c_implementation() {
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&[]);
        assert_eq!(hasher.finish(), 0x4b6a04fcdf7a4672);
    }

    #[test]
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
        let bytes: Vec<_> = (0..100).collect();
        let mut hasher = XxHash::from_seed(0xae0543311b702d91);
        hasher.write(&bytes);
        assert_eq!(hasher.finish(), 0x567e355e0682e1f1);
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use super::XxHash;

    #[inline(always)]
    fn straight_line_slice_bench(b: &mut test::Bencher, len: usize) {
        let bytes: Vec<_> = (0..100).cycle().take(len).collect();
        b.bytes = bytes.len() as u64;
        b.iter(|| {
            let mut hasher = XxHash::from_seed(0);
            hasher.write(&bytes);
            hasher.finish()
        });
    }

    #[bench]
    fn straight_line_megabyte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1024*1024);
    }

    #[bench]
    fn straight_line_1024_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1024);
    }

    #[bench]
    fn straight_line_512_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 512);
    }

    #[bench]
    fn straight_line_256_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 256);
    }

    #[bench]
    fn straight_line_128_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 128);
    }

    #[bench]
    fn straight_line_32_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 32);
    }

    #[bench]
    fn straight_line_16_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 16);
    }

    #[bench]
    fn straight_line_4_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 4);
    }

    #[bench]
    fn straight_line_1_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 1);
    }

    #[bench]
    fn straight_line_0_byte(b: &mut test::Bencher) {
        straight_line_slice_bench(b, 0);
    }
}
<|endoftext|>


<commit_before>//! ### TODO
//!
//! * Clarify terminology (to wire, to load, option, alternative, option).
//! * Single alternative options are a _special case_ of options/alternatives.
//!   To avoid confusion, all code & doc related to single alternative options
//!   should be listed after regular options/alternatives.
//! * Panics vs error?
//! * remove_option, remove_alternative?

#![feature(get_type_id)]
#![feature(box_syntax)]

#[macro_use] extern crate qdowncast;
extern crate qindex_multi;

#[macro_use] mod macros;

use qdowncast::QDowncastable;
use qindex_multi::MultiIndexable;

use std::any::{Any, TypeId};
use std::borrow::Borrow;
use std::collections::btree_map::{self, BTreeMap};
use std::ops::{Deref, DerefMut, Index, IndexMut};

// ++++++++++++++++++++ OptionReflect ++++++++++++++++++++

/// Our `Reflect`-derivative.
/// This supplies necessary information for retrieving an object at compile-time.
pub trait OptionReflect: Any {
    fn option_name() -> &'static str;
}

// ++++++++++++++++++++ GetObjectError ++++++++++++++++++++

#[derive(Debug, Clone)]
pub enum GetObjectError<'a> {
    TypeMismatch{ option_name: &'a str, expected: TypeId, found: TypeId },
    MissingOption(&'a str),
}

impl<'a> GetObjectError<'a> {
    pub fn type_mismatch<Expected>(found: TypeId) -> GetObjectError<'static>
        where Expected: OptionReflect
    {
        GetObjectError::TypeMismatch{
            option_name: Expected::option_name(),
            expected: TypeId::of::<Expected>(),
            found: found,
        }
    }
}

pub type GetObjectResult<'a, T> = Result<T, GetObjectError<'a>>;

// ++++++++++++++++++++ Entry ++++++++++++++++++++

/// TODO expose this to the user?
enum Entry<Obj: Any + ?Sized> {
    /// A option with zero or more alternatives. May be wired to one of its objects.
    Multi{
        wired: Option<usize>,
        alternatives: Vec<(String, Box<Obj>)>,
    }
    /// A single alternative option. Is always wired to exactly one object.
    Single(Box<Obj>),
}

impl<Obj: Any + ?Sized> Entry<Obj> {
    fn has_alternative(&self, alt_name: &str) -> bool {
        match self {
            &Entry::Multi{ ref alternatives, .. } => {
                alternatives.iter().any(|e| &*e.0 == alt_name)
            }
            _ => false,
        }
    }

    fn add_alternative(&mut self, alt_name: String, obj: Box<Obj>){
        assert!(!self.has_alternative(&alt_name),
                "Alternative '{}' already exists,", alt_name);

        match self {
            &mut Entry::Multi{ ref mut alternatives, .. } => {
                alternatives.push((alt_name, obj));
            }
            _ => {
                panic!("Can't add alternative '{}' to single alternative option", alt_name);
            }
        }
    }

    fn wire_alternative(&mut self, alt_name: &str) {
        assert!(self.has_alternative(&alt_name),
                "Can't wire missing alternative '{}'", alt_name);

        match self {
            &mut Entry::Multi{ ref mut wired, ref alternatives } => {
                *wired = Some(alternatives.iter().position(|e| &*e.0 == alt_name).unwrap());
            }
            _ => { unreachable!() }
        }
    }

    fn object_ref(&self) -> Option<&Obj> {
        match self {
            &Entry::Single(ref obj) => Some(&**obj),
            &Entry::Multi{ wired, ref alternatives } => match wired {
                Some(idx) => Some(&*alternatives[idx].1),
                None => None,
            }
        }
    }

    fn object_mut(&mut self) -> Option<&mut Obj> {
        match self {
            &mut Entry::Single(ref mut obj) => Some(&mut**obj),
            &mut Entry::Multi{ wired, ref mut alternatives } => match wired {
                Some(idx) => Some(&mut*alternatives[idx].1),
                None => None,
            }
        }
    }
}

// ++++++++++++++++++++ Register ++++++++++++++++++++

pub trait DefaultBase: Any {}
impl<T: Any + ?Sized> DefaultBase for T {}
qdowncastable!(DefaultBase);
qdowncast_methods!(DefaultBase);

pub struct Register<Obj: Any + ?Sized = DefaultBase> {
    entrys: BTreeMap<String, Entry<Obj>>,
}

impl<Obj: Any + ?Sized> Register<Obj> {
    /// Gets the object wired to option `opt_name` immutably.
    pub fn get_object(&self, opt_name: &str) -> Option<&Obj> {
        self.entrys.get(opt_name).and_then(|entry| entry.object_ref())
    }

    /// Gets the object wired to option `opt_name` mutably.
    pub fn get_object_mut(&mut self, opt_name: &str) -> Option<&mut Obj> {
        self.entrys.get_mut(opt_name).and_then(|entry| entry.object_mut())
    }

    /// Gets the object wired to option `opt_name` immutably, then tries to downcast it.
    pub fn get<T>(&self) -> GetObjectResult<&T>
        where T: OptionReflect, Obj: QDowncastable<T>
    {
        match self.get_object(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_ref(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetObjectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetObjectError::MissingOption(T::option_name()))
        }
    }

    /// Gets the object wired to option `opt_name` mutably, then tries to downcast it.
    pub fn get_mut<T>(&mut self) -> GetObjectResult<&mut T>
        where T: OptionReflect, Obj: QDowncastable<T>
    {
        match self.get_object_mut(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_mut(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetObjectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetObjectError::MissingOption(T::option_name()))
        }
    }

    /// Iterate over all wired objects immutably.
    pub fn iter(&self) -> Iter<Obj> {
        Iter{ entrys: self.entrys.iter() }
    }

    /// Iterate over all wired objects mutably.
    pub fn iter_mut(&mut self) -> IterMut<Obj> {
        IterMut{ entrys: self.entrys.iter_mut() }
    }
}

#[derive(Clone)]
pub struct Iter<'a, Obj: Any + ?Sized = DefaultBase> {
    entrys: btree_map::Iter<'a, String, Entry<Obj>>,
}

impl<'a, Obj: Any + ?Sized> Iterator for Iter<'a, Obj> {
    type Item = (&'a str, &'a Obj);
    fn next(&mut self) -> Option<Self::Item> {
        match self.entrys.next() {
            Some((opt_name, entry)) => match entry.object_ref() {
                Some(obj) => Some((&opt_name, obj)),
                None => self.next(),
            },
            None => None,
        }
    }
}

pub struct IterMut<'a, Obj: Any + ?Sized = DefaultBase> {
    entrys: btree_map::IterMut<'a, String, Entry<Obj>>,
}

impl<'a, Obj: Any + ?Sized> Iterator for IterMut<'a, Obj> {
    type Item = (&'a str, &'a mut Obj);
    fn next(&mut self) -> Option<Self::Item> {
        match self.entrys.next() {
            Some((opt_name, entry)) => match entry.object_mut() {
                Some(obj) => Some((&opt_name, obj)),
                None => self.next(),
            },
            None => None,
        }
    }
}

impl<'a, Obj: Any + ?Sized> IntoIterator for &'a Register<Obj> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = Iter<'a, Obj>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

impl<'a, Obj: Any + ?Sized> IntoIterator for &'a mut Register<Obj> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = IterMut<'a, Obj>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

impl<'a, Str, Obj: ?Sized> Index<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{
    type Output = Obj;
    fn index(&self, name: &'a Str) -> &Self::Output {
        self.get_object(name.borrow()).unwrap()
    }
}

impl<'a, Str, Obj: ?Sized> IndexMut<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{
    fn index_mut(&mut self, name: &'a Str) -> &mut Self::Output {
        self.get_object_mut(name.borrow()).unwrap()
    }
}

unsafe impl<'a, Str, Obj: ?Sized> MultiIndexable<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{}

// ++++++++++++++++++++ RegisterModifier ++++++++++++++++++++

pub struct RegisterModifier<Obj: Any + ?Sized = DefaultBase>(Register<Obj>);

impl<Obj: Any + ?Sized> Deref for RegisterModifier<Obj> {
    type Target = Register<Obj>;
    fn deref(&self) -> &Self::Target { &self.0 }
}
impl<Obj: Any + ?Sized> DerefMut for RegisterModifier<Obj> {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}

// TODO: remove duplicated code
impl<Obj: Any + ?Sized> RegisterModifier<Obj> {
    pub fn new() -> RegisterModifier<Obj> {
        RegisterModifier(Register{ entrys: BTreeMap::new() })
    }

    pub fn unwrap(self) -> Register<Obj> { self.0 }

    /// Adds a option to the register.
    pub fn add_option(&mut self, name: String){
        assert!(self.entrys.contains_key(&name), "Option '{}' already exists!", &name);

        self.entrys.insert(name, Entry::Multi{
            wired: None, alternatives: Vec::new()
        });
    }

    /// Adds an alternative to an option of the register.
    pub fn add_alternative(&mut self, opt_name: &str, alt_name: String, obj: Box<Obj>){
        let entry = self.entrys.get_mut(opt_name);
        let entry = entry.expect(&format!("Option '{}' doesn't exist", &opt_name));

        entry.add_alternative(alt_name, obj);
    }

    /// Wires an alternative of an option of this register.
    pub fn wire_alternative(&mut self, opt_name: &str, alt_name: &str){
        let entry = self.entrys.get_mut(opt_name);
        let entry = entry.expect(&format!("Option '{}' doesn't exist", &opt_name));

        entry.wire_alternative(alt_name);
    }

    /// Adds a single alternative option to the register.
    pub fn add_single(&mut self, name: String, obj: Box<Obj>){
        assert!(self.entrys.contains_key(&name), "Option '{}' already exists!", &name);

        self.entrys.insert(name, Entry::Single(obj));
    }
}

<commit_msg>fix syntaxerror<commit_after>//! ### TODO
//!
//! * Clarify terminology (to wire, to load, option, alternative, option).
//! * Single alternative options are a _special case_ of options/alternatives.
//!   To avoid confusion, all code & doc related to single alternative options
//!   should be listed after regular options/alternatives.
//! * Panics vs error?
//! * remove_option, remove_alternative?

#![feature(get_type_id)]
#![feature(box_syntax)]

#[macro_use] extern crate qdowncast;
extern crate qindex_multi;

#[macro_use] mod macros;

use qdowncast::QDowncastable;
use qindex_multi::MultiIndexable;

use std::any::{Any, TypeId};
use std::borrow::Borrow;
use std::collections::btree_map::{self, BTreeMap};
use std::ops::{Deref, DerefMut, Index, IndexMut};

// ++++++++++++++++++++ OptionReflect ++++++++++++++++++++

/// Our `Reflect`-derivative.
/// This supplies necessary information for retrieving an object at compile-time.
pub trait OptionReflect: Any {
    fn option_name() -> &'static str;
}

// ++++++++++++++++++++ GetObjectError ++++++++++++++++++++

#[derive(Debug, Clone)]
pub enum GetObjectError<'a> {
    TypeMismatch{ option_name: &'a str, expected: TypeId, found: TypeId },
    MissingOption(&'a str),
}

impl<'a> GetObjectError<'a> {
    pub fn type_mismatch<Expected>(found: TypeId) -> GetObjectError<'static>
        where Expected: OptionReflect
    {
        GetObjectError::TypeMismatch{
            option_name: Expected::option_name(),
            expected: TypeId::of::<Expected>(),
            found: found,
        }
    }
}

pub type GetObjectResult<'a, T> = Result<T, GetObjectError<'a>>;

// ++++++++++++++++++++ Entry ++++++++++++++++++++

/// TODO expose this to the user?
enum Entry<Obj: Any + ?Sized> {
    /// A option with zero or more alternatives. May be wired to one of its objects.
    Multi{
        wired: Option<usize>,
        alternatives: Vec<(String, Box<Obj>)>,
    },
    /// A single alternative option. Is always wired to exactly one object.
    Single(Box<Obj>),
}

impl<Obj: Any + ?Sized> Entry<Obj> {
    fn has_alternative(&self, alt_name: &str) -> bool {
        match self {
            &Entry::Multi{ ref alternatives, .. } => {
                alternatives.iter().any(|e| &*e.0 == alt_name)
            }
            _ => false,
        }
    }

    fn add_alternative(&mut self, alt_name: String, obj: Box<Obj>){
        assert!(!self.has_alternative(&alt_name),
                "Alternative '{}' already exists,", alt_name);

        match self {
            &mut Entry::Multi{ ref mut alternatives, .. } => {
                alternatives.push((alt_name, obj));
            }
            _ => {
                panic!("Can't add alternative '{}' to single alternative option", alt_name);
            }
        }
    }

    fn wire_alternative(&mut self, alt_name: &str) {
        assert!(self.has_alternative(&alt_name),
                "Can't wire missing alternative '{}'", alt_name);

        match self {
            &mut Entry::Multi{ ref mut wired, ref alternatives } => {
                *wired = Some(alternatives.iter().position(|e| &*e.0 == alt_name).unwrap());
            }
            _ => { unreachable!() }
        }
    }

    fn object_ref(&self) -> Option<&Obj> {
        match self {
            &Entry::Single(ref obj) => Some(&**obj),
            &Entry::Multi{ wired, ref alternatives } => match wired {
                Some(idx) => Some(&*alternatives[idx].1),
                None => None,
            }
        }
    }

    fn object_mut(&mut self) -> Option<&mut Obj> {
        match self {
            &mut Entry::Single(ref mut obj) => Some(&mut**obj),
            &mut Entry::Multi{ wired, ref mut alternatives } => match wired {
                Some(idx) => Some(&mut*alternatives[idx].1),
                None => None,
            }
        }
    }
}

// ++++++++++++++++++++ Register ++++++++++++++++++++

pub trait DefaultBase: Any {}
impl<T: Any + ?Sized> DefaultBase for T {}
qdowncastable!(DefaultBase);
qdowncast_methods!(DefaultBase);

pub struct Register<Obj: Any + ?Sized = DefaultBase> {
    entrys: BTreeMap<String, Entry<Obj>>,
}

impl<Obj: Any + ?Sized> Register<Obj> {
    /// Gets the object wired to option `opt_name` immutably.
    pub fn get_object(&self, opt_name: &str) -> Option<&Obj> {
        self.entrys.get(opt_name).and_then(|entry| entry.object_ref())
    }

    /// Gets the object wired to option `opt_name` mutably.
    pub fn get_object_mut(&mut self, opt_name: &str) -> Option<&mut Obj> {
        self.entrys.get_mut(opt_name).and_then(|entry| entry.object_mut())
    }

    /// Gets the object wired to option `opt_name` immutably, then tries to downcast it.
    pub fn get<T>(&self) -> GetObjectResult<&T>
        where T: OptionReflect, Obj: QDowncastable<T>
    {
        match self.get_object(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_ref(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetObjectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetObjectError::MissingOption(T::option_name()))
        }
    }

    /// Gets the object wired to option `opt_name` mutably, then tries to downcast it.
    pub fn get_mut<T>(&mut self) -> GetObjectResult<&mut T>
        where T: OptionReflect, Obj: QDowncastable<T>
    {
        match self.get_object_mut(T::option_name()) {
            Some(base) => {
                let ty = (&*base).get_type_id();
                match QDowncastable::downcast_mut(base) {
                    Some(ret) => Ok(ret),
                    None => Err(GetObjectError::type_mismatch::<T>(ty))
                }
            }
            None => Err(GetObjectError::MissingOption(T::option_name()))
        }
    }

    /// Iterate over all wired objects immutably.
    pub fn iter(&self) -> Iter<Obj> {
        Iter{ entrys: self.entrys.iter() }
    }

    /// Iterate over all wired objects mutably.
    pub fn iter_mut(&mut self) -> IterMut<Obj> {
        IterMut{ entrys: self.entrys.iter_mut() }
    }
}

#[derive(Clone)]
pub struct Iter<'a, Obj: Any + ?Sized = DefaultBase> {
    entrys: btree_map::Iter<'a, String, Entry<Obj>>,
}

impl<'a, Obj: Any + ?Sized> Iterator for Iter<'a, Obj> {
    type Item = (&'a str, &'a Obj);
    fn next(&mut self) -> Option<Self::Item> {
        match self.entrys.next() {
            Some((opt_name, entry)) => match entry.object_ref() {
                Some(obj) => Some((&opt_name, obj)),
                None => self.next(),
            },
            None => None,
        }
    }
}

pub struct IterMut<'a, Obj: Any + ?Sized = DefaultBase> {
    entrys: btree_map::IterMut<'a, String, Entry<Obj>>,
}

impl<'a, Obj: Any + ?Sized> Iterator for IterMut<'a, Obj> {
    type Item = (&'a str, &'a mut Obj);
    fn next(&mut self) -> Option<Self::Item> {
        match self.entrys.next() {
            Some((opt_name, entry)) => match entry.object_mut() {
                Some(obj) => Some((&opt_name, obj)),
                None => self.next(),
            },
            None => None,
        }
    }
}

impl<'a, Obj: Any + ?Sized> IntoIterator for &'a Register<Obj> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = Iter<'a, Obj>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

impl<'a, Obj: Any + ?Sized> IntoIterator for &'a mut Register<Obj> {
    type Item = <Self::IntoIter as Iterator>::Item;
    type IntoIter = IterMut<'a, Obj>;
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
}

impl<'a, Str, Obj: ?Sized> Index<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{
    type Output = Obj;
    fn index(&self, name: &'a Str) -> &Self::Output {
        self.get_object(name.borrow()).unwrap()
    }
}

impl<'a, Str, Obj: ?Sized> IndexMut<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{
    fn index_mut(&mut self, name: &'a Str) -> &mut Self::Output {
        self.get_object_mut(name.borrow()).unwrap()
    }
}

unsafe impl<'a, Str, Obj: ?Sized> MultiIndexable<&'a Str> for Register<Obj>
    where Str: Ord + Borrow<str>, Obj: Any
{}

// ++++++++++++++++++++ RegisterModifier ++++++++++++++++++++

pub struct RegisterModifier<Obj: Any + ?Sized = DefaultBase>(Register<Obj>);

impl<Obj: Any + ?Sized> Deref for RegisterModifier<Obj> {
    type Target = Register<Obj>;
    fn deref(&self) -> &Self::Target { &self.0 }
}
impl<Obj: Any + ?Sized> DerefMut for RegisterModifier<Obj> {
    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 }
}

// TODO: remove duplicated code
impl<Obj: Any + ?Sized> RegisterModifier<Obj> {
    pub fn new() -> RegisterModifier<Obj> {
        RegisterModifier(Register{ entrys: BTreeMap::new() })
    }

    pub fn unwrap(self) -> Register<Obj> { self.0 }

    /// Adds a option to the register.
    pub fn add_option(&mut self, name: String){
        assert!(self.entrys.contains_key(&name), "Option '{}' already exists!", &name);

        self.entrys.insert(name, Entry::Multi{
            wired: None, alternatives: Vec::new()
        });
    }

    /// Adds an alternative to an option of the register.
    pub fn add_alternative(&mut self, opt_name: &str, alt_name: String, obj: Box<Obj>){
        let entry = self.entrys.get_mut(opt_name);
        let entry = entry.expect(&format!("Option '{}' doesn't exist", &opt_name));

        entry.add_alternative(alt_name, obj);
    }

    /// Wires an alternative of an option of this register.
    pub fn wire_alternative(&mut self, opt_name: &str, alt_name: &str){
        let entry = self.entrys.get_mut(opt_name);
        let entry = entry.expect(&format!("Option '{}' doesn't exist", &opt_name));

        entry.wire_alternative(alt_name);
    }

    /// Adds a single alternative option to the register.
    pub fn add_single(&mut self, name: String, obj: Box<Obj>){
        assert!(self.entrys.contains_key(&name), "Option '{}' already exists!", &name);

        self.entrys.insert(name, Entry::Single(obj));
    }
}

<|endoftext|>