<commit_before>// Copyright 2014-2016 Johannes Köster, Taylor Cramer.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! The Burrows-Wheeler-Transform and related data structures.
//! The implementation is based on the lecture notes
//! "Algorithmen auf Sequenzen", Kopczynski, Marschall, Martin and Rahmann, 2008 - 2015.

use std::iter::repeat;

use utils::prescan;
use alphabets::Alphabet;
use data_structures::suffix_array::RawSuffixArray;
use std::ops::Deref;
use bytecount;

pub type BWT = Vec<u8>;
pub type BWTSlice = [u8];
pub type Less = Vec<usize>;
pub type BWTFind = Vec<usize>;

pub trait DerefBWT: Deref<Target = BWT> {}
impl<T: Deref<Target = BWT>> DerefBWT for T {}

pub trait DerefOcc: Deref<Target = Occ> {}
impl<T: Deref<Target = Occ>> DerefOcc for T {}

pub trait DerefLess: Deref<Target = Less> {}
impl<T: Deref<Target = Less>> DerefLess for T {}

/// Calculate Burrows-Wheeler-Transform of the given text of length n.
/// Complexity: O(n).
///
/// # Arguments
///
/// * `text` - the text ended by sentinel symbol (being lexicographically smallest)
/// * `pos` - the suffix array for the text
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::suffix_array;
/// use bio::data_structures::bwt::bwt;
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = suffix_array(text);
/// let bwt = bwt(text, &pos);
/// assert_eq!(bwt, b"ATTATTCAGGACCC$CTTTCAA");
/// ```
pub fn bwt(text: &[u8], pos: &RawSuffixArray) -> BWT {
    assert_eq!(text.len(), pos.len());
    let n = text.len();
    let mut bwt: BWT = repeat(0).take(n).collect();
    for r in 0..n {
        let p = pos[r];
        bwt[r] = if p > 0 { text[p - 1] } else { text[n - 1] };
    }

    bwt
}

/// Calculate the inverse of a BWT of length n, which is the original text.
/// Complexity: O(n).
///
/// # Arguments
///
/// * `bwt` - the BWT
pub fn invert_bwt(bwt: &BWTSlice) -> Vec<u8> {
    let alphabet = Alphabet::new(bwt);
    let n = bwt.len();
    let bwtfind = bwtfind(bwt, &alphabet);
    let mut inverse = Vec::with_capacity(n);

    let mut r = bwtfind[0];
    for _ in 0..n {
        r = bwtfind[r];
        inverse.push(bwt[r]);
    }

    inverse
}

/// An occurence array implementation.
#[derive(Serialize, Deserialize)]
pub struct Occ {
    occ: Vec<Vec<usize>>,
    k: u32,
}

impl Occ {
    /// Calculate occ array with sampling from BWT of length n.
    /// Time complexity: O(n).
    /// Space complexity: O(n / k * A) with A being the alphabet size.
    /// Alphabet size is determined on the fly from the BWT.
    /// For large texts, it is therefore advisable to transform
    /// the text before calculating the BWT (see alphabets::rank_transform).
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate: every k-th entry will be stored
    pub fn new(bwt: &BWTSlice, k: u32, alphabet: &Alphabet) -> Self {
        let n = bwt.len();
        let m = alphabet
            .max_symbol()
            .expect("Expecting non-empty alphabet.") as usize + 1;
        let mut occ = Vec::with_capacity(n / k as usize);
        let mut curr_occ: Vec<usize> = repeat(0).take(m).collect();
        for (i, &c) in bwt.iter().enumerate() {
            curr_occ[c as usize] += 1;
            if i % k as usize == 0 {
                occ.push(curr_occ.clone());
            }
        }

        Occ { occ: occ, k: k }
    }

    /// Get occurrence count of symbol a in BWT[..r+1].
    /// Complexity: O(k).
    pub fn get(&self, bwt: &BWTSlice, r: usize, a: u8) -> usize {
        // NOTE:
        //
        // Retrieving byte match counts in this function is critical to the performance of FM Index.
        //
        // The below manual count code is roughly equivalent to:
        // ```
        // let count = bwt[(i * self.k) + 1..r + 1].iter().filter(|&&c| c == a).count();
        // self.occ[i][a as usize] + count
        // ```
        //
        // But there are a couple of reasons to do this manually:
        // 1) As of 2016, versions of rustc/LLVM vectorize this manual loop more reliably
        //    than the iterator adapter version.
        // 2) Manually accumulating the byte match count in a single chunk can allows
        //    us to use a `u32` for that count, which has faster arithmetic on common arches.
        //    This does necessitate storing `k` as a u32.
        //
        // See the conversation in these issues for some of the history here:
        //
        // https://github.com/rust-bio/rust-bio/pull/74
        // https://github.com/rust-bio/rust-bio/pull/76

        // self.k is our sampling rate, so find our last sampled checkpoint
        let i = r / self.k as usize;
        let checkpoint = self.occ[i][a as usize];

        // find the portion of the BWT past the checkpoint which we need to count
        let start = (i * self.k as usize) + 1;
        let end = r + 1;

        // count all the matching bytes b/t the closest checkpoint and our desired lookup
        let count = bytecount::count(&bwt[start..end], a);

        // return the sampled checkpoint for this character + the manual count we just did
        checkpoint + (count as usize)
    }
}

/// Calculate the less array for a given BWT. Complexity O(n).
pub fn less(bwt: &BWTSlice, alphabet: &Alphabet) -> Less {
    let m = alphabet
        .max_symbol()
        .expect("Expecting non-empty alphabet.") as usize + 2;
    let mut less: Less = repeat(0).take(m).collect();
    for &c in bwt.iter() {
        less[c as usize] += 1;
    }
    // calculate +-prescan
    prescan(&mut less[..], 0, |a, b| a + b);

    less
}

/// Calculate the bwtfind array needed for inverting the BWT. Complexity O(n).
pub fn bwtfind(bwt: &BWTSlice, alphabet: &Alphabet) -> BWTFind {
    let n = bwt.len();
    let mut less = less(bwt, alphabet);

    let mut bwtfind: BWTFind = repeat(0).take(n).collect();
    for (r, &c) in bwt.iter().enumerate() {
        bwtfind[less[c as usize]] = r;
        less[c as usize] += 1;
    }

    bwtfind
}

#[cfg(test)]
mod tests {
    use super::{bwtfind, bwt, invert_bwt, Occ};
    use data_structures::suffix_array::suffix_array;
    use alphabets::Alphabet;

    #[test]
    fn test_bwtfind() {
        let text = b"cabca$";
        let alphabet = Alphabet::new(b"abc$");
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let bwtfind = bwtfind(&bwt, &alphabet);
        assert_eq!(bwtfind, vec![5, 0, 3, 4, 1, 2]);
    }

    #[test]
    fn test_invert_bwt() {
        let text = b"cabca$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let inverse = invert_bwt(&bwt);
        assert_eq!(inverse, text);
    }

    #[test]
    fn test_occ() {
        let bwt = vec![1u8, 3u8, 3u8, 1u8, 2u8, 0u8];
        let alphabet = Alphabet::new(&[0u8, 1u8, 2u8, 3u8]);
        let occ = Occ::new(&bwt, 3, &alphabet);
        assert_eq!(occ.occ, [[0, 1, 0, 0], [0, 2, 0, 2]]);
        assert_eq!(occ.get(&bwt, 4, 2u8), 1);
        assert_eq!(occ.get(&bwt, 4, 3u8), 2);
    }
}
<commit_msg>Fix issue #144<commit_after>// Copyright 2014-2016 Johannes Köster, Taylor Cramer.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! The Burrows-Wheeler-Transform and related data structures.
//! The implementation is based on the lecture notes
//! "Algorithmen auf Sequenzen", Kopczynski, Marschall, Martin and Rahmann, 2008 - 2015.

use std::iter::repeat;

use utils::prescan;
use alphabets::Alphabet;
use data_structures::suffix_array::RawSuffixArray;
use std::ops::Deref;
use bytecount;

pub type BWT = Vec<u8>;
pub type BWTSlice = [u8];
pub type Less = Vec<usize>;
pub type BWTFind = Vec<usize>;

pub trait DerefBWT: Deref<Target = BWT> {}
impl<T: Deref<Target = BWT>> DerefBWT for T {}

pub trait DerefOcc: Deref<Target = Occ> {}
impl<T: Deref<Target = Occ>> DerefOcc for T {}

pub trait DerefLess: Deref<Target = Less> {}
impl<T: Deref<Target = Less>> DerefLess for T {}

/// Calculate Burrows-Wheeler-Transform of the given text of length n.
/// Complexity: O(n).
///
/// # Arguments
///
/// * `text` - the text ended by sentinel symbol (being lexicographically smallest)
/// * `pos` - the suffix array for the text
///
/// # Example
///
/// ```
/// use bio::data_structures::suffix_array::suffix_array;
/// use bio::data_structures::bwt::bwt;
/// let text = b"GCCTTAACATTATTACGCCTA$";
/// let pos = suffix_array(text);
/// let bwt = bwt(text, &pos);
/// assert_eq!(bwt, b"ATTATTCAGGACCC$CTTTCAA");
/// ```
pub fn bwt(text: &[u8], pos: &RawSuffixArray) -> BWT {
    assert_eq!(text.len(), pos.len());
    let n = text.len();
    let mut bwt: BWT = repeat(0).take(n).collect();
    for r in 0..n {
        let p = pos[r];
        bwt[r] = if p > 0 { text[p - 1] } else { text[n - 1] };
    }

    bwt
}

