<commit_before>use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
pub(crate) const MULTIPLE: u64 = 6364136223846793005;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    pad: u64,
    extra_keys: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided key.
    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub fn new_with_keys(key1: u128, key2: u128) -> AHasher {
        let pi: [u128; 2] = PI.convert();
        let key1: [u64; 2] = (key1 ^ pi[0]).convert();
        let key2: [u64; 2] = (key2 ^ pi[1]).convert();
        AHasher {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[allow(unused)] // False positive
    pub(crate) fn test_with_keys(key1: u128, key2: u128) -> Self {
        let key1: [u64; 2] = key1.convert();
        let key2: [u64; 2] = key2.convert();
        Self {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
        AHasher {
            buffer: rand_state.k0,
            pad: rand_state.k1,
            extra_keys: [rand_state.k2, rand_state.k3],
        }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is vulnerable to attack. To avoid this input needs to be masked to with an
    /// unpredictable value. Other hashes such as murmurhash have taken this approach but were found vulnerable
    /// to attack. The attack was based on the idea of reversing the pre-mixing (Which is necessarily
    /// reversible otherwise bits would be lost) then placing a difference in the highest bit before the
    /// multiply used to mix the data. Because a multiply can never affect the bits to the right of it, a
    /// subsequent update that also differed in this bit could result in a predictable collision.
    ///
    /// This version avoids this vulnerability while still only using a single multiply. It takes advantage
    /// of the fact that when a 64 bit multiply is performed the upper 64 bits are usually computed and thrown
    /// away. Instead it creates two 128 bit values where the upper 64 bits are zeros and multiplies them.
    /// (The compiler is smart enough to turn this into a 64 bit multiplication in the assembly)
    /// Then the upper bits are xored with the lower bits to produce a single 64 bit result.
    ///
    /// To understand why this is a good scrambling function it helps to understand multiply-with-carry PRNGs:
    /// https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator
    /// If the multiple is chosen well, this creates a long period, decent quality PRNG.
    /// Notice that this function is equivalent to this except the `buffer`/`state` is being xored with each
    /// new block of data. In the event that data is all zeros, it is exactly equivalent to a MWC PRNG.
    ///
    /// This is impervious to attack because every bit buffer at the end is dependent on every bit in
    /// `new_data ^ buffer`. For example suppose two inputs differed in only the 5th bit. Then when the
    /// multiplication is performed the `result` will differ in bits 5-69. More specifically it will differ by
    /// 2^5 * MULTIPLE. However in the next step bits 65-128 are turned into a separate 64 bit value. So the
    /// differing bits will be in the lower 6 bits of this value. The two intermediate values that differ in
    /// bits 5-63 and in bits 0-5 respectively get added together. Producing an output that differs in every
    /// bit. The addition carries in the multiplication and at the end additionally mean that the even if an
    /// attacker somehow knew part of (but not all) the contents of the buffer before hand,
    /// they would not be able to predict any of the bits in the buffer at the end.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn update(&mut self, new_data: u64) {
        self.buffer = folded_multiply(new_data ^ self.buffer, MULTIPLE);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn update(&mut self, new_data: u64) {
        let d1 = (new_data ^ self.buffer).wrapping_mul(MULTIPLE);
        self.pad = (self.pad ^ d1).rotate_left(8).wrapping_mul(MULTIPLE);
        self.buffer = (self.buffer ^ self.pad).rotate_left(24);
    }

    /// Similar to the above this function performs an update using a "folded multiply".
    /// However it takes in 128 bits of data instead of 64. Both halves must be masked.
    ///
    /// This makes it impossible for an attacker to place a single bit difference between
    /// two blocks so as to cancel each other.
    ///
    /// However this is not sufficient. to prevent (a,b) from hashing the same as (b,a) the buffer itself must
    /// be updated between calls in a way that does not commute. To achieve this XOR and Rotate are used.
    /// Add followed by xor is not the same as xor followed by add, and rotate ensures that the same out bits
    /// can't be changed by the same set of input bits. To cancel this sequence with subsequent input would require
    /// knowing the keys.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        let combined = folded_multiply(block[0] ^ self.extra_keys[0], block[1] ^ self.extra_keys[1]);
        self.buffer = (self.buffer.wrapping_add(self.pad) ^ combined).rotate_left(ROT);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        self.update(block[0]);
        self.update(block[1]);
    }

    #[inline]
    #[cfg(feature = "specialize")]
    fn short_finish(&self) -> u64 {
        self.buffer.wrapping_add(self.pad)
    }
}

/// Provides [Hasher] methods to hash all of the primitive types.
///
/// [Hasher]: core::hash::Hasher
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.large_update(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u128();
                self.large_update(tail);
                while data.len() > 16 {
                    let (block, rest) = data.read_u128();
                    self.large_update(block);
                    data = rest;
                }
            } else {
                self.large_update([data.read_u64().0, data.read_last_u64()].convert());
            }
        } else {
            let value = read_small(data);
            self.large_update(value.convert());
        }
    }

    #[inline]
    #[cfg(feature = "folded_multiply")]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        folded_multiply(self.buffer, self.pad).rotate_left(rot)
    }

    #[inline]
    #[cfg(not(feature = "folded_multiply"))]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        (self.buffer.wrapping_mul(MULTIPLE) ^ self.pad).rotate_left(rot)
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherU64 {
    pub(crate) buffer: u64,
    pub(crate) pad: u64,
}

