<commit_before>//! `CuckooFilter` implementation.
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasher, Hash, Hasher};
use std::mem;

use rand::Rng;

use hash_utils::MyBuildHasherDefault;

// TODO: make fingerprint type a type param of CuckooFilter
type Fingerprint = u8;

const MAX_NUM_KICKS: usize = 500; // mentioned in paper

/// Error struct used to signal that a `CuckooFilter` is full, i.e. that a value cannot be inserted
/// because the implementation was unable to find a free bucket.
#[derive(Debug)]
pub struct CuckooFilterFull;

/// [`CuckooFilter`](https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf).
pub struct CuckooFilter<R, B = MyBuildHasherDefault<DefaultHasher>>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    table: Vec<Fingerprint>,
    n_elements: usize,
    buildhasher: B,
    bucketsize: usize,
    n_buckets: usize,
    rng: R,
}

impl<R> CuckooFilter<R>
where
    R: Rng,
{
    /// Create new CuckooFilter with:
    ///
    /// - `rng`: random number generator used for certain random actions
    /// - `bucketsize`: number of elements per bucket, must be at least 2
    /// - `n_buckets`: number of buckets, must be a power of 2 and at least 2
    ///
    /// The BuildHasher is set to the `DefaultHasher`.
    pub fn with_params(rng: R, bucketsize: usize, n_buckets: usize) -> Self {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_params_and_hash(rng, bucketsize, n_buckets, bh)
    }
}

impl<R, B> CuckooFilter<R, B>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    /// Create new CuckooFilter with:
    ///
    /// - `rng`: random number generator used for certain random actions
    /// - `bucketsize`: number of elements per bucket, must be at least 2
    /// - `n_buckets`: number of buckets, must be a power of 2 and at least 2
    /// - `bh`: BuildHasher that creates Hash objects, used for fingerprint creation and
    ///   fingerprint hashing
    pub fn with_params_and_hash(rng: R, bucketsize: usize, n_buckets: usize, bh: B) -> Self {
        assert!(
            bucketsize >= 2,
            "bucketsize ({}) should be greater or equal than 2",
            bucketsize
        );
        assert!(
            n_buckets.is_power_of_two() & (n_buckets >= 2),
            "n_buckets ({}) must be a power of 2 and greater or equal than 2",
            n_buckets
        );

        Self {
            table: vec![0; n_buckets * bucketsize],
            n_elements: 0,
            buildhasher: bh,
            bucketsize: bucketsize,
            n_buckets: n_buckets,
            rng: rng,
        }
    }

    /// Number of entries stored in a bucket.
    pub fn bucketsize(&self) -> usize {
        self.bucketsize
    }

    /// Number of buckets used by the CuckooFilter.
    pub fn n_buckets(&self) -> usize {
        self.n_buckets
    }

    /// Check if CuckooFilter is empty, i.e. contains no elements.
    pub fn empty(&self) -> bool {
        self.n_elements == 0
    }

    /// Return number of elements in the filter.
    pub fn len(&self) -> usize {
        self.n_elements
    }

    /// Insert new element into filter.
    ///
    /// The method may return an error if it was unable to find a free bucket. This means the
    /// filter is full and you should not add any additional elements to it. When this happens,
    /// `len` was not increased and the filter content was not altered.
    ///
    /// Inserting the same element multiple times is supported, but keep in mind that after
    /// `n_buckets * 2` times, the filter will return `Err(CuckooFilterFull)`.
    pub fn insert<T>(&mut self, t: &T) -> Result<(), CuckooFilterFull>
    where
        T: Hash,
    {
        let (mut f, i1, i2) = self.start(t);

        if self.write_to_bucket(i1, f) {
            self.n_elements += 1;
            return Ok(());
        }
        if self.write_to_bucket(i2, f) {
            self.n_elements += 1;
            return Ok(());
        }

        // cannot write to obvious buckets => relocate
        let table_backup = self.table.clone(); // may be required for rollback
        let mut i = if self.rng.gen::<bool>() { i1 } else { i2 };

        for _ in 0..MAX_NUM_KICKS {
            let e = self.rng.gen_range::<usize>(0, self.bucketsize);
            let offset = i * self.bucketsize;
            let x = offset + e;

            mem::swap(&mut self.table[x], &mut f);
            i = i ^ self.hash(&f);
            if self.write_to_bucket(i, f) {
                self.n_elements += 1;
                return Ok(());
            }
        }

        // no space left => fail
        self.table = table_backup; // rollback transaction
        Err(CuckooFilterFull)
    }

    /// Check if given element was inserted into the filter.
    pub fn lookup<T>(&self, t: &T) -> bool
    where
        T: Hash,
    {
        let (f, i1, i2) = self.start(t);

        if self.has_in_bucket(i1, f) {
            return true;
        }
        if self.has_in_bucket(i2, f) {
            return true;
        }
        false
    }

    /// Remove element from the filter.
    ///
    /// Returns `true` if element was in the filter, `false` if it was not in which case the operation did not modify
    /// the filter.
    pub fn delete<T>(&mut self, t: &T) -> bool
    where
        T: Hash,
    {
        let (f, i1, i2) = self.start(t);

        if self.remove_from_bucket(i1, f) {
            self.n_elements -= 1;
            return true;
        }
        if self.remove_from_bucket(i2, f) {
            self.n_elements -= 1;
            return true;
        }
        false
    }

    fn start<T>(&self, t: &T) -> (Fingerprint, usize, usize)
    where
        T: Hash,
    {
        let f = self.fingerprint(t);
        let i1 = self.hash(t);
        let i2 = i1 ^ self.hash(&f);
        (f, i1, i2)
    }

    fn fingerprint<T>(&self, t: &T) -> Fingerprint
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        hasher.write_usize(0); // IV
        t.hash(&mut hasher);

        // don't produce 0, since this is used as "free"-slot value
        1 + (hasher.finish() % (Fingerprint::max_value() as u64 - 1)) as Fingerprint
    }

    fn hash<T>(&self, t: &T) -> usize
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        hasher.write_usize(1); // IV
        t.hash(&mut hasher);
        (hasher.finish() & (self.n_buckets as u64 - 1)) as usize
    }

    fn write_to_bucket(&mut self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == 0 {
                self.table[x] = f;
                return true;
            }
        }
        false
    }

    fn has_in_bucket(&self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == f {
                return true;
            }
        }
        false
    }

    fn remove_from_bucket(&mut self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == f {
                self.table[x] = 0;
                return true;
            }
        }
        false
    }
}

impl<R, B> fmt::Debug for CuckooFilter<R, B>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "CuckooFilter {{ bucketsize: {}, n_buckets: {} }}",
            self.bucketsize, self.n_buckets
        )
    }
}

#[cfg(test)]
mod tests {
    use super::CuckooFilter;
    use rand::{ChaChaRng, SeedableRng};

    #[test]
    #[should_panic(expected = "bucketsize (0) should be greater or equal than 2")]
    fn new_panics_bucketsize_0() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 0, 16);
    }

    #[test]
    #[should_panic(expected = "bucketsize (1) should be greater or equal than 2")]
    fn new_panics_bucketsize_1() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 1, 16);
    }

    #[test]
    #[should_panic(expected = "n_buckets (0) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_0() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 0);
    }

    #[test]
    #[should_panic(expected = "n_buckets (1) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_1() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 1);
    }

    #[test]
    #[should_panic(expected = "n_buckets (5) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_5() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 5);
    }

    #[test]
    fn getter() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert_eq!(cf.bucketsize(), 2);
        assert_eq!(cf.n_buckets(), 16);
    }

    #[test]
    fn empty() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert!(cf.empty());
        assert_eq!(cf.len(), 0);
    }

    #[test]
    fn insert() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        cf.insert(&13).unwrap();
        assert!(!cf.empty());
        assert_eq!(cf.len(), 1);
        assert!(cf.lookup(&13));
        assert!(!cf.lookup(&42));
    }

    #[test]
    fn delete() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        cf.insert(&13).unwrap();
        cf.insert(&42).unwrap();
        assert!(cf.lookup(&13));
        assert!(cf.lookup(&42));
        assert_eq!(cf.len(), 2);

        assert!(cf.delete(&13));
        assert!(!cf.lookup(&13));
        assert!(cf.lookup(&42));
        assert_eq!(cf.len(), 1);
    }

    #[test]
    fn full() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 2);

        for i in 0..4 {
            cf.insert(&i).unwrap();
        }
        assert_eq!(cf.len(), 4);
        for i in 0..4 {
            assert!(cf.lookup(&i));
        }

        assert!(cf.insert(&5).is_err());
        assert_eq!(cf.len(), 4);
        assert!(!cf.lookup(&5)); // rollback was executed
    }

    #[test]
    fn debug() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert_eq!(
            format!("{:?}", cf),
            "CuckooFilter { bucketsize: 2, n_buckets: 16 }"
        );
    }
}
<commit_msg>cuckoofilter: impl Clone<commit_after>//! `CuckooFilter` implementation.
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasher, Hash, Hasher};
use std::mem;

use rand::Rng;

use hash_utils::MyBuildHasherDefault;

// TODO: make fingerprint type a type param of CuckooFilter
type Fingerprint = u8;

const MAX_NUM_KICKS: usize = 500; // mentioned in paper

/// Error struct used to signal that a `CuckooFilter` is full, i.e. that a value cannot be inserted
/// because the implementation was unable to find a free bucket.
#[derive(Debug)]
pub struct CuckooFilterFull;

/// [`CuckooFilter`](https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf).
#[derive(Clone)]
pub struct CuckooFilter<R, B = MyBuildHasherDefault<DefaultHasher>>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    table: Vec<Fingerprint>,
    n_elements: usize,
    buildhasher: B,
    bucketsize: usize,
    n_buckets: usize,
    rng: R,
}

impl<R> CuckooFilter<R>
where
    R: Rng,
{
    /// Create new CuckooFilter with:
    ///
    /// - `rng`: random number generator used for certain random actions
    /// - `bucketsize`: number of elements per bucket, must be at least 2
    /// - `n_buckets`: number of buckets, must be a power of 2 and at least 2
    ///
    /// The BuildHasher is set to the `DefaultHasher`.
    pub fn with_params(rng: R, bucketsize: usize, n_buckets: usize) -> Self {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_params_and_hash(rng, bucketsize, n_buckets, bh)
    }
}

