<commit_before>//! Bounds are restrictions applied to some types after they've been converted into the
//! `ty` form from the HIR.

use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_span::Span;

/// Collects together a list of type bounds. These lists of bounds occur in many places
/// in Rust's syntax:
///
/// ```text
/// trait Foo: Bar + Baz { }
///            ^^^^^^^^^ supertrait list bounding the `Self` type parameter
///
/// fn foo<T: Bar + Baz>() { }
///           ^^^^^^^^^ bounding the type parameter `T`
///
/// impl dyn Bar + Baz
///          ^^^^^^^^^ bounding the forgotten dynamic type
/// ```
///
/// Our representation is a bit mixed here -- in some cases, we
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
    /// A list of region bounds on the (implicit) self type. So if you
    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
    /// the `T` is not explicitly included).
    pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>,

    /// A list of trait bounds. So if you had `T: Debug` this would be
    /// `T: Debug`. Note that the self-type is explicit here.
    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>,

    /// A list of projection equality bounds. So if you had `T:
    /// Iterator<Item = u32>` this would include `<T as
    /// Iterator>::Item => u32`. Note that the self-type is explicit
    /// here.
    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,

    /// `Some` if there is *no* `?Sized` predicate. The `span`
    /// is the location in the source of the `T` declaration which can
    /// be cited as the source of the `T: Sized` requirement.
    pub implicitly_sized: Option<Span>,
}

impl<'tcx> Bounds<'tcx> {
    /// Converts a bounds list into a flat set of predicates (like
    /// where-clauses). Because some of our bounds listings (e.g.,
    /// regions) don't include the self-type, you must supply the
    /// self-type here (the `param_ty` parameter).
    pub fn predicates(
        &self,
        tcx: TyCtxt<'tcx>,
        param_ty: Ty<'tcx>,
    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
        // If it could be sized, and is, add the `Sized` predicate.
        let sized_predicate = self.implicitly_sized.and_then(|span| {
            tcx.lang_items().sized_trait().map(|sized| {
                let trait_ref = ty::Binder::dummy(ty::TraitRef {
                    def_id: sized,
                    substs: tcx.mk_substs_trait(param_ty, &[]),
                });
                (trait_ref.without_const().to_predicate(tcx), span)
            })
        });

        sized_predicate
            .into_iter()
            .chain(self.region_bounds.iter().map(|&(region_bound, span)| {
                (
                    region_bound
                        .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
                        .to_predicate(tcx),
                    span,
                )
            }))
            .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
                let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
                (predicate, span)
            }))
            .chain(
                self.projection_bounds
                    .iter()
                    .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
            )
            .collect()
    }
}
<commit_msg>move implicit `Sized` predicate to end of list<commit_after>//! Bounds are restrictions applied to some types after they've been converted into the
//! `ty` form from the HIR.

use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness};
use rustc_span::Span;

/// Collects together a list of type bounds. These lists of bounds occur in many places
/// in Rust's syntax:
///
/// ```text
/// trait Foo: Bar + Baz { }
///            ^^^^^^^^^ supertrait list bounding the `Self` type parameter
///
/// fn foo<T: Bar + Baz>() { }
///           ^^^^^^^^^ bounding the type parameter `T`
///
/// impl dyn Bar + Baz
///          ^^^^^^^^^ bounding the forgotten dynamic type
/// ```
///
/// Our representation is a bit mixed here -- in some cases, we
/// include the self type (e.g., `trait_bounds`) but in others we do not
#[derive(Default, PartialEq, Eq, Clone, Debug)]
pub struct Bounds<'tcx> {
    /// A list of region bounds on the (implicit) self type. So if you
    /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but
    /// the `T` is not explicitly included).
    pub region_bounds: Vec<(ty::Binder<'tcx, ty::Region<'tcx>>, Span)>,

    /// A list of trait bounds. So if you had `T: Debug` this would be
    /// `T: Debug`. Note that the self-type is explicit here.
    pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span, ty::BoundConstness)>,

    /// A list of projection equality bounds. So if you had `T:
    /// Iterator<Item = u32>` this would include `<T as
    /// Iterator>::Item => u32`. Note that the self-type is explicit
    /// here.
    pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,

    /// `Some` if there is *no* `?Sized` predicate. The `span`
    /// is the location in the source of the `T` declaration which can
    /// be cited as the source of the `T: Sized` requirement.
    pub implicitly_sized: Option<Span>,
}

impl<'tcx> Bounds<'tcx> {
    /// Converts a bounds list into a flat set of predicates (like
    /// where-clauses). Because some of our bounds listings (e.g.,
    /// regions) don't include the self-type, you must supply the
    /// self-type here (the `param_ty` parameter).
    pub fn predicates(
        &self,
        tcx: TyCtxt<'tcx>,
        param_ty: Ty<'tcx>,
    ) -> Vec<(ty::Predicate<'tcx>, Span)> {
        // If it could be sized, and is, add the `Sized` predicate.
        let sized_predicate = self.implicitly_sized.and_then(|span| {
            tcx.lang_items().sized_trait().map(|sized| {
                let trait_ref = ty::Binder::dummy(ty::TraitRef {
                    def_id: sized,
                    substs: tcx.mk_substs_trait(param_ty, &[]),
                });
                (trait_ref.without_const().to_predicate(tcx), span)
            })
        });

        self.region_bounds
            .iter()
            .map(|&(region_bound, span)| {
                (
                    region_bound
                        .map_bound(|region_bound| ty::OutlivesPredicate(param_ty, region_bound))
                        .to_predicate(tcx),
                    span,
                )
            })
            .chain(self.trait_bounds.iter().map(|&(bound_trait_ref, span, constness)| {
                let predicate = bound_trait_ref.with_constness(constness).to_predicate(tcx);
                (predicate, span)
            }))
            .chain(
                self.projection_bounds
                    .iter()
                    .map(|&(projection, span)| (projection.to_predicate(tcx), span)),
            )
            .chain(sized_predicate.into_iter())
            .collect()
    }
}
<|endoftext|>


<commit_before>use crate::convert::*;
use crate::operations::*;
#[cfg(feature = "specialize")]
use crate::HasherExt;
use core::hash::Hasher;

/// 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 {
    enc: u128,
    sum: u128,
    key: u128,
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    ///
    /// Normally hashers are created via `AHasher::default()` for fixed keys or `RandomState::new()` for randomly
    /// generated keys and `RandomState::with_seeds(a,b)` for seeds that are set and can be reused. All of these work at
    /// map creation time (and hence don't have any overhead on a per-item bais).
    ///
    /// This method directly creates the hasher instance and performs no transformation on the provided seeds. This may
    /// be useful where a HashBuilder is not desired, such as for testing purposes.
    ///
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(1234, 5678);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key1: u128, key2: u128) -> Self {
        Self {
            enc: key1,
            sum: key2,
            key: key1 ^ key2,
        }
    }

    #[doc(hidden)]
    pub fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::random_state::scramble_keys;
        let (k1, k2, k3, k4) = scramble_keys(key1, key2);
        AHasher {
            enc: [k1, k2].convert(),
            sum: [k3, k4].convert(),
            key: add_by_64s([k1, k2], [k3, k4]).convert(),
        }
    }

    #[inline(always)]
    fn add_in_length(&mut self, length: u64) {
        //This will be scrambled by the next AES round.
        let mut enc: [u64; 2] = self.enc.convert();
        enc[0] = enc[0].wrapping_add(length);
        self.enc = enc.convert();
    }

    #[inline(always)]
    fn hash_in(&mut self, new_value: u128) {
        self.enc = aesenc(self.enc, new_value);
        self.sum = shuffle_and_add(self.sum, new_value);
    }

    #[inline(always)]
    fn hash_in_2(&mut self, v1: u128, v2: u128) {
        self.enc = aesenc(self.enc, v1);
        self.sum = shuffle_and_add(self.sum, v1);
        self.enc = aesenc(self.enc, v2);
        self.sum = shuffle_and_add(self.sum, v2);
    }
}

#[cfg(feature = "specialize")]
impl HasherExt for AHasher {
    #[inline]
    fn hash_u64(self, value: u64) -> u64 {
        let mask = self.sum as u64;
        let rot = (self.enc & 64) as u32;
        (value ^ mask)
            .folded_multiply(crate::random_state::MULTIPLE)
            .rotate_left(rot)
    }