/// A specialized hasher for only primitives under 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherU64 {
    #[inline]
    fn finish(&self) -> u64 {
        let rot = (self.pad & 64) as u32;
        self.buffer.rotate_left(rot)
    }

    #[inline]
    fn write(&mut self, _bytes: &[u8]) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = folded_multiply(i ^ self.buffer, MULTIPLE);
    }

    #[inline]
    fn write_u128(&mut self, _i: u128) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_usize(&mut self, _i: usize) {
        unimplemented!()
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherFixed(pub AHasher);

/// A specialized hasher for fixed size primitives larger than 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherFixed {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.short_finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.0.write_u64(i);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.0.write_u128(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.0.write_usize(i);
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherStr(pub AHasher);

/// A specialized hasher for a single string
/// Note that the other types don't panic because the hash impl for String tacks on an unneeded call. (As does vec)
#[cfg(feature = "specialize")]
impl Hasher for AHasherStr {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        if bytes.len() > 8 {
            self.0.write(bytes)
        } else {
            let value = read_small(bytes);
            self.0.buffer = folded_multiply(value[0] ^ self.0.buffer,
                                           value[1] ^ self.0.extra_keys[1]);
            self.0.pad = self.0.pad.wrapping_add(bytes.len() as u64);
        }
    }

    #[inline]
    fn write_u8(&mut self, _i: u8) {}

    #[inline]
    fn write_u16(&mut self, _i: u16) {}

    #[inline]
    fn write_u32(&mut self, _i: u32) {}

    #[inline]
    fn write_u64(&mut self, _i: u64) {}

    #[inline]
    fn write_u128(&mut self, _i: u128) {}

    #[inline]
    fn write_usize(&mut self, _i: usize) {}
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<commit_msg>Use extra keys for strings even if not using folded multiply<commit_after>use crate::convert::*;
use crate::operations::folded_multiply;
use crate::operations::read_small;
use crate::random_state::PI;
use crate::RandomState;
use core::hash::Hasher;

///This constant come from Kunth's prng (Empirically it works better than those from splitmix32).
pub(crate) const MULTIPLE: u64 = 6364136223846793005;
const ROT: u32 = 23; //17

/// A `Hasher` for hashing an arbitrary stream of bytes.
///
/// Instances of [`AHasher`] represent state that is updated while hashing data.
///
/// Each method updates the internal state based on the new data provided. Once
/// all of the data has been provided, the resulting hash can be obtained by calling
/// `finish()`
///
/// [Clone] is also provided in case you wish to calculate hashes for two different items that
/// start with the same data.
///
#[derive(Debug, Clone)]
pub struct AHasher {
    buffer: u64,
    pad: u64,
    extra_keys: [u64; 2],
}

impl AHasher {
    /// Creates a new hasher keyed to the provided key.
    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub fn new_with_keys(key1: u128, key2: u128) -> AHasher {
        let pi: [u128; 2] = PI.convert();
        let key1: [u64; 2] = (key1 ^ pi[0]).convert();
        let key2: [u64; 2] = (key2 ^ pi[1]).convert();
        AHasher {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[allow(unused)] // False positive
    pub(crate) fn test_with_keys(key1: u128, key2: u128) -> Self {
        let key1: [u64; 2] = key1.convert();
        let key2: [u64; 2] = key2.convert();
        Self {
            buffer: key1[0],
            pad: key1[1],
            extra_keys: key2,
        }
    }

    #[inline]
    #[allow(dead_code)] // Is not called if non-fallback hash is used.
    pub(crate) fn from_random_state(rand_state: &RandomState) -> AHasher {
        AHasher {
            buffer: rand_state.k0,
            pad: rand_state.k1,
            extra_keys: [rand_state.k2, rand_state.k3],
        }
    }

    /// This update function has the goal of updating the buffer with a single multiply
    /// FxHash does this but is vulnerable to attack. To avoid this input needs to be masked to with an
    /// unpredictable value. Other hashes such as murmurhash have taken this approach but were found vulnerable
    /// to attack. The attack was based on the idea of reversing the pre-mixing (Which is necessarily
    /// reversible otherwise bits would be lost) then placing a difference in the highest bit before the
    /// multiply used to mix the data. Because a multiply can never affect the bits to the right of it, a
    /// subsequent update that also differed in this bit could result in a predictable collision.
    ///
    /// This version avoids this vulnerability while still only using a single multiply. It takes advantage
    /// of the fact that when a 64 bit multiply is performed the upper 64 bits are usually computed and thrown
    /// away. Instead it creates two 128 bit values where the upper 64 bits are zeros and multiplies them.
    /// (The compiler is smart enough to turn this into a 64 bit multiplication in the assembly)
    /// Then the upper bits are xored with the lower bits to produce a single 64 bit result.
    ///
    /// To understand why this is a good scrambling function it helps to understand multiply-with-carry PRNGs:
    /// https://en.wikipedia.org/wiki/Multiply-with-carry_pseudorandom_number_generator
    /// If the multiple is chosen well, this creates a long period, decent quality PRNG.
    /// Notice that this function is equivalent to this except the `buffer`/`state` is being xored with each
    /// new block of data. In the event that data is all zeros, it is exactly equivalent to a MWC PRNG.
    ///
    /// This is impervious to attack because every bit buffer at the end is dependent on every bit in
    /// `new_data ^ buffer`. For example suppose two inputs differed in only the 5th bit. Then when the
    /// multiplication is performed the `result` will differ in bits 5-69. More specifically it will differ by
    /// 2^5 * MULTIPLE. However in the next step bits 65-128 are turned into a separate 64 bit value. So the
    /// differing bits will be in the lower 6 bits of this value. The two intermediate values that differ in
    /// bits 5-63 and in bits 0-5 respectively get added together. Producing an output that differs in every
    /// bit. The addition carries in the multiplication and at the end additionally mean that the even if an
    /// attacker somehow knew part of (but not all) the contents of the buffer before hand,
    /// they would not be able to predict any of the bits in the buffer at the end.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn update(&mut self, new_data: u64) {
        self.buffer = folded_multiply(new_data ^ self.buffer, MULTIPLE);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn update(&mut self, new_data: u64) {
        let d1 = (new_data ^ self.buffer).wrapping_mul(MULTIPLE);
        self.pad = (self.pad ^ d1).rotate_left(8).wrapping_mul(MULTIPLE);
        self.buffer = (self.buffer ^ self.pad).rotate_left(24);
    }

    /// Similar to the above this function performs an update using a "folded multiply".
    /// However it takes in 128 bits of data instead of 64. Both halves must be masked.
    ///
    /// This makes it impossible for an attacker to place a single bit difference between
    /// two blocks so as to cancel each other.
    ///
    /// However this is not sufficient. to prevent (a,b) from hashing the same as (b,a) the buffer itself must
    /// be updated between calls in a way that does not commute. To achieve this XOR and Rotate are used.
    /// Add followed by xor is not the same as xor followed by add, and rotate ensures that the same out bits
    /// can't be changed by the same set of input bits. To cancel this sequence with subsequent input would require
    /// knowing the keys.
    #[inline(always)]
    #[cfg(feature = "folded_multiply")]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        let combined = folded_multiply(block[0] ^ self.extra_keys[0], block[1] ^ self.extra_keys[1]);
        self.buffer = (self.buffer.wrapping_add(self.pad) ^ combined).rotate_left(ROT);
    }

    #[inline(always)]
    #[cfg(not(feature = "folded_multiply"))]
    fn large_update(&mut self, new_data: u128) {
        let block: [u64; 2] = new_data.convert();
        self.update(block[0] ^ self.extra_keys[0]);
        self.update(block[1] ^ self.extra_keys[1]);
    }

    #[inline]
    #[cfg(feature = "specialize")]
    fn short_finish(&self) -> u64 {
        self.buffer.wrapping_add(self.pad)
    }
}

/// Provides [Hasher] methods to hash all of the primitive types.
///
/// [Hasher]: core::hash::Hasher
impl Hasher for AHasher {
    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.update(i as u64);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.large_update(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.write_u64(i as u64);
    }

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //Needs to be an add rather than an xor because otherwise it could be canceled with carefully formed input.
        self.buffer = self.buffer.wrapping_add(length).wrapping_mul(MULTIPLE);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() > 8 {
            if data.len() > 16 {
                let tail = data.read_last_u128();
                self.large_update(tail);
                while data.len() > 16 {
                    let (block, rest) = data.read_u128();
                    self.large_update(block);
                    data = rest;
                }
            } else {
                self.large_update([data.read_u64().0, data.read_last_u64()].convert());
            }
        } else {
            let value = read_small(data);
            self.large_update(value.convert());
        }
    }

    #[inline]
    #[cfg(feature = "folded_multiply")]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        folded_multiply(self.buffer, self.pad).rotate_left(rot)
    }

    #[inline]
    #[cfg(not(feature = "folded_multiply"))]
    fn finish(&self) -> u64 {
        let rot = (self.buffer & 63) as u32;
        (self.buffer.wrapping_mul(MULTIPLE) ^ self.pad).rotate_left(rot)
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherU64 {
    pub(crate) buffer: u64,
    pub(crate) pad: u64,
}

/// A specialized hasher for only primitives under 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherU64 {
    #[inline]
    fn finish(&self) -> u64 {
        let rot = (self.pad & 64) as u32;
        self.buffer.rotate_left(rot)
    }

    #[inline]
    fn write(&mut self, _bytes: &[u8]) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.buffer = folded_multiply(i ^ self.buffer, MULTIPLE);
    }

    #[inline]
    fn write_u128(&mut self, _i: u128) {
        unreachable!("This should never be called")
    }

    #[inline]
    fn write_usize(&mut self, _i: usize) {
        unimplemented!()
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherFixed(pub AHasher);

/// A specialized hasher for fixed size primitives larger than 64 bits.
#[cfg(feature = "specialize")]
impl Hasher for AHasherFixed {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.short_finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }

    #[inline]
    fn write_u8(&mut self, i: u8) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u16(&mut self, i: u16) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u32(&mut self, i: u32) {
        self.write_u64(i as u64);
    }

    #[inline]
    fn write_u64(&mut self, i: u64) {
        self.0.write_u64(i);
    }

    #[inline]
    fn write_u128(&mut self, i: u128) {
        self.0.write_u128(i);
    }

    #[inline]
    fn write_usize(&mut self, i: usize) {
        self.0.write_usize(i);
    }
}

#[cfg(feature = "specialize")]
pub(crate) struct AHasherStr(pub AHasher);

/// A specialized hasher for a single string
/// Note that the other types don't panic because the hash impl for String tacks on an unneeded call. (As does vec)
#[cfg(feature = "specialize")]
impl Hasher for AHasherStr {
    #[inline]
    fn finish(&self) -> u64 {
        self.0.finish()
    }

    #[inline]
    fn write(&mut self, bytes: &[u8]) {
        if bytes.len() > 8 {
            self.0.write(bytes)
        } else {
            let value = read_small(bytes);
            self.0.buffer = folded_multiply(value[0] ^ self.0.buffer,
                                           value[1] ^ self.0.extra_keys[1]);
            self.0.pad = self.0.pad.wrapping_add(bytes.len() as u64);
        }
    }

    #[inline]
    fn write_u8(&mut self, _i: u8) {}

    #[inline]
    fn write_u16(&mut self, _i: u16) {}

    #[inline]
    fn write_u32(&mut self, _i: u32) {}

    #[inline]
    fn write_u64(&mut self, _i: u64) {}

    #[inline]
    fn write_u128(&mut self, _i: u128) {}

    #[inline]
    fn write_usize(&mut self, _i: usize) {}
}

#[cfg(test)]
mod tests {
    use crate::convert::Convert;
    use crate::fallback_hash::*;

    #[test]
    fn test_hash() {
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value: u64 = 1 << 32;
        hasher.update(value);
        let result = hasher.buffer;
        let mut hasher = AHasher::new_with_keys(0, 0);
        let value2: u64 = 1;
        hasher.update(value2);
        let result2 = hasher.buffer;
        let result: [u8; 8] = result.convert();
        let result2: [u8; 8] = result2.convert();
        assert_ne!(hex::encode(result), hex::encode(result2));
    }

    #[test]
    fn test_conversion() {
        let input: &[u8] = "dddddddd".as_bytes();
        let bytes: u64 = as_array!(input, 8).convert();
        assert_eq!(bytes, 0x6464646464646464);
    }
}
<|endoftext|>


<commit_before>//! Compiles the profiler part of the `compiler-rt` library.
//!
//! See the build.rs for libcompiler_builtins crate for details.

use std::env;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut cc::Build::new();

    // FIXME: `rerun-if-changed` directives are not currently emitted and the build script
    // will not rerun on changes in these source files or headers included into them.
    let mut profile_sources = vec![
        "GCDAProfiling.c",
        "InstrProfiling.c",
        "InstrProfilingBuffer.c",
        "InstrProfilingFile.c",
        "InstrProfilingMerge.c",
        "InstrProfilingMergeFile.c",
        "InstrProfilingNameVar.c",
        "InstrProfilingPlatformDarwin.c",
        "InstrProfilingPlatformLinux.c",
        "InstrProfilingPlatformOther.c",
        "InstrProfilingPlatformWindows.c",
        "InstrProfilingUtil.c",
        "InstrProfilingValue.c",
        "InstrProfilingWriter.c",
        // This file was renamed in LLVM 10.
        "InstrProfilingRuntime.cc",
        "InstrProfilingRuntime.cpp",
        // These files were added in LLVM 11.
        "InstrProfilingInternal.c",
        "InstrProfilingBiasVar.c",
    ];

    if target.contains("msvc") {
        // Don't pull in extra libraries on MSVC
        cfg.flag("/Zl");
        profile_sources.push("WindowsMMap.c");
        cfg.define("strdup", Some("_strdup"));
        cfg.define("open", Some("_open"));
        cfg.define("fdopen", Some("_fdopen"));
        cfg.define("getpid", Some("_getpid"));
        cfg.define("fileno", Some("_fileno"));
    } else {
        // Turn off various features of gcc and such, mostly copying
        // compiler-rt's build system already
        cfg.flag("-fno-builtin");
        cfg.flag("-fvisibility=hidden");
        cfg.flag("-fomit-frame-pointer");
        cfg.define("VISIBILITY_HIDDEN", None);
        if !target.contains("windows") {
            cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
        } else {
            profile_sources.push("WindowsMMap.c");
        }
    }

    // Assume that the Unixes we are building this for have fnctl() available
    if env::var_os("CARGO_CFG_UNIX").is_some() {
        cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1"));
    }

    // This should be a pretty good heuristic for when to set
    // COMPILER_RT_HAS_ATOMICS
    if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC")
        .map(|features| features.to_string_lossy().to_lowercase().contains("ptr"))
        .unwrap_or(false)
    {
        cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
    }

    // Note that this should exist if we're going to run (otherwise we just
    // don't build profiler builtins at all).
    let root = Path::new("../../src/llvm-project/compiler-rt");

    let src_root = root.join("lib").join("profile");
    for src in profile_sources {
        let path = src_root.join(src);
        if path.exists() {
            cfg.file(path);
        }
    }

    cfg.include(root.join("include"));
    cfg.warnings(false);
    cfg.compile("profiler-rt");
}
<commit_msg>Add InstrProfilingPlatformFuchsia.c to profiler_builtins<commit_after>//! Compiles the profiler part of the `compiler-rt` library.
//!
//! See the build.rs for libcompiler_builtins crate for details.