impl<R, B> CuckooFilter<R, B>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    /// Create new CuckooFilter with:
    ///
    /// - `rng`: random number generator used for certain random actions
    /// - `bucketsize`: number of elements per bucket, must be at least 2
    /// - `n_buckets`: number of buckets, must be a power of 2 and at least 2
    /// - `bh`: BuildHasher that creates Hash objects, used for fingerprint creation and
    ///   fingerprint hashing
    pub fn with_params_and_hash(rng: R, bucketsize: usize, n_buckets: usize, bh: B) -> Self {
        assert!(
            bucketsize >= 2,
            "bucketsize ({}) should be greater or equal than 2",
            bucketsize
        );
        assert!(
            n_buckets.is_power_of_two() & (n_buckets >= 2),
            "n_buckets ({}) must be a power of 2 and greater or equal than 2",
            n_buckets
        );

        Self {
            table: vec![0; n_buckets * bucketsize],
            n_elements: 0,
            buildhasher: bh,
            bucketsize: bucketsize,
            n_buckets: n_buckets,
            rng: rng,
        }
    }

    /// Number of entries stored in a bucket.
    pub fn bucketsize(&self) -> usize {
        self.bucketsize
    }

    /// Number of buckets used by the CuckooFilter.
    pub fn n_buckets(&self) -> usize {
        self.n_buckets
    }

    /// Check if CuckooFilter is empty, i.e. contains no elements.
    pub fn empty(&self) -> bool {
        self.n_elements == 0
    }

    /// Return number of elements in the filter.
    pub fn len(&self) -> usize {
        self.n_elements
    }

    /// Insert new element into filter.
    ///
    /// The method may return an error if it was unable to find a free bucket. This means the
    /// filter is full and you should not add any additional elements to it. When this happens,
    /// `len` was not increased and the filter content was not altered.
    ///
    /// Inserting the same element multiple times is supported, but keep in mind that after
    /// `n_buckets * 2` times, the filter will return `Err(CuckooFilterFull)`.
    pub fn insert<T>(&mut self, t: &T) -> Result<(), CuckooFilterFull>
    where
        T: Hash,
    {
        let (mut f, i1, i2) = self.start(t);

        if self.write_to_bucket(i1, f) {
            self.n_elements += 1;
            return Ok(());
        }
        if self.write_to_bucket(i2, f) {
            self.n_elements += 1;
            return Ok(());
        }

        // cannot write to obvious buckets => relocate
        let table_backup = self.table.clone(); // may be required for rollback
        let mut i = if self.rng.gen::<bool>() { i1 } else { i2 };

        for _ in 0..MAX_NUM_KICKS {
            let e = self.rng.gen_range::<usize>(0, self.bucketsize);
            let offset = i * self.bucketsize;
            let x = offset + e;

            mem::swap(&mut self.table[x], &mut f);
            i = i ^ self.hash(&f);
            if self.write_to_bucket(i, f) {
                self.n_elements += 1;
                return Ok(());
            }
        }

        // no space left => fail
        self.table = table_backup; // rollback transaction
        Err(CuckooFilterFull)
    }

    /// Check if given element was inserted into the filter.
    pub fn lookup<T>(&self, t: &T) -> bool
    where
        T: Hash,
    {
        let (f, i1, i2) = self.start(t);

        if self.has_in_bucket(i1, f) {
            return true;
        }
        if self.has_in_bucket(i2, f) {
            return true;
        }
        false
    }

    /// Remove element from the filter.
    ///
    /// Returns `true` if element was in the filter, `false` if it was not in which case the operation did not modify
    /// the filter.
    pub fn delete<T>(&mut self, t: &T) -> bool
    where
        T: Hash,
    {
        let (f, i1, i2) = self.start(t);

        if self.remove_from_bucket(i1, f) {
            self.n_elements -= 1;
            return true;
        }
        if self.remove_from_bucket(i2, f) {
            self.n_elements -= 1;
            return true;
        }
        false
    }

    fn start<T>(&self, t: &T) -> (Fingerprint, usize, usize)
    where
        T: Hash,
    {
        let f = self.fingerprint(t);
        let i1 = self.hash(t);
        let i2 = i1 ^ self.hash(&f);
        (f, i1, i2)
    }

    fn fingerprint<T>(&self, t: &T) -> Fingerprint
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        hasher.write_usize(0); // IV
        t.hash(&mut hasher);

        // don't produce 0, since this is used as "free"-slot value
        1 + (hasher.finish() % (Fingerprint::max_value() as u64 - 1)) as Fingerprint
    }

    fn hash<T>(&self, t: &T) -> usize
    where
        T: Hash,
    {
        let mut hasher = self.buildhasher.build_hasher();
        hasher.write_usize(1); // IV
        t.hash(&mut hasher);
        (hasher.finish() & (self.n_buckets as u64 - 1)) as usize
    }

    fn write_to_bucket(&mut self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == 0 {
                self.table[x] = f;
                return true;
            }
        }
        false
    }

    fn has_in_bucket(&self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == f {
                return true;
            }
        }
        false
    }

    fn remove_from_bucket(&mut self, i: usize, f: Fingerprint) -> bool {
        let offset = i * self.bucketsize;
        for x in offset..(offset + self.bucketsize) {
            if self.table[x] == f {
                self.table[x] = 0;
                return true;
            }
        }
        false
    }
}

impl<R, B> fmt::Debug for CuckooFilter<R, B>
where
    R: Rng,
    B: BuildHasher + Clone + Eq,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "CuckooFilter {{ bucketsize: {}, n_buckets: {} }}",
            self.bucketsize, self.n_buckets
        )
    }
}

#[cfg(test)]
mod tests {
    use super::CuckooFilter;
    use rand::{ChaChaRng, SeedableRng};

    #[test]
    #[should_panic(expected = "bucketsize (0) should be greater or equal than 2")]
    fn new_panics_bucketsize_0() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 0, 16);
    }

    #[test]
    #[should_panic(expected = "bucketsize (1) should be greater or equal than 2")]
    fn new_panics_bucketsize_1() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 1, 16);
    }

    #[test]
    #[should_panic(expected = "n_buckets (0) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_0() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 0);
    }

    #[test]
    #[should_panic(expected = "n_buckets (1) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_1() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 1);
    }

    #[test]
    #[should_panic(expected = "n_buckets (5) must be a power of 2 and greater or equal than 2")]
    fn new_panics_n_buckets_5() {
        CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 5);
    }

    #[test]
    fn getter() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert_eq!(cf.bucketsize(), 2);
        assert_eq!(cf.n_buckets(), 16);
    }

    #[test]
    fn empty() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert!(cf.empty());
        assert_eq!(cf.len(), 0);
    }

    #[test]
    fn insert() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        cf.insert(&13).unwrap();
        assert!(!cf.empty());
        assert_eq!(cf.len(), 1);
        assert!(cf.lookup(&13));
        assert!(!cf.lookup(&42));
    }

    #[test]
    fn delete() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        cf.insert(&13).unwrap();
        cf.insert(&42).unwrap();
        assert!(cf.lookup(&13));
        assert!(cf.lookup(&42));
        assert_eq!(cf.len(), 2);

        assert!(cf.delete(&13));
        assert!(!cf.lookup(&13));
        assert!(cf.lookup(&42));
        assert_eq!(cf.len(), 1);
    }

    #[test]
    fn full() {
        let mut cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 2);

        for i in 0..4 {
            cf.insert(&i).unwrap();
        }
        assert_eq!(cf.len(), 4);
        for i in 0..4 {
            assert!(cf.lookup(&i));
        }

        assert!(cf.insert(&5).is_err());
        assert_eq!(cf.len(), 4);
        assert!(!cf.lookup(&5)); // rollback was executed
    }

    #[test]
    fn debug() {
        let cf = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        assert_eq!(
            format!("{:?}", cf),
            "CuckooFilter { bucketsize: 2, n_buckets: 16 }"
        );
    }

    #[test]
    fn clone() {
        let mut cf1 = CuckooFilter::with_params(ChaChaRng::from_seed([0; 32]), 2, 16);
        cf1.insert(&13).unwrap();
        assert!(cf1.lookup(&13));

        let cf2 = cf1.clone();
        cf1.insert(&42).unwrap();
        assert!(cf2.lookup(&13));
        assert!(!cf2.lookup(&42));
    }
}
<|endoftext|>


<commit_before>use std::num::{Zero, One};
use std::{cmp, util, uint};
use extra::bitv::BitvSet;

pub enum Step<T> { Plus(T), Minus(T) }

impl<T> Step<T> {
    fn ref_abs<'a>(&'a self) -> &'a T {
        match *self {
            Plus(ref s) => s,
            Minus(ref s) => s
        }
    }
}

impl<T: Add<T, T> + Sub<T, T>> Step<T> {
    fn add_to(&self, val: &T) -> T {
        match *self {
            Plus(ref s)  => val + *s,
            Minus(ref s) => val - *s
        }
    }
}

pub struct Range<T> {
    cur: T,
    step: Step<T>,
    cnt: T,
}

impl<T: Integer> Range<T> {
    pub fn new_with_step(start: T, stop: T, step: Step<T>) -> Range<T> {
        if step.ref_abs().is_zero() { fail!("Range::new() called with step == 0"); }

        let mut cnt = Zero::zero();
        match step {
            Plus(ref abs_step) if start < stop => {
                let diff = (stop - start);
                cnt = diff / *abs_step;
                if !diff.is_multiple_of(abs_step) { cnt = cnt + One::one(); }
            }
            Minus(ref abs_step) if start > stop => {
                let diff = (start - stop);
                cnt = diff / *abs_step;
                if !diff.is_multiple_of(abs_step) { cnt = cnt + One::one(); }
            }
            _ => { }
        }
        return Range { cur: start, cnt: cnt, step: step };
    }
}

impl<T: Integer> Iterator<T> for Range<T> {
    #[inline(always)]
    fn next(&mut self) -> Option<T> {
        if self.cnt <= Zero::zero() { return None; }
        self.cnt = self.cnt - One::one();

        let mut val = self.step.add_to(&self.cur);
        util::swap(&mut val, &mut self.cur);
        return Some(val);
    }
}

pub struct Area2DIterator {
    cur: (int, int),
    dv: (int, int),
    cnt: uint
}