    #[inline]
    fn short_finish(&self) -> u64 {
        let buffer: [u64; 2] = self.enc.convert();
        buffer[0].folded_multiply(buffer[1])
    }
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {
    #[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_u128(&mut self, i: u128) {
        self.hash_in(i);
    }

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

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

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len();
        self.add_in_length(length as u64);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() < 8 {
            let value: [u64; 2] = if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    [data.read_u32().0 as u64, data.read_last_u32() as u64]
                } else {
                    //len 2-3
                    [data.read_u16().0 as u64, data[data.len() - 1] as u64]
                }
            } else {
                if data.len() > 0 {
                    [data[0] as u64, 0]
                } else {
                    [0, 0]
                }
            };
            self.hash_in(value.convert());
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let tail = data.read_last_u128x4();
                    let mut current: [u128; 4] = [self.key; 4];
                    current[0] = aesenc(current[0], tail[0]);
                    current[1] = aesenc(current[1], tail[1]);
                    current[2] = aesenc(current[2], tail[2]);
                    current[3] = aesenc(current[3], tail[3]);
                    let mut sum: [u128; 2] = [self.key, self.key];
                    sum[0] = add_by_64s(sum[0].convert(), tail[0].convert()).convert();
                    sum[1] = add_by_64s(sum[1].convert(), tail[1].convert()).convert();
                    sum[0] = shuffle_and_add(sum[0], tail[2]);
                    sum[1] = shuffle_and_add(sum[1], tail[3]);
                    while data.len() > 64 {
                        let (blocks, rest) = data.read_u128x4();
                        current[0] = aesenc(current[0], blocks[0]);
                        current[1] = aesenc(current[1], blocks[1]);
                        current[2] = aesenc(current[2], blocks[2]);
                        current[3] = aesenc(current[3], blocks[3]);
                        sum[0] = shuffle_and_add(sum[0], blocks[0]);
                        sum[1] = shuffle_and_add(sum[1], blocks[1]);
                        sum[0] = shuffle_and_add(sum[0], blocks[2]);
                        sum[1] = shuffle_and_add(sum[1], blocks[3]);
                        data = rest;
                    }
                    current[0] = aesenc(current[0], current[1]);
                    current[2] = aesenc(current[2], current[3]);
                    self.hash_in_2(current[0], current[2]);
                    self.hash_in(add_by_64s(sum[0].convert(), sum[1].convert()).convert());
                } else {
                    //len 33-64
                    let (head, _) = data.read_u128x2();
                    let tail = data.read_last_u128x2();
                    self.hash_in_2(head[0], head[1]);
                    self.hash_in_2(tail[0], tail[1]);
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.hash_in_2(data.read_u128().0, data.read_last_u128());
                } else {
                    //len 9-16
                    let value: [u64; 2] = [data.read_u64().0, data.read_last_u64()];
                    self.hash_in(value.convert());
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let combined = aesdec(self.sum, self.enc);
        let result: [u64; 2] = aesenc(aesenc(combined, self.key), combined).convert();
        result[0]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::convert::Convert;
    use crate::operations::aesenc;
    use crate::RandomState;
    use std::hash::{BuildHasher, Hasher};
    #[test]
    fn test_sanity() {
        let mut hasher = RandomState::with_seeds(192837465, 1234567890).build_hasher();
        hasher.write_u64(0);
        let h1 = hasher.finish();
        hasher.write(&[1, 0, 0, 0, 0, 0, 0, 0]);
        let h2 = hasher.finish();
        assert_ne!(h1, h2);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        use std::collections::HashMap;
        use std::hash::BuildHasherDefault;

        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        let a_enc: [u64; 2] = hasher_a.enc.convert();
        let a_sum: [u64; 2] = hasher_a.sum.convert();
        assert_ne!(0, a_enc[0]);
        assert_ne!(0, a_enc[1]);
        assert_ne!(0, a_sum[0]);
        assert_ne!(0, a_sum[1]);
        assert_ne!(a_enc[0], a_enc[1]);
        assert_ne!(a_sum[0], a_sum[1]);
        assert_ne!(a_enc[0], a_sum[0]);
        assert_ne!(a_enc[1], a_sum[1]);
        let hasher_b = AHasher::default();
        let b_enc: [u64; 2] = hasher_b.enc.convert();
        let b_sum: [u64; 2] = hasher_b.sum.convert();
        assert_eq!(a_enc[0], b_enc[0]);
        assert_eq!(a_enc[1], b_enc[1]);
        assert_eq!(a_sum[0], b_sum[0]);
        assert_eq!(a_sum[1], b_sum[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aesenc(value.convert(), result.convert()).convert();
        result = aesenc(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aesenc(value2.convert(), result2.convert()).convert();
        result2 = aesenc(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = 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>Avoid confusion with local variables.<commit_after>use crate::convert::*;
use crate::operations::*;
#[cfg(feature = "specialize")]
use crate::HasherExt;
use core::hash::Hasher;

/// 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 {
    enc: u128,
    sum: u128,
    key: u128,
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    ///
    /// Normally hashers are created via `AHasher::default()` for fixed keys or `RandomState::new()` for randomly
    /// generated keys and `RandomState::with_seeds(a,b)` for seeds that are set and can be reused. All of these work at
    /// map creation time (and hence don't have any overhead on a per-item bais).
    ///
    /// This method directly creates the hasher instance and performs no transformation on the provided seeds. This may
    /// be useful where a HashBuilder is not desired, such as for testing purposes.
    ///
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(1234, 5678);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key1: u128, key2: u128) -> Self {
        Self {
            enc: key1,
            sum: key2,
            key: key1 ^ key2,
        }
    }

    #[doc(hidden)]
    pub fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::random_state::scramble_keys;
        let (k1, k2, k3, k4) = scramble_keys(key1, key2);
        AHasher {
            enc: [k1, k2].convert(),
            sum: [k3, k4].convert(),
            key: add_by_64s([k1, k2], [k3, k4]).convert(),
        }
    }

    #[inline(always)]
    fn add_in_length(&mut self, length: u64) {
        //This will be scrambled by the next AES round.
        let mut enc: [u64; 2] = self.enc.convert();
        enc[0] = enc[0].wrapping_add(length);
        self.enc = enc.convert();
    }

    #[inline(always)]
    fn hash_in(&mut self, new_value: u128) {
        self.enc = aesenc(self.enc, new_value);
        self.sum = shuffle_and_add(self.sum, new_value);
    }

    #[inline(always)]
    fn hash_in_2(&mut self, v1: u128, v2: u128) {
        self.enc = aesenc(self.enc, v1);
        self.sum = shuffle_and_add(self.sum, v1);
        self.enc = aesenc(self.enc, v2);
        self.sum = shuffle_and_add(self.sum, v2);
    }
}

#[cfg(feature = "specialize")]
impl HasherExt for AHasher {
    #[inline]
    fn hash_u64(self, value: u64) -> u64 {
        let mask = self.sum as u64;
        let rot = (self.enc & 64) as u32;
        (value ^ mask)
            .folded_multiply(crate::random_state::MULTIPLE)
            .rotate_left(rot)
    }

    #[inline]
    fn short_finish(&self) -> u64 {
        let buffer: [u64; 2] = self.enc.convert();
        buffer[0].folded_multiply(buffer[1])
    }
}

/// Provides methods to hash all of the primitive types.
impl Hasher for AHasher {
    #[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_u128(&mut self, i: u128) {
        self.hash_in(i);
    }

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

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

    #[inline]
    #[allow(clippy::collapsible_if)]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len();
        self.add_in_length(length as u64);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() < 8 {
            let value: [u64; 2] = if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    [data.read_u32().0 as u64, data.read_last_u32() as u64]
                } else {
                    //len 2-3
                    [data.read_u16().0 as u64, data[data.len() - 1] as u64]
                }
            } else {
                if data.len() > 0 {
                    [data[0] as u64, 0]
                } else {
                    [0, 0]
                }
            };
            self.hash_in(value.convert());
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let tail = data.read_last_u128x4();
                    let mut current: [u128; 4] = [self.key; 4];
                    current[0] = aesenc(current[0], tail[0]);
                    current[1] = aesenc(current[1], tail[1]);
                    current[2] = aesenc(current[2], tail[2]);
                    current[3] = aesenc(current[3], tail[3]);
                    let mut sum: [u128; 2] = [self.key, self.key];
                    sum[0] = add_by_64s(sum[0].convert(), tail[0].convert()).convert();
                    sum[1] = add_by_64s(sum[1].convert(), tail[1].convert()).convert();
                    sum[0] = shuffle_and_add(sum[0], tail[2]);
                    sum[1] = shuffle_and_add(sum[1], tail[3]);
                    while data.len() > 64 {
                        let (blocks, rest) = data.read_u128x4();
                        current[0] = aesenc(current[0], blocks[0]);
                        current[1] = aesenc(current[1], blocks[1]);
                        current[2] = aesenc(current[2], blocks[2]);
                        current[3] = aesenc(current[3], blocks[3]);
                        sum[0] = shuffle_and_add(sum[0], blocks[0]);
                        sum[1] = shuffle_and_add(sum[1], blocks[1]);
                        sum[0] = shuffle_and_add(sum[0], blocks[2]);
                        sum[1] = shuffle_and_add(sum[1], blocks[3]);
                        data = rest;
                    }
                    self.hash_in_2(aesenc(current[0], current[1]), aesenc(current[2], current[3]));
                    self.hash_in(add_by_64s(sum[0].convert(), sum[1].convert()).convert());
                } else {
                    //len 33-64
                    let (head, _) = data.read_u128x2();
                    let tail = data.read_last_u128x2();
                    self.hash_in_2(head[0], head[1]);
                    self.hash_in_2(tail[0], tail[1]);
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.hash_in_2(data.read_u128().0, data.read_last_u128());
                } else {
                    //len 9-16
                    let value: [u64; 2] = [data.read_u64().0, data.read_last_u64()];
                    self.hash_in(value.convert());
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let combined = aesdec(self.sum, self.enc);
        let result: [u64; 2] = aesenc(aesenc(combined, self.key), combined).convert();
        result[0]
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::convert::Convert;
    use crate::operations::aesenc;
    use crate::RandomState;
    use std::hash::{BuildHasher, Hasher};
    #[test]
    fn test_sanity() {
        let mut hasher = RandomState::with_seeds(192837465, 1234567890).build_hasher();
        hasher.write_u64(0);
        let h1 = hasher.finish();
        hasher.write(&[1, 0, 0, 0, 0, 0, 0, 0]);
        let h2 = hasher.finish();
        assert_ne!(h1, h2);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        use std::collections::HashMap;
        use std::hash::BuildHasherDefault;

        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        let a_enc: [u64; 2] = hasher_a.enc.convert();
        let a_sum: [u64; 2] = hasher_a.sum.convert();
        assert_ne!(0, a_enc[0]);
        assert_ne!(0, a_enc[1]);
        assert_ne!(0, a_sum[0]);
        assert_ne!(0, a_sum[1]);
        assert_ne!(a_enc[0], a_enc[1]);
        assert_ne!(a_sum[0], a_sum[1]);
        assert_ne!(a_enc[0], a_sum[0]);
        assert_ne!(a_enc[1], a_sum[1]);
        let hasher_b = AHasher::default();
        let b_enc: [u64; 2] = hasher_b.enc.convert();
        let b_sum: [u64; 2] = hasher_b.sum.convert();
        assert_eq!(a_enc[0], b_enc[0]);
        assert_eq!(a_enc[1], b_enc[1]);
        assert_eq!(a_sum[0], b_sum[0]);
        assert_eq!(a_sum[1], b_sum[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aesenc(value.convert(), result.convert()).convert();
        result = aesenc(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aesenc(value2.convert(), result2.convert()).convert();
        result2 = aesenc(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = 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>use crate::convert::*;
use crate::folded_multiply::*;
use core::hash::Hasher;

/// 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; 2],
    sum: [u64; 2],
    key: u128,
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> Self {
        Self {
            buffer: [key0, key1],
            sum: [key1, key0],
            key: [key0, key1].convert(),
        }
    }

    #[cfg(test)]
    pub(crate) fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::random_state::scramble_keys;
        let (k1, k2) = scramble_keys(key1, key2);
        AHasher {
            buffer: [k1, k2],
            sum: [k2, k1],
            key: [k1, k2].convert(),
        }
    }

    #[inline(always)]
    fn hash_in(&mut self, new_value: u128) {
        self.buffer = aeshash(self.buffer.convert(), new_value).convert();
        self.sum = add_by_64s(self.sum.convert(), self.buffer.convert()).convert();
    }

    #[inline(always)]
    fn hash_in_2(&mut self, v1: u128, v2: u128) {
        self.hash_in(v1);
        self.hash_in(v2);
    }
}

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

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

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

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

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

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

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //This will be scrambled by the first AES round in any branch.
        self.buffer[1] = self.buffer[1].wrapping_add(length);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() <= 8 {
            let value: [u64; 2] = if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    [data.read_u32().0 as u64, data.read_last_u32() as u64]
                } else {
                    //len 2-3
                    [data.read_u16().0 as u64, data[data.len() - 1] as u64]
                }
            } else {
                if data.len() > 0 {
                    [data[0] as u64, 0]
                } else {
                    [0, 0]
                }
            };
            self.hash_in(value.convert());
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let tail = data.read_last_u128x4();
                    let mut current: [u128; 2] = [self.buffer.convert(), self.key];
                    let mut sum: [u128; 2] = [0, 0];
                    current[0] = aeshash(current[0], tail[0]);
                    current[1] = aeshash(current[1], tail[1]);
                    sum[0] = add_by_64s(sum[0], current[0]);
                    sum[1] = add_by_64s(sum[1], current[1]);
                    current[0] = aeshash(current[0], tail[2]);
                    current[1] = aeshash(current[1], tail[3]);
                    sum[0] = add_by_64s(sum[0], current[0]);
                    sum[1] = add_by_64s(sum[1], current[1]);
                    while data.len() > 64 {
                        let (blocks, rest) = data.read_u128x4();
                        current[0] = aeshash(current[0], blocks[0]);
                        current[1] = aeshash(current[1], blocks[1]);
                        sum[0] = add_by_64s(sum[0], current[0]);
                        sum[1] = add_by_64s(sum[1], current[1]);
                        current[0] = aeshash(current[0], blocks[2]);
                        current[1] = aeshash(current[1], blocks[3]);
                        sum[0] = add_by_64s(sum[0], current[0]);
                        sum[1] = add_by_64s(sum[1], current[1]);
                        data = rest;
                    }
                    self.buffer = current[0].convert();
                    self.hash_in(current[1]);
                    self.sum = add_by_64s(self.sum.convert(), sum[0]).convert();
                    self.sum = add_by_64s(self.sum.convert(), sum[1]).convert();
                } else {
                    //len 33-64
                    let (head, _) = data.read_u128x2();
                    let tail = data.read_last_u128x2();
                    self.hash_in_2(head[0], head[1]);
                    self.hash_in_2(tail[0], tail[1]);
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.hash_in_2(data.read_u128().0, data.read_last_u128());
                } else {
                    //len 9-16
                    let value: [u64; 2] = [data.read_u64().0, data.read_last_u64()];
                    self.hash_in(value.convert());
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = aeshashx2(self.sum.convert(), self.key, self.buffer.convert()).convert();
        result[0] //.wrapping_add(result[1])
    }
}

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[inline(always)]
fn aeshash(value: u128, xor: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesdec_si128(value, transmute(xor)))
    }
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[inline(always)]
fn aeshashx2(value: u128, k1: u128, k2: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        let value = _mm_aesdec_si128(value, transmute(k1));
        transmute(_mm_aesdec_si128(value, transmute(k2)))
    }
}