/// Calculate the inverse of a BWT of length n, which is the original text.
/// Complexity: O(n).
///
/// This only works if the last sentinel in the original text is unique
/// and lexicographically the smallest.
///
/// # Arguments
///
/// * `bwt` - the BWT
pub fn invert_bwt(bwt: &BWTSlice) -> Vec<u8> {
    let alphabet = Alphabet::new(bwt);
    let n = bwt.len();
    let bwtfind = bwtfind(bwt, &alphabet);
    let mut inverse = Vec::with_capacity(n);

    let mut r = bwtfind[0];
    for _ in 0..n {
        r = bwtfind[r];
        inverse.push(bwt[r]);
    }

    inverse
}

/// An occurence array implementation.
#[derive(Serialize, Deserialize)]
pub struct Occ {
    occ: Vec<Vec<usize>>,
    k: u32,
}

impl Occ {
    /// Calculate occ array with sampling from BWT of length n.
    /// Time complexity: O(n).
    /// Space complexity: O(n / k * A) with A being the alphabet size.
    /// Alphabet size is determined on the fly from the BWT.
    /// For large texts, it is therefore advisable to transform
    /// the text before calculating the BWT (see alphabets::rank_transform).
    ///
    /// # Arguments
    ///
    /// * `bwt` - the BWT
    /// * `k` - the sampling rate: every k-th entry will be stored
    pub fn new(bwt: &BWTSlice, k: u32, alphabet: &Alphabet) -> Self {
        let n = bwt.len();
        let m = alphabet
            .max_symbol()
            .expect("Expecting non-empty alphabet.") as usize + 1;
        let mut occ = Vec::with_capacity(n / k as usize);
        let mut curr_occ: Vec<usize> = repeat(0).take(m).collect();
        for (i, &c) in bwt.iter().enumerate() {
            curr_occ[c as usize] += 1;
            if i % k as usize == 0 {
                occ.push(curr_occ.clone());
            }
        }

        Occ { occ: occ, k: k }
    }

    /// Get occurrence count of symbol a in BWT[..r+1].
    /// Complexity: O(k).
    pub fn get(&self, bwt: &BWTSlice, r: usize, a: u8) -> usize {
        // NOTE:
        //
        // Retrieving byte match counts in this function is critical to the performance of FM Index.
        //
        // The below manual count code is roughly equivalent to:
        // ```
        // let count = bwt[(i * self.k) + 1..r + 1].iter().filter(|&&c| c == a).count();
        // self.occ[i][a as usize] + count
        // ```
        //
        // But there are a couple of reasons to do this manually:
        // 1) As of 2016, versions of rustc/LLVM vectorize this manual loop more reliably
        //    than the iterator adapter version.
        // 2) Manually accumulating the byte match count in a single chunk can allows
        //    us to use a `u32` for that count, which has faster arithmetic on common arches.
        //    This does necessitate storing `k` as a u32.
        //
        // See the conversation in these issues for some of the history here:
        //
        // https://github.com/rust-bio/rust-bio/pull/74
        // https://github.com/rust-bio/rust-bio/pull/76

        // self.k is our sampling rate, so find our last sampled checkpoint
        let i = r / self.k as usize;
        let checkpoint = self.occ[i][a as usize];

        // find the portion of the BWT past the checkpoint which we need to count
        let start = (i * self.k as usize) + 1;
        let end = r + 1;

        // count all the matching bytes b/t the closest checkpoint and our desired lookup
        let count = bytecount::count(&bwt[start..end], a);

        // return the sampled checkpoint for this character + the manual count we just did
        checkpoint + (count as usize)
    }
}

/// Calculate the less array for a given BWT. Complexity O(n).
pub fn less(bwt: &BWTSlice, alphabet: &Alphabet) -> Less {
    let m = alphabet
        .max_symbol()
        .expect("Expecting non-empty alphabet.") as usize + 2;
    let mut less: Less = repeat(0).take(m).collect();
    for &c in bwt.iter() {
        less[c as usize] += 1;
    }
    // calculate +-prescan
    prescan(&mut less[..], 0, |a, b| a + b);

    less
}

/// Calculate the bwtfind array needed for inverting the BWT. Complexity O(n).
pub fn bwtfind(bwt: &BWTSlice, alphabet: &Alphabet) -> BWTFind {
    let n = bwt.len();
    let mut less = less(bwt, alphabet);

    let mut bwtfind: BWTFind = repeat(0).take(n).collect();
    for (r, &c) in bwt.iter().enumerate() {
        bwtfind[less[c as usize]] = r;
        less[c as usize] += 1;
    }

    bwtfind
}

#[cfg(test)]
mod tests {
    use super::{bwtfind, bwt, invert_bwt, Occ};
    use data_structures::suffix_array::suffix_array;
    use alphabets::Alphabet;

    #[test]
    fn test_bwtfind() {
        let text = b"cabca$";
        let alphabet = Alphabet::new(b"abc$");
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let bwtfind = bwtfind(&bwt, &alphabet);
        assert_eq!(bwtfind, vec![5, 0, 3, 4, 1, 2]);
    }

    #[test]
    fn test_invert_bwt() {
        let text = b"cabca$";
        let pos = suffix_array(text);
        let bwt = bwt(text, &pos);
        let inverse = invert_bwt(&bwt);
        assert_eq!(inverse, text);
    }

    #[test]
    fn test_occ() {
        let bwt = vec![1u8, 3u8, 3u8, 1u8, 2u8, 0u8];
        let alphabet = Alphabet::new(&[0u8, 1u8, 2u8, 3u8]);
        let occ = Occ::new(&bwt, 3, &alphabet);
        assert_eq!(occ.occ, [[0, 1, 0, 0], [0, 2, 0, 2]]);
        assert_eq!(occ.get(&bwt, 4, 2u8), 1);
        assert_eq!(occ.get(&bwt, 4, 3u8), 2);
    }
}
<|endoftext|>


<commit_before>use client::AsyncClient;
use futures::Future;
use index::btree::external;
use index::btree::external::ExtNode;

pub fn store_changed_nodes(neb: &AsyncClient) {
    let nodes = external::flush_changed();
    nodes.into_iter().for_each(|(id, node)| {
        if let Some(node) = node {
            node.persist(neb);
        } else {
            neb.remove_cell(id).wait().unwrap().unwrap();
        }
    })
}
<commit_msg>parallel persist<commit_after>use client::AsyncClient;
use futures::Future;
use index::btree::external;
use index::btree::external::ExtNode;
use rayon::prelude::*;

pub fn store_changed_nodes(neb: &AsyncClient) {
    let nodes = external::flush_changed();
    nodes.into_par_iter().for_each(|(id, node)| {
        if let Some(node) = node {
            node.persist(neb);
        } else {
            neb.remove_cell(id).wait().unwrap().unwrap();
        }
    })
}
<|endoftext|>


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

//! An implementation of SipHash.

use prelude::v1::*;

use marker::PhantomData;
use ptr;

/// An implementation of SipHash 1-3.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "29754")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher13 {
    hasher: Hasher<Sip13Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "29754")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher24 {
    hasher: Hasher<Sip24Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);

#[derive(Debug)]
struct Hasher<S: Sip> {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    state: State, // hash State
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
    _marker: PhantomData<S>,
}

#[derive(Debug, Clone, Copy)]
struct State {
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64,
    v2: u64,
    v1: u64,
    v3: u64,
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($state:expr) => ({
        compress!($state.v0, $state.v1, $state.v2, $state.v3)
    });
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    });
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        SipHasher(SipHasher24::new_with_keys(key0, key1))
    }
}

impl SipHasher13 {
    /// Creates a new `SipHasher13` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "29754")]
    pub fn new() -> SipHasher13 {
        SipHasher13::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher13` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "29754")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
        SipHasher13 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl SipHasher24 {
    /// Creates a new `SipHasher24` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "29754")]
    pub fn new() -> SipHasher24 {
        SipHasher24::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher24` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "29754")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
        SipHasher24 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl<S: Sip> Hasher<S> {
    #[inline]
    fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
        let mut state = Hasher {
            k0: key0,
            k1: key1,
            length: 0,
            state: State {
                v0: 0,
                v1: 0,
                v2: 0,
                v3: 0,
            },
            tail: 0,
            ntail: 0,
            _marker: PhantomData,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.state.v0 = self.k0 ^ 0x736f6d6570736575;
        self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.state.v2 = self.k0 ^ 0x6c7967656e657261;
        self.state.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl super::Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.0.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "29754")]
impl super::Hasher for SipHasher13 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "29754")]
impl super::Hasher for SipHasher24 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

impl<S: Sip> super::Hasher for Hasher<S> {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.state.v3 ^= m;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.state.v3 ^= mi;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut state = self.state;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        state.v3 ^= b;
        S::c_rounds(&mut state);
        state.v0 ^= b;

        state.v2 ^= 0xff;
        S::d_rounds(&mut state);

        state.v0 ^ state.v1 ^ state.v2 ^ state.v3
    }
}

impl<S: Sip> Clone for Hasher<S> {
    #[inline]
    fn clone(&self) -> Hasher<S> {
        Hasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            state: self.state,
            tail: self.tail,
            ntail: self.ntail,
            _marker: self._marker,
        }
    }
}

impl<S: Sip> Default for Hasher<S> {
    #[inline]
    fn default() -> Hasher<S> {
        Hasher::new_with_keys(0, 0)
    }
}

#[doc(hidden)]
trait Sip {
    fn c_rounds(&mut State);
    fn d_rounds(&mut State);
}

#[derive(Debug, Clone, Default)]
struct Sip13Rounds;

impl Sip for Sip13Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
    }
}

#[derive(Debug, Clone, Default)]
struct Sip24Rounds;