impl Area2DIterator {
    #[inline(always)]
    pub fn new((x0, y0): (int, int), (dx, dy): (int, int), (x_min, y_min): (int, int), (x_max, y_max): (int, int)) -> Area2DIterator {
        if dx == 0 && dy == 0 { fail!("Area2DIterator::new called with (dx, dy) == (0, 0)") }

        #[inline(always)]
        fn get_cnt(p0: int, dp: int, min: int, max: int) -> uint {
            if p0 < min || max < p0 { return 0; }
            return match dp.cmp(&0) {
                Equal   => uint::max_value,
                Greater => ((max + 1 - p0) / dp) as uint,
                Less    => ((p0 + 1 - min) / (-dp)) as uint
            };
        }

        Area2DIterator {
            cur: (x0, y0),
            dv: (dx, dy),
            cnt: cmp::min(get_cnt(x0, dx, x_min, x_max), get_cnt(y0, dy, y_min, y_max))
        }
    }

    #[inline(always)]
    pub fn new_from_matrix(start: (int, int), dv: (int, int), (w, h): (int, int)) -> Area2DIterator {
        assert!(w > 0 && h > 0);
        Area2DIterator::new(start, dv, (0, 0), (w - 1, h - 1))
    }
}

impl Iterator<(int, int)> for Area2DIterator {
    #[inline(always)]
    fn next(&mut self) -> Option<(int, int)> {
        if self.cnt <= 0 { return None; }
        self.cnt -= 1;
        let ((x, y), (dx, dy)) = (self.cur, self.dv);
        self.cur = (x + dx, y + dy);
        return Some((x, y));
    }
}

pub struct CombIterator {
    priv consumed: bool,
    priv size: uint,
    priv set: BitvSet
}

impl Iterator<BitvSet> for CombIterator {
    fn next(&mut self) -> Option<BitvSet> {
        if !self.consumed {
            self.consumed = true;
            return Some(self.set.clone());
        }

        let mut n = self.size;
        loop {
            match range(0, n).invert().find(|i| self.set.contains(i)) {
                None => return None,
                Some(x) => {
                    if x < self.size - 1 && !self.set.contains(&(x + 1)) {
                        n = x;
                        break;
                    }
                    n = x;
                }
            }
        }
        self.set.remove(&n);
        self.set.insert(n + 1);
        let mut j = n + 2;
        for i in range(n + 2, self.size) {
            if self.set.contains(&i) {
                self.set.remove(&i);
                self.set.insert(j);
                j += 1;
            }
        }
        Some(self.set.clone())
    }
}

impl CombIterator {
    pub fn new(cnt: uint, size: uint) -> CombIterator {
        assert!(cnt <= size);
        let mut set = BitvSet::new();
        for i in range(0, cnt) {
            set.insert(i);
        }
        CombIterator { consumed: false, size: size, set: set }
    }
}

#[cfg(test)]
mod test {
    use std::uint;
    use super::{Area2DIterator, CombIterator, Plus, Minus, Range};

    #[test]
    fn test_range() {
        fn gen(start: uint, end: uint, step: int) -> ~[uint] {
            let s = if step >= 0 { Plus(step as uint) } else { Minus((-step) as uint) };
            Range::new_with_step(start, end, s).to_owned_vec()
        }
        assert_eq!(gen(0, 3, 1), ~[0, 1, 2]);
        assert_eq!(gen(13, 10, -1), ~[13, 12, 11]);
        assert_eq!(gen(20, 26, 2), ~[20, 22, 24]);
        assert_eq!(gen(36, 30, -2), ~[36, 34, 32]);
        assert_eq!(gen(uint::max_value - 2, uint::max_value, 2),
                   ~[uint::max_value - 2]);
        assert_eq!(gen(uint::max_value - 3, uint::max_value, 2),
                   ~[uint::max_value - 3, uint::max_value - 1]);
        assert_eq!(gen(uint::min_value + 2, uint::min_value, -2),
                   ~[uint::min_value + 2]);
        assert_eq!(gen(uint::min_value + 3, uint::min_value, -2),
                   ~[uint::min_value + 3, uint::min_value + 1]);
    }

    #[test]
    fn test_area2d() {
        let vs = Area2DIterator::new((0, 0), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (1, 1), (2, 2), (3, 3)]);

        let vs = Area2DIterator::new((1, 1), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(1, 1), (2, 2), (3, 3)]);

        let vs = Area2DIterator::new((3, 3), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3)]);

        let vs = Area2DIterator::new((0, 0), (2, 2), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (2, 2)]);

        let vs = Area2DIterator::new((0, 0), (0, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (0, 1), (0, 2), (0, 3)]);

        let vs = Area2DIterator::new((0, 0), (0, 1), (0, 0), (3, 5)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]);

        let vs = Area2DIterator::new((0, 0), (1, 2), (0, 0), (3, 5)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (1, 2), (2, 4)]);

        let vs = Area2DIterator::new((3, 3), (-1, -1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3), (2, 2), (1, 1), (0, 0)]);

        let vs = Area2DIterator::new((3, 3), (-2, -2), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3), (1, 1)]);
    }

    #[test]
    fn test_comb_iterator() {
        fn check(cnt: uint, size: uint, expected: ~[~[uint]]) {
            let actual = CombIterator::new(cnt, size)
                .map(|set| set.iter().to_owned_vec())
                .to_owned_vec();
            assert_eq!(actual, expected);
        }
        check(0, 4, ~[~[]]);
        check(1, 4, ~[~[0], ~[1], ~[2], ~[3]]);
        check(2, 4, ~[~[0, 1], ~[0, 2], ~[0, 3],
                      ~[1, 2], ~[1, 3],
                      ~[2, 3]]);
        check(3, 4, ~[~[0, 1, 2], ~[0, 1, 3], ~[0, 2, 3], ~[1, 2, 3]]);
        check(4, 4, ~[~[0, 1, 2, 3]]);

        check(0, 0, ~[~[]]);
        check(0, 1, ~[~[]]);
        check(1, 1, ~[~[0]]);
    }
}
<commit_msg>Remove data::extiter::Range<commit_after>use std::{cmp, uint};
use extra::bitv::BitvSet;

pub struct Area2DIterator {
    cur: (int, int),
    dv: (int, int),
    cnt: uint
}

impl Area2DIterator {
    #[inline(always)]
    pub fn new((x0, y0): (int, int), (dx, dy): (int, int), (x_min, y_min): (int, int), (x_max, y_max): (int, int)) -> Area2DIterator {
        if dx == 0 && dy == 0 { fail!("Area2DIterator::new called with (dx, dy) == (0, 0)") }

        #[inline(always)]
        fn get_cnt(p0: int, dp: int, min: int, max: int) -> uint {
            if p0 < min || max < p0 { return 0; }
            return match dp.cmp(&0) {
                Equal   => uint::max_value,
                Greater => ((max + 1 - p0) / dp) as uint,
                Less    => ((p0 + 1 - min) / (-dp)) as uint
            };
        }

        Area2DIterator {
            cur: (x0, y0),
            dv: (dx, dy),
            cnt: cmp::min(get_cnt(x0, dx, x_min, x_max), get_cnt(y0, dy, y_min, y_max))
        }
    }

    #[inline(always)]
    pub fn new_from_matrix(start: (int, int), dv: (int, int), (w, h): (int, int)) -> Area2DIterator {
        assert!(w > 0 && h > 0);
        Area2DIterator::new(start, dv, (0, 0), (w - 1, h - 1))
    }
}

impl Iterator<(int, int)> for Area2DIterator {
    #[inline(always)]
    fn next(&mut self) -> Option<(int, int)> {
        if self.cnt <= 0 { return None; }
        self.cnt -= 1;
        let ((x, y), (dx, dy)) = (self.cur, self.dv);
        self.cur = (x + dx, y + dy);
        return Some((x, y));
    }
}

pub struct CombIterator {
    priv consumed: bool,
    priv size: uint,
    priv set: BitvSet
}

impl Iterator<BitvSet> for CombIterator {
    fn next(&mut self) -> Option<BitvSet> {
        if !self.consumed {
            self.consumed = true;
            return Some(self.set.clone());
        }

        let mut n = self.size;
        loop {
            match range(0, n).invert().find(|i| self.set.contains(i)) {
                None => return None,
                Some(x) => {
                    if x < self.size - 1 && !self.set.contains(&(x + 1)) {
                        n = x;
                        break;
                    }
                    n = x;
                }
            }
        }
        self.set.remove(&n);
        self.set.insert(n + 1);
        let mut j = n + 2;
        for i in range(n + 2, self.size) {
            if self.set.contains(&i) {
                self.set.remove(&i);
                self.set.insert(j);
                j += 1;
            }
        }
        Some(self.set.clone())
    }
}

impl CombIterator {
    pub fn new(cnt: uint, size: uint) -> CombIterator {
        assert!(cnt <= size);
        let mut set = BitvSet::new();
        for i in range(0, cnt) {
            set.insert(i);
        }
        CombIterator { consumed: false, size: size, set: set }
    }
}

#[cfg(test)]
mod test {
    use super::{Area2DIterator, CombIterator};

    #[test]
    fn test_area2d() {
        let vs = Area2DIterator::new((0, 0), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (1, 1), (2, 2), (3, 3)]);

        let vs = Area2DIterator::new((1, 1), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(1, 1), (2, 2), (3, 3)]);

        let vs = Area2DIterator::new((3, 3), (1, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3)]);

        let vs = Area2DIterator::new((0, 0), (2, 2), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (2, 2)]);

        let vs = Area2DIterator::new((0, 0), (0, 1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (0, 1), (0, 2), (0, 3)]);

        let vs = Area2DIterator::new((0, 0), (0, 1), (0, 0), (3, 5)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]);

        let vs = Area2DIterator::new((0, 0), (1, 2), (0, 0), (3, 5)).to_owned_vec();
        assert_eq!(vs, ~[(0, 0), (1, 2), (2, 4)]);

        let vs = Area2DIterator::new((3, 3), (-1, -1), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3), (2, 2), (1, 1), (0, 0)]);

        let vs = Area2DIterator::new((3, 3), (-2, -2), (0, 0), (3, 3)).to_owned_vec();
        assert_eq!(vs, ~[(3, 3), (1, 1)]);
    }

    #[test]
    fn test_comb_iterator() {
        fn check(cnt: uint, size: uint, expected: ~[~[uint]]) {
            let actual = CombIterator::new(cnt, size)
                .map(|set| set.iter().to_owned_vec())
                .to_owned_vec();
            assert_eq!(actual, expected);
        }
        check(0, 4, ~[~[]]);
        check(1, 4, ~[~[0], ~[1], ~[2], ~[3]]);
        check(2, 4, ~[~[0, 1], ~[0, 2], ~[0, 3],
                      ~[1, 2], ~[1, 3],
                      ~[2, 3]]);
        check(3, 4, ~[~[0, 1, 2], ~[0, 1, 3], ~[0, 2, 3], ~[1, 2, 3]]);
        check(4, 4, ~[~[0, 1, 2, 3]]);

        check(0, 0, ~[~[]]);
        check(0, 1, ~[~[]]);
        check(1, 1, ~[~[0]]);
    }
}
<|endoftext|>