#[cfg(test)]
mod tests {
    use crate::aes_hash::*;
    use crate::convert::Convert;
    use std::collections::HashMap;
    use std::hash::BuildHasherDefault;

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer[0]);
        assert_ne!(0, hasher_a.buffer[1]);
        assert_ne!(hasher_a.buffer[0], hasher_a.buffer[1]);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer[0], hasher_b.buffer[0]);
        assert_eq!(hasher_a.buffer[1], hasher_b.buffer[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aeshash(value.convert(), result.convert()).convert();
        result = aeshash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aeshash(value2.convert(), result2.convert()).convert();
        result2 = aeshash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = 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 full state in output.<commit_after>use crate::convert::*;
use crate::folded_multiply::*;
use core::hash::Hasher;

/// 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; 2],
    sum: [u64; 2],
    key: u128,
}

impl AHasher {
    /// Creates a new hasher keyed to the provided keys.
    /// # Example
    ///
    /// ```
    /// use std::hash::Hasher;
    /// use ahash::AHasher;
    ///
    /// let mut hasher = AHasher::new_with_keys(123, 456);
    ///
    /// hasher.write_u32(1989);
    /// hasher.write_u8(11);
    /// hasher.write_u8(9);
    /// hasher.write(b"Huh?");
    ///
    /// println!("Hash is {:x}!", hasher.finish());
    /// ```
    #[inline]
    pub fn new_with_keys(key0: u64, key1: u64) -> Self {
        Self {
            buffer: [key0, key1],
            sum: [key1, key0],
            key: [key0, key1].convert(),
        }
    }

    #[cfg(test)]
    pub(crate) fn test_with_keys(key1: u64, key2: u64) -> AHasher {
        use crate::random_state::scramble_keys;
        let (k1, k2) = scramble_keys(key1, key2);
        AHasher {
            buffer: [k1, k2],
            sum: [k2, k1],
            key: [k1, k2].convert(),
        }
    }

    #[inline(always)]
    fn hash_in(&mut self, new_value: u128) {
        self.buffer = aeshash(self.buffer.convert(), new_value).convert();
        self.sum = add_by_64s(self.sum.convert(), self.buffer.convert()).convert();
    }

    #[inline(always)]
    fn hash_in_2(&mut self, v1: u128, v2: u128) {
        self.hash_in(v1);
        self.hash_in(v2);
    }
}

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

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

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

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

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

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

    #[inline]
    fn write(&mut self, input: &[u8]) {
        let mut data = input;
        let length = data.len() as u64;
        //This will be scrambled by the first AES round in any branch.
        self.buffer[1] = self.buffer[1].wrapping_add(length);
        //A 'binary search' on sizes reduces the number of comparisons.
        if data.len() <= 8 {
            let value: [u64; 2] = if data.len() >= 2 {
                if data.len() >= 4 {
                    //len 4-8
                    [data.read_u32().0 as u64, data.read_last_u32() as u64]
                } else {
                    //len 2-3
                    [data.read_u16().0 as u64, data[data.len() - 1] as u64]
                }
            } else {
                if data.len() > 0 {
                    [data[0] as u64, 0]
                } else {
                    [0, 0]
                }
            };
            self.hash_in(value.convert());
        } else {
            if data.len() > 32 {
                if data.len() > 64 {
                    let tail = data.read_last_u128x4();
                    let mut current: [u128; 2] = [self.buffer.convert(), self.key];
                    let mut sum: [u128; 2] = [0, 0];
                    current[0] = aeshash(current[0], tail[0]);
                    current[1] = aeshash(current[1], tail[1]);
                    sum[0] = add_by_64s(sum[0], current[0]);
                    sum[1] = add_by_64s(sum[1], current[1]);
                    current[0] = aeshash(current[0], tail[2]);
                    current[1] = aeshash(current[1], tail[3]);
                    sum[0] = add_by_64s(sum[0], current[0]);
                    sum[1] = add_by_64s(sum[1], current[1]);
                    while data.len() > 64 {
                        let (blocks, rest) = data.read_u128x4();
                        current[0] = aeshash(current[0], blocks[0]);
                        current[1] = aeshash(current[1], blocks[1]);
                        sum[0] = add_by_64s(sum[0], current[0]);
                        sum[1] = add_by_64s(sum[1], current[1]);
                        current[0] = aeshash(current[0], blocks[2]);
                        current[1] = aeshash(current[1], blocks[3]);
                        sum[0] = add_by_64s(sum[0], current[0]);
                        sum[1] = add_by_64s(sum[1], current[1]);
                        data = rest;
                    }
                    self.buffer = current[0].convert();
                    self.hash_in(current[1]);
                    self.sum = add_by_64s(self.sum.convert(), sum[0]).convert();
                    self.sum = add_by_64s(self.sum.convert(), sum[1]).convert();
                } else {
                    //len 33-64
                    let (head, _) = data.read_u128x2();
                    let tail = data.read_last_u128x2();
                    self.hash_in_2(head[0], head[1]);
                    self.hash_in_2(tail[0], tail[1]);
                }
            } else {
                if data.len() > 16 {
                    //len 17-32
                    self.hash_in_2(data.read_u128().0, data.read_last_u128());
                } else {
                    //len 9-16
                    let value: [u64; 2] = [data.read_u64().0, data.read_last_u64()];
                    self.hash_in(value.convert());
                }
            }
        }
    }
    #[inline]
    fn finish(&self) -> u64 {
        let result: [u64; 2] = aeshashx2(self.sum.convert(), self.key, self.buffer.convert()).convert();
        result[0].wrapping_add(result[1])
    }
}

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[inline(always)]
fn aeshash(value: u128, xor: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        transmute(_mm_aesdec_si128(value, transmute(xor)))
    }
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes", not(miri)))]
#[inline(always)]
fn aeshashx2(value: u128, k1: u128, k2: u128) -> u128 {
    #[cfg(target_arch = "x86")]
    use core::arch::x86::*;
    #[cfg(target_arch = "x86_64")]
    use core::arch::x86_64::*;
    use core::mem::transmute;
    unsafe {
        let value = transmute(value);
        let value = _mm_aesdec_si128(value, transmute(k1));
        transmute(_mm_aesdec_si128(value, transmute(k2)))
    }
}