use std::env;
use std::path::Path;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    let cfg = &mut cc::Build::new();

    // FIXME: `rerun-if-changed` directives are not currently emitted and the build script
    // will not rerun on changes in these source files or headers included into them.
    let mut profile_sources = vec![
        "GCDAProfiling.c",
        "InstrProfiling.c",
        "InstrProfilingBuffer.c",
        "InstrProfilingFile.c",
        "InstrProfilingMerge.c",
        "InstrProfilingMergeFile.c",
        "InstrProfilingNameVar.c",
        "InstrProfilingPlatformDarwin.c",
        "InstrProfilingPlatformFuchsia.c",
        "InstrProfilingPlatformLinux.c",
        "InstrProfilingPlatformOther.c",
        "InstrProfilingPlatformWindows.c",
        "InstrProfilingUtil.c",
        "InstrProfilingValue.c",
        "InstrProfilingWriter.c",
        // This file was renamed in LLVM 10.
        "InstrProfilingRuntime.cc",
        "InstrProfilingRuntime.cpp",
        // These files were added in LLVM 11.
        "InstrProfilingInternal.c",
        "InstrProfilingBiasVar.c",
    ];

    if target.contains("msvc") {
        // Don't pull in extra libraries on MSVC
        cfg.flag("/Zl");
        profile_sources.push("WindowsMMap.c");
        cfg.define("strdup", Some("_strdup"));
        cfg.define("open", Some("_open"));
        cfg.define("fdopen", Some("_fdopen"));
        cfg.define("getpid", Some("_getpid"));
        cfg.define("fileno", Some("_fileno"));
    } else {
        // Turn off various features of gcc and such, mostly copying
        // compiler-rt's build system already
        cfg.flag("-fno-builtin");
        cfg.flag("-fvisibility=hidden");
        cfg.flag("-fomit-frame-pointer");
        cfg.define("VISIBILITY_HIDDEN", None);
        if !target.contains("windows") {
            cfg.define("COMPILER_RT_HAS_UNAME", Some("1"));
        } else {
            profile_sources.push("WindowsMMap.c");
        }
    }

    // Assume that the Unixes we are building this for have fnctl() available
    if env::var_os("CARGO_CFG_UNIX").is_some() {
        cfg.define("COMPILER_RT_HAS_FCNTL_LCK", Some("1"));
    }

    // This should be a pretty good heuristic for when to set
    // COMPILER_RT_HAS_ATOMICS
    if env::var_os("CARGO_CFG_TARGET_HAS_ATOMIC")
        .map(|features| features.to_string_lossy().to_lowercase().contains("ptr"))
        .unwrap_or(false)
    {
        cfg.define("COMPILER_RT_HAS_ATOMICS", Some("1"));
    }

    // Note that this should exist if we're going to run (otherwise we just
    // don't build profiler builtins at all).
    let root = Path::new("../../src/llvm-project/compiler-rt");

    let src_root = root.join("lib").join("profile");
    for src in profile_sources {
        let path = src_root.join(src);
        if path.exists() {
            cfg.file(path);
        }
    }

    cfg.include(root.join("include"));
    cfg.warnings(false);
    cfg.compile("profiler-rt");
}
<|endoftext|>


<commit_before>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs;
use std::fs::File;
use std::io::{ self, BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };
use std::str::FromStr;

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct Package {
    pub name: String,
    pub version: u32,
    pub crc32: u32,
    pub url: String,
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() &&
        path.extension().unwrap_or(OsStr::new("")) != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}

pub fn download_and_find(name: &str, url:&str, path:&Path) -> Result<Vec<Package>, String>{
    if update_package_list(url, path).is_ok() {
        return find_package(name, path)
    } else {
        return Err(String::from("Error occured while downloading package list"))
    }
}

pub fn select_package(name: &str, path: &Path) -> Result<Package, String>{
    let found_packages = find_package(name, path)?;

    if found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            println!("Package {}: {}", i, package.name);
        }

        let mut input = String::new();
        custom_try!(io::stdin().read_line(&mut input));
        let input: u16 = custom_try!(input.trim().parse::<u16>());

        if input > found_packages.len() as u16 {
            return Err(String::from("Invalid input"))
        } else {
            return Ok(found_packages[input as usize].clone())
        }
    } else {
        return Ok(found_packages[0].clone())
    }
}<commit_msg>Remove unused use.<commit_after>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::ffi::OsStr;
use std::fs::{ self, File };
use std::io::{ self, BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable, Clone)]
pub struct Package {
    pub name: String,
    pub version: u32,
    pub crc32: u32,
    pub url: String,
    pub dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() &&
        path.extension().unwrap_or(OsStr::new("")) != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}

pub fn download_and_find(name: &str, url:&str, path:&Path) -> Result<Vec<Package>, String>{
    if update_package_list(url, path).is_ok() {
        return find_package(name, path)
    } else {
        return Err(String::from("Error occured while downloading package list"))
    }
}

pub fn select_package(name: &str, path: &Path) -> Result<Package, String>{
    let found_packages = find_package(name, path)?;

    if found_packages.len() > 1 {
        for (i, package) in found_packages.iter().enumerate() {
            println!("Package {}: {}", i, package.name);
        }

        let mut input = String::new();
        custom_try!(io::stdin().read_line(&mut input));
        let input: u16 = custom_try!(input.trim().parse::<u16>());

        if input > found_packages.len() as u16 {
            return Err(String::from("Invalid input"))
        } else {
            return Ok(found_packages[input as usize].clone())
        }
    } else {
        return Ok(found_packages[0].clone())
    }
}<|endoftext|>


<commit_before>use crate::constants;
use reqwest::blocking::{
    Client,
    RequestBuilder as ReqwestRequestBuilder,
};
use reqwest::{
    header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT, HeaderMap as Headers, HeaderValue},
    Url,
};
use super::{
    HttpError,
    routing::RouteInfo,
};

pub struct RequestBuilder<'a> {
    body: Option<&'a [u8]>,
    headers: Option<Headers>,
    route: RouteInfo<'a>,
}

impl<'a> RequestBuilder<'a> {
    pub fn new(route_info: RouteInfo<'a>) -> Self {
        Self {
            body: None,
            headers: None,
            route: route_info,
        }
    }

    pub fn build(self) -> Request<'a> {
        Request::new(self)
    }

    pub fn body(&mut self, body: Option<&'a [u8]>) -> &mut Self {
        self.body = body;

        self
    }

    pub fn headers(&mut self, headers: Option<Headers>) -> &mut Self {
        self.headers = headers;

        self
    }

    pub fn route(&mut self, route_info: RouteInfo<'a>) -> &mut Self {
        self.route = route_info;

        self
    }
}

#[derive(Clone, Debug)]
pub struct Request<'a> {
    pub(super) body: Option<&'a [u8]>,
    pub(super) headers: Option<Headers>,
    pub(super) route: RouteInfo<'a>,
}

impl<'a> Request<'a> {
    pub fn new(builder: RequestBuilder<'a>) -> Self {
        let RequestBuilder { body, headers, route } = builder;

        Self { body, headers, route }
    }

    pub fn build(&'a self, client: &Client, token: &str) -> Result<ReqwestRequestBuilder, HttpError> {
        let Request {
            body,
            headers: ref request_headers,
            route: ref route_info,
        } = *self;

        let (method, _, path) = route_info.deconstruct();

        let mut builder = client.request(
            method.reqwest_method(),
            Url::parse(&path)?,
        );

        if let Some(ref bytes) = body {
            builder = builder.body(Vec::from(*bytes));
        }

        let mut headers = Headers::with_capacity(4);
        headers.insert(USER_AGENT, HeaderValue::from_static(&constants::USER_AGENT));
        headers.insert(AUTHORIZATION,
            HeaderValue::from_str(&token).map_err(HttpError::InvalidHeader)?);
        headers.insert(CONTENT_TYPE, HeaderValue::from_static(&"application/json"));
        headers.insert(CONTENT_LENGTH, HeaderValue::from_static(&"0"));
        headers.insert("X-Ratelimit-Precision", HeaderValue::from_static("millisecond"));

        if let Some(ref request_headers) = request_headers {
            headers.extend(request_headers.clone());
        }

        Ok(builder.headers(headers))
    }