<commit_before>mod command;

use std::io::{stdin, stdout};
use std::io::prelude::*;
use std::borrow::Cow;

use cpu::cpu::Cpu;
use cpu::cpu::GFX_HEIGHT;
use cpu::cpu::GFX_WIDTH;
use self::command::Command;

pub struct Debugger {
    cpu: Cpu,
    last_commad: Option<Command>,
}

impl Debugger {
    pub fn new(cpu: Cpu) -> Debugger {
        Debugger {
            cpu: cpu,
            last_commad: None,
        }
    }

    pub fn run(&mut self) {
        let mut cnt = 1;
        loop {
            print!("chip8:{}> ", cnt);
            stdout().flush().unwrap();

            let command = match (read_stdin().parse(), self.last_commad) {
                (Ok(Command::Repeat), Some(c)) => Ok(c),
                (Ok(Command::Repeat), None) => Err("No last command".into()),
                (Ok(c), _) => Ok(c),
                (Err(e), _) => Err(e),
            };

            match command {
                Ok(Command::Step(count)) => self.step(count),
                Ok(Command::Exit) => break,
                Ok(Command::Repeat) => unreachable!(),
                Err(ref e) => println!("{}", e),
            }

            self.last_commad = command.ok();
            cnt += 1;
        }
    }

    pub fn step(&mut self, count: usize) {
        for _ in 0..count {
            let curr_pc = self.cpu.curr_pc();
            let curr_index = self.cpu.curr_index();
            let curr_opcode = self.cpu.curr_opcode();
            let curr_regs = self.cpu.curr_regs();
            let curr_stack = self.cpu.curr_stack();
            let curr_sp = self.cpu.curr_sp();
            let curr_gfx = self.cpu.curr_gfx();

            print!("pc:{:04X},", curr_pc);
            print!("index:{:04X},", curr_index);
            println!("opcode:{:04X}", curr_opcode);
            println!("=============================================");

            println!("stack:");
            print_stack(curr_stack, curr_sp);
            println!("=============================================");
            println!("registers:");
            print_regs(curr_regs);
            println!("=============================================");
            println!("screen:");
            print_gfx(curr_gfx);
            println!("=============================================");

            self.cpu.emulate_cycle();
        }
    }
}

fn print_gfx(gfx: Vec<u8>) {
    for i in 0..GFX_HEIGHT {
        for j in 0..GFX_WIDTH {
            print!("{}", gfx[(i * GFX_WIDTH + j) as usize]);
        }
        println!();
    }
}

fn print_regs(regs: Vec<u8>) {
    println!("| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F|");
    for i in 0..regs.len() {
        print!("|{:02X}", regs[i as usize]);
    }
    println!("|");
}

fn print_stack(stack: Vec<usize>, sp: usize) {
    for i in 0..stack.len() {
        print!("|");
        if i == sp {
            print!("[");
        }
        print!("{:04X}", stack[i as usize]);
        if i == sp {
            print!("]");
        }
    }
    println!("|");
}

fn read_stdin() -> String {
    let mut input = String::new();
    stdin().read_line(&mut input).unwrap();
    input.trim().into()
}
<commit_msg>Change print screen function to be more readable<commit_after>mod command;

use std::io::{stdin, stdout};
use std::io::prelude::*;
use std::borrow::Cow;

use cpu::cpu::Cpu;
use cpu::cpu::GFX_HEIGHT;
use cpu::cpu::GFX_WIDTH;
use self::command::Command;

pub struct Debugger {
    cpu: Cpu,
    last_commad: Option<Command>,
}

impl Debugger {
    pub fn new(cpu: Cpu) -> Debugger {
        Debugger {
            cpu: cpu,
            last_commad: None,
        }
    }

    pub fn run(&mut self) {
        let mut cnt = 1;
        loop {
            print!("chip8:{}> ", cnt);
            stdout().flush().unwrap();

            let command = match (read_stdin().parse(), self.last_commad) {
                (Ok(Command::Repeat), Some(c)) => Ok(c),
                (Ok(Command::Repeat), None) => Err("No last command".into()),
                (Ok(c), _) => Ok(c),
                (Err(e), _) => Err(e),
            };

            match command {
                Ok(Command::Step(count)) => self.step(count),
                Ok(Command::Exit) => break,
                Ok(Command::Repeat) => unreachable!(),
                Err(ref e) => println!("{}", e),
            }

            self.last_commad = command.ok();
            cnt += 1;
        }
    }

    pub fn step(&mut self, count: usize) {
        for _ in 0..count {
            let curr_pc = self.cpu.curr_pc();
            let curr_index = self.cpu.curr_index();
            let curr_opcode = self.cpu.curr_opcode();
            let curr_regs = self.cpu.curr_regs();
            let curr_stack = self.cpu.curr_stack();
            let curr_sp = self.cpu.curr_sp();
            let curr_gfx = self.cpu.curr_gfx();

            print!("pc:{:04X},", curr_pc);
            print!("index:{:04X},", curr_index);
            println!("opcode:{:04X}", curr_opcode);
            println!("=============================================");

            println!("stack:");
            print_stack(curr_stack, curr_sp);
            println!("=============================================");
            println!("registers:");
            print_regs(curr_regs);
            println!("=============================================");
            println!("screen:");
            print_gfx(curr_gfx);
            println!("=============================================");

            self.cpu.emulate_cycle();
        }
    }
}

fn print_gfx(gfx: Vec<u8>) {
    for _ in 0..GFX_WIDTH {
        print!("-");
    }
    println!("--");
    for i in 0..GFX_HEIGHT {
        print!("|");
        for j in 0..GFX_WIDTH {
            // print!("{}", gfx[(i * GFX_WIDTH + j) as usize]);
            if gfx[(i * GFX_WIDTH + j) as usize] == 1 {
                print!("*");
            } else {
                print!(" ");
            }
        }
        println!("|");
    }
    for _ in 0..GFX_WIDTH {
        print!("-");
    }
    println!("--");
}

fn print_regs(regs: Vec<u8>) {
    println!("| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| A| B| C| D| E| F|");
    for i in 0..regs.len() {
        print!("|{:02X}", regs[i as usize]);
    }
    println!("|");
}

fn print_stack(stack: Vec<usize>, sp: usize) {
    for i in 0..stack.len() {
        print!("|");
        if i == sp {
            print!("[");
        }
        print!("{:04X}", stack[i as usize]);
        if i == sp {
            print!("]");
        }
    }
    println!("|");
}

fn read_stdin() -> String {
    let mut input = String::new();
    stdin().read_line(&mut input).unwrap();
    input.trim().into()
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      if camera.model == "DSLR-A100" {
        return self.image_a100(camera)
      } else { // try decoding as SRF
        return self.image_srf(camera)
      }
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let mut height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts).get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression).get_u32(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample).get_u32(0)
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => {
        if camera.model == "DSC-R1" {
          decode_14be_unpacked(src, width as usize, height as usize)
        } else {
          decode_16le(src, width as usize, height as usize)
        }
      }
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          height += 8;
          ArwDecoder::decode_arw1(src, width as usize, height as usize)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width as usize, height as usize, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn image_a100(&self, camera: &Camera) -> Result<Image,String> {
    // We've caught the elusive A100 in the wild, a transitional format
    // between the simple sanity of the MRW custom format and the wordly
    // wonderfullness of the Tiff-based ARW format, let's shoot from the hip
    let data = self.tiff.find_ifds_with_tag(Tag::SubIFDs);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = 3881;
    let height = 2608;
    let offset = fetch_tag!(raw, Tag::SubIFDs).get_u32(0) as usize;

    let src = &self.buffer[offset .. self.buffer.len()];
    let image = ArwDecoder::decode_arw1(src, width as usize, height as usize);

    // Get the WB the MRW way
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea).get_u32(0);
    let buf = &self.buffer[priv_offset as usize..];
    let mut currpos: usize = 8;
    let mut wb_vals: [u16;4] = [0;4];
    // At most we read 20 bytes from currpos so check we don't step outside that
    while currpos+20 < buf.len() {
      let tag: u32 = BEu32(buf,currpos);
      let len: u32 = LEu32(buf,currpos+4);
      if tag == 0x574247 { // WBG
        for i in 0..4 {
          wb_vals[i] = LEu16(buf, currpos+12+i*2);
        }
        break;
      }
      currpos += (len+8) as usize;
    }
    let wb_coeffs = [wb_vals[0] as f32, wb_vals[1] as f32, wb_vals[3] as f32, f32::NAN];

    ok_image(camera, width, height, wb_coeffs, image)
  }

  fn image_srf(&self, camera: &Camera) -> Result<Image,String> {
    let data = self.tiff.find_ifds_with_tag(Tag::ImageWidth);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];

    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);
    let len = (width*height*2) as usize;

    // Constants taken from dcraw
    let off: usize = 862144;
    let key_off: usize = 200896;
    let head_off: usize = 164600;

    // Replicate the dcraw contortions to get the "decryption" key
    let offset = (self.buffer[key_off as usize] as usize)*4;
    let first_key = BEu32(self.buffer, key_off+offset);
    let head = ArwDecoder::sony_decrypt(self.buffer, head_off, 40, first_key);
    let second_key = LEu32(&head, 22);

    // "Decrypt" the whole image buffer
    let image_data = ArwDecoder::sony_decrypt(self.buffer, off, len, second_key);
    let image = decode_16be(&image_data, width as usize, height as usize);

    ok_image(camera, width, height, [f32::NAN,f32::NAN,f32::NAN,f32::NAN], image)
  }

  fn decode_arw1(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
    let mut pump = BitPumpMSB::new(buf);
    let mut out: Vec<u16> = vec![0; (width*height) as usize];

    let mut sum: i32 = 0;
    for x in 0..width {
      let col = width-1-x;
      let mut row = 0;
      while row <= height {
        if row == height {
          row = 1;
        }

        let mut len: u32 = 4 - pump.get_bits(2);
        if len == 3 && pump.get_bits(1) != 0 {
          len = 0;
        } else if len == 4 {
          let zeros = pump.peek_bits(13).leading_zeros() - 19;
          len += zeros;
          pump.get_bits(cmp::min(13, zeros+1));
        }
        let diff: i32 = pump.get_ibits(len);
        sum += diff;
        if len > 0 && (diff & (1 << (len - 1))) == 0 {
          sum -= (1 << len) - 1;
        }
        out[row*width+col] = sum as u16;
        row += 2
      }
    }
    out
  }

  fn decode_arw2(buf: &[u8], width: usize, height: usize, curve: &LookupTable) -> Vec<u16> {
    decode_threaded(width, height, &(|out: &mut [u16], row| {
      let mut pump = BitPumpLSB::new(&buf[(row*width)..]);

      // Process 16 pixels at a time in interleaved fashion
      let mut col = 0;
      let mut random = pump.peek_bits(24);
      while col < (width-30) {
        let max = pump.get_bits(11);
        let min = pump.get_bits(11);
        let delta = max-min;
        // Calculate the size of the data shift needed by how large the delta is
        // A delta with 11 bits requires a shift of 4, 10 bits of 3, etc
        let delta_shift: u32 = cmp::max(0, (32-(delta.leading_zeros() as i32)) - 7) as u32;
        let imax = pump.get_bits(4);
        let imin = pump.get_bits(4);

        for i in 0..16 {
          let val = if i == imax {
            max
          } else if i == imin {
            min
          } else {
            cmp::min(0x7ff,(pump.get_bits(7) << delta_shift) + min)
          };
          out[col+(i*2) as usize] = curve.dither((val<<1) as u16, &mut random);
        }
        col += if (col & 1) != 0 {31} else {1};  // Skip to next 16 pixels
      }
    }))
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea).get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN).unwrap();
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset).get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength).get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey).get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN).unwrap();
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u32(1) as f32, levels.get_u32(0) as f32, levels.get_u32(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u32(0) as f32, levels.get_u32(1) as f32, levels.get_u32(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve);
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u32(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    let mut out = Vec::with_capacity(length+4);
    for i in 0..(length/4+1) {
      let p = i + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i*4) ^ pad[p & 127];
      let bytes: [u8;4] = unsafe { transmute(output.to_le()) };
      out.push(bytes[0]);
      out.push(bytes[1]);
      out.push(bytes[2]);
      out.push(bytes[3]);
    }
    out
  }
}
<commit_msg>ARW: slight cleanup and possibly speedup<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::basics::*;
use std::mem::transmute;
use std::f32;
use std::cmp;