#[cfg(test)]
mod tests {
    use crate::aes_hash::*;
    use crate::convert::Convert;
    use std::collections::HashMap;
    use std::hash::BuildHasherDefault;

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_builder() {
        let mut map = HashMap::<u32, u64, BuildHasherDefault<AHasher>>::default();
        map.insert(1, 3);
    }

    #[cfg(feature = "compile-time-rng")]
    #[test]
    fn test_default() {
        let hasher_a = AHasher::default();
        assert_ne!(0, hasher_a.buffer[0]);
        assert_ne!(0, hasher_a.buffer[1]);
        assert_ne!(hasher_a.buffer[0], hasher_a.buffer[1]);
        let hasher_b = AHasher::default();
        assert_eq!(hasher_a.buffer[0], hasher_b.buffer[0]);
        assert_eq!(hasher_a.buffer[1], hasher_b.buffer[1]);
    }

    #[test]
    fn test_hash() {
        let mut result: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value: [u64; 2] = [1 << 32, 0xFEDCBA9876543210];
        result = aeshash(value.convert(), result.convert()).convert();
        result = aeshash(result.convert(), result.convert()).convert();
        let mut result2: [u64; 2] = [0x6c62272e07bb0142, 0x62b821756295c58d];
        let value2: [u64; 2] = [1, 0xFEDCBA9876543210];
        result2 = aeshash(value2.convert(), result2.convert()).convert();
        result2 = aeshash(result2.convert(), result.convert()).convert();
        let result: [u8; 16] = result.convert();
        let result2: [u8; 16] = 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>use hyper::server::Request;

use common::*;

pub fn announce(req: &Request) -> Result<Vec<u8>, String>
{
    let query_hashmap = query_hashmap(&req.uri);

    // Check we have everything we need
    let info_hash = match query_hashmap.get("info_hash")
        .ok_or_else(|| "No info_hash specified".to_owned())
        .and_then(|i| parse_info_hash(i)) {
            Ok(j) => j,
            Err(j) => return Err(j),
    };
    let port = match query_hashmap.get("port")
        .ok_or_else(|| "No port specified".to_owned())
        .and_then(|i| i.parse::<u16>().map_err(|_| "Invalid port specified".to_owned())) {
            Ok(i) => i,
            Err(j) => return Err(j),
    };

    return Ok("worked".to_owned().into_bytes());
}
<commit_msg>Bare minimum of announce parameters retrieved<commit_after>use hyper::server::Request;

use common::*;

pub fn announce(req: &Request) -> Result<Vec<u8>, String>
{
    let query_hashmap = query_hashmap(&req.uri);

    // Check we have everything we need
    let info_hash = match query_hashmap.get("info_hash")
        .ok_or_else(|| "No info_hash specified".to_owned())
        .and_then(|i| parse_info_hash(i)) {
            Ok(j) => j,
            Err(j) => return Err(j),
    };
    let peer_id = match query_hashmap.get("peer_id")
        .ok_or_else(|| "No peer_id specified".to_owned())
        .and_then(|i| parse_peer_id(i)) {
            Ok(j) => j,
            Err(j) => return Err(j),
    };
    let port = match query_hashmap.get("port")
        .ok_or_else(|| "No port specified".to_owned())
        .and_then(|i| i.parse::<u16>().map_err(|_| "Invalid port specified".to_owned())) {
            Ok(i) => i,
            Err(j) => return Err(j),
    };
    let left = match query_hashmap.get("left")
        .ok_or_else(|| "No left specified".to_owned())
        .and_then(|i| i.parse::<u64>().map_err(|_| "Invalid left specified".to_owned())) {
            Ok(i) => i,
            Err(j) => return Err(j),
    };
    let compact = match query_hashmap.get("compact")
        .ok_or_else(|| "No compact specified".to_owned())
        .and_then(|i| i.parse::<u64>().map_err(|_| "Invalid left specified".to_owned())) {
            Ok(i) => i,
            Err(j) => return Err(j),
    };
    let ip = req.remote_addr.ip();

    return Ok("worked".to_owned().into_bytes());
}
<|endoftext|>


<commit_before>/*
 * Built-in method definitions for scheme
 *
 * Done:
 * +, -, *, / (works on lists of numbers)
 * =, >, <, >=, <= (works on list of numbers)
 * not (works on single argument)
 * list (works on any arguments)
 * list?, null?, symbol? (works on single argument)
 * cons, car, cdr, append
 * equal?
 *
 * Coming:
 * eq?
 *
 *    {'+':op.add, '-':op.sub, '*':op.mul, '/':op.div, 'not':op.not_,
       '>':op.gt, '<':op.lt, '>=':op.ge, '<=':op.le, '=':op.eq,
       'equal?':op.eq, 'eq?':op.is_, 'length':len, 'cons':lambda x,y:[x]+y,
       'car':lambda x:x[0],'cdr':lambda x:x[1:], 'append':op.add,
       'list':lambda *x:list(x), 'list?': lambda x:isa(x,list),
       'null?':lambda x:x==[], 'symbol?':lambda x: isa(x, Symbol)})
 *
 */

macro_rules! math_function {
    ($function:ident $identity:expr) => {
        pub fn $function( args:~[Expression], _:@Environment) -> Expression {
            match args {
                [] => $identity,
                [head] => vec::foldl($identity, ~[head], |x, y| {x.$function(y)}),
                [head, ..tail] => vec::foldl(head, tail, |x, y| {x.$function(y)})
            }
        }
    }
}

math_function!(add Int(0))
math_function!(sub Int(0))
math_function!(mul Int(1))
math_function!(div Int(1))

pub fn equals( args:~[Expression], _:@Environment) -> Expression {
    for args.tail().each() |&expr| {
        if expr != args.head() {
            return Bool(false);
        }
    }
    return Bool(true);
}

pub fn assert_number_of_args( function:~str, min:uint, max:uint, args:~[Expression] ) {
    if args.len() > max || args.len() < min {
        if max == min {
            fail fmt!("Built-in function '%s' takes only %u argument%s. It was called with %u '%s'", function, max, if max==1 {~""} else {~"s"}, args.len(), List(args).to_str());
        } else {
            fail fmt!("Built-in function '%s' takes between %u and %u arguments. It was called with %u '%s'", function, min, max, args.len(), List(args).to_str());
        }
    }
}

pub fn not( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"not", 1, 1, copy args );

    return Bool(!args[0].to_bool());
}

pub fn car( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"car", 1, 1, copy args );