impl Sip for Sip24Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
        compress!(state);
    }
}
<commit_msg>Rollup merge of #34768 - alexcrichton:issue-audit, r=aturon<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An implementation of SipHash.

use prelude::v1::*;

use marker::PhantomData;
use ptr;

/// An implementation of SipHash 1-3.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher13 {
    hasher: Hasher<Sip13Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
#[unstable(feature = "sip_hash_13", issue = "34767")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher24 {
    hasher: Hasher<Sip24Rounds>,
}

/// An implementation of SipHash 2-4.
///
/// See: https://131002.net/siphash/
///
/// This is currently the default hashing function used by standard library
/// (eg. `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such as
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
///
/// Although the SipHash algorithm is considered to be generally strong,
/// it is not intended for cryptographic purposes. As such, all
/// cryptographic uses of this implementation are _strongly discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug, Clone, Default)]
pub struct SipHasher(SipHasher24);

#[derive(Debug)]
struct Hasher<S: Sip> {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    state: State, // hash State
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
    _marker: PhantomData<S>,
}

#[derive(Debug, Clone, Copy)]
struct State {
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64,
    v2: u64,
    v1: u64,
    v3: u64,
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($state:expr) => ({
        compress!($state.v0, $state.v1, $state.v2, $state.v3)
    });
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    });
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        SipHasher(SipHasher24::new_with_keys(key0, key1))
    }
}

impl SipHasher13 {
    /// Creates a new `SipHasher13` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    pub fn new() -> SipHasher13 {
        SipHasher13::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher13` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
        SipHasher13 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl SipHasher24 {
    /// Creates a new `SipHasher24` with the two initial keys set to 0.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    pub fn new() -> SipHasher24 {
        SipHasher24::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher24` that is keyed off the provided keys.
    #[inline]
    #[unstable(feature = "sip_hash_13", issue = "34767")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 {
        SipHasher24 {
            hasher: Hasher::new_with_keys(key0, key1)
        }
    }
}

impl<S: Sip> Hasher<S> {
    #[inline]
    fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
        let mut state = Hasher {
            k0: key0,
            k1: key1,
            length: 0,
            state: State {
                v0: 0,
                v1: 0,
                v2: 0,
                v3: 0,
            },
            tail: 0,
            ntail: 0,
            _marker: PhantomData,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.state.v0 = self.k0 ^ 0x736f6d6570736575;
        self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.state.v2 = self.k0 ^ 0x6c7967656e657261;
        self.state.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl super::Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.0.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher13 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

#[unstable(feature = "sip_hash_13", issue = "34767")]
impl super::Hasher for SipHasher24 {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        self.hasher.write(msg)
    }

    #[inline]
    fn finish(&self) -> u64 {
        self.hasher.finish()
    }
}

impl<S: Sip> super::Hasher for Hasher<S> {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.state.v3 ^= m;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.state.v3 ^= mi;
            S::c_rounds(&mut self.state);
            self.state.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut state = self.state;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        state.v3 ^= b;
        S::c_rounds(&mut state);
        state.v0 ^= b;

        state.v2 ^= 0xff;
        S::d_rounds(&mut state);

        state.v0 ^ state.v1 ^ state.v2 ^ state.v3
    }
}

impl<S: Sip> Clone for Hasher<S> {
    #[inline]
    fn clone(&self) -> Hasher<S> {
        Hasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            state: self.state,
            tail: self.tail,
            ntail: self.ntail,
            _marker: self._marker,
        }
    }
}

impl<S: Sip> Default for Hasher<S> {
    #[inline]
    fn default() -> Hasher<S> {
        Hasher::new_with_keys(0, 0)
    }
}

#[doc(hidden)]
trait Sip {
    fn c_rounds(&mut State);
    fn d_rounds(&mut State);
}

#[derive(Debug, Clone, Default)]
struct Sip13Rounds;

impl Sip for Sip13Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
    }
}

#[derive(Debug, Clone, Default)]
struct Sip24Rounds;

impl Sip for Sip24Rounds {
    #[inline]
    fn c_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
    }

    #[inline]
    fn d_rounds(state: &mut State) {
        compress!(state);
        compress!(state);
        compress!(state);
        compress!(state);
    }
}
<|endoftext|>


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

#[forbid(deprecated_mode)];
#[allow(missing_doc)];

pub mod icu {
    pub type UBool = u8;
    pub type UProperty = int;
    pub type UChar32 = char;

    pub static TRUE : u8 = 1u8;
    pub static FALSE : u8 = 1u8;

    pub static UCHAR_ALPHABETIC : UProperty = 0;
    pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
    pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
    pub static UCHAR_BIDI_CONTROL : UProperty = 2;

    pub static UCHAR_BIDI_MIRRORED : UProperty = 3;
    pub static UCHAR_DASH : UProperty = 4;
    pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
    pub static UCHAR_DEPRECATED : UProperty = 6;

    pub static UCHAR_DIACRITIC : UProperty = 7;
    pub static UCHAR_EXTENDER : UProperty = 8;
    pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
    pub static UCHAR_GRAPHEME_BASE : UProperty = 10;

    pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11;
    pub static UCHAR_GRAPHEME_LINK : UProperty = 12;
    pub static UCHAR_HEX_DIGIT : UProperty = 13;
    pub static UCHAR_HYPHEN : UProperty = 14;

    pub static UCHAR_ID_CONTINUE : UProperty = 15;
    pub static UCHAR_ID_START : UProperty = 16;
    pub static UCHAR_IDEOGRAPHIC : UProperty = 17;
    pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;

    pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
    pub static UCHAR_JOIN_CONTROL : UProperty = 20;
    pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
    pub static UCHAR_LOWERCASE : UProperty = 22;

    pub static UCHAR_MATH : UProperty = 23;
    pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
    pub static UCHAR_QUOTATION_MARK : UProperty = 25;
    pub static UCHAR_RADICAL : UProperty = 26;

    pub static UCHAR_SOFT_DOTTED : UProperty = 27;
    pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
    pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
    pub static UCHAR_UPPERCASE : UProperty = 30;

    pub static UCHAR_WHITE_SPACE : UProperty = 31;
    pub static UCHAR_XID_CONTINUE : UProperty = 32;
    pub static UCHAR_XID_START : UProperty = 33;
    pub static UCHAR_CASE_SENSITIVE : UProperty = 34;

    pub static UCHAR_S_TERM : UProperty = 35;
    pub static UCHAR_VARIATION_SELECTOR : UProperty = 36;
    pub static UCHAR_NFD_INERT : UProperty = 37;
    pub static UCHAR_NFKD_INERT : UProperty = 38;

    pub static UCHAR_NFC_INERT : UProperty = 39;
    pub static UCHAR_NFKC_INERT : UProperty = 40;
    pub static UCHAR_SEGMENT_STARTER : UProperty = 41;
    pub static UCHAR_PATTERN_SYNTAX : UProperty = 42;

    pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
    pub static UCHAR_POSIX_ALNUM : UProperty = 44;
    pub static UCHAR_POSIX_BLANK : UProperty = 45;
    pub static UCHAR_POSIX_GRAPH : UProperty = 46;

    pub static UCHAR_POSIX_PRINT : UProperty = 47;
    pub static UCHAR_POSIX_XDIGIT : UProperty = 48;
    pub static UCHAR_CASED : UProperty = 49;
    pub static UCHAR_CASE_IGNORABLE : UProperty = 50;

    pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
    pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
    pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
    pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;

    pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
    pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
    pub static UCHAR_BINARY_LIMIT : UProperty = 57;
    pub static UCHAR_BIDI_CLASS : UProperty = 0x1000;

    pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
    pub static UCHAR_BLOCK : UProperty = 0x1001;
    pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
    pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;

    pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
    pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
    pub static UCHAR_JOINING_GROUP : UProperty = 0x1006;
    pub static UCHAR_JOINING_TYPE : UProperty = 0x1007;

    pub static UCHAR_LINE_BREAK : UProperty = 0x1008;
    pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
    pub static UCHAR_SCRIPT : UProperty = 0x100A;
    pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;

    pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
    pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
    pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
    pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;

    pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
    pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
    pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
    pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013;

    pub static UCHAR_WORD_BREAK : UProperty = 0x1014;
    pub static UCHAR_INT_LIMIT : UProperty = 0x1015;

    pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
    pub static UCHAR_MASK_START : UProperty = 0x2000;
    // = UCHAR_GENERAL_CATEGORY_MASK
    pub static UCHAR_MASK_LIMIT : UProperty = 0x2001;

    pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
    pub static UCHAR_DOUBLE_START : UProperty = 0x3000;
    // = UCHAR_NUMERIC_VALUE
    pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;

    pub static UCHAR_AGE : UProperty = 0x4000;
    pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
    pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
    pub static UCHAR_CASE_FOLDING : UProperty = 0x4002;

    pub static UCHAR_ISO_COMMENT : UProperty = 0x4003;
    pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
    pub static UCHAR_NAME : UProperty = 0x4005;
    pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;

    pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
    pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
    pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
    pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;

    pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
    pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
    pub static UCHAR_STRING_LIMIT : UProperty = 0x400D;

    pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
    pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
    // = UCHAR_SCRIPT_EXTENSIONS;
    pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;

    pub static UCHAR_INVALID_CODE : UProperty = -1;

    pub mod libicu {
        #[link_name = "icuuc"]
        #[abi = "cdecl"]
        extern {
            pub unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty)
                                              -> UBool;
            pub unsafe fn u_isdigit(c: UChar32) -> UBool;
            pub unsafe fn u_islower(c: UChar32) -> UBool;
            pub unsafe fn u_isspace(c: UChar32) -> UBool;
            pub unsafe fn u_isupper(c: UChar32) -> UBool;
            pub unsafe fn u_tolower(c: UChar32) -> UChar32;
            pub unsafe fn u_toupper(c: UChar32) -> UChar32;
        }
    }
}