#[derive(Debug, Clone)]
pub struct ArwDecoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> ArwDecoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> ArwDecoder<'a> {
    ArwDecoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for ArwDecoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let data = self.tiff.find_ifds_with_tag(Tag::StripOffsets);
    if data.len() == 0 {
      if camera.model == "DSLR-A100" {
        return self.image_a100(camera)
      } else { // try decoding as SRF
        return self.image_srf(camera)
      }
    }
    let raw = data[0];
    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let mut height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_u32(0) as usize;
    let count = fetch_tag!(raw, Tag::StripByteCounts).get_u32(0) as usize;
    let compression = fetch_tag!(raw, Tag::Compression).get_u32(0);
    let bps = if camera.bps != 0 {
      camera.bps
    } else {
      fetch_tag!(raw, Tag::BitsPerSample).get_u32(0)
    };
    let src = &self.buffer[offset .. self.buffer.len()];

    let image = match compression {
      1 => {
        if camera.model == "DSC-R1" {
          decode_14be_unpacked(src, width as usize, height as usize)
        } else {
          decode_16le(src, width as usize, height as usize)
        }
      }
      32767 => {
        if ((width*height*bps) as usize) != count*8 {
          height += 8;
          ArwDecoder::decode_arw1(src, width as usize, height as usize)
        } else {
          match bps {
            8 => {let curve = try!(ArwDecoder::get_curve(raw)); ArwDecoder::decode_arw2(src, width as usize, height as usize, &curve)},
            12 => decode_12le(src, width as usize, height as usize),
            _ => return Err(format!("ARW2: Don't know how to decode images with {} bps", bps)),
          }
        }
      },
      _ => return Err(format!("ARW: Don't know how to decode type {}", compression).to_string()),
    };

    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> ArwDecoder<'a> {
  fn image_a100(&self, camera: &Camera) -> Result<Image,String> {
    // We've caught the elusive A100 in the wild, a transitional format
    // between the simple sanity of the MRW custom format and the wordly
    // wonderfullness of the Tiff-based ARW format, let's shoot from the hip
    let data = self.tiff.find_ifds_with_tag(Tag::SubIFDs);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];
    let width = 3881;
    let height = 2608;
    let offset = fetch_tag!(raw, Tag::SubIFDs).get_u32(0) as usize;

    let src = &self.buffer[offset .. self.buffer.len()];
    let image = ArwDecoder::decode_arw1(src, width as usize, height as usize);

    // Get the WB the MRW way
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea).get_u32(0);
    let buf = &self.buffer[priv_offset as usize..];
    let mut currpos: usize = 8;
    let mut wb_vals: [u16;4] = [0;4];
    // At most we read 20 bytes from currpos so check we don't step outside that
    while currpos+20 < buf.len() {
      let tag: u32 = BEu32(buf,currpos);
      let len: u32 = LEu32(buf,currpos+4);
      if tag == 0x574247 { // WBG
        for i in 0..4 {
          wb_vals[i] = LEu16(buf, currpos+12+i*2);
        }
        break;
      }
      currpos += (len+8) as usize;
    }
    let wb_coeffs = [wb_vals[0] as f32, wb_vals[1] as f32, wb_vals[3] as f32, f32::NAN];

    ok_image(camera, width, height, wb_coeffs, image)
  }

  fn image_srf(&self, camera: &Camera) -> Result<Image,String> {
    let data = self.tiff.find_ifds_with_tag(Tag::ImageWidth);
    if data.len() == 0 {
      return Err("ARW: Couldn't find the data IFD!".to_string())
    }
    let raw = data[0];

    let width = fetch_tag!(raw, Tag::ImageWidth).get_u32(0);
    let height = fetch_tag!(raw, Tag::ImageLength).get_u32(0);
    let len = (width*height*2) as usize;

    // Constants taken from dcraw
    let off: usize = 862144;
    let key_off: usize = 200896;
    let head_off: usize = 164600;

    // Replicate the dcraw contortions to get the "decryption" key
    let offset = (self.buffer[key_off as usize] as usize)*4;
    let first_key = BEu32(self.buffer, key_off+offset);
    let head = ArwDecoder::sony_decrypt(self.buffer, head_off, 40, first_key);
    let second_key = LEu32(&head, 22);

    // "Decrypt" the whole image buffer
    let image_data = ArwDecoder::sony_decrypt(self.buffer, off, len, second_key);
    let image = decode_16be(&image_data, width as usize, height as usize);

    ok_image(camera, width, height, [f32::NAN,f32::NAN,f32::NAN,f32::NAN], image)
  }

  fn decode_arw1(buf: &[u8], width: usize, height: usize) -> Vec<u16> {
    let mut pump = BitPumpMSB::new(buf);
    let mut out: Vec<u16> = vec![0; (width*height) as usize];

    let mut sum: i32 = 0;
    for x in 0..width {
      let col = width-1-x;
      let mut row = 0;
      while row <= height {
        if row == height {
          row = 1;
        }

        let mut len: u32 = 4 - pump.get_bits(2);
        if len == 3 && pump.get_bits(1) != 0 {
          len = 0;
        } else if len == 4 {
          let zeros = pump.peek_bits(13).leading_zeros() - 19;
          len += zeros;
          pump.get_bits(cmp::min(13, zeros+1));
        }
        let diff: i32 = pump.get_ibits(len);
        sum += diff;
        if len > 0 && (diff & (1 << (len - 1))) == 0 {
          sum -= (1 << len) - 1;
        }
        out[row*width+col] = sum as u16;
        row += 2
      }
    }
    out
  }

  fn decode_arw2(buf: &[u8], width: usize, height: usize, curve: &LookupTable) -> Vec<u16> {
    decode_threaded(width, height, &(|out: &mut [u16], row| {
      let mut pump = BitPumpLSB::new(&buf[(row*width)..]);

      let mut random = pump.peek_bits(24);
      for out in out.chunks_mut(32) {
        // Process 32 pixels at a time in interleaved fashion
        for j in 0..2 {
          let max = pump.get_bits(11);
          let min = pump.get_bits(11);
          let delta = max-min;
          // Calculate the size of the data shift needed by how large the delta is
          // A delta with 11 bits requires a shift of 4, 10 bits of 3, etc
          let delta_shift: u32 = cmp::max(0, (32-(delta.leading_zeros() as i32)) - 7) as u32;
          let imax = pump.get_bits(4);
          let imin = pump.get_bits(4);

          for i in 0..16 {
            let val = if i == imax {
              max
            } else if i == imin {
              min
            } else {
              cmp::min(0x7ff,(pump.get_bits(7) << delta_shift) + min)
            };
            out[j+(i*2) as usize] = curve.dither((val<<1) as u16, &mut random);
          }
        }
      }
    }))
  }

  fn get_wb(&self) -> Result<[f32;4], String> {
    let priv_offset = fetch_tag!(self.tiff, Tag::DNGPrivateArea).get_u32(0);
    let priv_tiff = TiffIFD::new(self.buffer, priv_offset as usize, 0, 0, LITTLE_ENDIAN).unwrap();
    let sony_offset = fetch_tag!(priv_tiff, Tag::SonyOffset).get_u32(0) as usize;
    let sony_length = fetch_tag!(priv_tiff, Tag::SonyLength).get_u32(0) as usize;
    let sony_key = fetch_tag!(priv_tiff, Tag::SonyKey).get_u32(0);
    let decrypted_buf = ArwDecoder::sony_decrypt(self.buffer, sony_offset, sony_length, sony_key);
    let decrypted_tiff = TiffIFD::new(&decrypted_buf, 0, sony_offset, 0, LITTLE_ENDIAN).unwrap();
    let grgb_levels = decrypted_tiff.find_entry(Tag::SonyGRBG);
    let rggb_levels = decrypted_tiff.find_entry(Tag::SonyRGGB);
    if grgb_levels.is_some() {
      let levels = grgb_levels.unwrap();
      Ok([levels.get_u32(1) as f32, levels.get_u32(0) as f32, levels.get_u32(2) as f32, f32::NAN])
    } else if rggb_levels.is_some() {
      let levels = rggb_levels.unwrap();
      Ok([levels.get_u32(0) as f32, levels.get_u32(1) as f32, levels.get_u32(3) as f32, f32::NAN])
    } else {
      Err("ARW: Couldn't find GRGB or RGGB levels".to_string())
    }
  }

  fn get_curve(raw: &TiffIFD) -> Result<LookupTable, String> {
    let centry = fetch_tag!(raw, Tag::SonyCurve);
    let mut curve: [u32;6] = [ 0, 0, 0, 0, 0, 4095 ];

    for i in 0..4 {
      curve[i+1] = ((centry.get_u32(i) >> 2) & 0xfff) as u32;
    }

    let mut out = vec![0 as u16; (curve[5]+1) as usize];
    for i in 0..5 {
      for j in (curve[i]+1)..(curve[i+1]+1) {
        out[j as usize] = out[(j-1) as usize] + (1<<i);
      }
    }

    Ok(LookupTable::new(&out))
  }

  fn sony_decrypt(buf: &[u8], offset: usize, length: usize, key: u32) -> Vec<u8>{
    let mut pad: [u32; 128] = [0 as u32; 128];
    let mut mkey = key;
    // Initialize the decryption pad from the key
    for p in 0..4 {
      mkey = mkey.wrapping_mul(48828125).wrapping_add(1);
      pad[p] = mkey;
    }
    pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
    for p in 4..127 {
      pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
    }
    for p in 0..127 {
      pad[p] = u32::from_be(pad[p]);
    }

    let mut out = Vec::with_capacity(length+4);
    for i in 0..(length/4+1) {
      let p = i + 127;
      pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
      let output = LEu32(buf, offset+i*4) ^ pad[p & 127];
      let bytes: [u8;4] = unsafe { transmute(output.to_le()) };
      out.push(bytes[0]);
      out.push(bytes[1]);
      out.push(bytes[2]);
      out.push(bytes[3]);
    }
    out
  }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