    pub fn body_ref(&self) -> &Option<&'a [u8]> {
        &self.body
    }

    pub fn body_mut(&mut self) -> &mut Option<&'a [u8]> {
        &mut self.body
    }

    pub fn headers_ref(&self) -> &Option<Headers> {
        &self.headers
    }

    pub fn headers_mut(&mut self) -> &mut Option<Headers> {
        &mut self.headers
    }

    pub fn route_ref(&self) -> &RouteInfo<'_> {
        &self.route
    }

    pub fn route_mut(&mut self) -> &mut RouteInfo<'a> {
        &mut self.route
    }
}
<commit_msg>Only set the content type header if there's a body<commit_after>use crate::constants;
use reqwest::blocking::{
    Client,
    RequestBuilder as ReqwestRequestBuilder,
};
use reqwest::{
    header::{AUTHORIZATION, CONTENT_LENGTH, CONTENT_TYPE, USER_AGENT, HeaderMap as Headers, HeaderValue},
    Url,
};
use super::{
    HttpError,
    routing::RouteInfo,
};

pub struct RequestBuilder<'a> {
    body: Option<&'a [u8]>,
    headers: Option<Headers>,
    route: RouteInfo<'a>,
}

impl<'a> RequestBuilder<'a> {
    pub fn new(route_info: RouteInfo<'a>) -> Self {
        Self {
            body: None,
            headers: None,
            route: route_info,
        }
    }

    pub fn build(self) -> Request<'a> {
        Request::new(self)
    }

    pub fn body(&mut self, body: Option<&'a [u8]>) -> &mut Self {
        self.body = body;

        self
    }

    pub fn headers(&mut self, headers: Option<Headers>) -> &mut Self {
        self.headers = headers;

        self
    }

    pub fn route(&mut self, route_info: RouteInfo<'a>) -> &mut Self {
        self.route = route_info;

        self
    }
}

#[derive(Clone, Debug)]
pub struct Request<'a> {
    pub(super) body: Option<&'a [u8]>,
    pub(super) headers: Option<Headers>,
    pub(super) route: RouteInfo<'a>,
}

impl<'a> Request<'a> {
    pub fn new(builder: RequestBuilder<'a>) -> Self {
        let RequestBuilder { body, headers, route } = builder;

        Self { body, headers, route }
    }

    pub fn build(&'a self, client: &Client, token: &str) -> Result<ReqwestRequestBuilder, HttpError> {
        let Request {
            body,
            headers: ref request_headers,
            route: ref route_info,
        } = *self;

        let (method, _, path) = route_info.deconstruct();

        let mut builder = client.request(
            method.reqwest_method(),
            Url::parse(&path)?,
        );

        if let Some(ref bytes) = body {
            builder = builder.body(Vec::from(*bytes));
        }

        let mut headers = Headers::with_capacity(4);
        headers.insert(USER_AGENT, HeaderValue::from_static(&constants::USER_AGENT));
        headers.insert(AUTHORIZATION,
            HeaderValue::from_str(&token).map_err(HttpError::InvalidHeader)?);

        // Discord will return a 400: Bad Request response if we set the content type header,
        // but don't give a body.
        if self.body.is_some() {
            headers.insert(CONTENT_TYPE, HeaderValue::from_static(&"application/json"));
            headers.insert(CONTENT_LENGTH, HeaderValue::from_static(&"0"));
        }

        headers.insert("X-Ratelimit-Precision", HeaderValue::from_static("millisecond"));

        if let Some(ref request_headers) = request_headers {
            headers.extend(request_headers.clone());
        }

        Ok(builder.headers(headers))
    }

    pub fn body_ref(&self) -> &Option<&'a [u8]> {
        &self.body
    }

    pub fn body_mut(&mut self) -> &mut Option<&'a [u8]> {
        &mut self.body
    }

    pub fn headers_ref(&self) -> &Option<Headers> {
        &self.headers
    }

    pub fn headers_mut(&mut self) -> &mut Option<Headers> {
        &mut self.headers
    }

    pub fn route_ref(&self) -> &RouteInfo<'_> {
        &self.route
    }

    pub fn route_mut(&mut self) -> &mut RouteInfo<'a> {
        &mut self.route
    }
}
<|endoftext|>


<commit_before>use buffer::{Buffer, BufferType};
use gl;
use BufferExt;
use GlObject;

use backend::Facade;

use sync;

use index::IndicesSource;
use index::ToIndicesSource;
use index::IntoIndexBuffer;
use index::Index;
use index::IndexType;
use index::PrimitiveType;

use std::mem;
use std::ops::Range;
use std::cell::RefCell;

/// A list of indices loaded in the graphics card's memory.
#[derive(Debug)]
pub struct IndexBuffer {
    buffer: Buffer,
    data_type: IndexType,
    primitives: PrimitiveType,
}

pub struct IndexBufferSlice<'a> {
    buffer: &'a IndexBuffer,
    offset: usize,  // in number of elements
    len: usize,     // in number of elements
}

impl IndexBuffer {
    /// Builds a new index buffer.
    pub fn new<T: IntoIndexBuffer, F>(facade: &F, data: T) -> IndexBuffer where F: Facade {
        data.into_index_buffer(facade)
    }

    /// Builds a new index buffer from raw data and a primitive type.
    pub fn from_raw<T, F>(facade: &F, data: Vec<T>, prim: PrimitiveType) -> IndexBuffer
                       where T: Index, F: Facade
    {
        assert!(mem::align_of::<T>() <= mem::size_of::<T>(), "Buffer elements are not \
                                                              packed in memory");
        IndexBuffer {
            buffer: Buffer::new(facade, &data, BufferType::ArrayBuffer,
                                false).unwrap(),    // FIXME: ElementArrayBuffer
            data_type: <T as Index>::get_type(),
            primitives: prim,
        }
    }

    /// Returns the type of primitives associated with this index buffer.
    pub fn get_primitives_type(&self) -> PrimitiveType {
        self.primitives
    }

    /// Returns the data type of the indices inside this index buffer.
    pub fn get_indices_type(&self) -> IndexType {
        self.data_type
    }

    /// Returns `None` if out of range.
    pub fn slice(&self, Range { start, end }: Range<usize>) -> Option<IndexBufferSlice> {
        let len = end - start;

        if start > self.buffer.get_elements_count() ||
            start + len > self.buffer.get_elements_count()
        {
            return None;
        }

        Some(IndexBufferSlice {
            buffer: self,
            offset: start,
            len: len,
        })
    }
}

impl BufferExt for IndexBuffer {
    fn add_fence(&self) -> Option<&RefCell<Option<sync::LinearSyncFence>>> {
        self.buffer.add_fence()
    }
}

impl GlObject for IndexBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl ToIndicesSource for IndexBuffer {
    type Data = u16;      // TODO: u16?

    fn to_indices_source(&self) -> IndicesSource<u16> {     // TODO: u16?
        IndicesSource::IndexBuffer {
            buffer: self,
            offset: 0,
            length: self.buffer.get_elements_count() as usize,
        }
    }
}

impl<'a> ToIndicesSource for IndexBufferSlice<'a> {
    type Data = u16;      // TODO: u16?

    fn to_indices_source(&self) -> IndicesSource<u16> {     // TODO: u16?
        IndicesSource::IndexBuffer {
            buffer: self.buffer,
            offset: self.offset,
            length: self.len,
        }
    }
}
<commit_msg>Allow index buffer creation from slice<commit_after>use buffer::{Buffer, BufferType};
use gl;
use BufferExt;
use GlObject;

use backend::Facade;

use sync;

use index::IndicesSource;
use index::ToIndicesSource;
use index::IntoIndexBuffer;
use index::Index;
use index::IndexType;
use index::PrimitiveType;

use std::mem;
use std::convert::AsRef;
use std::ops::Range;
use std::cell::RefCell;

/// A list of indices loaded in the graphics card's memory.
#[derive(Debug)]
pub struct IndexBuffer {
    buffer: Buffer,
    data_type: IndexType,
    primitives: PrimitiveType,
}

pub struct IndexBufferSlice<'a> {
    buffer: &'a IndexBuffer,
    offset: usize,  // in number of elements
    len: usize,     // in number of elements
}

impl IndexBuffer {
    /// Builds a new index buffer.
    pub fn new<T: IntoIndexBuffer, F>(facade: &F, data: T) -> IndexBuffer where F: Facade {
        data.into_index_buffer(facade)
    }

    /// Builds a new index buffer from raw data and a primitive type.
    pub fn from_raw<T, F, D>(facade: &F, data: D, prim: PrimitiveType) -> IndexBuffer
                       where T: Index, F: Facade, D: AsRef<[T]>
    {
        assert!(mem::align_of::<T>() <= mem::size_of::<T>(), "Buffer elements are not \
                                                              packed in memory");
        IndexBuffer {
            buffer: Buffer::new(facade, data.as_ref(), BufferType::ArrayBuffer,
                                false).unwrap(),    // FIXME: ElementArrayBuffer
            data_type: <T as Index>::get_type(),
            primitives: prim,
        }
    }