pub fn is_XID_start(c: char) -> bool {
    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

pub fn is_XID_continue(c: char) -> bool {
    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

/*
Function: is_digit

Returns true if a character is a digit.
*/
pub fn is_digit(c: char) -> bool {
    return icu::libicu::u_isdigit(c) == icu::TRUE;
}

/*
Function: is_lower

Returns true if a character is a lowercase letter.
*/
pub fn is_lower(c: char) -> bool {
    return icu::libicu::u_islower(c) == icu::TRUE;
}

/*
Function: is_space

Returns true if a character is space.
*/
pub fn is_space(c: char) -> bool {
    return icu::libicu::u_isspace(c) == icu::TRUE;
}

/*
Function: is_upper

Returns true if a character is an uppercase letter.
*/
pub fn is_upper(c: char) -> bool {
    return icu::libicu::u_isupper(c) == icu::TRUE;
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_is_digit() {
        assert!((unicode::icu::is_digit('0')));
        assert!((!unicode::icu::is_digit('m')));
    }

    #[test]
    fn test_is_lower() {
        assert!((unicode::icu::is_lower('m')));
        assert!((!unicode::icu::is_lower('M')));
    }

    #[test]
    fn test_is_space() {
        assert!((unicode::icu::is_space(' ')));
        assert!((!unicode::icu::is_space('m')));
    }

    #[test]
    fn test_is_upper() {
        assert!((unicode::icu::is_upper('M')));
        assert!((!unicode::icu::is_upper('m')));
    }
}
<commit_msg>auto merge of #8137 : omasanori/rust/ubool-false, r=bblum<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[forbid(deprecated_mode)];
#[allow(missing_doc)];

pub mod icu {
    pub type UBool = u8;
    pub type UProperty = int;
    pub type UChar32 = char;

    pub static TRUE : u8 = 1u8;
    pub static FALSE : u8 = 0u8;

    pub static UCHAR_ALPHABETIC : UProperty = 0;
    pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
    pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
    pub static UCHAR_BIDI_CONTROL : UProperty = 2;

    pub static UCHAR_BIDI_MIRRORED : UProperty = 3;
    pub static UCHAR_DASH : UProperty = 4;
    pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
    pub static UCHAR_DEPRECATED : UProperty = 6;

    pub static UCHAR_DIACRITIC : UProperty = 7;
    pub static UCHAR_EXTENDER : UProperty = 8;
    pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
    pub static UCHAR_GRAPHEME_BASE : UProperty = 10;

    pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11;
    pub static UCHAR_GRAPHEME_LINK : UProperty = 12;
    pub static UCHAR_HEX_DIGIT : UProperty = 13;
    pub static UCHAR_HYPHEN : UProperty = 14;

    pub static UCHAR_ID_CONTINUE : UProperty = 15;
    pub static UCHAR_ID_START : UProperty = 16;
    pub static UCHAR_IDEOGRAPHIC : UProperty = 17;
    pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;

    pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
    pub static UCHAR_JOIN_CONTROL : UProperty = 20;
    pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
    pub static UCHAR_LOWERCASE : UProperty = 22;

    pub static UCHAR_MATH : UProperty = 23;
    pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
    pub static UCHAR_QUOTATION_MARK : UProperty = 25;
    pub static UCHAR_RADICAL : UProperty = 26;

    pub static UCHAR_SOFT_DOTTED : UProperty = 27;
    pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
    pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
    pub static UCHAR_UPPERCASE : UProperty = 30;

    pub static UCHAR_WHITE_SPACE : UProperty = 31;
    pub static UCHAR_XID_CONTINUE : UProperty = 32;
    pub static UCHAR_XID_START : UProperty = 33;
    pub static UCHAR_CASE_SENSITIVE : UProperty = 34;

    pub static UCHAR_S_TERM : UProperty = 35;
    pub static UCHAR_VARIATION_SELECTOR : UProperty = 36;
    pub static UCHAR_NFD_INERT : UProperty = 37;
    pub static UCHAR_NFKD_INERT : UProperty = 38;

    pub static UCHAR_NFC_INERT : UProperty = 39;
    pub static UCHAR_NFKC_INERT : UProperty = 40;
    pub static UCHAR_SEGMENT_STARTER : UProperty = 41;
    pub static UCHAR_PATTERN_SYNTAX : UProperty = 42;

    pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
    pub static UCHAR_POSIX_ALNUM : UProperty = 44;
    pub static UCHAR_POSIX_BLANK : UProperty = 45;
    pub static UCHAR_POSIX_GRAPH : UProperty = 46;

    pub static UCHAR_POSIX_PRINT : UProperty = 47;
    pub static UCHAR_POSIX_XDIGIT : UProperty = 48;
    pub static UCHAR_CASED : UProperty = 49;
    pub static UCHAR_CASE_IGNORABLE : UProperty = 50;

    pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
    pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
    pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
    pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;

    pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
    pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
    pub static UCHAR_BINARY_LIMIT : UProperty = 57;
    pub static UCHAR_BIDI_CLASS : UProperty = 0x1000;

    pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
    pub static UCHAR_BLOCK : UProperty = 0x1001;
    pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
    pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;

    pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
    pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
    pub static UCHAR_JOINING_GROUP : UProperty = 0x1006;
    pub static UCHAR_JOINING_TYPE : UProperty = 0x1007;

    pub static UCHAR_LINE_BREAK : UProperty = 0x1008;
    pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
    pub static UCHAR_SCRIPT : UProperty = 0x100A;
    pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;

    pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
    pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
    pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
    pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;

    pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
    pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
    pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
    pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013;

    pub static UCHAR_WORD_BREAK : UProperty = 0x1014;
    pub static UCHAR_INT_LIMIT : UProperty = 0x1015;

    pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
    pub static UCHAR_MASK_START : UProperty = 0x2000;
    // = UCHAR_GENERAL_CATEGORY_MASK
    pub static UCHAR_MASK_LIMIT : UProperty = 0x2001;

    pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
    pub static UCHAR_DOUBLE_START : UProperty = 0x3000;
    // = UCHAR_NUMERIC_VALUE
    pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;

    pub static UCHAR_AGE : UProperty = 0x4000;
    pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
    pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
    pub static UCHAR_CASE_FOLDING : UProperty = 0x4002;

    pub static UCHAR_ISO_COMMENT : UProperty = 0x4003;
    pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
    pub static UCHAR_NAME : UProperty = 0x4005;
    pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;

    pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
    pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
    pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
    pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;

    pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
    pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
    pub static UCHAR_STRING_LIMIT : UProperty = 0x400D;

    pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
    pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
    // = UCHAR_SCRIPT_EXTENSIONS;
    pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;

    pub static UCHAR_INVALID_CODE : UProperty = -1;

    pub mod libicu {
        #[link_name = "icuuc"]
        #[abi = "cdecl"]
        extern {
            pub unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty)
                                              -> UBool;
            pub unsafe fn u_isdigit(c: UChar32) -> UBool;
            pub unsafe fn u_islower(c: UChar32) -> UBool;
            pub unsafe fn u_isspace(c: UChar32) -> UBool;
            pub unsafe fn u_isupper(c: UChar32) -> UBool;
            pub unsafe fn u_tolower(c: UChar32) -> UChar32;
            pub unsafe fn u_toupper(c: UChar32) -> UChar32;
        }
    }
}

pub fn is_XID_start(c: char) -> bool {
    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

pub fn is_XID_continue(c: char) -> bool {
    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
        == icu::TRUE;
}

/*
Function: is_digit

Returns true if a character is a digit.
*/
pub fn is_digit(c: char) -> bool {
    return icu::libicu::u_isdigit(c) == icu::TRUE;
}

/*
Function: is_lower

Returns true if a character is a lowercase letter.
*/
pub fn is_lower(c: char) -> bool {
    return icu::libicu::u_islower(c) == icu::TRUE;
}

/*
Function: is_space

Returns true if a character is space.
*/
pub fn is_space(c: char) -> bool {
    return icu::libicu::u_isspace(c) == icu::TRUE;
}

/*
Function: is_upper

Returns true if a character is an uppercase letter.
*/
pub fn is_upper(c: char) -> bool {
    return icu::libicu::u_isupper(c) == icu::TRUE;
}

#[cfg(test)]
mod tests {

    #[test]
    fn test_is_digit() {
        assert!((unicode::icu::is_digit('0')));
        assert!((!unicode::icu::is_digit('m')));
    }

    #[test]
    fn test_is_lower() {
        assert!((unicode::icu::is_lower('m')));
        assert!((!unicode::icu::is_lower('M')));
    }

    #[test]
    fn test_is_space() {
        assert!((unicode::icu::is_space(' ')));
        assert!((!unicode::icu::is_space('m')));
    }

    #[test]
    fn test_is_upper() {
        assert!((unicode::icu::is_upper('M')));
        assert!((!unicode::icu::is_upper('m')));
    }
}
<|endoftext|>


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

//! Implementation of panics via stack unwinding
//!
//! This crate is an implementation of panics in Rust using "most native" stack
//! unwinding mechanism of the platform this is being compiled for. This
//! essentially gets categorized into three buckets currently:
//!
//! 1. MSVC targets use SEH in the `seh.rs` file.
//! 2. The 64-bit MinGW target half-uses SEH and half-use gcc-like information
//!    in the `seh64_gnu.rs` module.
//! 3. All other targets use libunwind/libgcc in the `gcc/mod.rs` module.
//!
//! More documentation about each implementation can be found in the respective
//! module.

#![no_std]
#![unstable(feature = "panic_unwind", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]

#![feature(allocator_api)]
#![feature(alloc)]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(panic_unwind)]
#![feature(raw)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(unwind_attributes)]
#![cfg_attr(target_env = "msvc", feature(raw))]

#![panic_runtime]
#![feature(panic_runtime)]

extern crate alloc;
extern crate libc;
#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
extern crate unwind;

use alloc::boxed::Box;
use core::intrinsics;
use core::mem;
use core::raw;
use core::panic::BoxMeUp;

// Rust runtime's startup objects depend on these symbols, so make them public.
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
pub use imp::eh_frame_registry::*;

// *-pc-windows-msvc
#[cfg(target_env = "msvc")]
#[path = "seh.rs"]
mod imp;

// x86_64-pc-windows-gnu
#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
#[path = "seh64_gnu.rs"]
mod imp;

// i686-pc-windows-gnu and all others
#[cfg(any(all(unix, not(target_os = "emscripten")),
          target_os = "cloudabi",
          target_os = "redox",
          all(windows, target_arch = "x86", target_env = "gnu")))]