use euclid::{Point2D, Size2D};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: MsgSender<ApiMsg>,
               payload_sender: PayloadSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: MsgSender<ApiMsg>,
    pub payload_sender: PayloadSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Gets the dimensions for the supplied glyph keys
    ///
    /// Note: Internally, the internal texture cache doesn't store
    /// 'empty' textures (height or width = 0)
    /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
    pub fn get_glyph_dimensions(&self, glyph_keys: Vec<GlyphKey>)
                                -> Vec<Option<GlyphDimensions>> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::GetGlyphDimensions(glyph_keys, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    /// Creates an `ImageKey`.
    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    /// Adds an image and returns the corresponding `ImageKey`.
    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     stride: Option<u32>,
                     format: ImageFormat,
                     data: ImageData) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, stride, format, data);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Flushes all messages and will send a notification when the render
    /// backend thread has finished processing all previous messages.
    /// This is a temporary API And users should not expect this to be API
    /// to exist in the future.
    pub fn flush(&self) {
        let msg = ApiMsg::Flush;
        self.api_sender.send(msg).unwrap();
    }

    /// Updates a specific image.
    ///
    /// Currently doesn't support changing dimensions or format by updating.
    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    /// Deletes the specific image.
    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    /// Sets the root pipeline.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
    /// let api = sender.create_api();
    /// ...
    /// let pipeline_id = PipelineId(0,0);
    /// api.set_root_pipeline(pipeline_id);
    /// ```
    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the display list.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [new_frame_ready()][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `display_list`: The root Display list used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_display_list(&self,
                                 background_color: ColorF,
                                 epoch: Epoch,
                                 pipeline_id: PipelineId,
                                 viewport_size: Size2D<f32>,
                                 display_list: BuiltDisplayList,
                                 auxiliary_lists: AuxiliaryLists) {
        let msg = ApiMsg::SetRootDisplayList(background_color,
                                             epoch,
                                             pipeline_id,
                                             viewport_size,
                                             display_list.descriptor().clone(),
                                             *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();
        payload.extend_from_slice(display_list.data());
        payload.extend_from_slice(auxiliary_lists.data());
        self.payload_sender.send_vec(payload).unwrap();
    }

    /// Scrolls the scrolling layer under the `cursor`
    ///
    /// Webrender looks for the layer closest to the user
    /// which has `ScrollPolicy::Scrollable` set.
    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    /// Translates a point from viewport coordinates to layer space
    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn resize_webgl_context(&self, context_id: WebGLContextId, size: &Size2D<i32>) {
        let msg = ApiMsg::ResizeWebGLContext(context_id, *size);
        self.api_sender.send(msg).unwrap();
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    pub fn generate_frame(&self) {
        let msg = ApiMsg::GenerateFrame;
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<commit_msg>Auto merge of #580 - JerryShih:reuse-alloc_image-func, r=glennw<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use byteorder::{LittleEndian, WriteBytesExt};
use channel::{self, MsgSender, PayloadHelperMethods, PayloadSender};
use euclid::{Point2D, Size2D};
use offscreen_gl_context::{GLContextAttributes, GLLimits};
use std::cell::Cell;
use {ApiMsg, AuxiliaryLists, BuiltDisplayList, ColorF, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState};
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};

impl RenderApiSender {
    pub fn new(api_sender: MsgSender<ApiMsg>,
               payload_sender: PayloadSender)
               -> RenderApiSender {
        RenderApiSender {
            api_sender: api_sender,
            payload_sender: payload_sender,
        }
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender {
            ref api_sender,
            ref payload_sender
        } = *self;
        let (sync_tx, sync_rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        api_sender.send(msg).unwrap();
        RenderApi {
            api_sender: api_sender.clone(),
            payload_sender: payload_sender.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub api_sender: MsgSender<ApiMsg>,
    pub payload_sender: PayloadSender,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.api_sender.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Gets the dimensions for the supplied glyph keys
    ///
    /// Note: Internally, the internal texture cache doesn't store
    /// 'empty' textures (height or width = 0)
    /// This means that glyph dimensions e.g. for spaces (' ') will mostly be None.
    pub fn get_glyph_dimensions(&self, glyph_keys: Vec<GlyphKey>)
                                -> Vec<Option<GlyphDimensions>> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::GetGlyphDimensions(glyph_keys, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    /// Creates an `ImageKey`.
    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    /// Adds an image and returns the corresponding `ImageKey`.
    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     stride: Option<u32>,
                     format: ImageFormat,
                     data: ImageData) -> ImageKey {
        let key = self.alloc_image();
        let msg = ApiMsg::AddImage(key, width, height, stride, format, data);
        self.api_sender.send(msg).unwrap();
        key
    }

    /// Flushes all messages and will send a notification when the render
    /// backend thread has finished processing all previous messages.
    /// This is a temporary API And users should not expect this to be API
    /// to exist in the future.
    pub fn flush(&self) {
        let msg = ApiMsg::Flush;
        self.api_sender.send(msg).unwrap();
    }

    /// Updates a specific image.
    ///
    /// Currently doesn't support changing dimensions or format by updating.
    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.api_sender.send(msg).unwrap();
    }

    /// Deletes the specific image.
    pub fn delete_image(&self, key: ImageKey) {
        let msg = ApiMsg::DeleteImage(key);
        self.api_sender.send(msg).unwrap();
    }

    /// Sets the root pipeline.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// let (mut renderer, sender) = webrender::renderer::Renderer::new(opts);
    /// let api = sender.create_api();
    /// ...
    /// let pipeline_id = PipelineId(0,0);
    /// api.set_root_pipeline(pipeline_id);
    /// ```
    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.api_sender.send(msg).unwrap();
    }

    /// Supplies a new frame to WebRender.
    ///
    /// Non-blocking, it notifies a worker process which processes the display list.
    /// When it's done and a RenderNotifier has been set in `webrender::renderer::Renderer`,
    /// [new_frame_ready()][notifier] gets called.
    ///
    /// Note: Scrolling doesn't require an own Frame.
    ///
    /// Arguments:
    ///
    /// * `background_color`: The background color of this pipeline.
    /// * `epoch`: The unique Frame ID, monotonically increasing.
    /// * `pipeline_id`: The ID of the pipeline that is supplying this display list.
    /// * `viewport_size`: The size of the viewport for this frame.
    /// * `display_list`: The root Display list used in this frame.
    /// * `auxiliary_lists`: Various items that the display lists and stacking contexts reference.
    ///
    /// [notifier]: trait.RenderNotifier.html#tymethod.new_frame_ready
    pub fn set_root_display_list(&self,
                                 background_color: ColorF,
                                 epoch: Epoch,
                                 pipeline_id: PipelineId,
                                 viewport_size: Size2D<f32>,
                                 display_list: BuiltDisplayList,
                                 auxiliary_lists: AuxiliaryLists) {
        let msg = ApiMsg::SetRootDisplayList(background_color,
                                             epoch,
                                             pipeline_id,
                                             viewport_size,
                                             display_list.descriptor().clone(),
                                             *auxiliary_lists.descriptor());
        self.api_sender.send(msg).unwrap();

        let mut payload = vec![];
        payload.write_u32::<LittleEndian>(epoch.0).unwrap();
        payload.extend_from_slice(display_list.data());
        payload.extend_from_slice(auxiliary_lists.data());
        self.payload_sender.send_vec(payload).unwrap();
    }

    /// Scrolls the scrolling layer under the `cursor`
    ///
    /// Webrender looks for the layer closest to the user
    /// which has `ScrollPolicy::Scrollable` set.
    pub fn scroll(&self, delta: Point2D<f32>, cursor: Point2D<f32>, phase: ScrollEventPhase) {
        let msg = ApiMsg::Scroll(delta, cursor, phase);
        self.api_sender.send(msg).unwrap();
    }

    pub fn tick_scrolling_bounce_animations(&self) {
        let msg = ApiMsg::TickScrollingBounce;
        self.api_sender.send(msg).unwrap();
    }

    /// Translates a point from viewport coordinates to layer space
    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>)
                                          -> (Point2D<f32>, PipelineId) {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn get_scroll_layer_state(&self) -> Vec<ScrollLayerState> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::GetScrollLayerState(tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn request_webgl_context(&self, size: &Size2D<i32>, attributes: GLContextAttributes)
                                 -> Result<(WebGLContextId, GLLimits), String> {
        let (tx, rx) = channel::msg_channel().unwrap();
        let msg = ApiMsg::RequestWebGLContext(*size, attributes, tx);
        self.api_sender.send(msg).unwrap();
        rx.recv().unwrap()
    }

    pub fn resize_webgl_context(&self, context_id: WebGLContextId, size: &Size2D<i32>) {
        let msg = ApiMsg::ResizeWebGLContext(context_id, *size);
        self.api_sender.send(msg).unwrap();
    }

    pub fn send_webgl_command(&self, context_id: WebGLContextId, command: WebGLCommand) {
        let msg = ApiMsg::WebGLCommand(context_id, command);
        self.api_sender.send(msg).unwrap();
    }

    pub fn generate_frame(&self) {
        let msg = ApiMsg::GenerateFrame;
        self.api_sender.send(msg).unwrap();
    }

    #[inline]
    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}

<|endoftext|>


<commit_before>use nalgebra::DMatrix;
/// For a given a set of data vectors in the following format y = {y₁, y₂, ... yn}
/// and X = {xi₁, xi₂, ... xin}, where i 𝜖 1..k
///
/// computes the vector β = {β₁, β₂, ...βk} using ordinary least squares regression
fn get_coefficients(x: &DMatrix<f64>, y: &DMatrix<f64>) -> DMatrix<f64> {
    (x.transpose() * x).try_inverse().unwrap() * x.transpose() * y
}

#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
fn main() {
    let x = vec![
        1.47_f64, 1.50, 1.52, 1.55, 1.57, 1.60, 1.63, 1.65, 1.68, 1.70, 1.73, 1.75, 1.78, 1.80,
        1.83,
    ];

    let y = vec![
        52.21_f64, 53.12, 54.48, 55.84, 57.20, 58.57, 59.93, 61.29, 63.11, 64.47, 66.28, 68.10,
        69.92, 72.19, 74.46,
    ];

    // generate 1, x, and x^2
    let x = DMatrix::from_fn(x.len(), 3, |row, col| x[row].powi(col as i32));
    let y = DMatrix::from_vec(y.len(), 1, y);
    println!(
        "\u{3B2} parameters using least squares regression :{}",
        get_coefficients(&x, &y)
    );
}

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

    #[test]
    fn test_get_coefficients() {
        let x = DMatrix::from_vec(5, 1, vec![2_f64, 1., 3., 4., 5.]);
        let y = DMatrix::from_vec(5, 1, vec![1_f64, 2., 3., 4., 5.]);
        let result = get_coefficients(&x, &y);
        assert_approx_eq!(result[(0)], 0.9818181818181818);

        let x = DMatrix::from_vec(3, 2, vec![1_f64, 2., 1., 1., 1., 2.]);
        let y = DMatrix::from_vec(3, 1, vec![3_f64, 4., 5.]);
        let result = get_coefficients(&x, &y);
        assert_approx_eq!(result[(0)], 1.);
        assert_approx_eq!(result[(1)], 2.);
    }
}
<commit_msg>Use unicode literal<commit_after>use nalgebra::DMatrix;
/// For a given a set of data vectors in the following format y = {y₁, y₂, ... yn}
/// and X = {xi₁, xi₂, ... xin}, where i 𝜖 1..k
///
/// computes the vector β = {β₁, β₂, ...βk} using ordinary least squares regression
fn get_coefficients(x: &DMatrix<f64>, y: &DMatrix<f64>) -> DMatrix<f64> {
    (x.transpose() * x).try_inverse().unwrap() * x.transpose() * y
}

#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_possible_wrap)]
fn main() {
    let x = vec![
        1.47_f64, 1.50, 1.52, 1.55, 1.57, 1.60, 1.63, 1.65, 1.68, 1.70, 1.73, 1.75, 1.78, 1.80,
        1.83,
    ];

    let y = vec![
        52.21_f64, 53.12, 54.48, 55.84, 57.20, 58.57, 59.93, 61.29, 63.11, 64.47, 66.28, 68.10,
        69.92, 72.19, 74.46,
    ];

    // generate 1, x, and x^2
    let x = DMatrix::from_fn(x.len(), 3, |row, col| x[row].powi(col as i32));
    let y = DMatrix::from_vec(y.len(), 1, y);
    println!(
        "β parameters using least squares regression :{}",
        get_coefficients(&x, &y)
    );
}

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

    #[test]
    fn test_get_coefficients() {
        let x = DMatrix::from_vec(5, 1, vec![2_f64, 1., 3., 4., 5.]);
        let y = DMatrix::from_vec(5, 1, vec![1_f64, 2., 3., 4., 5.]);
        let result = get_coefficients(&x, &y);
        assert_approx_eq!(result[(0)], 0.9818181818181818);

        let x = DMatrix::from_vec(3, 2, vec![1_f64, 2., 1., 1., 1., 2.]);
        let y = DMatrix::from_vec(3, 1, vec![3_f64, 4., 5.]);
        let result = get_coefficients(&x, &y);
        assert_approx_eq!(result[(0)], 1.);
        assert_approx_eq!(result[(1)], 2.);
    }
}
<|endoftext|>


<commit_before>#[repr(packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<commit_msg>Add size function for elf section headers.<commit_after>#[repr(packed)]
pub struct ElfSectionTag {
    tag_type: u32,
    size: u32,
    num: u16,
    entsize: u16,
    shndx: u16,
    reserved: u16,
    first_section: ElfSectionHeader
}

impl ElfSectionTag {
    pub fn elf_sections(&'static self) -> ElfSectionIter {
        ElfSectionIter {
            current_section: &self.first_section,
            section_index: 0,
            total_sections: self.num as u32,
            entry_size: self.entsize as u64
        }
    }
}

#[repr(C)]
pub struct ElfSectionHeader {
    sh_name: u32,
    sh_type: u32,
    sh_flags: u64,
    sh_addr: u64,
    sh_offset: u64,
    sh_size: u64,
    sh_link: u32,
    sh_info: u32,
    sh_addralign: u64,
    sh_entsize: u64
}

impl ElfSectionHeader {
    pub fn name(&self) -> usize {
        self.sh_name as usize
    }

    pub fn section_type(&self) -> usize {
        self.sh_type as usize
    }

    pub fn start_address(&self) -> usize {
        self.sh_addr as usize
    }

    pub fn end_address(&self) -> usize {
        (self.sh_addr + self.sh_size) as usize
    }

    pub fn size(&self) -> usize {
        self.sh_size as usize
    }
}

pub struct ElfSectionIter {
    current_section: &'static ElfSectionHeader,
    section_index: u32,
    total_sections: u32,
    entry_size: u64
}

impl Iterator for ElfSectionIter {
    type Item = &'static ElfSectionHeader;

    fn next(&mut self) -> Option<Self::Item> {
        if self.section_index >= self.total_sections {
            return None;
        } else {
            let section = self.current_section;
            let next_section_addr =
                (self.current_section as *const ElfSectionHeader as u64) + self.entry_size;
            let next_section = unsafe {
                &*(next_section_addr as *const ElfSectionHeader)
            };

            self.current_section = next_section;
            self.section_index += 1;

            Some(section)
        }
    }
}
<|endoftext|>


<commit_before>use nom::{be_i8, be_i16, be_i32, be_i64, be_u8, be_u16, be_u32, be_u64, float, double};
use std::collections::HashMap;

pub type UOctet    = u8;
pub type UShort    = u16;
pub type ULong     = u32;
pub type ULongLong = u64;
pub type Timestamp = u64;

named!(pub short_string<&str>,
    do_parse!(
        length: be_u8             >>
        string: take_str!(length) >>
        (string)
    )
);

named!(pub long_string<&str>,
    do_parse!(
        length: be_u32            >>
        string: take_str!(length) >>
        (string)
    )
);
//a long string is a BE u32 followed by data. Maybe handle this in the state machine?

// Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or
// underlines, to a maximum length of 128 characters.
// The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD
// signal a connection exception with reply code 503 (syntax error).

#[derive(Clone,Debug,PartialEq)]
pub enum Value {
  Boolean(bool),
  ShortShortInt(i8),
  ShortShortUInt(u8),
  ShortInt(i16),
  ShortUInt(u16),
  LongInt(i32),
  LongUInt(u32),
  LongLongInt(i64),
  LongLongUInt(u64),
  Float(f32),
  Double(f64),
  Decimal(f32),
  ShortString(String),
  LongString(String),
  Array(Vec<Value>),
  Timestamp(u64),
  Table(HashMap<String,Value>),
  None
}

named!(pub value<Value>,
  switch!(map!(be_u8, |u| u as char),
    't' => call!(parse_boolean)          |
    //FIXME: the spec says b for i8, B for u8, but U for i16, u for u16, I for i32, i for u32, etc
    // is that right?
    'b' => call!(parse_short_short_int)  |
    'B' => call!(parse_short_short_uint) |
    'U' => call!(parse_short_int)        |
    'u' => call!(parse_short_uint)       |
    'I' => call!(parse_long_int)         |
    'i' => call!(parse_long_uint)        |
    'L' => call!(parse_long_long_int)    |
    'l' => call!(parse_long_long_uint)   |
    'f' => call!(parse_float)            |
    'd' => call!(parse_double)           |
    'D' => call!(parse_decimal)          |
    's' => call!(parse_short_string)     |
    'S' => call!(parse_long_string)      |
    'A' => call!(parse_array)            |
    'T' => call!(parse_timestamp)        |
    'F' => call!(parse_table)            |
    'V' => value!(Value::None)
  )
);
named!(pub field_name_value<(String, Value)>,
  tuple!(map!(short_string, |s:&str| s.to_string()), value)
);

named!(parse_boolean<Value>,
  map!(be_u8, |u| Value::Boolean(u != 0))
);

named!(parse_short_short_int<Value>,
  map!(be_i8, |i| Value::ShortShortInt(i))
);
named!(parse_short_short_uint<Value>,
  map!(be_u8, |i| Value::ShortShortUInt(i))
);
named!(parse_short_int<Value>,
  map!(be_i16, |i| Value::ShortInt(i))
);
named!(parse_short_uint<Value>,
  map!(be_u16, |i| Value::ShortUInt(i))
);
named!(parse_long_int<Value>,
  map!(be_i32, |i| Value::LongInt(i))
);
named!(parse_long_uint<Value>,
  map!(be_u32, |i| Value::LongUInt(i))
);
named!(parse_long_long_int<Value>,
  map!(be_i64, |i| Value::LongLongInt(i))
);
named!(parse_long_long_uint<Value>,
  map!(be_u64, |i| Value::LongLongUInt(i))
);
named!(parse_float<Value>,
  map!(float, |i| Value::Float(i))
);
named!(parse_double<Value>,
  map!(double, |i| Value::Double(i))
);
named!(parse_decimal<Value>,
  map!(float, |i| Value::Decimal(i))
);
named!(parse_short_string<Value>,
  map!(short_string, |s:&str| Value::ShortString(s.to_string()))
);

named!(parse_long_string<Value>,
  map!(long_string, |s:&str| Value::LongString(s.to_string()))
);

named!(parse_array<Value>,
  do_parse!(
    quantity: be_u32 >>
    //FIXME: the spec specifies a long int there, but a long uint for the table?
    vec: map!(count!(value, quantity as usize), |v| Value::Array(v)) >>
    (vec)
  )
);
named!(parse_timestamp<Value>,
  map!(be_u64, |i| Value::Timestamp(i))
);
named!(parse_table<Value>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(field_name_value)), |v:Vec<(String,Value)>| {
      Value::Table(v.iter().cloned().collect())
    }) >>
    (h)
  )
);