    /// Returns the type of primitives associated with this index buffer.
    pub fn get_primitives_type(&self) -> PrimitiveType {
        self.primitives
    }

    /// Returns the data type of the indices inside this index buffer.
    pub fn get_indices_type(&self) -> IndexType {
        self.data_type
    }

    /// Returns `None` if out of range.
    pub fn slice(&self, Range { start, end }: Range<usize>) -> Option<IndexBufferSlice> {
        let len = end - start;

        if start > self.buffer.get_elements_count() ||
            start + len > self.buffer.get_elements_count()
        {
            return None;
        }

        Some(IndexBufferSlice {
            buffer: self,
            offset: start,
            len: len,
        })
    }
}

impl BufferExt for IndexBuffer {
    fn add_fence(&self) -> Option<&RefCell<Option<sync::LinearSyncFence>>> {
        self.buffer.add_fence()
    }
}

impl GlObject for IndexBuffer {
    type Id = gl::types::GLuint;
    fn get_id(&self) -> gl::types::GLuint {
        self.buffer.get_id()
    }
}

impl ToIndicesSource for IndexBuffer {
    type Data = u16;      // TODO: u16?

    fn to_indices_source(&self) -> IndicesSource<u16> {     // TODO: u16?
        IndicesSource::IndexBuffer {
            buffer: self,
            offset: 0,
            length: self.buffer.get_elements_count() as usize,
        }
    }
}

impl<'a> ToIndicesSource for IndexBufferSlice<'a> {
    type Data = u16;      // TODO: u16?

    fn to_indices_source(&self) -> IndicesSource<u16> {     // TODO: u16?
        IndicesSource::IndexBuffer {
            buffer: self.buffer,
            offset: self.offset,
            length: self.len,
        }
    }
}
<|endoftext|>


<commit_before>use dynasmrt::x64::Assembler;
use dynasmrt::{DynasmApi, DynasmLabelApi};

use super::*;
use peephole::{self, Count};

dynasm!(asm
    ; .alias pointer, r12
    ; .alias mem_start, r13
    ; .alias mem_limit, r14
    ; .alias rts, r15
);

/// Compiles peephole-optimized AST to x64 machine code.
///
/// Uses the `dynasmrt` assembler
pub fn compile(program: &peephole::Program, checked: bool) -> Program {
    let mut asm = dynasmrt::x64::Assembler::new();
    let start = asm.offset();

    dynasm!(asm
        ; push r12
        ; push r13
        ; push r14
        ; push r15
        ; mov pointer, rcx
        ; mov mem_start, rcx
        ; mov mem_limit, rcx
        ; add mem_limit, rdx
        ; mov rts, r8
    );

    compile_sequence(&mut asm, program, checked);

    dynasm!(asm
        ; mov rax, rts::OKAY as i32
        ; jmp ->finish

        ; ->underflow:
        ; mov rax, rts::UNDERFLOW as i32
        ; jmp ->finish

        ; ->overflow:
        ; mov rax, rts::OVERFLOW as i32

        ; ->finish:
        ; pop r15
        ; pop r14
        ; pop r13
        ; pop r12
        ; ret
    );

    let code = asm.finalize().unwrap();

    Program {
        code: code,
        start: start,
    }
}

fn compile_sequence(asm: &mut Assembler, program: &[peephole::Instruction], checked: bool) {
    for instruction in program {
        compile_instruction(asm, instruction, checked);
    }
}

fn compile_instruction(asm: &mut Assembler, instruction: &peephole::Instruction, checked: bool) {
    use peephole::Instruction::*;

    match *instruction {
        Right(count) => {
            dynasm!(asm
                ;; load_pos_offset(asm, count, checked)
                ; add pointer, rax
            );
        }

        Left(count) => {
            dynasm!(asm
                ;; load_neg_offset(asm, count, checked)
                ; sub pointer, rax
            );
        }

        Change(count) => {
            dynasm!(asm
                ; add [pointer], BYTE u8_to_i8(count)
            );
        }

        In => {
            dynasm!(asm
                ; mov rax, QWORD rts::RtsState::read as _
                ; mov rcx, rts
                ; sub rsp, BYTE 0x28
                ; call rax
                ; add rsp, BYTE 0x28
                ; mov [pointer], al
            );
        }

        Out => {
            dynasm!(asm
                ; mov rax, QWORD rts::RtsState::write as _
                ; mov rcx, rts
                ; xor rdx, rdx
                ; mov dl, [pointer]
                ; sub rsp, BYTE 0x28
                ; call rax
                ; add rsp, BYTE 0x28
            );
        }

        SetZero => {
            dynasm!(asm
                ; mov BYTE [pointer], 0
            )
        }

        FindZeroRight(skip) => {
            dynasm!(asm
                ; jmp >end_loop
                ; begin_loop:
                ;; load_pos_offset(asm, skip, checked)
                ; add pointer, rax
                ; end_loop:
                ; cmp BYTE [pointer], 0
                ; jnz <begin_loop
            )
        }

        FindZeroLeft(skip) => {
            dynasm!(asm
                ; jmp >end_loop
                ; begin_loop:
                ;; load_neg_offset(asm, skip, checked)
                ; sub pointer, rax
                ; end_loop:
                ; cmp BYTE [pointer], 0
                ; jnz <begin_loop
            )
        }

        OffsetAddRight(offset) => {
            dynasm!(asm
                ; cmp BYTE [pointer], 0
                ; jz >skip
                ;; load_pos_offset(asm, offset, checked)
                ; mov cl, BYTE [pointer]
                ; mov BYTE [pointer], 0
                ; add BYTE [pointer + rax], cl
                ; skip:
            );
        }

        OffsetAddLeft(offset) => {
            dynasm!(asm
                ; cmp BYTE [pointer], 0
                ; jz >skip
                ;; load_neg_offset(asm, offset, checked)
                ; mov cl, BYTE [pointer]
                ; mov BYTE [pointer], 0
                ; neg rax
                ; add BYTE [pointer + rax], cl
                ; skip:
            );
        }

        Loop(ref body) => {
            let begin_label = asm.new_dynamic_label();
            let end_label   = asm.new_dynamic_label();

            dynasm!(asm
                ; jmp =>end_label
                ; =>begin_label
            );

            compile_sequence(asm, body, checked);

            dynasm!(asm
                ; =>end_label
                ; cmp BYTE [pointer], 0
                ; jnz =>begin_label
            );
        }
    }
}

#[inline]
fn load_offset(asm: &mut Assembler, offset: Count) {
    if offset as i32 as Count == offset {
        dynasm!(asm
            ; mov rax, DWORD offset as i32
        );
    } else {
        dynasm!(asm
            ; mov rax, QWORD offset as i64
        );
    }
}

fn load_pos_offset(asm: &mut Assembler, offset: Count, checked: bool) {
    load_offset(asm, offset);

    if checked {
        dynasm!(asm
            ; mov rcx, mem_limit
            ; sub rcx, pointer
            ; cmp rcx, rax
            ; jle ->overflow
        );
    }
}

fn load_neg_offset(asm: &mut Assembler, offset: Count, checked: bool) {
    load_offset(asm, offset);

    if checked {
        dynasm!(asm
            ; mov rcx, pointer
            ; sub rcx, mem_start
            ; cmp rcx, rax
            ; jl ->underflow
        );
    }
}

fn u8_to_i8(n: u8) -> i8 {
    let mut n = n as isize % 256;
    if n > 127 { n -= 256 };
    n as i8
}
<commit_msg>No need for extra code to check u8 to i8 cast.<commit_after>use dynasmrt::x64::Assembler;
use dynasmrt::{DynasmApi, DynasmLabelApi};

use super::*;
use peephole::{self, Count};

dynasm!(asm
    ; .alias pointer, r12
    ; .alias mem_start, r13
    ; .alias mem_limit, r14
    ; .alias rts, r15
);

/// Compiles peephole-optimized AST to x64 machine code.
///
/// Uses the `dynasmrt` assembler
pub fn compile(program: &peephole::Program, checked: bool) -> Program {
    let mut asm = dynasmrt::x64::Assembler::new();
    let start = asm.offset();

    dynasm!(asm
        ; push r12
        ; push r13
        ; push r14
        ; push r15
        ; mov pointer, rcx
        ; mov mem_start, rcx
        ; mov mem_limit, rcx
        ; add mem_limit, rdx
        ; mov rts, r8
    );

    compile_sequence(&mut asm, program, checked);

    dynasm!(asm
        ; mov rax, rts::OKAY as i32
        ; jmp ->finish

        ; ->underflow:
        ; mov rax, rts::UNDERFLOW as i32
        ; jmp ->finish

        ; ->overflow:
        ; mov rax, rts::OVERFLOW as i32

        ; ->finish:
        ; pop r15
        ; pop r14
        ; pop r13
        ; pop r12
        ; ret
    );

    let code = asm.finalize().unwrap();

    Program {
        code: code,
        start: start,
    }
}

fn compile_sequence(asm: &mut Assembler, program: &[peephole::Instruction], checked: bool) {
    for instruction in program {
        compile_instruction(asm, instruction, checked);
    }
}