#[path = "gcc.rs"]
mod imp;

// emscripten
#[cfg(target_os = "emscripten")]
#[path = "emcc.rs"]
mod imp;

#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
#[path = "wasm32.rs"]
mod imp;

mod dwarf;
mod windows;

// Entry point for catching an exception, implemented using the `try` intrinsic
// in the compiler.
//
// The interaction between the `payload` function and the compiler is pretty
// hairy and tightly coupled, for more information see the compiler's
// implementation of this.
#[no_mangle]
pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                                  data: *mut u8,
                                                  data_ptr: *mut usize,
                                                  vtable_ptr: *mut usize)
                                                  -> u32 {
    let mut payload = imp::payload();
    if intrinsics::try(f, data, &mut payload as *mut _ as *mut _) == 0 {
        0
    } else {
        let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
        *data_ptr = obj.data as usize;
        *vtable_ptr = obj.vtable as usize;
        1
    }
}

// Entry point for raising an exception, just delegates to the platform-specific
// implementation.
#[no_mangle]
#[unwind(allowed)]
pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
    let payload = payload as *mut &mut dyn BoxMeUp;
    imp::panic(Box::from_raw((*payload).box_me_up()))
}
<commit_msg>Fix failure on msvc<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of panics via stack unwinding
//!
//! This crate is an implementation of panics in Rust using "most native" stack
//! unwinding mechanism of the platform this is being compiled for. This
//! essentially gets categorized into three buckets currently:
//!
//! 1. MSVC targets use SEH in the `seh.rs` file.
//! 2. The 64-bit MinGW target half-uses SEH and half-use gcc-like information
//!    in the `seh64_gnu.rs` module.
//! 3. All other targets use libunwind/libgcc in the `gcc/mod.rs` module.
//!
//! More documentation about each implementation can be found in the respective
//! module.

#![no_std]
#![unstable(feature = "panic_unwind", issue = "32837")]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]

#![feature(allocator_api)]
#![feature(alloc)]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(panic_unwind)]
#![feature(raw)]
#![feature(staged_api)]
#![feature(std_internals)]
#![feature(unwind_attributes)]

#![panic_runtime]
#![feature(panic_runtime)]

extern crate alloc;
extern crate libc;
#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
extern crate unwind;

use alloc::boxed::Box;
use core::intrinsics;
use core::mem;
use core::raw;
use core::panic::BoxMeUp;

// Rust runtime's startup objects depend on these symbols, so make them public.
#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
pub use imp::eh_frame_registry::*;

// *-pc-windows-msvc
#[cfg(target_env = "msvc")]
#[path = "seh.rs"]
mod imp;

// x86_64-pc-windows-gnu
#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
#[path = "seh64_gnu.rs"]
mod imp;

// i686-pc-windows-gnu and all others
#[cfg(any(all(unix, not(target_os = "emscripten")),
          target_os = "cloudabi",
          target_os = "redox",
          all(windows, target_arch = "x86", target_env = "gnu")))]
#[path = "gcc.rs"]
mod imp;

// emscripten
#[cfg(target_os = "emscripten")]
#[path = "emcc.rs"]
mod imp;

#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
#[path = "wasm32.rs"]
mod imp;

mod dwarf;
mod windows;

// Entry point for catching an exception, implemented using the `try` intrinsic
// in the compiler.
//
// The interaction between the `payload` function and the compiler is pretty
// hairy and tightly coupled, for more information see the compiler's
// implementation of this.
#[no_mangle]
pub unsafe extern "C" fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                                  data: *mut u8,
                                                  data_ptr: *mut usize,
                                                  vtable_ptr: *mut usize)
                                                  -> u32 {
    let mut payload = imp::payload();
    if intrinsics::try(f, data, &mut payload as *mut _ as *mut _) == 0 {
        0
    } else {
        let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload));
        *data_ptr = obj.data as usize;
        *vtable_ptr = obj.vtable as usize;
        1
    }
}

// Entry point for raising an exception, just delegates to the platform-specific
// implementation.
#[no_mangle]
#[unwind(allowed)]
pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 {
    let payload = payload as *mut &mut dyn BoxMeUp;
    imp::panic(Box::from_raw((*payload).box_me_up()))
}
<|endoftext|>


<commit_before>extern crate rand;

use std::ops::Add;
use rand::Rng;
use time::{Timespec, get_time};

///
/// This could be using u64 but is i64 to be compatible with the [`time`] crate
///
#[derive(Eq, Ord, PartialEq, PartialOrd, Debug, Copy, Clone, Hash)]
pub struct Timestamp {
    pub sec: i64,
}

impl Timestamp {
    pub fn new(sec: i64) -> Self {
        Timestamp { sec }
    }

    pub fn now() -> Self {
        Self::new(get_time().sec)
    }
}

impl From<Timespec> for Timestamp {
    fn from(value: Timespec) -> Self {
        Self::new(value.sec)
    }
}

impl From<i64> for Timestamp {
    fn from(value: i64) -> Self {
        Self::new(value)
    }
}

impl Into<i64> for Timestamp {
    fn into(self) -> i64 {
        self.sec
    }
}

impl Add<i64> for Timestamp {
    type Output = Timestamp;

    fn add(self, rhs: i64) -> Self::Output {
        Timestamp::new(self.sec + rhs)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct EntryId {
    timestamp: Timestamp,
    id: u16,
}

#[derive(Debug)]
pub struct Entry<T: Send + 'static> {
    id: EntryId,
    data: T,
}

impl EntryId {
    pub fn new<TS: Into<Timestamp>>(timestamp: TS, id: u16) -> Self {
        EntryId { timestamp: timestamp.into(), id }
    }

    pub fn gen<TS: Into<Timestamp>>(timestamp: TS) -> Self {
        let mut rng = rand::thread_rng();
        let id = rng.gen::<u16>();

        Self::new(timestamp, id)
    }

    pub fn timestamp(&self) -> Timestamp {
        self.timestamp
    }

    pub fn id(&self) -> u16 {
        self.id
    }
}

impl<T: Send + 'static> Entry<T> {
    pub fn new(id: EntryId, data: T) -> Self {
        Entry { id, data }
    }

    pub fn gen<TS: Into<Timestamp>>(timestamp: TS, data: T) -> Self {
        Self::new(EntryId::gen(timestamp), data)
    }

    pub fn id(&self) -> EntryId {
        self.id
    }

    pub fn data(&self) -> &T {
        &self.data
    }
}<commit_msg>Update import of rand<commit_after>use std::ops::Add;
use rand::{Rng, thread_rng};
use time::{Timespec, get_time};

///
/// This could be using u64 but is i64 to be compatible with the [`time`] crate
///
#[derive(Eq, Ord, PartialEq, PartialOrd, Debug, Copy, Clone, Hash)]
pub struct Timestamp {
    pub sec: i64,
}

impl Timestamp {
    pub fn new(sec: i64) -> Self {
        Timestamp { sec }
    }

    pub fn now() -> Self {
        Self::new(get_time().sec)
    }
}

impl From<Timespec> for Timestamp {
    fn from(value: Timespec) -> Self {
        Self::new(value.sec)
    }
}

impl From<i64> for Timestamp {
    fn from(value: i64) -> Self {
        Self::new(value)
    }
}

impl Into<i64> for Timestamp {
    fn into(self) -> i64 {
        self.sec
    }
}

impl Add<i64> for Timestamp {
    type Output = Timestamp;

    fn add(self, rhs: i64) -> Self::Output {
        Timestamp::new(self.sec + rhs)
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct EntryId {
    timestamp: Timestamp,
    id: u16,
}

#[derive(Debug)]
pub struct Entry<T: Send + 'static> {
    id: EntryId,
    data: T,
}

impl EntryId {
    pub fn new<TS: Into<Timestamp>>(timestamp: TS, id: u16) -> Self {
        EntryId { timestamp: timestamp.into(), id }
    }

    pub fn gen<TS: Into<Timestamp>>(timestamp: TS) -> Self {
        let mut rng = thread_rng();
        let id = rng.gen::<u16>();

        Self::new(timestamp, id)
    }

    pub fn timestamp(&self) -> Timestamp {
        self.timestamp
    }

    pub fn id(&self) -> u16 {
        self.id
    }
}

impl<T: Send + 'static> Entry<T> {
    pub fn new(id: EntryId, data: T) -> Self {
        Entry { id, data }
    }

    pub fn gen<TS: Into<Timestamp>>(timestamp: TS, data: T) -> Self {
        Self::new(EntryId::gen(timestamp), data)
    }