named!(pub field_table<HashMap<String,Value>>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(complete!(field_name_value))), |v:Vec<(String,Value)>| {
      v.iter().cloned().collect()
    }) >>
    (h)
  )
);
<commit_msg>fields generators<commit_after>use nom::{be_i8, be_i16, be_i32, be_i64, be_u8, be_u16, be_u32, be_u64, float, double};
use rusticata_macros::*;
use std::collections::HashMap;

pub type UOctet    = u8;
pub type UShort    = u16;
pub type ULong     = u32;
pub type ULongLong = u64;
pub type Timestamp = u64;

named!(pub short_string<&str>,
    do_parse!(
        length: be_u8             >>
        string: take_str!(length) >>
        (string)
    )
);

named!(pub long_string<&str>,
    do_parse!(
        length: be_u32            >>
        string: take_str!(length) >>
        (string)
    )
);

pub fn gen_short_string<'a>(x:(&'a mut [u8],usize), s: &str) -> Result<(&'a mut [u8],usize),GenError> {
  do_gen!(
    x,
    gen_be_u8!(s.len() as u8) >>
    gen_slice!(s.as_bytes())
  )
}

pub fn gen_long_string<'a>(x:(&'a mut [u8],usize), s: &str) -> Result<(&'a mut [u8],usize),GenError> {
  do_gen!(
    x,
    gen_be_u32!(s.len() as u32) >>
    gen_slice!(s.as_bytes())
  )
}