fn compile_instruction(asm: &mut Assembler, instruction: &peephole::Instruction, checked: bool) {
    use peephole::Instruction::*;

    match *instruction {
        Right(count) => {
            dynasm!(asm
                ;; load_pos_offset(asm, count, checked)
                ; add pointer, rax
            );
        }

        Left(count) => {
            dynasm!(asm
                ;; load_neg_offset(asm, count, checked)
                ; sub pointer, rax
            );
        }

        Change(count) => {
            dynasm!(asm
                ; add [pointer], BYTE count as i8
            );
        }

        In => {
            dynasm!(asm
                ; mov rax, QWORD rts::RtsState::read as _
                ; mov rcx, rts
                ; sub rsp, BYTE 0x28
                ; call rax
                ; add rsp, BYTE 0x28
                ; mov [pointer], al
            );
        }

        Out => {
            dynasm!(asm
                ; mov rax, QWORD rts::RtsState::write as _
                ; mov rcx, rts
                ; xor rdx, rdx
                ; mov dl, [pointer]
                ; sub rsp, BYTE 0x28
                ; call rax
                ; add rsp, BYTE 0x28
            );
        }

        SetZero => {
            dynasm!(asm
                ; mov BYTE [pointer], 0
            )
        }

        FindZeroRight(skip) => {
            dynasm!(asm
                ; jmp >end_loop
                ; begin_loop:
                ;; load_pos_offset(asm, skip, checked)
                ; add pointer, rax
                ; end_loop:
                ; cmp BYTE [pointer], 0
                ; jnz <begin_loop
            )
        }

        FindZeroLeft(skip) => {
            dynasm!(asm
                ; jmp >end_loop
                ; begin_loop:
                ;; load_neg_offset(asm, skip, checked)
                ; sub pointer, rax
                ; end_loop:
                ; cmp BYTE [pointer], 0
                ; jnz <begin_loop
            )
        }

        OffsetAddRight(offset) => {
            dynasm!(asm
                ; cmp BYTE [pointer], 0
                ; jz >skip
                ;; load_pos_offset(asm, offset, checked)
                ; mov cl, BYTE [pointer]
                ; mov BYTE [pointer], 0
                ; add BYTE [pointer + rax], cl
                ; skip:
            );
        }

        OffsetAddLeft(offset) => {
            dynasm!(asm
                ; cmp BYTE [pointer], 0
                ; jz >skip
                ;; load_neg_offset(asm, offset, checked)
                ; mov cl, BYTE [pointer]
                ; mov BYTE [pointer], 0
                ; neg rax
                ; add BYTE [pointer + rax], cl
                ; skip:
            );
        }

        Loop(ref body) => {
            let begin_label = asm.new_dynamic_label();
            let end_label   = asm.new_dynamic_label();

            dynasm!(asm
                ; jmp =>end_label
                ; =>begin_label
            );

            compile_sequence(asm, body, checked);

            dynasm!(asm
                ; =>end_label
                ; cmp BYTE [pointer], 0
                ; jnz =>begin_label
            );
        }
    }
}

#[inline]
fn load_offset(asm: &mut Assembler, offset: Count) {
    if offset as i32 as Count == offset {
        dynasm!(asm
            ; mov rax, DWORD offset as i32
        );
    } else {
        dynasm!(asm
            ; mov rax, QWORD offset as i64
        );
    }
}

fn load_pos_offset(asm: &mut Assembler, offset: Count, checked: bool) {
    load_offset(asm, offset);

    if checked {
        dynasm!(asm
            ; mov rcx, mem_limit
            ; sub rcx, pointer
            ; cmp rcx, rax
            ; jle ->overflow
        );
    }
}

fn load_neg_offset(asm: &mut Assembler, offset: Count, checked: bool) {
    load_offset(asm, offset);

    if checked {
        dynasm!(asm
            ; mov rcx, pointer
            ; sub rcx, mem_start
            ; cmp rcx, rax
            ; jl ->underflow
        );
    }
}

<|endoftext|>


<commit_before>mod js_obj;
mod js_type;
mod js_str;
<commit_msg>Make all current js_types mods public<commit_after>pub mod js_obj;
pub mod js_type;
pub mod js_str;
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! Traits for working with Errors.
//!
//! # The `Error` trait
//!
//! `Error` is a trait representing the basic expectations for error values,
//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
//! a description, but they may optionally provide additional detail (via
//! `Display`) and cause chain information:
//!
//! ```
//! use std::fmt::Display;
//!
//! trait Error: Display {
//!     fn description(&self) -> &str;
//!
//!     fn cause(&self) -> Option<&Error> { None }
//! }
//! ```
//!
//! The `cause` method is generally used when errors cross "abstraction
//! boundaries", i.e.  when a one module must report an error that is "caused"
//! by an error from a lower-level module. This setup makes it possible for the
//! high-level module to provide its own errors that do not commit to any
//! particular implementation, but also reveal some of its implementation for
//! debugging via `cause` chains.
//!
//! # The `FromError` trait
//!
//! `FromError` is a simple trait that expresses conversions between different
//! error types. To provide maximum flexibility, it does not require either of
//! the types to actually implement the `Error` trait, although this will be the
//! common case.
//!
//! The main use of this trait is in the `try!` macro, which uses it to
//! automatically convert a given error to the error specified in a function's
//! return type.
//!
//! For example,
//!
//! ```
//! # #![feature(os, old_io, old_path)]
//! use std::error::FromError;
//! use std::old_io::{File, IoError};
//! use std::os::{MemoryMap, MapError};
//! use std::old_path::Path;
//!
//! enum MyError {
//!     Io(IoError),
//!     Map(MapError)
//! }
//!
//! impl FromError<IoError> for MyError {
//!     fn from_error(err: IoError) -> MyError {
//!         MyError::Io(err)
//!     }
//! }
//!
//! impl FromError<MapError> for MyError {
//!     fn from_error(err: MapError) -> MyError {
//!         MyError::Map(err)
//!     }
//! }
//!
//! #[allow(unused_variables)]
//! fn open_and_map() -> Result<(), MyError> {
//!     let f = try!(File::open(&Path::new("foo.txt")));
//!     let m = try!(MemoryMap::new(0, &[]));
//!     // do something interesting here...
//!     Ok(())
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;
use fmt::{Debug, Display};

/// Base functionality for all errors in Rust.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
    /// A short description of the error.
    ///
    /// The description should not contain newlines or sentence-ending
    /// punctuation, to facilitate embedding in larger user-facing
    /// strings.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn description(&self) -> &str;

    /// The lower-level cause of this error, if any.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn cause(&self) -> Option<&Error> { None }
}

/// A trait for types that can be converted from a given error type `E`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromError<E> {
    /// Perform the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_error(err: E) -> Self;
}

// Any type is convertable from itself
#[stable(feature = "rust1", since = "1.0.0")]
impl<E> FromError<E> for E {
    fn from_error(err: E) -> E {
        err
    }
}
<commit_msg>Rollup merge of #23836 - Hoverbear:patch-1, r=steveklabnik<commit_after>// Copyright 2014 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.

//! Traits for working with Errors.
//!
//! # The `Error` trait
//!
//! `Error` is a trait representing the basic expectations for error values,
//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
//! a description, but they may optionally provide additional detail (via
//! `Display`) and cause chain information:
//!
//! ```
//! use std::fmt::Display;
//!
//! trait Error: Display {
//!     fn description(&self) -> &str;
//!
//!     fn cause(&self) -> Option<&Error> { None }
//! }
//! ```
//!
//! The `cause` method is generally used when errors cross "abstraction
//! boundaries", i.e.  when a one module must report an error that is "caused"
//! by an error from a lower-level module. This setup makes it possible for the
//! high-level module to provide its own errors that do not commit to any
//! particular implementation, but also reveal some of its implementation for
//! debugging via `cause` chains.
//!
//! # The `FromError` trait
//!
//! `FromError` is a simple trait that expresses conversions between different
//! error types. To provide maximum flexibility, it does not require either of
//! the types to actually implement the `Error` trait, although this will be the
//! common case.
//!
//! The main use of this trait is in the `try!` macro, which uses it to
//! automatically convert a given error to the error specified in a function's
//! return type.
//!
//! For example,
//!
//! ```
//! #![feature(core)]
//! use std::error::FromError;
//! use std::{io, str};
//! use std::fs::File;
//!
//! enum MyError {
//!     Io(io::Error),
//!     Utf8(str::Utf8Error),
//! }
//!
//! impl FromError<io::Error> for MyError {
//!     fn from_error(err: io::Error) -> MyError { MyError::Io(err) }
//! }
//!
//! impl FromError<str::Utf8Error> for MyError {
//!     fn from_error(err: str::Utf8Error) -> MyError { MyError::Utf8(err) }
//! }
//!
//! #[allow(unused_variables)]
//! fn open_and_map() -> Result<(), MyError> {
//!     let b = b"foo.txt";
//!     let s = try!(str::from_utf8(b));
//!     let f = try!(File::open(s));
//!
//!     // do something interesting here...
//!     Ok(())
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;
use fmt::{Debug, Display};

/// Base functionality for all errors in Rust.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
    /// A short description of the error.
    ///
    /// The description should not contain newlines or sentence-ending
    /// punctuation, to facilitate embedding in larger user-facing
    /// strings.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn description(&self) -> &str;

    /// The lower-level cause of this error, if any.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn cause(&self) -> Option<&Error> { None }
}

/// A trait for types that can be converted from a given error type `E`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromError<E> {
    /// Perform the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_error(err: E) -> Self;
}

// Any type is convertable from itself
#[stable(feature = "rust1", since = "1.0.0")]
impl<E> FromError<E> for E {
    fn from_error(err: E) -> E {
        err
    }
}
<|endoftext|>


<commit_before>//! LR(1) interpeter. Just builds up parse trees. Intended for testing.

use lr1::{Action, State, Lookahead};
use grammar::repr::*;
use std::fmt::{Debug, Display, Formatter, Error};
use util::Sep;