    pub fn id(&self) -> EntryId {
        self.id
    }

    pub fn data(&self) -> &T {
        &self.data
    }
}<|endoftext|>


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

// aux-build:proc-macro-gates.rs
// gate-test-proc_macro_non_items
// gate-test-proc_macro_path_invoc
// gate-test-proc_macro_mod line
// gate-test-proc_macro_expr
// gate-test-proc_macro_mod

#![feature(proc_macro, stmt_expr_attributes)]

extern crate proc_macro_gates as foo;

use foo::*;

#[foo::a] //~ ERROR: paths of length greater than one
fn _test() {}

#[a] //~ ERROR: custom attributes cannot be applied to modules
mod _test2 {}

#[a = y] //~ ERROR: must only be followed by a delimiter token
fn _test3() {}

#[a = ] //~ ERROR: must only be followed by a delimiter token
fn _test4() {}

#[a () = ] //~ ERROR: must only be followed by a delimiter token
fn _test5() {}

fn main() {
    #[a] //~ ERROR: custom attributes cannot be applied to statements
    let _x = 2;
    let _x = #[a] 2;
    //~^ ERROR: custom attributes cannot be applied to expressions

    let _x: m!(u32) = 3;
    //~^ ERROR: procedural macros cannot be expanded to types
    if let m!(Some(_x)) = Some(3) {
    //~^ ERROR: procedural macros cannot be expanded to patterns
    }
    let _x = m!(3);
    //~^ ERROR: procedural macros cannot be expanded to expressions
    m!(let _x = 3;);
    //~^ ERROR: procedural macros cannot be expanded to statements
}
<commit_msg>Rollup merge of #50325 - petrochenkov:pmgate, r=alexcrichton<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// aux-build:proc-macro-gates.rs
// gate-test-proc_macro_non_items
// gate-test-proc_macro_path_invoc
// gate-test-proc_macro_mod line
// gate-test-proc_macro_expr
// gate-test-proc_macro_mod

#![feature(proc_macro, stmt_expr_attributes)]

extern crate proc_macro_gates as foo;

use foo::*;

#[foo::a] //~ ERROR: paths of length greater than one
fn _test() {}

fn _test_inner() {
    #![a] // OK
}

#[a] //~ ERROR: custom attributes cannot be applied to modules
mod _test2 {}

mod _test2_inner {
    #![a] //~ ERROR: custom attributes cannot be applied to modules
}

#[a = y] //~ ERROR: must only be followed by a delimiter token
fn _test3() {}

#[a = ] //~ ERROR: must only be followed by a delimiter token
fn _test4() {}

#[a () = ] //~ ERROR: must only be followed by a delimiter token
fn _test5() {}

fn attrs() {
    // Statement, item
    #[a] // OK
    struct S;

    // Statement, macro
    #[a] //~ ERROR: custom attributes cannot be applied to statements
    println!();

    // Statement, semi
    #[a] //~ ERROR: custom attributes cannot be applied to statements
    S;

    // Statement, local
    #[a] //~ ERROR: custom attributes cannot be applied to statements
    let _x = 2;

    // Expr
    let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions

    // Opt expr
    let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions

    // Expr macro
    let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions
}

fn main() {
    let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types
    if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns

    m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements
    m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements

    let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions
    let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions
}
<|endoftext|>


<commit_before>use memory::Memory;
use std::vec::Vec;
use std::sync::atomic::{AtomicIsize, Ordering};

/// Maps multiple `Memory`s into a single address space.
///
/// The `MappedMemory` allows to unify multiple `Memory`s in one address space.
/// A `Memory` is mounted at a certain address and is from now on responsible
/// for all reads and writes between that starting at that address (the “mount
/// point”) and ending where the mounted memory ends.
/// The read and write calls for the responsible `Memory` will be given an
/// address _relative_ to the mount point.
///
/// ```text
///                   Unmapped
///                <-------->
///       mem_a                   mem_b
/// |--------------|            |------|
///                            NullMemory
///                         |--------------
/// |------------- mapped_mem ----------->
/// |              |            |      |
/// 0            0x100        0x200  0x280
/// ```
///
/// For example: `mapped_mem.get(0x208)` would yield the same value as
/// `mem_b.get(0x008)`.
///
/// # Examples
///
/// ```
/// use osciemu::memory::{Memory, SliceMemory, MappedMemory};
///
/// let mut mm = MappedMemory::new();
/// let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
/// let m2 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));
/// // Now mm =~ [1, _, 2, 2]
/// assert_eq!(mm.get(0), 1);
/// assert_eq!(mm.get(3), 2);
/// ```
///
/// The `MemoryToken`s can be used to access the `Memory` even if it has been
/// mounted. They work like `std::cell::RefCell`.
///
/// ```
/// use osciemu::memory::{Memory, NullMemory, SliceMemory, MappedMemory};
/// use osciemu::memory::mappedmemory::MemoryToken;
///
/// let mut mm = MappedMemory::new();
/// let m1 = mm.mount(0, Box::new(NullMemory::new()));
/// let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 2, 3, 4]))));
/// mm.set(0, 99);
/// assert_eq!(mm.get(0), 99);
/// assert_eq!(mm.borrow(&m2).get(0), 99);
/// ```
///
/// The `MemoryToken`s are also used to unmount a mounted `Memory`.
///
/// ```
/// # use osciemu::memory::{Memory, NullMemory, SliceMemory, MappedMemory};
/// # use osciemu::memory::mappedmemory::MemoryToken;
/// # let mut mm = MappedMemory::new();
/// # let m1 = mm.mount(0, Box::new(NullMemory::new()));
/// # let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 2, 3, 4]))));
/// # mm.set(0, 99);
/// // ...
/// mm.disable_mount(&m2);
/// assert_eq!(mm.get(0), 0);
/// assert_eq!(mm.borrow(&m2).get(0), 99);
/// ```
///
/// # Panics
/// `MappedMemory` panics when an unmapped address is read or written.
pub struct MappedMemory {
    memories: Vec<Entry>,
}

static id_counter: AtomicIsize = AtomicIsize::new(0);

struct Entry {
    id: isize,
    start_address: usize,
    size: usize,
    active: bool,
    memory: Box<Memory>,
}

impl Entry {
    fn contains(&self, addr: usize) -> bool {
        self.start_address <= addr && self.start_address + self.size > addr
    }
}

#[derive(Clone)]
pub struct MemoryToken {
    id: isize,
}

impl MappedMemory {
    pub fn new() -> MappedMemory {
        MappedMemory {
            memories: Vec::new(),
        }
    }

    /// Mounts a `Memory` at the given address.
    pub fn mount(&mut self, start_address: usize, memory: Box<Memory>) -> MemoryToken {
        let size = memory.size();
        let id = id_counter.fetch_add(1, Ordering::Relaxed);
        let new_entry = Entry {
            id,
            start_address,
            size,
            memory,
            active: true
        };
        self.memories.push(new_entry);
        MemoryToken{id}
    }

    pub fn unmount(&mut self, token: MemoryToken) -> Box<Memory> {
        let idx = self.memories
            .iter()
            .enumerate()
            .find(|&(_idx, ref entry)| entry.id == token.id)
            .map(|(idx, ref _entry)| idx)
            .unwrap();

        self.memories.remove(idx).memory
    }

    pub fn disable_mount(&mut self, token: &MemoryToken) {
        let entry = self.entry_for_token_mut(token);
        entry.active = false;
    }

    pub fn enable_mount(&mut self, token: &MemoryToken) {
        let entry = self.entry_for_token_mut(token);
        entry.active = true;
    }

    pub fn borrow(&self, token: &MemoryToken) -> &Box<Memory> {
        &self.entry_for_token(token).memory
    }

    pub fn borrow_mut(&mut self, token: &MemoryToken) -> &mut Box<Memory> {
        &mut self.entry_for_token_mut(token).memory
    }

    fn entry_for_token(&self, token: &MemoryToken) -> &Entry {
        self.memories
            .iter()
            .find(|ref entry| entry.id == token.id)
            .unwrap()
    }

    fn entry_for_token_mut(&mut self, token: &MemoryToken) -> &mut Entry {
        self.memories
            .iter_mut()
            .find(|ref mut entry| entry.id == token.id)
            .unwrap()
    }

    fn active_entry_at_addr(&self, addr: usize) -> Option<&Entry> {
        self.memories
            .iter()
            .rev()
            .filter(|entry| entry.active)
            .find(|entry| entry.contains(addr))
    }

    fn active_entry_at_addr_mut(&mut self, addr: usize) -> Option<&mut Entry> {
        self.memories
            .iter_mut()
            .rev()
            .filter(|entry| entry.active)
            .find(|entry| entry.contains(addr))
    }
}

impl Memory for MappedMemory {
    fn get(&self, addr: usize) -> u32 {
        self.active_entry_at_addr(addr)
            .map(|entry| entry.memory.get(addr - entry.start_address))
            .expect("Out of bounds")
    }

    fn set(&mut self, addr: usize, value: u32) {
        self.active_entry_at_addr_mut(addr)
            .map(|entry| entry.memory.set(addr - entry.start_address, value))
            .expect("Out of bounds")
    }

    fn size(&self) -> usize {
        self.memories
            .iter()
            .filter(|entry| entry.active)
            .map(|entry| entry.start_address + entry.size)
            .max()
            .unwrap_or(0)
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory, NullMemory};