    match copy args[0] {
        List(list) => list.head(),
        _ => fail fmt!("Built-in function 'car' requires a list argument. It was called with %s", args[0].to_str())
    }
}

pub fn cdr( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"cdr", 1, 1, copy args );

    match copy args[0] {
        List(list) => List(list.tail()),
        _ => fail fmt!("Built-in function 'cdr' requires a list argument. It was called with %s", args[0].to_str())
    }
}

pub fn cons( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"cons", 2, 2, copy args );

    match copy args[1] {
        List(list) => List( ~[args[0]] + list ),
        x => List( ~[args[0]] + ~[x] )
    }
}

pub fn append( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"append", 2, 2, copy args );

    match copy args[0] {
        List(list1) => {
            match copy args[1] {
                List(list) => List( list1 + list ),
                x => List( list1 + ~[x] )
            }
        }
        _ => fail fmt!("Built-in function 'append' requires a list as the first arguments. It was called with %s", List(args).to_str())
    }
}

pub fn length( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"length", 1, 1, copy args );

    match copy args[0] {
        List(list) => Int(list.len() as int),
        _ => fail fmt!("Built-in function 'append' requires a list argument. It was called with %s", List(args).to_str())
    }
}

pub fn equal_( args:~[Expression], _:@Environment ) -> Expression {
    assert_number_of_args( ~"equal?", 2, 2, copy args );

    Bool(args[0] == args[1])
}

pub fn symbol_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"symbol?", 1, 1, copy args );

    match args[0] {
        Symbol(_) => Bool(true),
        _ => Bool(false)
    }
}

pub fn list_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"list?", 1, 1, copy args );

    match args[0] {
        List(_) => Bool(true),
        _ => Bool(false)
    }
}

pub fn null_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"null?", 1, 1, copy args );

    match copy args[0] {
        List(list) => Bool(list.len() == 0),
        _ => Bool(false)
    }
}

pub fn list( args:~[Expression], _:@Environment) -> Expression {
    List(args)
}

pub fn builtins() -> ~[(~str,~fn(~[Expression], @Environment) -> Expression)] {
    ~[ (~"+", add), (~"-", sub), (~"*", mul), (~"/", div),
       (~"=", equals), (~"not", not),
       (~"car", car), (~"cdr", cdr),
       (~"cons", cons), (~"append", append),
       (~"list", list), (~"length", length),
       (~"equal?", equal_),
       (~"symbol?", symbol_),
       (~"list?", list_),
       (~"null?", null_)
    ]
}
<commit_msg>Add eq? and eqv? (with tests)<commit_after>/*
 * Built-in method definitions for scheme
 *
 * Done:
 * +, -, *, / (works on lists of numbers)
 * =, >, <, >=, <= (works on list of numbers)
 * not (works on single argument)
 * list (works on any arguments)
 * list?, null?, symbol? (works on single argument)
 * cons, car, cdr, append
 * equal?
 *
 * Coming:
 * eq?
 *
 *    {'+':op.add, '-':op.sub, '*':op.mul, '/':op.div, 'not':op.not_,
       '>':op.gt, '<':op.lt, '>=':op.ge, '<=':op.le, '=':op.eq,
       'equal?':op.eq, 'eq?':op.is_, 'length':len, 'cons':lambda x,y:[x]+y,
       'car':lambda x:x[0],'cdr':lambda x:x[1:], 'append':op.add,
       'list':lambda *x:list(x), 'list?': lambda x:isa(x,list),
       'null?':lambda x:x==[], 'symbol?':lambda x: isa(x, Symbol)})
 *
 */

macro_rules! math_function {
    ($function:ident $identity:expr) => {
        pub fn $function( args:~[Expression], _:@Environment) -> Expression {
            match args {
                [] => $identity,
                [head] => vec::foldl($identity, ~[head], |x, y| {x.$function(y)}),
                [head, ..tail] => vec::foldl(head, tail, |x, y| {x.$function(y)})
            }
        }
    }
}

math_function!(add Int(0))
math_function!(sub Int(0))
math_function!(mul Int(1))
math_function!(div Int(1))

pub fn equals( args:~[Expression], _:@Environment) -> Expression {
    for args.tail().each() |&expr| {
        if expr != args.head() {
            return Bool(false);
        }
    }
    return Bool(true);
}

pub fn assert_number_of_args( function:~str, min:uint, max:uint, args:~[Expression] ) {
    if args.len() > max || args.len() < min {
        if max == min {
            fail fmt!("Built-in function '%s' takes only %u argument%s. It was called with %u '%s'", function, max, if max==1 {~""} else {~"s"}, args.len(), List(args).to_str());
        } else {
            fail fmt!("Built-in function '%s' takes between %u and %u arguments. It was called with %u '%s'", function, min, max, args.len(), List(args).to_str());
        }
    }
}

pub fn not( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"not", 1, 1, copy args );

    return Bool(!args[0].to_bool());
}

pub fn car( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"car", 1, 1, copy args );

    match copy args[0] {
        List(list) => list.head(),
        _ => fail fmt!("Built-in function 'car' requires a list argument. It was called with %s", args[0].to_str())
    }
}

pub fn cdr( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"cdr", 1, 1, copy args );

    match copy args[0] {
        List(list) => List(list.tail()),
        _ => fail fmt!("Built-in function 'cdr' requires a list argument. It was called with %s", args[0].to_str())
    }
}

pub fn cons( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"cons", 2, 2, copy args );

    match copy args[1] {
        List(list) => List( ~[args[0]] + list ),
        x => List( ~[args[0]] + ~[x] )
    }
}

pub fn append( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"append", 2, 2, copy args );

    match copy args[0] {
        List(list1) => {
            match copy args[1] {
                List(list) => List( list1 + list ),
                x => List( list1 + ~[x] )
            }
        }
        _ => fail fmt!("Built-in function 'append' requires a list as the first arguments. It was called with %s", List(args).to_str())
    }
}

pub fn length( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"length", 1, 1, copy args );

    match copy args[0] {
        List(list) => Int(list.len() as int),
        _ => fail fmt!("Built-in function 'append' requires a list argument. It was called with %s", List(args).to_str())
    }
}

pub fn equal_( args:~[Expression], _:@Environment ) -> Expression {
    assert_number_of_args( ~"equal?", 2, 2, copy args );

    Bool(args[0] == args[1])
}

pub fn symbol_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"symbol?", 1, 1, copy args );

    match args[0] {
        Symbol(_) => Bool(true),
        _ => Bool(false)
    }
}

pub fn list_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"list?", 1, 1, copy args );

    match args[0] {
        List(_) => Bool(true),
        _ => Bool(false)
    }
}

pub fn null_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"null?", 1, 1, copy args );

    match copy args[0] {
        List(list) => Bool(list.len() == 0),
        _ => Bool(false)
    }
}

pub fn list( args:~[Expression], _:@Environment) -> Expression {
    List(args)
}

pub fn eq_( args:~[Expression], _:@Environment) -> Expression {
    assert_number_of_args( ~"eq?", 2, 2, copy args );

    Bool( args[0] == args[1] )
}

pub fn eqv_( args:~[Expression], _env:@Environment) -> Expression {
    assert_number_of_args( ~"eq?", 2, 2, copy args );

    eq_( args, _env )
}