#[derive(PartialEq, Eq)]
pub enum ParseTree {
    Nonterminal(NonterminalString, Vec<ParseTree>),
    Terminal(TerminalString),
}

pub fn interpret<'g,TOKENS>(states: &'g [State<'g>], tokens: TOKENS)
                            -> Result<ParseTree, ()>
    where TOKENS: Iterator<Item=TerminalString>
{
    let mut m = Machine::new(states);
    m.execute(tokens)
}

struct Machine<'grammar> {
    states: &'grammar [State<'grammar>],
    state_stack: Vec<&'grammar State<'grammar>>,
    data_stack: Vec<ParseTree>,
}

impl<'grammar> Machine<'grammar> {
    fn new(states: &'grammar [State<'grammar>]) -> Machine<'grammar> {
        Machine { states: states,
                  state_stack: vec![],
                  data_stack: vec![] }
    }

    fn execute<TOKENS>(&mut self, mut tokens: TOKENS) -> Result<ParseTree, ()>
        where TOKENS: Iterator<Item=TerminalString>
    {
        assert!(self.state_stack.is_empty());
        assert!(self.data_stack.is_empty());

        self.state_stack.push(&self.states[0]);

        let mut token = tokens.next();
        while let Some(terminal) = token {
            let state = *self.state_stack.last().unwrap();

            // check whether we can shift this token
            match state.tokens.get(&Lookahead::Terminal(terminal)) {
                None => { return Err(()); }

                Some(&Action::Shift(next_index)) => {
                    self.data_stack.push(ParseTree::Terminal(terminal));
                    self.state_stack.push(&self.states[next_index.0]);
                    token = tokens.next();
                }

                Some(&Action::Reduce(production)) => {
                    let more = self.reduce(production);
                    assert!(more);
                }
            }
        }

        // drain now for EOF
        loop {
            let state = *self.state_stack.last().unwrap();
            match state.tokens.get(&Lookahead::EOF) {
                None => { return Err(()); }
                Some(&Action::Shift(_)) => { unreachable!("cannot shift EOF") }
                Some(&Action::Reduce(production)) => {
                    if !self.reduce(production) {
                        assert_eq!(self.data_stack.len(), 1);
                        return Ok(self.data_stack.pop().unwrap());
                    }
                }
            }
        }
    }

    fn reduce(&mut self, production: &Production) -> bool {
        let args = production.symbols.len();

        // remove the top N items from the data stack
        let mut popped = vec![];
        for _ in 0 .. args {
            popped.push(self.data_stack.pop().unwrap());
        }
        popped.reverse();

        // remove the top N states
        for _ in 0 .. args {
            self.state_stack.pop().unwrap();
        }

        // construct the new, reduced tree and push it on the stack
        let tree = ParseTree::Nonterminal(production.nonterminal, popped);
        self.data_stack.push(tree);

        // recover the state and extract the "Goto" action
        let receiving_state = *self.state_stack.last().unwrap();
        match receiving_state.gotos.get(&production.nonterminal) {
            Some(goto_state) => {
                self.state_stack.push(&self.states[goto_state.0]);
                true // keep going
            }
            None => {
                false // all done
            }
        }
    }
}

impl Debug for ParseTree {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        Display::fmt(self, fmt)
    }
}

impl Display for ParseTree {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            ParseTree::Nonterminal(id, ref trees) => write!(fmt, "[{}: {}]", id, Sep(", ", trees)),
            ParseTree::Terminal(id) => write!(fmt, "{}", id),
        }
    }
}
<commit_msg>distinguish lifetimes of the state table from the underlying grammar<commit_after>//! LR(1) interpeter. Just builds up parse trees. Intended for testing.

use lr1::{Action, State, Lookahead};
use grammar::repr::*;
use std::fmt::{Debug, Display, Formatter, Error};
use util::Sep;

#[derive(PartialEq, Eq)]
pub enum ParseTree {
    Nonterminal(NonterminalString, Vec<ParseTree>),
    Terminal(TerminalString),
}

pub fn interpret<TOKENS>(states: &[State], tokens: TOKENS) -> Result<ParseTree, ()>
    where TOKENS: Iterator<Item=TerminalString>
{
    let mut m = Machine::new(states);
    m.execute(tokens)
}

struct Machine<'states, 'grammar:'states> {
    states: &'states [State<'grammar>],
    state_stack: Vec<&'states State<'grammar>>,
    data_stack: Vec<ParseTree>,
}

impl<'states, 'grammar> Machine<'states, 'grammar> {
    fn new(states: &'states [State<'grammar>]) -> Machine<'states,'grammar> {
        Machine { states: states,
                  state_stack: vec![],
                  data_stack: vec![] }
    }

    fn execute<TOKENS>(&mut self, mut tokens: TOKENS) -> Result<ParseTree, ()>
        where TOKENS: Iterator<Item=TerminalString>
    {
        assert!(self.state_stack.is_empty());
        assert!(self.data_stack.is_empty());

        self.state_stack.push(&self.states[0]);

        let mut token = tokens.next();
        while let Some(terminal) = token {
            let state = *self.state_stack.last().unwrap();

            // check whether we can shift this token
            match state.tokens.get(&Lookahead::Terminal(terminal)) {
                None => { return Err(()); }

                Some(&Action::Shift(next_index)) => {
                    self.data_stack.push(ParseTree::Terminal(terminal));
                    self.state_stack.push(&self.states[next_index.0]);
                    token = tokens.next();
                }

                Some(&Action::Reduce(production)) => {
                    let more = self.reduce(production);
                    assert!(more);
                }
            }
        }

        // drain now for EOF
        loop {
            let state = *self.state_stack.last().unwrap();
            match state.tokens.get(&Lookahead::EOF) {
                None => { return Err(()); }
                Some(&Action::Shift(_)) => { unreachable!("cannot shift EOF") }
                Some(&Action::Reduce(production)) => {
                    if !self.reduce(production) {
                        assert_eq!(self.data_stack.len(), 1);
                        return Ok(self.data_stack.pop().unwrap());
                    }
                }
            }
        }
    }

    fn reduce(&mut self, production: &Production) -> bool {
        let args = production.symbols.len();

        // remove the top N items from the data stack
        let mut popped = vec![];
        for _ in 0 .. args {
            popped.push(self.data_stack.pop().unwrap());
        }
        popped.reverse();

        // remove the top N states
        for _ in 0 .. args {
            self.state_stack.pop().unwrap();
        }

        // construct the new, reduced tree and push it on the stack
        let tree = ParseTree::Nonterminal(production.nonterminal, popped);
        self.data_stack.push(tree);

        // recover the state and extract the "Goto" action
        let receiving_state = *self.state_stack.last().unwrap();
        match receiving_state.gotos.get(&production.nonterminal) {
            Some(goto_state) => {
                self.state_stack.push(&self.states[goto_state.0]);
                true // keep going
            }
            None => {
                false // all done
            }
        }
    }
}

impl Debug for ParseTree {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        Display::fmt(self, fmt)
    }
}

impl Display for ParseTree {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            ParseTree::Nonterminal(id, ref trees) => write!(fmt, "[{}: {}]", id, Sep(", ", trees)),
            ParseTree::Terminal(id) => write!(fmt, "{}", id),
        }
    }
}
<|endoftext|>


<commit_before>use cocoa::appkit::{NSPasteboard, NSPasteboardTypeString};
use cocoa::base::{id, nil};
use cocoa::foundation::{NSArray, NSString};
use std::ffi::CStr;
use {Clipboard, Item, Result};

pub trait ClipboardExt: Clipboard {
    fn clipboard_with_name(&self, name: &str) -> Self;

    fn get_clipboard_text_as_nsstring(&self) -> id;
    fn get_raw_clipboard(&self) -> id;
}

#[derive(Debug)]
pub struct CocoaClipboard(id);

impl Clipboard for CocoaClipboard {
    fn get() -> Result<Self> where Self: Sized {
        let pboard = unsafe { NSPasteboard::generalPasteboard(nil) };
        if pboard.is_null() {
            Err(From::from("could not get pasteboard"))
        } else {
            Ok(CocoaClipboard(pboard))
        }
    }

    fn copy(&mut self, item: Item) -> Result<()> {
        unsafe {
            let item = match item {
                Item::Text(ref text) => NSString::alloc(nil).init_str(text),
                Item::Image(ref _image) => {
                    unimplemented!();
                }
                _ => return Ok(())
            };

            self.0.clearContents();
            self.0.declareTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeString), nil);
            NSPasteboard::setString_forType(self.0, item, NSPasteboardTypeString);
            Ok(())
        }
    }

    fn get_paste_text(&self)  -> Result<&str> {
        unsafe {
            let text = NSPasteboard::stringForType(self.0, NSPasteboardTypeString);
            Ok(CStr::from_ptr(text.UTF8String()).to_str().unwrap_or(""))
        }
    }
}
<commit_msg>Create an NSData from an Item::Image<commit_after>use cocoa::appkit::{NSPasteboard, NSPasteboardTypeString};
use cocoa::base::{id, nil};
use cocoa::foundation::{NSArray, NSData, NSString, NSUInteger};
use std::ffi::CStr;
use {Clipboard, Item, Result};

pub trait ClipboardExt: Clipboard {
    fn clipboard_with_name(&self, name: &str) -> Self;

    fn get_clipboard_text_as_nsstring(&self) -> id;
    fn get_raw_clipboard(&self) -> id;
}

#[derive(Debug)]
pub struct CocoaClipboard(id);