    #[test]
    fn overlapping_mounts() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(NullMemory::new()));
        let m2 = mm.mount(1, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));
        let m3 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([3]))));
        assert_eq!(mm.get(0), 0);
        assert_eq!(mm.get(1), 2);
        assert_eq!(mm.get(2), 3);
        assert_eq!(mm.get(3), 0);
    }

    #[test]
    fn get_and_set() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
        let m2 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));

        assert_eq!(mm.get(0), 1);
        assert_eq!(mm.get(2), 2);

        mm.set(0, 3);
        assert_eq!(mm.get(0), 3);

        mm.set(3, 0);
        assert_eq!(mm.get(3), 0);
        assert_eq!(mm.borrow(&m1).get(0), 3);
        assert_eq!(mm.borrow(&m2).get(1), 0);
    }

    #[test]
    fn size() {
        let mut mm = super::MappedMemory::new();
        let m1 = Box::new(SliceMemory::from_slice(Box::new([1])));
        let m2 = Box::new(SliceMemory::from_slice(Box::new([2, 2])));
        assert_eq!(mm.size(), 0);

        mm.mount(0, m1);
        assert_eq!(mm.size(), 1);

        mm.mount(2, m2);
        assert_eq!(mm.size(), 4);
    }

    #[test]
    fn size_with_overlap() {
        let mut mm = super::MappedMemory::new();
        let m1 = Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1])));
        let m2 = Box::new(SliceMemory::from_slice(Box::new([2, 2])));
        let m3 = Box::new(SliceMemory::from_slice(Box::new([3, 3, 3])));

        mm.mount(0, m1);
        mm.mount(2, m2);
        assert_eq!(mm.size(), 5);

        mm.mount(6, m3);
        assert_eq!(mm.size(), 9);
    }

    #[test]
    fn disable_mount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));
        let m3 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([3, 3, 3, 3, 3]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 3);
        }
        mm.disable_mount(&m3);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        mm.disable_mount(&m1);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
    }

    #[test]
    fn enable_mount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        mm.disable_mount(&m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 1);
        }
        mm.enable_mount(&m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
    }

    #[test]
    fn unmount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        let m2 = mm.unmount(m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 1);
            assert_eq!(m2.get(i), 2);
        }
    }

    #[test]
    #[should_panic]
    fn read_disabled() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
        let m2 = mm.mount(1, Box::new(SliceMemory::from_slice(Box::new([2]))));
        let m3 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([3]))));
        mm.disable_mount(&m2);
        mm.get(1);
    }
}
<commit_msg>docs(mappedmemory): Update documentation<commit_after>use memory::Memory;
use std::vec::Vec;
use std::sync::atomic::{AtomicIsize, Ordering};

/// Maps multiple `Memory`s into a single address space.
///
/// The `MappedMemory` allows to unify multiple `Memory`s in one address space.
/// A `Memory` is mounted at a certain address and is from now on responsible
/// for all reads and writes starting at that address (the “mount point”) and
/// ending where the mounted memory ends. The read and write calls for the
/// responsible `Memory` will be given an address _relative_ to e mount point.
///
/// ```text
///                   Unmapped
///                <-------->
///       mem_a                   mem_b
/// |--------------|            |------|
///                            NullMemory
///                         |--------------
/// |------------- mapped_mem ----------->
/// |              |            |      |
/// 0            0x100        0x200  0x280
/// ```
///
/// For example: `mapped_mem.get(0x208)` would yield the same value as
/// `mem_b.get(0x008)`.
///
/// # Examples
///
/// ```
/// use osciemu::memory::{Memory, SliceMemory, MappedMemory};
///
/// let mut mm = MappedMemory::new();
/// let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
/// let m2 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));
/// // Now mm =~ [1, _, 2, 2]
/// assert_eq!(mm.get(0), 1);
/// assert_eq!(mm.get(3), 2);
/// ```
///
/// A call to `mount` returns a `MemoryToken`. These tokens can be used to
/// borrow a `Memory` even if it has been mounted. This works similar to a
/// `std::cell::RefCell`.
///
/// ```
/// use osciemu::memory::{Memory, NullMemory, SliceMemory, MappedMemory};
/// use osciemu::memory::mappedmemory::MemoryToken;
///
/// let mut mm = MappedMemory::new();
/// let m1 = mm.mount(0, Box::new(NullMemory::new()));
/// let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 2, 3, 4]))));
/// mm.set(0, 99);
/// assert_eq!(mm.get(0), 99);
/// assert_eq!(mm.borrow(&m2).get(0), 99);
/// ```
///
/// The `MemoryToken`s are also used to disable a mounted `Memory`. A disabled
/// memory is effectively unmounted, but remains in the ownership of the
/// `MappedMemory` and can be enabled using `enable_mount()`.
///
/// ```
/// # use osciemu::memory::{Memory, NullMemory, SliceMemory, MappedMemory};
/// # use osciemu::memory::mappedmemory::MemoryToken;
/// # let mut mm = MappedMemory::new();
/// # let m1 = mm.mount(0, Box::new(NullMemory::new()));
/// # let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 2, 3, 4]))));
/// # mm.set(0, 99);
/// // ...
/// mm.disable_mount(&m2);
/// assert_eq!(mm.get(0), 0);
/// assert_eq!(mm.borrow(&m2).get(0), 99);
/// ```
///
/// To move a memory out of the `MappedMemory`, a memory can be unmounted:
///
/// ```
/// # use osciemu::memory::{Memory, NullMemory, SliceMemory, MappedMemory};
/// # use osciemu::memory::mappedmemory::MemoryToken;
/// # let mut mm = MappedMemory::new();
/// # let m1 = mm.mount(0, Box::new(NullMemory::new()));
/// # let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 2, 3, 4]))));
/// # mm.set(0, 99);
/// // ...
/// let m2 = mm.unmount(m2);
/// assert_eq!(mm.get(0), 0);
/// assert_eq!(m2.get(0), 99);
/// ```
///
/// # Panics
/// `MappedMemory` panics when an unmapped address is read or written.
pub struct MappedMemory {
    memories: Vec<Entry>,
}

static id_counter: AtomicIsize = AtomicIsize::new(0);

struct Entry {
    id: isize,
    start_address: usize,
    size: usize,
    active: bool,
    memory: Box<Memory>,
}

impl Entry {
    fn contains(&self, addr: usize) -> bool {
        self.start_address <= addr && self.start_address + self.size > addr
    }
}

#[derive(Clone)]
pub struct MemoryToken {
    id: isize,
}

impl MappedMemory {
    pub fn new() -> MappedMemory {
        MappedMemory {
            memories: Vec::new(),
        }
    }

    /// Mounts a `Memory` at the given address.
    pub fn mount(&mut self, start_address: usize, memory: Box<Memory>) -> MemoryToken {
        let size = memory.size();
        let id = id_counter.fetch_add(1, Ordering::Relaxed);
        let new_entry = Entry {
            id,
            start_address,
            size,
            memory,
            active: true
        };
        self.memories.push(new_entry);
        MemoryToken{id}
    }

    /// Unmounts a memory.
    pub fn unmount(&mut self, token: MemoryToken) -> Box<Memory> {
        let idx = self.memories
            .iter()
            .enumerate()
            .find(|&(_idx, ref entry)| entry.id == token.id)
            .map(|(idx, ref _entry)| idx)
            .unwrap();

        self.memories.remove(idx).memory
    }

    /// Disables a memory. This is the same as unmounting without moving
    /// ownership
    pub fn disable_mount(&mut self, token: &MemoryToken) {
        let entry = self.entry_for_token_mut(token);
        entry.active = false;
    }

    // Enables a memory. The mount point remains unchanged.
    pub fn enable_mount(&mut self, token: &MemoryToken) {
        let entry = self.entry_for_token_mut(token);
        entry.active = true;
    }

    /// Borrows a memory.
    pub fn borrow(&self, token: &MemoryToken) -> &Box<Memory> {
        &self.entry_for_token(token).memory
    }

    /// Mutable borrows a memory.
    pub fn borrow_mut(&mut self, token: &MemoryToken) -> &mut Box<Memory> {
        &mut self.entry_for_token_mut(token).memory
    }

    fn entry_for_token(&self, token: &MemoryToken) -> &Entry {
        self.memories
            .iter()
            .find(|ref entry| entry.id == token.id)
            .unwrap()
    }

    fn entry_for_token_mut(&mut self, token: &MemoryToken) -> &mut Entry {
        self.memories
            .iter_mut()
            .find(|ref mut entry| entry.id == token.id)
            .unwrap()
    }

    fn active_entry_at_addr(&self, addr: usize) -> Option<&Entry> {
        self.memories
            .iter()
            .rev()
            .filter(|entry| entry.active)
            .find(|entry| entry.contains(addr))
    }

    fn active_entry_at_addr_mut(&mut self, addr: usize) -> Option<&mut Entry> {
        self.memories
            .iter_mut()
            .rev()
            .filter(|entry| entry.active)
            .find(|entry| entry.contains(addr))
    }
}

impl Memory for MappedMemory {
    fn get(&self, addr: usize) -> u32 {
        self.active_entry_at_addr(addr)
            .map(|entry| entry.memory.get(addr - entry.start_address))
            .expect("Out of bounds")
    }

    fn set(&mut self, addr: usize, value: u32) {
        self.active_entry_at_addr_mut(addr)
            .map(|entry| entry.memory.set(addr - entry.start_address, value))
            .expect("Out of bounds")
    }

    fn size(&self) -> usize {
        self.memories
            .iter()
            .filter(|entry| entry.active)
            .map(|entry| entry.start_address + entry.size)
            .max()
            .unwrap_or(0)
    }
}

#[cfg(test)]
mod tests {
    use memory::{Memory, SliceMemory, NullMemory};