#[test]
fn test_eqv_() {
    fn eqv__( args:~[Expression] ) -> Expression {
        eqv_( args, @Environment::new_global_environment() )
    }

    assert( Bool(true) == eqv__( ~[ Bool(true), Bool(true) ] ) );
    assert( Bool(true) == eqv__( ~[ Bool(false), Bool(false) ] ) );
    assert( Bool(false) == eqv__( ~[ Bool(true), Bool(false) ] ) );
    assert( Bool(true) == eqv__( ~[ Symbol(~"a"), Symbol(~"a") ] ) );
    assert( Bool(false) == eqv__( ~[ Symbol(~"b"), Symbol(~"a") ] ) );
    assert( Bool(true) == eqv__( ~[ Int(1), Int(1) ] ) );
    assert( Bool(false) == eqv__( ~[ Int(2), Int(1) ] ) );
    assert( Bool(true) == eqv__( ~[ Float(1.0), Float(1.0) ] ) );
    assert( Bool(false) == eqv__( ~[ Float(2.0), Float(1.0) ] ) );
    assert( Bool(true) == eqv__( ~[ List( ~[] ), List( ~[] ) ] ) );
    assert( Bool(false) == eqv__( ~[ List( ~[Int(1)] ), List( ~[] ) ] ) );

    let proc = eval( parse("(lambda (x) (* x x))"), @Environment::new_global_environment() ).first();
    let proc2 = eval( parse("(lambda (x) (* x x))"), @Environment::new_global_environment() ).first();
    assert( Bool(true) == eqv__( ~[ proc, proc ] ) );
    assert( Bool(false) == eqv__( ~[ proc, proc2 ] ) );
}

pub fn builtins() -> ~[(~str,~fn(~[Expression], @Environment) -> Expression)] {
    ~[ (~"+", add), (~"-", sub), (~"*", mul), (~"/", div),
       (~"=", equals), (~"not", not),
       (~"car", car), (~"cdr", cdr),
       (~"cons", cons), (~"append", append),
       (~"list", list), (~"length", length),
       (~"eq?", eq_), (~"eqv?", eqv_),
       (~"equal?", equal_),
       (~"symbol?", symbol_),
       (~"list?", list_),
       (~"null?", null_)
    ]
}
<|endoftext|>


<commit_before>extern crate columnar;
#[macro_use] extern crate columnar_derive;

#[derive(Columnar, Debug)]
struct Data {
    id: usize,
    val: f64,
}

#[derive(Columnar, Debug)]
struct DataGen<A: Copy> {
    id: A,
    val: f64,
}

fn main() {

    let mut u = <Data as Columnar>::Container::new();

    let ds = vec![Data { id: 0, val: 3.141 }, Data { id: 1, val: 42.}];
    u.extend(ds);

    for e in u.iter() {
        println!("Element: {:?}", e);
    }
    for mut e in u.iter_mut() {
        *e.val *= 2.;
    }
    for e in u.iter() {
        println!("Element: {:?}", e);
    }

    let mut g = DataGenColumnar::new();
    g.extend(vec![DataGen {id: "A", val: 1.}]);
    for e in g.iter() {
        println!("Element: {:?}", e);
    }
}
<commit_msg>Fix example/columnar<commit_after>extern crate columnar;
#[macro_use] extern crate columnar_derive;

use columnar::{Columnar, Container};

#[derive(Columnar, Debug)]
struct Data {
    id: usize,
    val: f64,
}

#[derive(Columnar, Debug)]
pub struct DataGen<A: Copy> {
    id: A,
    val: f64,
}

fn main() {

    let mut u = <Data as Columnar>::Container::new();

    let ds = vec![Data { id: 0, val: 3.141 }, Data { id: 1, val: 42.}];
    u.extend(ds);

    for e in u.iter() {
        println!("Element: {:?}", e);
    }
    for mut e in u.iter_mut() {
        *e.val *= 2.;
    }
    for e in u.iter() {
        println!("Element: {:?}", e);
    }

    let mut g = <DataGen<&str> as Columnar>::Container::new();
    g.extend(vec![DataGen {id: "A", val: 1.}]);
    for e in g.iter() {
        println!("Element: {:?}", e);
    }
}
<|endoftext|>


<commit_before>use std::io::Error as IoError;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::HashMap;

use libc::{c_int};
use libc::consts::os::posix88::{EINTR, ETIMEDOUT, EAGAIN};
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use time::Duration;

use super::signal;
use super::util::{get_time};
use self::Event::*;

const SIGCHLD: c_int = 17;

#[derive(Debug)]
pub enum Event<Name> {
    Signal(signal::Signal),
    Timeout(Name),
    Input(Name),
}

struct FileDesc(c_int);

struct Unordered<T>(T);

impl<T> PartialOrd for Unordered<T> {
    fn partial_cmp(&self, _: &Unordered<T>) -> Option<Ordering> {
        Some(Ordering::Equal)
    }
}
impl<T> Ord for Unordered<T> {
    fn cmp(&self, _: &Unordered<T>) -> Ordering {
        Ordering::Equal
    }
}
impl<T> PartialEq for Unordered<T> {
    fn eq(&self, _: &Unordered<T>) -> bool { false }
}
impl<T> Eq for Unordered<T> {}

pub struct Loop<Name> {
    queue: BinaryHeap<(i64, Unordered<Name>)>,
    epoll_fd: FileDesc,
    signal_fd: FileDesc,
    inputs: HashMap<c_int, Name>,
}

extern {
    fn create_epoll() -> c_int;
    fn create_signalfd() -> c_int;
    fn close(fd: c_int) -> c_int;
    fn epoll_add_read(efd: c_int, fd: c_int) -> c_int;
    fn epoll_wait_read(epfd: c_int, timeout: c_int) -> c_int;
    fn read_signal(rd: c_int) -> c_int;
}