impl Clipboard for CocoaClipboard {
    fn get() -> Result<Self> where Self: Sized {
        let pboard = unsafe { NSPasteboard::generalPasteboard(nil) };
        if pboard.is_null() {
            Err(From::from("could not get pasteboard"))
        } else {
            Ok(CocoaClipboard(pboard))
        }
    }

    fn copy(&mut self, item: Item) -> Result<()> {
        unsafe {
            let item = match item {
                Item::Text(ref text) => NSString::alloc(nil).init_str(text),
                Item::Image(ref image) => {
                    let slice = image.bytes();
                    let _data = NSData::dataWithBytes_length_(nil,
                                                              slice.as_ptr() as *const _,
                                                              slice.len() as NSUInteger);
                    unimplemented!();
                }
                _ => return Ok(())
            };

            self.0.clearContents();
            self.0.declareTypes_owner(NSArray::arrayWithObject(nil, NSPasteboardTypeString), nil);
            NSPasteboard::setString_forType(self.0, item, NSPasteboardTypeString);
            Ok(())
        }
    }

    fn get_paste_text(&self)  -> Result<&str> {
        unsafe {
            let text = NSPasteboard::stringForType(self.0, NSPasteboardTypeString);
            Ok(CStr::from_ptr(text.UTF8String()).to_str().unwrap_or(""))
        }
    }
}
<|endoftext|>


<commit_before>macro_rules! e { ($e:expr) => { $e } }

/// Macro for constructing a new matrix type.
///
/// This can be used to construct fixed-sized matrices of whatever dimension
/// the user would like. While this crate only provides matrices of dimensons
/// 2 through 5, it's trivial to make matrices of arbitrary length using this
/// macro.
///
/// Another potential use of this macro is to create new matrices whose
/// subscripts have different names than those provided in this crate. The
/// matrices in `lin`  have subscripts where the rows are named _x_`n` and the
/// columns _y_`n` (as in Cartesian coördinates), but in some use cases, they
/// might represent different quantities. Thus, users can use this macro to
/// create new matrix types whose subscripts have names with semantic meanings
/// more appropriate to their individual use case.
///
/// # Arguments
///    - `$name`: The name of the new matrix type
///    - `$rows`: The number of rows in this matrix
///    - `$cols`: The number of columns in this matrix
///    - `$sub`: The name of each subscript or element of the matrix
///              Note that the number of `$sub`s should be equal to `$cols` *  ///              `$rows`.
///
#[macro_export]
macro_rules! make_matrix {
    ($name: ident, rows: $rows:expr, cols: $cols:expr, $($sub: ident),+) => {
        #[cfg(not(simd))]
        #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Default)]
        #[repr(C)]
        pub struct $name<N> {
            $(pub $sub: N),+
        }
        impl_matrix! { $name, $rows, $cols }
        impl_converts! { $name, $cols, $rows }
        impl_index! { $name, $cols}

    }
}

#[cfg(features = "unstable")]
macro_rules! impl_matrix {
    ($name: ident, $rows:expr, $cols:expr) => {
        impl<N> Matrix<N> for $name<N> {
            const fn nrows(&self) -> usize { $rows }
            const fn ncols(&self) -> usize { $cols }
        }
    }
}

#[cfg(not(features = "unstable"))]
macro_rules! impl_matrix {
    ($name: ident, $rows:expr, $cols:expr) => {
        impl<N> Matrix<N> for $name<N> {
            #[inline] fn nrows(&self) -> usize { $rows }
            #[inline] fn ncols(&self) -> usize { $cols }
        }
    }
}

macro_rules! impl_converts {
    ($($m: ident, $c: expr, $r: expr),+) => { $(
        impl<N> convert::AsRef<[[N; $c]; $r]> for $m<N>
        where N: Copy {

            #[inline] fn as_ref(&self) -> &[[N; $c]; $r] {
                unsafe { transmute(self) }
            }
        }
        impl<N> convert::AsMut<[[N; $c]; $c]> for $m<N>
        where N: Copy {

            #[inline] fn as_mut(&mut self) -> &mut [[N; $c]; $c] {
                unsafe { transmute(self) }
            }
        }
        impl<'a, N> convert::From<&'a [[N; $c]; $r]> for &'a $m<N>
        where N: Numeric
            , N: Copy {

            #[inline] fn from(a: &'a [[N; $c]; $r]) -> &'a $m<N> {
                unsafe { transmute(a) }
            }
        }
        impl<'a, N> convert::From<&'a mut [[N; $c]; $r]> for &'a mut $m<N>
        where N: Numeric
            , N: Copy {

            #[inline] fn from(a: &'a mut [[N; $c]; $r]) -> &'a mut $m<N> {
                unsafe { transmute(a) }
            }
        }
    )+}
}

macro_rules! impl_index {
    ($($m: ident, $c: expr),+) => { $(
        impl<N> ops::Index<(usize, usize)> for $m<N>
        where N: Copy {

            type Output = N;
            #[inline] fn index(&self, (x, y): (usize, usize)) -> &N {
                unsafe {
                    &transmute::<&$m<N>, &[N; $c * $c]>(self)[x + y * $c]
                }
            }
        }

        impl<N> ops::IndexMut<(usize, usize)> for $m<N>
        where N: Copy {

            #[inline] fn index_mut(&mut self, (x, y): (usize, usize))
                                  -> &mut N {
                unsafe {
                    &mut transmute::<&mut $m<N>, &mut [N; $c * $c]>(self)
                        [x + y * $c]
                }
            }
        }

    )+}
}
<commit_msg>[matrix] fix broken docs in `make_matrix`<commit_after>macro_rules! e { ($e:expr) => { $e } }

/// Macro for constructing a new matrix type.
///
/// This can be used to construct fixed-sized matrices of whatever dimension
/// the user would like. While this crate only provides matrices of dimensons
/// 2 through 5, it's trivial to make matrices of arbitrary length using this
/// macro.
///
/// Another potential use of this macro is to create new matrices whose
/// subscripts have different names than those provided in this crate. The
/// matrices in `lin`  have subscripts where the rows are named _x_`n` and the
/// columns _y_`n` (as in Cartesian coördinates), but in some use cases, they
/// might represent different quantities. Thus, users can use this macro to
/// create new matrix types whose subscripts have names with semantic meanings
/// more appropriate to their individual use case.
///
/// # Arguments
///    - `$name`: The name of the new matrix type
///    - `$rows`: The number of rows in this matrix
///    - `$cols`: The number of columns in this matrix
///    - `$sub`: The name of each subscript or element of the matrix
///              Note that the number of `$sub`s should be equal to `$cols` *
///              `$rows`.
///
#[macro_export]
macro_rules! make_matrix {
    ($name: ident, rows: $rows:expr, cols: $cols:expr, $($sub: ident),+) => {
        #[cfg(not(simd))]
        #[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Debug, Default)]
        #[repr(C)]
        pub struct $name<N> {
            $(pub $sub: N),+
        }
        impl_matrix! { $name, $rows, $cols }
        impl_converts! { $name, $cols, $rows }
        impl_index! { $name, $cols}

    }
}

#[cfg(features = "unstable")]
macro_rules! impl_matrix {
    ($name: ident, $rows:expr, $cols:expr) => {
        impl<N> Matrix<N> for $name<N> {
            const fn nrows(&self) -> usize { $rows }
            const fn ncols(&self) -> usize { $cols }
        }
    }
}

#[cfg(not(features = "unstable"))]
macro_rules! impl_matrix {
    ($name: ident, $rows:expr, $cols:expr) => {
        impl<N> Matrix<N> for $name<N> {
            #[inline] fn nrows(&self) -> usize { $rows }
            #[inline] fn ncols(&self) -> usize { $cols }
        }
    }
}

macro_rules! impl_converts {
    ($($m: ident, $c: expr, $r: expr),+) => { $(
        impl<N> convert::AsRef<[[N; $c]; $r]> for $m<N>
        where N: Copy {

            #[inline] fn as_ref(&self) -> &[[N; $c]; $r] {
                unsafe { transmute(self) }
            }
        }
        impl<N> convert::AsMut<[[N; $c]; $c]> for $m<N>
        where N: Copy {

            #[inline] fn as_mut(&mut self) -> &mut [[N; $c]; $c] {
                unsafe { transmute(self) }
            }
        }
        impl<'a, N> convert::From<&'a [[N; $c]; $r]> for &'a $m<N>
        where N: Numeric
            , N: Copy {

            #[inline] fn from(a: &'a [[N; $c]; $r]) -> &'a $m<N> {
                unsafe { transmute(a) }
            }
        }
        impl<'a, N> convert::From<&'a mut [[N; $c]; $r]> for &'a mut $m<N>
        where N: Numeric
            , N: Copy {

            #[inline] fn from(a: &'a mut [[N; $c]; $r]) -> &'a mut $m<N> {
                unsafe { transmute(a) }
            }
        }
    )+}
}

macro_rules! impl_index {
    ($($m: ident, $c: expr),+) => { $(
        impl<N> ops::Index<(usize, usize)> for $m<N>
        where N: Copy {

            type Output = N;
            #[inline] fn index(&self, (x, y): (usize, usize)) -> &N {
                unsafe {
                    &transmute::<&$m<N>, &[N; $c * $c]>(self)[x + y * $c]
                }
            }
        }

        impl<N> ops::IndexMut<(usize, usize)> for $m<N>
        where N: Copy {

            #[inline] fn index_mut(&mut self, (x, y): (usize, usize))
                                  -> &mut N {
                unsafe {
                    &mut transmute::<&mut $m<N>, &mut [N; $c * $c]>(self)
                        [x + y * $c]
                }
            }
        }

    )+}
}
<|endoftext|>