    #[test]
    fn overlapping_mounts() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(NullMemory::new()));
        let m2 = mm.mount(1, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));
        let m3 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([3]))));
        assert_eq!(mm.get(0), 0);
        assert_eq!(mm.get(1), 2);
        assert_eq!(mm.get(2), 3);
        assert_eq!(mm.get(3), 0);
    }

    #[test]
    fn get_and_set() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
        let m2 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([2, 2]))));

        assert_eq!(mm.get(0), 1);
        assert_eq!(mm.get(2), 2);

        mm.set(0, 3);
        assert_eq!(mm.get(0), 3);

        mm.set(3, 0);
        assert_eq!(mm.get(3), 0);
        assert_eq!(mm.borrow(&m1).get(0), 3);
        assert_eq!(mm.borrow(&m2).get(1), 0);
    }

    #[test]
    fn size() {
        let mut mm = super::MappedMemory::new();
        let m1 = Box::new(SliceMemory::from_slice(Box::new([1])));
        let m2 = Box::new(SliceMemory::from_slice(Box::new([2, 2])));
        assert_eq!(mm.size(), 0);

        mm.mount(0, m1);
        assert_eq!(mm.size(), 1);

        mm.mount(2, m2);
        assert_eq!(mm.size(), 4);
    }

    #[test]
    fn size_with_overlap() {
        let mut mm = super::MappedMemory::new();
        let m1 = Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1])));
        let m2 = Box::new(SliceMemory::from_slice(Box::new([2, 2])));
        let m3 = Box::new(SliceMemory::from_slice(Box::new([3, 3, 3])));

        mm.mount(0, m1);
        mm.mount(2, m2);
        assert_eq!(mm.size(), 5);

        mm.mount(6, m3);
        assert_eq!(mm.size(), 9);
    }

    #[test]
    fn disable_mount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));
        let m3 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([3, 3, 3, 3, 3]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 3);
        }
        mm.disable_mount(&m3);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        mm.disable_mount(&m1);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
    }

    #[test]
    fn enable_mount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        mm.disable_mount(&m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 1);
        }
        mm.enable_mount(&m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
    }

    #[test]
    fn unmount() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1, 1, 1, 1, 1]))));
        let m2 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([2, 2, 2, 2, 2]))));

        for i in 0..5 {
            assert_eq!(mm.get(i), 2);
        }
        let m2 = mm.unmount(m2);
        for i in 0..5 {
            assert_eq!(mm.get(i), 1);
            assert_eq!(m2.get(i), 2);
        }
    }

    #[test]
    #[should_panic]
    fn read_disabled() {
        let mut mm = super::MappedMemory::new();
        let m1 = mm.mount(0, Box::new(SliceMemory::from_slice(Box::new([1]))));
        let m2 = mm.mount(1, Box::new(SliceMemory::from_slice(Box::new([2]))));
        let m3 = mm.mount(2, Box::new(SliceMemory::from_slice(Box::new([3]))));
        mm.disable_mount(&m2);
        mm.get(1);
    }
}
<|endoftext|>


<commit_before>use std::collections::{VecDeque, HashMap};
use std::hash::Hash;
use std::iter;

enum NodeIterType {
  Bfs,
  Dfs
}

pub struct PredecessorIter<'a, G: Graph<V>, V: Hash + Eq + Copy> {
  node_iter: NodeIter<'a, G, V>
}

impl<'a, G: Graph<V>, V: Hash + Eq + Copy> PredecessorIter<'a, G, V> {
  pub fn construct_path(&mut self, target: V) -> Option<Vec<V>> {
    self.node_iter.construct_path(target)
  }
}

impl<'a, G: Graph<V>, V: Hash + Eq + Copy> Iterator for PredecessorIter<'a, G, V> {
  type Item = (Option<V>, V);

  fn next(&mut self) -> Option<Self::Item> {
    self.node_iter.next()
    .and_then(|v| {
      self.node_iter.predecessor_map.get(&v).map(|&p| (p, v))
    })
  }
}

pub struct NodeIter<'a, G: Graph<V>, V: Hash + Eq + Copy> {
  graph: &'a G,
  start: V,
  queue: VecDeque<V>,
  predecessor_map: HashMap<V, Option<V>>,
  iter_type: NodeIterType
}

impl<'a, G: Graph<V>, V: Hash + Eq + Copy> NodeIter<'a, G, V> {
  pub fn predecessor(self) -> PredecessorIter<'a, G, V> where Self: Sized {
    PredecessorIter {
      node_iter: self
    }
  }

  pub fn construct_path(&mut self, target: V) -> Option<Vec<V>> {
    if !self.predecessor_map.contains_key(&target) {
      self.find(|&v| v == target);
    }

    let mut path = vec![target];

    while let Some(&Some(previous)) = self.predecessor_map.get(path.last().unwrap()) {
      path.push(previous);
    }

    path.reverse();

    if path[0] == self.start {
      Some(path)
    } else {
      None
    }
  }
}

impl<'a, G: Graph<V>, V: Hash + Eq + Copy> Iterator for NodeIter<'a, G, V> {
  type Item = V;

  fn next(&mut self) -> Option<Self::Item> {
    let vertex = match self.iter_type {
      NodeIterType::Bfs => self.queue.pop_front(),
      NodeIterType::Dfs => self.queue.pop_back()
    };

    vertex.map(|vertex| {
      for neighbor in self.graph.get_neighbors(vertex) {
        if self.predecessor_map.contains_key(&neighbor) {
          continue;
        }

        self.queue.push_back(neighbor);
        self.predecessor_map.insert(neighbor, Some(vertex));
      }

      vertex
    })
  }
}

pub trait Graph<V: Hash + Eq + Copy> {
  fn get_neighbors(&self, vertex: V) -> Vec<V>;

  fn bfs<'a>(&'a self, start: V) -> NodeIter<'a, Self, V> where Self: Sized {
    NodeIter {
      graph: self,
      start,
      queue: iter::once(start).collect(),
      predecessor_map: iter::once((start, None)).collect(),
      iter_type: NodeIterType::Bfs
    }
  }

  fn dfs<'a>(&'a self, start: V) -> NodeIter<'a, Self, V> where Self: Sized {
    NodeIter {
      graph: self,
      start,
      queue: iter::once(start).collect(),
      predecessor_map: iter::once((start, None)).collect(),
      iter_type: NodeIterType::Dfs
    }
  }
}
<commit_msg>Introduce Vertex trait<commit_after>use std::collections::{VecDeque, HashMap};
use std::hash::Hash;
use std::iter;

enum NodeIterType {
  Bfs,
  Dfs
}

pub trait Vertex: Hash + Eq + Clone {}
impl<T: Hash + Eq + Clone> Vertex for T {}

pub struct PredecessorIter<'a, G: Graph<V>, V: Vertex> {
  node_iter: NodeIter<'a, G, V>
}

impl<'a, G: Graph<V>, V: Vertex> PredecessorIter<'a, G, V> {
  pub fn construct_path(self, target: V) -> Option<Vec<V>> {
    self.node_iter.construct_path(target)
  }
}

impl<'a, G: Graph<V>, V: Vertex> Iterator for PredecessorIter<'a, G, V> {
  type Item = (Option<V>, V);

  fn next(&mut self) -> Option<Self::Item> {
    self.node_iter.next()
    .and_then(|v| {
      self.node_iter.predecessor_map.get(&v).map(|p| (p.clone(), v))
    })
  }
}

pub struct NodeIter<'a, G: Graph<V>, V: Vertex> {
  graph: &'a G,
  start: V,
  queue: VecDeque<V>,
  predecessor_map: HashMap<V, Option<V>>,
  iter_type: NodeIterType
}

impl<'a, G: Graph<V>, V: Vertex> NodeIter<'a, G, V> {
  fn new(graph: &'a G, start: V, iter_type: NodeIterType) -> NodeIter<'a, G, V> {
    NodeIter {
      graph,
      start: start.clone(),
      queue: iter::once(start.clone()).collect(),
      predecessor_map: iter::once((start, None)).collect(),
      iter_type
    }
  }

  pub fn predecessor(self) -> PredecessorIter<'a, G, V> where Self: Sized {
    PredecessorIter {
      node_iter: self
    }
  }

  pub fn construct_path(mut self, target: V) -> Option<Vec<V>> {
    if !self.predecessor_map.contains_key(&target) {
      self.find(|v| v == &target);
    }

    let mut path = vec![target];

    while let Some(Some(previous)) = self.predecessor_map.remove(path.last().unwrap()) {
      path.push(previous);
    }

    path.reverse();

    if path[0] == self.start {
      Some(path)
    } else {
      None
    }
  }
}

impl<'a, G: Graph<V>, V: Vertex> Iterator for NodeIter<'a, G, V> {
  type Item = V;

  fn next(&mut self) -> Option<Self::Item> {
    let vertex = match self.iter_type {
      NodeIterType::Bfs => self.queue.pop_front(),
      NodeIterType::Dfs => self.queue.pop_back()
    };

    vertex.map(|vertex| {
      for neighbor in self.graph.get_neighbors(vertex.clone()) {
        if self.predecessor_map.contains_key(&neighbor) {
          continue;
        }

        self.queue.push_back(neighbor.clone());
        self.predecessor_map.insert(neighbor, Some(vertex.clone()));
      }

      vertex
    })
  }
}

pub trait Graph<V: Vertex> {
  fn get_neighbors(&self, vertex: V) -> Vec<V>;

  fn bfs<'a>(&'a self, start: V) -> NodeIter<'a, Self, V> where Self: Sized {
    NodeIter::new(self, start, NodeIterType::Bfs)
  }

  fn dfs<'a>(&'a self, start: V) -> NodeIter<'a, Self, V> where Self: Sized {
    NodeIter::new(self, start, NodeIterType::Dfs)
  }
}
<|endoftext|>