impl<Name: Clone> Loop<Name> {
    pub fn new() -> Result<Loop<Name>, IoError> {
        let efd = unsafe { create_epoll() };
        if efd < 0 {
            return Err(IoError::last_os_error());
        }
        let epoll = FileDesc(efd);
        let sfd = unsafe { create_signalfd() };
        if sfd < 0 {
            return Err(IoError::last_os_error());
        }
        let sig = FileDesc(sfd);
        if unsafe { epoll_add_read(efd, sfd) } < 0 {
            return Err(IoError::last_os_error());
        }
        return Ok(Loop {
            queue: BinaryHeap::new(),
            epoll_fd: epoll,
            signal_fd: sig,
            inputs: HashMap::new(),
        });
    }
    pub fn add_timeout(&mut self, duration: Duration, name: Name) {
        self.queue.push((-(get_time()*1000.) as i64, Unordered(name)));
    }
    fn get_timeout(&mut self) -> c_int {
        self.queue.peek()
            .map(|&(ts, _)| (-ts) - (get_time()*1000.0) as i64)
            .map(|ts| if ts >= 0 { ts } else { 0 })
            .unwrap_or(-1)
            as i32
    }
    pub fn poll(&mut self) -> Event<Name> {
        loop {
            if let Some(sig) = signal::check_children() {
                return Signal(sig);
            }
            let timeo = self.get_timeout();
            let FileDesc(sfd) = self.signal_fd;
            let FileDesc(efd) = self.epoll_fd;
            let fd = unsafe { epoll_wait_read(efd, timeo) };
            if fd == -ETIMEDOUT { // Timeout
                debug!("Timeout");
                if self.get_timeout() != 0 {
                    continue;
                }
                let (_, Unordered(name)) = self.queue.pop().unwrap();
                return Timeout(name);
            } else if fd == -EINTR {
                continue
            } else if fd < 0 {
                panic!(format!("Error in epoll: {}", IoError::last_os_error()));
            } else if fd == sfd { // Signal
                debug!("Signal");
                let rc =  unsafe { read_signal(sfd) };
                if rc == -EINTR || rc == -EAGAIN {
                    continue;
                } else if rc <= 0 {
                    panic!(format!("Error in read_signal: {}",
                        IoError::last_os_error()));
                } else {
                    match rc {
                        sig@SIGTERM | sig@SIGINT | sig@SIGQUIT => {
                            return Signal(
                                signal::Signal::Terminate(sig));
                        }
                        SIGCHLD => {
                            continue;  // Will waitpid on next iteration
                        }
                        _ => {
                            warn!("Signal {} ignored", rc);
                            continue;
                        }
                    }
                }
            } else {
                debug!("Input {}", fd);
                return Input(self.inputs[&fd].clone());
            }
            unreachable!();
        }
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        let FileDesc(fd) = *self;
        unsafe { close(fd) };
    }
}
<commit_msg>Use duration argument in add_timeout (fixes #49)<commit_after>use std::io::Error as IoError;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::collections::HashMap;

use libc::{c_int};
use libc::consts::os::posix88::{EINTR, ETIMEDOUT, EAGAIN};
use libc::consts::os::posix88::{SIGTERM, SIGINT, SIGQUIT};
use time::Duration;

use super::signal;
use super::util::{get_time};
use self::Event::*;

const SIGCHLD: c_int = 17;

#[derive(Debug)]
pub enum Event<Name> {
    Signal(signal::Signal),
    Timeout(Name),
    Input(Name),
}

struct FileDesc(c_int);

struct Unordered<T>(T);

impl<T> PartialOrd for Unordered<T> {
    fn partial_cmp(&self, _: &Unordered<T>) -> Option<Ordering> {
        Some(Ordering::Equal)
    }
}
impl<T> Ord for Unordered<T> {
    fn cmp(&self, _: &Unordered<T>) -> Ordering {
        Ordering::Equal
    }
}
impl<T> PartialEq for Unordered<T> {
    fn eq(&self, _: &Unordered<T>) -> bool { false }
}
impl<T> Eq for Unordered<T> {}

pub struct Loop<Name> {
    queue: BinaryHeap<(i64, Unordered<Name>)>,
    epoll_fd: FileDesc,
    signal_fd: FileDesc,
    inputs: HashMap<c_int, Name>,
}

extern {
    fn create_epoll() -> c_int;
    fn create_signalfd() -> c_int;
    fn close(fd: c_int) -> c_int;
    fn epoll_add_read(efd: c_int, fd: c_int) -> c_int;
    fn epoll_wait_read(epfd: c_int, timeout: c_int) -> c_int;
    fn read_signal(rd: c_int) -> c_int;
}

impl<Name: Clone> Loop<Name> {
    pub fn new() -> Result<Loop<Name>, IoError> {
        let efd = unsafe { create_epoll() };
        if efd < 0 {
            return Err(IoError::last_os_error());
        }
        let epoll = FileDesc(efd);
        let sfd = unsafe { create_signalfd() };
        if sfd < 0 {
            return Err(IoError::last_os_error());
        }
        let sig = FileDesc(sfd);
        if unsafe { epoll_add_read(efd, sfd) } < 0 {
            return Err(IoError::last_os_error());
        }
        return Ok(Loop {
            queue: BinaryHeap::new(),
            epoll_fd: epoll,
            signal_fd: sig,
            inputs: HashMap::new(),
        });
    }
    pub fn add_timeout(&mut self, duration: Duration, name: Name) {
        self.queue.push(
            (-(get_time()*1000. + duration.num_milliseconds() as f64) as i64,
            Unordered(name)));
    }
    fn get_timeout(&mut self) -> c_int {
        self.queue.peek()
            .map(|&(ts, _)| (-ts) - (get_time()*1000.0) as i64)
            .map(|ts| if ts >= 0 { ts } else { 0 })
            .unwrap_or(-1)
            as i32
    }
    pub fn poll(&mut self) -> Event<Name> {
        loop {
            if let Some(sig) = signal::check_children() {
                return Signal(sig);
            }
            let timeo = self.get_timeout();
            let FileDesc(sfd) = self.signal_fd;
            let FileDesc(efd) = self.epoll_fd;
            let fd = unsafe { epoll_wait_read(efd, timeo) };
            if fd == -ETIMEDOUT { // Timeout
                debug!("Timeout");
                if self.get_timeout() != 0 {
                    continue;
                }
                let (_, Unordered(name)) = self.queue.pop().unwrap();
                return Timeout(name);
            } else if fd == -EINTR {
                continue
            } else if fd < 0 {
                panic!(format!("Error in epoll: {}", IoError::last_os_error()));
            } else if fd == sfd { // Signal
                debug!("Signal");
                let rc =  unsafe { read_signal(sfd) };
                if rc == -EINTR || rc == -EAGAIN {
                    continue;
                } else if rc <= 0 {
                    panic!(format!("Error in read_signal: {}",
                        IoError::last_os_error()));
                } else {
                    match rc {
                        sig@SIGTERM | sig@SIGINT | sig@SIGQUIT => {
                            return Signal(
                                signal::Signal::Terminate(sig));
                        }
                        SIGCHLD => {
                            continue;  // Will waitpid on next iteration
                        }
                        _ => {
                            warn!("Signal {} ignored", rc);
                            continue;
                        }
                    }
                }
            } else {
                debug!("Input {}", fd);
                return Input(self.inputs[&fd].clone());
            }
            unreachable!();
        }
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        let FileDesc(fd) = *self;
        unsafe { close(fd) };
    }
}
<|endoftext|>


<commit_before>/// Unittest for parsing module

use std::iter::Iterator;
use super::ast::*;
use super::token:: {TokenSpan, Lit};
use super::lex::Lexer;
use std::mem::swap;
use super::token::Token;
use super::Span;
use super::super::storage::SqlType;
use super::parser;
use std::collections::HashMap;

// ============================================================================
// Result::Ok unittest
// ============================================================================

#[test]
fn test_create_table_empty() {
    let mut p = parser::Parser::create("cReAtE table
        foo");

    assert_eq!(p.parse(), Ok(Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {tid: "foo".to_string(),
            cols: Vec::<ColumnInfo>::new()
        })))));
}

#[test]
fn test_create_table_content() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255))");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_table_content_primary() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255) primary key)");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: true,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_database() {
    let mut p = parser::Parser::create("create database Database");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Database("Database".to_string()))));
}

#[test]
fn test_alter_table_add_column() {
    let mut p = parser::Parser::create("alter table foo add bar int");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: false,
        })
    }))));
}

#[test]
fn test_alter_table_add_column_primary() {
    let mut p = parser::Parser::create("alter table foo add bar int primary key");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: true,
        })
    }))));
}

#[test]
fn test_alter_table_drop_column() {
    let mut p = parser::Parser::create("alter table foo drop column bar");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Drop("bar".to_string())
        })
    )));
}

#[test]
fn test_alter_table_modify() {
    let mut p = parser::Parser::create("alter table foo modify
        column bar bool");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Modify(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Bool,
            primary: false,
        })
    }))));
}

#[test]
fn test_drop_table() {
    let mut p = parser::Parser::create("drop table foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Table("foo".to_string()))));
}

#[test]
fn test_drop_database() {
    let mut p = parser::Parser::create("drop database foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Database("foo".to_string()))));
}

#[test]
fn test_use_database() {
    let mut p = parser::Parser::create("use database foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Use(UseStmt::Database("foo".to_string()))));
}

#[test]
fn test_describe_column() {
    let mut p = parser::Parser::create("describe foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Describe("foo".to_string())));
}

#[test]
fn test_insert_1() {
    let mut p = parser::Parser::create("insert into foo values
        ('peter', 'pan', 3) ");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(3)],
    })));
}

#[test]
fn test_insert_2() {
    let mut p = parser::Parser::create("insert into foo () values
        ('peter', 'pan', 4)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(4)],
    })));
}

#[test]
fn test_insert_3() {
    let mut p = parser::Parser::create("insert into foo (eins, zwei, drei)
        values ('peter', 'pan', 5)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: vec!["eins".to_string(), "zwei".to_string(), "drei".to_string()],
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(5)],
    })));
}

#[test]
fn test_delete_row() {
    let mut p = parser::Parser::create("delete from foo where name = 'peter'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(Conditions::Leaf(Condition {
                aliascol: None,
                col: "name".to_string(),
                op: CompType::Equ,
                aliasrhs: None,
                rhs: CondType::Literal(Lit::Str("peter".to_string())),
            })),
    })));
}
#[test]
fn test_delete_full_with_alias() {
    let mut p = parser::Parser::create("delete from foo bar");
    let mut aliashm = HashMap::new();
    aliashm.insert("bar".to_string(), "foo".to_string());

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: aliashm,
            cond: None,
    })));
}
#[test]
fn test_mult_where_blocks() {
    let mut p = parser::Parser::create("delete from foo where lname = 'peng' or
        fname = 'peter' and lname = 'pan'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(
                    Conditions::Or(Box::new(
                        Conditions::Leaf(Condition {
                            aliascol: None,
                            col: "lname".to_string(),
                            op: CompType::Equ,
                            aliasrhs: None,
                            rhs: CondType::Literal(Lit::Str("peng".to_string())),
                            }
                        )
                    ), Box::new(
                        Conditions::And(Box::new(
                            Conditions::Leaf(Condition {
                                aliascol: None,
                                col: "fname".to_string(),
                                op: CompType::Equ,
                                aliasrhs: None,
                                rhs: CondType::Literal(Lit::Str("peter".to_string())),
                                }
                            )), Box::new(Conditions::Leaf(Condition{
                                aliascol: None,
                                col: "lname".to_string(),
                                op: CompType::Equ,
                                aliasrhs: None,
                                rhs: CondType::Literal(Lit::Str("pan".to_string())),
                                }))
                            )
                        )
                    )
                )
            }
        ))
    );
}

// ============================================================================
// Result::Err unittest
// ============================================================================

#[test]
fn test_create_table_error1() {
    let mut p = parser::Parser::create("cReAtE table");
    let sol = parser::ParseError::UnexpectedEoq;
    assert_eq!(p.parse(), Err(sol));
}

#[test]
fn test_create_keyword1() {
    let mut p = parser::Parser::create("   table create");
    let sol = parser::ParseError::WrongKeyword(Span {
        lo : 5,
        hi : 10,
    });

    assert_eq!(p.parse(), Err(sol));
}