//a long string is a BE u32 followed by data. Maybe handle this in the state machine?

// Field names MUST start with a letter, '$' or '#' and may continue with letters, '$' or '#', digits, or
// underlines, to a maximum length of 128 characters.
// The server SHOULD validate field names and upon receiving an invalid field name, it SHOULD
// signal a connection exception with reply code 503 (syntax error).

#[derive(Clone,Debug,PartialEq)]
pub enum Value {
  Boolean(bool),
  ShortShortInt(i8),
  ShortShortUInt(u8),
  ShortInt(i16),
  ShortUInt(u16),
  LongInt(i32),
  LongUInt(u32),
  LongLongInt(i64),
  LongLongUInt(u64),
  Float(f32),
  Double(f64),
  Decimal(f32),
  ShortString(String),
  LongString(String),
  Array(Vec<Value>),
  Timestamp(u64),
  Table(HashMap<String,Value>),
  None
}

named!(pub value<Value>,
  switch!(map!(be_u8, |u| u as char),
    't' => call!(parse_boolean)          |
    //FIXME: the spec says b for i8, B for u8, but U for i16, u for u16, I for i32, i for u32, etc
    // is that right?
    'b' => call!(parse_short_short_int)  |
    'B' => call!(parse_short_short_uint) |
    'U' => call!(parse_short_int)        |
    'u' => call!(parse_short_uint)       |
    'I' => call!(parse_long_int)         |
    'i' => call!(parse_long_uint)        |
    'L' => call!(parse_long_long_int)    |
    'l' => call!(parse_long_long_uint)   |
    'f' => call!(parse_float)            |
    'd' => call!(parse_double)           |
    'D' => call!(parse_decimal)          |
    's' => call!(parse_short_string)     |
    'S' => call!(parse_long_string)      |
    'A' => call!(parse_array)            |
    'T' => call!(parse_timestamp)        |
    'F' => call!(parse_table)            |
    'V' => value!(Value::None)
  )
);

named!(pub field_name_value<(String, Value)>,
  tuple!(map!(short_string, |s:&str| s.to_string()), value)
);

named!(parse_boolean<Value>,
  map!(be_u8, |u| Value::Boolean(u != 0))
);

named!(parse_short_short_int<Value>,
  map!(be_i8, |i| Value::ShortShortInt(i))
);
named!(parse_short_short_uint<Value>,
  map!(be_u8, |i| Value::ShortShortUInt(i))
);
named!(parse_short_int<Value>,
  map!(be_i16, |i| Value::ShortInt(i))
);
named!(parse_short_uint<Value>,
  map!(be_u16, |i| Value::ShortUInt(i))
);
named!(parse_long_int<Value>,
  map!(be_i32, |i| Value::LongInt(i))
);
named!(parse_long_uint<Value>,
  map!(be_u32, |i| Value::LongUInt(i))
);
named!(parse_long_long_int<Value>,
  map!(be_i64, |i| Value::LongLongInt(i))
);
named!(parse_long_long_uint<Value>,
  map!(be_u64, |i| Value::LongLongUInt(i))
);
named!(parse_float<Value>,
  map!(float, |i| Value::Float(i))
);
named!(parse_double<Value>,
  map!(double, |i| Value::Double(i))
);
named!(parse_decimal<Value>,
  map!(float, |i| Value::Decimal(i))
);
named!(parse_short_string<Value>,
  map!(short_string, |s:&str| Value::ShortString(s.to_string()))
);

named!(parse_long_string<Value>,
  map!(long_string, |s:&str| Value::LongString(s.to_string()))
);

named!(parse_array<Value>,
  do_parse!(
    quantity: be_u32 >>
    //FIXME: the spec specifies a long int there, but a long uint for the table?
    vec: map!(count!(value, quantity as usize), |v| Value::Array(v)) >>
    (vec)
  )
);
named!(parse_timestamp<Value>,
  map!(be_u64, |i| Value::Timestamp(i))
);
named!(parse_table<Value>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(field_name_value)), |v:Vec<(String,Value)>| {
      Value::Table(v.iter().cloned().collect())
    }) >>
    (h)
  )
);

named!(pub field_table<HashMap<String,Value>>,
  do_parse!(
    //FIXME: the spec specifies a long uint there, but a long int for the array?
    quantity: be_u32 >>
    h: map!(flat_map!(take!(quantity as usize), many0!(complete!(field_name_value))), |v:Vec<(String,Value)>| {
      v.iter().cloned().collect()
    }) >>
    (h)
  )
);

pub fn gen_value<'a>(x:(&'a mut [u8],usize), v: &Value) -> Result<(&'a mut [u8],usize),GenError> {
  match *v {
    Value::Boolean(ref b) => {
      do_gen!(x,
        gen_be_u8!('t' as u8) >>
        gen_be_u8!(*b as u8)
      )
    },
    /*
    Value::ShortShortInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('b' as u8) >>
        gen_be_i8!(i)
      )
    },
    */
    Value::ShortShortUInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('B' as u8) >>
        gen_be_u8!(*i)
      )
    },
    /*
    Value::ShortInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('U' as u8) >>
        gen_be_i16!(i)
      )
    },
    */
    Value::ShortInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('u' as u8) >>
        gen_be_u16!(*i)
      )
    },
    /*
    Value::LongInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('I' as u8) >>
        gen_be_i32!(*i)
      )
    },
    */
    Value::LongUInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('i' as u8) >>
        gen_be_u32!(*i)
      )
    },
    /*
    Value::LongLongInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('L' as u8) >>
        gen_be_i64!(*i)
      )
    },
    */
    Value::LongLongUInt(ref i) => {
      do_gen!(x,
        gen_be_u8!('l' as u8) >>
        gen_be_u64!(*i)
      )
    },
    /*
    Value::Float(f32),
    Value::Double(f64),
    Value::Decimal(f32),
    */
    Value::ShortString(ref s) => {
      do_gen!(x,
        gen_be_u8!('s' as u8) >>
        gen_short_string(&s)
      )
    },
    Value::LongString(ref s) => {
      do_gen!(x,
        gen_be_u8!('s' as u8) >>
        gen_long_string(&s)
      )
    },
    Value::Timestamp(ref i) => {
      do_gen!(x,
        gen_be_u8!('T' as u8) >>
        gen_be_u64!(*i)
      )
    },
    Value::Array(ref v) => {
      if let Ok((x1, index1)) = gen_be_u8!(x, 'A' as u8) {
        if let Ok((x2, index2)) = gen_many_ref!((x1, index1+4), v, gen_value) {
          if let Ok((x3,_)) = gen_be_u32!((x2, index1), index2 - index1 - 4) {
            Ok((x3, index2))
          } else {
            Err(GenError::CustomError(42))
          }
        } else {
          Err(GenError::CustomError(42))
        }
      } else {
        Err(GenError::CustomError(42))
      }
    },
    Value::Table(ref h) => {
      if let Ok((x1, index1)) = gen_be_u8!(x, 'F' as u8) {
        if let Ok((x2, index2)) = gen_many_ref!((x1, index1+4), h, gen_field_value) {
          if let Ok((x3,_)) = gen_be_u32!((x2, index1), index2 - index1 - 4) {
            Ok((x3, index2))
          } else {
            Err(GenError::CustomError(42))
          }
        } else {
          Err(GenError::CustomError(42))
        }
      } else {
        Err(GenError::CustomError(42))
      }
    },
    /*
    Value::None
    */
    _ => Err(GenError::CustomError(1))
  }
}

pub fn gen_field_value<'a>(x:(&'a mut [u8],usize), kv: &(&String,&Value)) -> Result<(&'a mut [u8],usize),GenError> {
  do_gen!(x,
    gen_short_string(kv.0) >>
    gen_value(kv.1)
  )
}

<|endoftext|>