//Missing parentheses in front
#[test]
fn test_create_missing_p_front() {
    let mut p = parser::Parser::create("create table Studenten )");
    let sol = parser::ParseError::WrongToken(Span {
        lo : 24,
        hi : 24,
    });

    assert_eq!(p.parse(), Err(sol));
}
<commit_msg>Shorten unnecessary newlines and indentations concerning functions with lots of parentheses<commit_after>/// Unittest for parsing module

use std::iter::Iterator;
use super::ast::*;
use super::token:: {TokenSpan, Lit};
use super::lex::Lexer;
use std::mem::swap;
use super::token::Token;
use super::Span;
use super::super::storage::SqlType;
use super::parser;
use std::collections::HashMap;

// ============================================================================
// Result::Ok unittest
// ============================================================================

#[test]
fn test_create_table_empty() {
    let mut p = parser::Parser::create("cReAtE table
        foo");

    assert_eq!(p.parse(), Ok(Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {tid: "foo".to_string(),
            cols: Vec::<ColumnInfo>::new()
        })))));
}

#[test]
fn test_create_table_content() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255))");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_table_content_primary() {
    let mut p = parser::Parser::create(
        "create table foo (FirstName char(255), LastName char(255) primary key)");

    let vec = vec![ColumnInfo  {
            cid: "FirstName".to_string(),
            datatype: SqlType::Char(255),
            primary: false,
        },  ColumnInfo  {
            cid: "LastName".to_string(),
            datatype: SqlType::Char(255),
            primary: true,
        }
    ];

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Table(CreateTableStmt {
            tid: "foo".to_string(), cols: vec }))))
}

#[test]
fn test_create_database() {
    let mut p = parser::Parser::create("create database Database");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Create(
        CreateStmt::Database("Database".to_string()))));
}

#[test]
fn test_alter_table_add_column() {
    let mut p = parser::Parser::create("alter table foo add bar int");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: false,
        })
    }))));
}

#[test]
fn test_alter_table_add_column_primary() {
    let mut p = parser::Parser::create("alter table foo add bar int primary key");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Add(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Int,
            primary: true,
        })
    }))));
}

#[test]
fn test_alter_table_drop_column() {
    let mut p = parser::Parser::create("alter table foo drop column bar");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Drop("bar".to_string())
        })
    )));
}

#[test]
fn test_alter_table_modify() {
    let mut p = parser::Parser::create("alter table foo modify
        column bar bool");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Alter(
        AltStmt::Table(AlterTableStmt {tid: "foo".to_string(),
        op: AlterOp::Modify(ColumnInfo {
            cid: "bar".to_string(),
            datatype: SqlType::Bool,
            primary: false,
        })
    }))));
}

#[test]
fn test_drop_table() {
    let mut p = parser::Parser::create("drop table foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Table("foo".to_string()))));
}

#[test]
fn test_drop_database() {
    let mut p = parser::Parser::create("drop database foo");

    assert_eq!(p.parse().unwrap(), Query::DefStmt(DefStmt::Drop(
        DropStmt::Database("foo".to_string()))));
}

#[test]
fn test_use_database() {
    let mut p = parser::Parser::create("use database foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Use(UseStmt::Database("foo".to_string()))));
}

#[test]
fn test_describe_column() {
    let mut p = parser::Parser::create("describe foo");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Describe("foo".to_string())));
}

#[test]
fn test_insert_1() {
    let mut p = parser::Parser::create("insert into foo values
        ('peter', 'pan', 3) ");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(3)],
    })));
}

#[test]
fn test_insert_2() {
    let mut p = parser::Parser::create("insert into foo () values
        ('peter', 'pan', 4)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: Vec::<String>::new(),
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(4)],
    })));
}

#[test]
fn test_insert_3() {
    let mut p = parser::Parser::create("insert into foo (eins, zwei, drei)
        values ('peter', 'pan', 5)");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Insert(InsertStmt {
            tid: "foo".to_string(),
            col: vec!["eins".to_string(), "zwei".to_string(), "drei".to_string()],
            val: vec![Lit::Str("peter".to_string()),
                Lit::Str("pan".to_string()),
                Lit::Int(5)],
    })));
}

#[test]
fn test_delete_row() {
    let mut p = parser::Parser::create("delete from foo where name = 'peter'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(Conditions::Leaf(Condition {
                aliascol: None,
                col: "name".to_string(),
                op: CompType::Equ,
                aliasrhs: None,
                rhs: CondType::Literal(Lit::Str("peter".to_string())),
            })),
    })));
}

#[test]
fn test_delete_full_with_alias() {
    let mut p = parser::Parser::create("delete from foo bar");
    let mut aliashm = HashMap::new();
    aliashm.insert("bar".to_string(), "foo".to_string());

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: aliashm,
            cond: None,
    })));
}

#[test]
fn test_mult_where_blocks() {
    let mut p = parser::Parser::create("delete from foo where lname = 'peng' or
        fname = 'peter' and lname = 'pan'");

    assert_eq!(p.parse().unwrap(), Query::ManipulationStmt(
        ManipulationStmt::Delete(DeleteStmt {
            tid: "foo".to_string(),
            alias: HashMap::new(),
            cond: Some(Conditions::Or(Box::new(
                Conditions::Leaf(Condition {
                    aliascol: None,
                    col: "lname".to_string(),
                    op: CompType::Equ,
                    aliasrhs: None,
                    rhs: CondType::Literal(Lit::Str("peng".to_string())),
                    }
                )
            ), Box::new(Conditions::And(Box::new(
                    Conditions::Leaf(Condition {
                        aliascol: None,
                        col: "fname".to_string(),
                        op: CompType::Equ,
                        aliasrhs: None,
                        rhs: CondType::Literal(Lit::Str("peter".to_string())),
                        }
                    )), Box::new(Conditions::Leaf(Condition{
                        aliascol: None,
                        col: "lname".to_string(),
                        op: CompType::Equ,
                        aliasrhs: None,
                        rhs: CondType::Literal(Lit::Str("pan".to_string())),
                        }))
                    )
                )
            ))
        }))
    );
}

// ============================================================================
// Result::Err unittest
// ============================================================================

#[test]
fn test_create_table_error1() {
    let mut p = parser::Parser::create("cReAtE table");
    let sol = parser::ParseError::UnexpectedEoq;
    assert_eq!(p.parse(), Err(sol));
}

#[test]
fn test_create_keyword1() {
    let mut p = parser::Parser::create("   table create");
    let sol = parser::ParseError::WrongKeyword(Span {
        lo : 5,
        hi : 10,
    });

    assert_eq!(p.parse(), Err(sol));
}

//Missing parentheses in front
#[test]
fn test_create_missing_p_front() {
    let mut p = parser::Parser::create("create table Studenten )");
    let sol = parser::ParseError::WrongToken(Span {
        lo : 24,
        hi : 24,
    });

    assert_eq!(p.parse(), Err(sol));
}
<|endoftext|>


<commit_before>
const ROW_SIZE: usize = 9;

fn from_str(sudoku: &str) -> [[u32; ROW_SIZE]; ROW_SIZE] {
    let mut board = [[0; ROW_SIZE]; ROW_SIZE];
    let mut row = 0;
    let mut col = 0;
    for c in sudoku.chars() {
        board[row][col] = c.to_digit(10).unwrap();
        col += 1;
        if col == ROW_SIZE {
            col = 0;
            row += 1;
        }
    }
    board
}

fn main() {
    let sudoku_example = "200000060000075030048090100000300000300010009000008000001020570080730000090000004";
    let mut board: [[u32; ROW_SIZE]; ROW_SIZE] = from_str(sudoku_example);
    println!("{:?}", board)
}

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

//     #[test]
//     fn read_sudoku_string_to_struct() {
//         let sudoku_example = "200000060000075030048090100000300000300010009000008000001020570080730000090000004";
//         println!("{:?}", board)
//     }
// }
<commit_msg>Board struct<commit_after>
const ROW_SIZE: usize = 9;

#[derive(Debug)]
struct Board([[u32; ROW_SIZE]; ROW_SIZE]);

impl Board {
    fn from_str(sudoku: &str) -> Board {
        let mut board = [[0; ROW_SIZE]; ROW_SIZE];
        let mut row = 0;
        let mut col = 0;
        for c in sudoku.chars() {
            board[row][col] = c.to_digit(10).unwrap();
            col += 1;
            if col == ROW_SIZE {
                col = 0;
                row += 1;
            }
        }
        Board(board)
    }
}

fn main() {
    let sudoku_example = "200000060000075030048090100000300000300010009000008000001020570080730000090000004";
    let board = Board::from_str(sudoku_example);
    println!("{:?}", board)
}

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

//     #[test]
//     fn read_sudoku_string_to_struct() {
//         let sudoku_example = "200000060000075030048090100000300000300010009000008000001020570080730000090000004";
//         println!("{:?}", board)
//     }
// }
<|endoftext|>