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

//! Adapters for various formats for [`Uuid`]s
//!
//! [`Uuid`]: ../struct.Uuid.html

use prelude::*;

mod core_support;

/// The length of a Hyphenated [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_HYPHENATED_LENGTH: usize = 36;

/// The length of a Simple [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_SIMPLE_LENGTH: usize = 32;

/// The length of a Urn [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_URN_LENGTH: usize = 45;

// TODO: documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidHyphenated(Uuid);
// TODO: documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidHyphenatedRef<'a>(&'a Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidSimple(Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidSimpleRef<'a>(&'a Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidUrn(Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidUrnRef<'a>(&'a Uuid);

impl Uuid {
    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_hyphenated(self) -> UuidHyphenated {
        UuidHyphenated::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_hyphenated_ref(&self) -> UuidHyphenatedRef {
        UuidHyphenatedRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_simple(self) -> UuidSimple {
        UuidSimple::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_simple_ref(&self) -> UuidSimpleRef {
        UuidSimpleRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_urn(self) -> UuidUrn {
        UuidUrn::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[inline]
    pub fn to_urn_ref(&self) -> UuidUrnRef {
        UuidUrnRef::from_uuid_ref(self)
    }
}

impl UuidHyphenated {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidHyphenated(uuid)
    }
}

impl<'a> UuidHyphenatedRef<'a> {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidHyphenatedRef(uuid)
    }
}

impl UuidSimple {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidSimple(uuid)
    }
}

impl<'a> UuidSimpleRef<'a> {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidSimpleRef(uuid)
    }
}

impl UuidUrn {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidUrn(uuid)
    }
}

impl<'a> UuidUrnRef<'a> {
    // TODO(kinggoesgaming): documentation
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidUrnRef(uuid)
    }
}
<commit_msg>have const and non-const variants<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Adapters for various formats for [`Uuid`]s
//!
//! [`Uuid`]: ../struct.Uuid.html

use prelude::*;

mod core_support;

/// The length of a Hyphenated [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_HYPHENATED_LENGTH: usize = 36;

/// The length of a Simple [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_SIMPLE_LENGTH: usize = 32;

/// The length of a Urn [`Uuid`] string.
///
/// [`Uuid`]: ../struct.Uuid.html
pub const UUID_URN_LENGTH: usize = 45;

// TODO: documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidHyphenated(Uuid);
// TODO: documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidHyphenatedRef<'a>(&'a Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidSimple(Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidSimpleRef<'a>(&'a Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidUrn(Uuid);
// TODO(kinggoesgaming): documentation
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct UuidUrnRef<'a>(&'a Uuid);

impl Uuid {
    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated(self) -> UuidHyphenated {
        UuidHyphenated::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_hyphenated(self) -> UuidHyphenated {
        UuidHyphenated::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_hyphenated_ref(&self) -> UuidHyphenatedRef {
        UuidHyphenatedRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_hyphenated_ref(&self) -> UuidHyphenatedRef {
        UuidHyphenatedRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple(self) -> UuidSimple {
        UuidSimple::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_simple(self) -> UuidSimple {
        UuidSimple::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_simple_ref(&self) -> UuidSimpleRef {
        UuidSimpleRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_simple_ref(&self) -> UuidSimpleRef {
        UuidSimpleRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn(self) -> UuidUrn {
        UuidUrn::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_urn(self) -> UuidUrn {
        UuidUrn::from_uuid(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(not(feature = "const_fn"))]
    #[inline]
    pub fn to_urn_ref(&self) -> UuidUrnRef {
        UuidUrnRef::from_uuid_ref(self)
    }

    // TODO(kinggoesgaming): documentation
    // TODO(kinggoesgaming): discuss to_ vs as_ vs into_
    #[cfg(feature = "const_fn")]
    #[inline]
    pub fn to_urn_ref(&self) -> UuidUrnRef {
        UuidUrnRef::from_uuid_ref(self)
    }
}

impl UuidHyphenated {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidHyphenated(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidHyphenated(uuid)
    }
}

impl<'a> UuidHyphenatedRef<'a> {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidHyphenatedRef(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidHyphenatedRef(uuid)
    }
}

impl UuidSimple {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidSimple(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidSimple(uuid)
    }
}

impl<'a> UuidSimpleRef<'a> {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidSimpleRef(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidSimpleRef(uuid)
    }
}

impl UuidUrn {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidUrn(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid(uuid: Uuid) -> Self {
        UuidUrn(uuid)
    }
}

impl<'a> UuidUrnRef<'a> {
    // TODO(kinggoesgaming): documentation
    #[cfg(not(feature = "const_fn"))]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidUrnRef(uuid)
    }

    // TODO(kinggoesgaming): documentation
    #[cfg(feature = "const_fn")]
    pub fn from_uuid_ref(uuid: &'a Uuid) -> Self {
        UuidUrnRef(uuid)
    }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasher, Hash};

use fixedbitset::FixedBitSet;

use utils::{HashIter, MyBuildHasherDefault};

/// Simple implementation of a [BloomFilter](https://en.wikipedia.org/wiki/Bloom_filter)
#[derive(Clone)]
pub struct BloomFilter<B = MyBuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    bs: FixedBitSet,
    k: usize,
    buildhasher: B,
}

impl BloomFilter {
    /// Create new, empty BloomFilter with internal parameters.
    ///
    /// - `k` is the number of hash functions
    /// - `m` is the number of bits used to store state
    pub fn with_params(m: usize, k: usize) -> BloomFilter {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_params_and_hash(m, k, bh)
    }

    /// Create new, empty BloomFilter with given properties.
    ///
    /// - `n` number of unique elements the BloomFilter is expected to hold, must be `> 0`
    /// - `p` false positive property when querying the BloomFilter after adding `n` unique
    ///   elements, must be `> 0` and `< 1`
    ///
    /// Panics if the parameters are not in range.
    pub fn with_properties(n: usize, p: f64) -> BloomFilter {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_properties_and_hash(n, p, bh)
    }
}

impl<B> BloomFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// Same as `with_params` but with specific `BuildHasher`.
    pub fn with_params_and_hash(m: usize, k: usize, buildhasher: B) -> BloomFilter<B> {
        BloomFilter {
            bs: FixedBitSet::with_capacity(m),
            k: k,
            buildhasher: buildhasher,
        }
    }

    /// Same as `with_properties` but with specific `BuildHasher`.
    pub fn with_properties_and_hash(n: usize, p: f64, buildhasher: B) -> BloomFilter<B> {
        assert!(n > 0);
        assert!(p > 0.);
        assert!(p < 1.);

        let k = (-p.log2()) as usize;
        let ln2 = (2f64).ln();
        let m = (-((n as f64) * p.ln()) / (ln2 * ln2)) as usize;

        BloomFilter::with_params_and_hash(m, k, buildhasher)
    }

    /// Get `k` (number of hash functions).
    pub fn k(&self) -> usize {
        self.k
    }

    /// Get `m` (number of stored bits).
    pub fn m(&self) -> usize {
        self.bs.len()
    }

    /// Get `BuildHasher`.
    pub fn buildhasher(&self) -> &B {
        &self.buildhasher
    }

    /// Add new element to the BloomFilter.
    ///
    /// If the same element is added multiple times or if an element results in the same hash
    /// signature, this method does not have any effect.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        for pos in HashIter::new(self.bs.len(), self.k, obj, &self.buildhasher) {
            self.bs.set(pos, true);
        }
    }

    /// Guess if the given element was added to the BloomFilter.
    pub fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        for pos in HashIter::new(self.bs.len(), self.k, obj, &self.buildhasher) {
            if !self.bs[pos] {
                return false;
            }
        }
        true
    }

    /// Clear state of the BloomFilter, so that it behaves like a fresh one.
    pub fn clear(&mut self) {
        self.bs.clear()
    }

    /// Check whether the BloomFilter is empty.
    pub fn is_empty(&self) -> bool {
        self.bs.ones().next().is_none()
    }

    /// Add the entire content of another bloomfilter to this BloomFilter.
    ///
    /// The result is the same as adding all elements added to `other` to `self` in the first
    /// place.
    ///
    /// Panics if `k`,`m` or `buildhasher` of the two BloomFilters are not identical.
    pub fn union(&mut self, other: &BloomFilter<B>) {
        assert_eq!(self.k, other.k);
        assert_eq!(self.bs.len(), other.bs.len());
        assert!(self.buildhasher == other.buildhasher);

        self.bs = &self.bs | &other.bs;
    }

    /// Guess the number of unique elements added to the BloomFilter.
    pub fn guess_n(&self) -> usize {
        let m = self.bs.len() as f64;
        let k = self.k as f64;
        let x = self.bs.ones().count() as f64;

        (-m / k * (1. - x / m).ln()) as usize
    }
}

impl fmt::Debug for BloomFilter {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "BloomFilter {{ m: {}, k: {} }}", self.bs.len(), self.k)
    }
}

impl<T> Extend<T> for BloomFilter
where
    T: Hash,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(&elem);
        }
    }
}

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

    #[test]
    fn getter() {
        let bf = BloomFilter::with_params(100, 2);
        assert_eq!(bf.k(), 2);
        assert_eq!(bf.m(), 100);
        bf.buildhasher();
    }

    #[test]
    fn empty() {
        let bf = BloomFilter::with_params(100, 2);
        assert!(!bf.query(&1));
    }

    #[test]
    fn add() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.add(&1);
        assert!(bf.query(&1));
        assert!(!bf.query(&2));
    }

    #[test]
    fn clear() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.add(&1);
        bf.clear();
        assert!(!bf.query(&1));
    }

    #[test]
    fn is_empty() {
        let mut bf = BloomFilter::with_params(100, 2);
        assert!(bf.is_empty());

        bf.add(&1);
        assert!(!bf.is_empty());

        bf.clear();
        assert!(bf.is_empty());
    }

    #[test]
    fn clone() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        bf1.add(&1);

        let bf2 = bf1.clone();
        bf1.add(&2);
        assert!(bf2.query(&1));
        assert!(!bf2.query(&2));
    }

    #[test]
    fn union() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        bf1.add(&1);
        assert!(bf1.query(&1));
        assert!(!bf1.query(&2));
        assert!(!bf1.query(&3));

        let mut bf2 = BloomFilter::with_params(100, 2);
        bf2.add(&2);
        assert!(!bf2.query(&1));
        assert!(bf2.query(&2));
        assert!(!bf2.query(&3));

        bf1.union(&bf2);
        assert!(bf1.query(&1));
        assert!(bf1.query(&2));
        assert!(!bf1.query(&3));
    }

    #[test]
    fn with_properties() {
        let bf = BloomFilter::with_properties(1000, 0.1);
        assert_eq!(bf.k(), 3);
        assert_eq!(bf.m(), 4792);
    }

    #[test]
    fn guess_n() {
        let mut bf = BloomFilter::with_params(100, 2);
        assert_eq!(bf.guess_n(), 0);

        bf.add(&1);
        assert_eq!(bf.guess_n(), 1);

        bf.add(&1);
        assert_eq!(bf.guess_n(), 1);

        bf.add(&2);
        assert_eq!(bf.guess_n(), 2);
    }

    #[test]
    fn debug() {
        let bf = BloomFilter::with_params(100, 2);
        assert_eq!(format!("{:?}", bf), "BloomFilter { m: 100, k: 2 }");
    }

    #[test]
    fn extend() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.extend(vec![1, 2]);
        assert!(bf.query(&1));
        assert!(bf.query(&2));
        assert!(!bf.query(&3));
    }
}
<commit_msg>bloomfilter: test asserts<commit_after>use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{BuildHasher, Hash};

use fixedbitset::FixedBitSet;

use utils::{HashIter, MyBuildHasherDefault};

/// Simple implementation of a [BloomFilter](https://en.wikipedia.org/wiki/Bloom_filter)
#[derive(Clone)]
pub struct BloomFilter<B = MyBuildHasherDefault<DefaultHasher>>
where
    B: BuildHasher + Clone + Eq,
{
    bs: FixedBitSet,
    k: usize,
    buildhasher: B,
}

impl BloomFilter {
    /// Create new, empty BloomFilter with internal parameters.
    ///
    /// - `k` is the number of hash functions
    /// - `m` is the number of bits used to store state
    pub fn with_params(m: usize, k: usize) -> BloomFilter {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_params_and_hash(m, k, bh)
    }

    /// Create new, empty BloomFilter with given properties.
    ///
    /// - `n` number of unique elements the BloomFilter is expected to hold, must be `> 0`
    /// - `p` false positive property when querying the BloomFilter after adding `n` unique
    ///   elements, must be `> 0` and `< 1`
    ///
    /// Panics if the parameters are not in range.
    pub fn with_properties(n: usize, p: f64) -> BloomFilter {
        let bh = MyBuildHasherDefault::<DefaultHasher>::default();
        Self::with_properties_and_hash(n, p, bh)
    }
}

impl<B> BloomFilter<B>
where
    B: BuildHasher + Clone + Eq,
{
    /// Same as `with_params` but with specific `BuildHasher`.
    pub fn with_params_and_hash(m: usize, k: usize, buildhasher: B) -> BloomFilter<B> {
        BloomFilter {
            bs: FixedBitSet::with_capacity(m),
            k: k,
            buildhasher: buildhasher,
        }
    }

    /// Same as `with_properties` but with specific `BuildHasher`.
    pub fn with_properties_and_hash(n: usize, p: f64, buildhasher: B) -> BloomFilter<B> {
        assert!(n > 0, "n must be greater than 0");
        assert!(
            (p > 0.) & (p < 1.),
            "p ({}) must be greater than 0 and smaller than 1",
            p
        );

        let k = (-p.log2()) as usize;
        let ln2 = (2f64).ln();
        let m = (-((n as f64) * p.ln()) / (ln2 * ln2)) as usize;

        BloomFilter::with_params_and_hash(m, k, buildhasher)
    }

    /// Get `k` (number of hash functions).
    pub fn k(&self) -> usize {
        self.k
    }

    /// Get `m` (number of stored bits).
    pub fn m(&self) -> usize {
        self.bs.len()
    }

    /// Get `BuildHasher`.
    pub fn buildhasher(&self) -> &B {
        &self.buildhasher
    }

    /// Add new element to the BloomFilter.
    ///
    /// If the same element is added multiple times or if an element results in the same hash
    /// signature, this method does not have any effect.
    pub fn add<T>(&mut self, obj: &T)
    where
        T: Hash,
    {
        for pos in HashIter::new(self.bs.len(), self.k, obj, &self.buildhasher) {
            self.bs.set(pos, true);
        }
    }

    /// Guess if the given element was added to the BloomFilter.
    pub fn query<T>(&self, obj: &T) -> bool
    where
        T: Hash,
    {
        for pos in HashIter::new(self.bs.len(), self.k, obj, &self.buildhasher) {
            if !self.bs[pos] {
                return false;
            }
        }
        true
    }

    /// Clear state of the BloomFilter, so that it behaves like a fresh one.
    pub fn clear(&mut self) {
        self.bs.clear()
    }

    /// Check whether the BloomFilter is empty.
    pub fn is_empty(&self) -> bool {
        self.bs.ones().next().is_none()
    }

    /// Add the entire content of another bloomfilter to this BloomFilter.
    ///
    /// The result is the same as adding all elements added to `other` to `self` in the first
    /// place.
    ///
    /// Panics if `k`,`m` or `buildhasher` of the two BloomFilters are not identical.
    pub fn union(&mut self, other: &BloomFilter<B>) {
        assert_eq!(
            self.k, other.k,
            "k must be equal (left={}, right={})",
            self.k, other.k
        );
        assert_eq!(
            self.bs.len(),
            other.bs.len(),
            "m must be equal (left={}, right={})",
            self.bs.len(),
            other.bs.len()
        );
        assert!(
            self.buildhasher == other.buildhasher,
            "buildhasher must be equal"
        );

        self.bs = &self.bs | &other.bs;
    }

    /// Guess the number of unique elements added to the BloomFilter.
    pub fn guess_n(&self) -> usize {
        let m = self.bs.len() as f64;
        let k = self.k as f64;
        let x = self.bs.ones().count() as f64;

        (-m / k * (1. - x / m).ln()) as usize
    }
}

impl fmt::Debug for BloomFilter {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "BloomFilter {{ m: {}, k: {} }}", self.bs.len(), self.k)
    }
}

impl<T> Extend<T> for BloomFilter
where
    T: Hash,
{
    fn extend<S: IntoIterator<Item = T>>(&mut self, iter: S) {
        for elem in iter {
            self.add(&elem);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::BloomFilter;
    use utils::BuildHasherSeeded;

    #[test]
    fn getter() {
        let bf = BloomFilter::with_params(100, 2);
        assert_eq!(bf.k(), 2);
        assert_eq!(bf.m(), 100);
        bf.buildhasher();
    }

    #[test]
    fn empty() {
        let bf = BloomFilter::with_params(100, 2);
        assert!(!bf.query(&1));
    }

    #[test]
    fn add() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.add(&1);
        assert!(bf.query(&1));
        assert!(!bf.query(&2));
    }

    #[test]
    fn clear() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.add(&1);
        bf.clear();
        assert!(!bf.query(&1));
    }

    #[test]
    fn is_empty() {
        let mut bf = BloomFilter::with_params(100, 2);
        assert!(bf.is_empty());

        bf.add(&1);
        assert!(!bf.is_empty());

        bf.clear();
        assert!(bf.is_empty());
    }

    #[test]
    fn clone() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        bf1.add(&1);

        let bf2 = bf1.clone();
        bf1.add(&2);
        assert!(bf2.query(&1));
        assert!(!bf2.query(&2));
    }

    #[test]
    fn union() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        bf1.add(&1);
        assert!(bf1.query(&1));
        assert!(!bf1.query(&2));
        assert!(!bf1.query(&3));

        let mut bf2 = BloomFilter::with_params(100, 2);
        bf2.add(&2);
        assert!(!bf2.query(&1));
        assert!(bf2.query(&2));
        assert!(!bf2.query(&3));

        bf1.union(&bf2);
        assert!(bf1.query(&1));
        assert!(bf1.query(&2));
        assert!(!bf1.query(&3));
    }

    #[test]
    #[should_panic(expected = "k must be equal (left=2, right=3)")]
    fn union_panics_k() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        let bf2 = BloomFilter::with_params(100, 3);
        bf1.union(&bf2);
    }

    #[test]
    #[should_panic(expected = "m must be equal (left=100, right=200)")]
    fn union_panics_m() {
        let mut bf1 = BloomFilter::with_params(100, 2);
        let bf2 = BloomFilter::with_params(200, 2);
        bf1.union(&bf2);
    }

    #[test]
    #[should_panic(expected = "buildhasher must be equal")]
    fn union_panics_buildhasher() {
        let mut bf1 = BloomFilter::with_params_and_hash(100, 2, BuildHasherSeeded::new(0));
        let bf2 = BloomFilter::with_params_and_hash(100, 2, BuildHasherSeeded::new(1));
        bf1.union(&bf2);
    }

    #[test]
    fn with_properties() {
        let bf = BloomFilter::with_properties(1000, 0.1);
        assert_eq!(bf.k(), 3);
        assert_eq!(bf.m(), 4792);
    }

    #[test]
    #[should_panic(expected = "n must be greater than 0")]
    fn with_properties_panics_n0() {
        BloomFilter::with_properties(0, 0.1);
    }

    #[test]
    #[should_panic(expected = "p (0) must be greater than 0 and smaller than 1")]
    fn with_properties_panics_p0() {
        BloomFilter::with_properties(1000, 0.);
    }

    #[test]
    #[should_panic(expected = "p (1) must be greater than 0 and smaller than 1")]
    fn with_properties_panics_p1() {
        BloomFilter::with_properties(1000, 1.);
    }

    #[test]
    fn guess_n() {
        let mut bf = BloomFilter::with_params(100, 2);
        assert_eq!(bf.guess_n(), 0);

        bf.add(&1);
        assert_eq!(bf.guess_n(), 1);

        bf.add(&1);
        assert_eq!(bf.guess_n(), 1);

        bf.add(&2);
        assert_eq!(bf.guess_n(), 2);
    }

    #[test]
    fn debug() {
        let bf = BloomFilter::with_params(100, 2);
        assert_eq!(format!("{:?}", bf), "BloomFilter { m: 100, k: 2 }");
    }

    #[test]
    fn extend() {
        let mut bf = BloomFilter::with_params(100, 2);

        bf.extend(vec![1, 2]);
        assert!(bf.query(&1));
        assert!(bf.query(&2));
        assert!(!bf.query(&3));
    }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;
use image::{ImageEncoder, ImageError, ImageResult};

const BITMAPFILEHEADER_SIZE: u32 = 14;
const BITMAPINFOHEADER_SIZE: u32 = 40;
const BITMAPV4HEADER_SIZE: u32 = 108;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> ImageResult<()> {
        let bmp_header_size = BITMAPFILEHEADER_SIZE;

        let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes

        let image_size = width * height * written_pixel_size + (height * row_pad_size);
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        self.writer.write_u8(b'B')?;
        self.writer.write_u8(b'M')?;
        self.writer.write_u32::<LittleEndian>(file_size)?; // file size
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
        self.writer
            .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)?; // image data offset

        // write DIB header
        self.writer.write_u32::<LittleEndian>(dib_header_size)?;
        self.writer.write_i32::<LittleEndian>(width as i32)?;
        self.writer.write_i32::<LittleEndian>(height as i32)?;
        self.writer.write_u16::<LittleEndian>(1)?; // color planes
        self.writer
            .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)?; // bits per pixel
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
        } else {
            self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
        }
        self.writer.write_u32::<LittleEndian>(image_size)?;
        self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
        self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
        self.writer.write_u32::<LittleEndian>(palette_color_count)?;
        self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
            self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
            self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
            self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
            self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB

            // endpoints (3x3) and gamma (3)
            for _ in 0..12 {
                self.writer.write_u32::<LittleEndian>(0)?;
            }
        }

        // write image data
        match c {
            color::ColorType::Rgb8 => {
                self.encode_rgb(image, width, height, row_pad_size, 3)?
            }
            color::ColorType::Rgba8 => {
                self.encode_rgba(image, width, height, row_pad_size, 4)?
            }
            color::ColorType::L8 => {
                self.encode_gray(image, width, height, row_pad_size, 1)?
            }
            color::ColorType::La8 => {
                self.encode_gray(image, width, height, row_pad_size, 2)?
            }
            _ => {
                return Err(ImageError::IoError(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                )))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_rgba(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                let a = image[pixel_start + 3];
                // written as BGRA
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                self.writer.write_u8(a)?;
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(0)?;
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                self.writer.write_u8(image[pixel_start])?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            self.writer.write_u8(0)?;
        }

        Ok(())
    }
}

impl<'a, W: Write> ImageEncoder for BMPEncoder<'a, W> {
    fn write_image(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: color::ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::Rgb8 => (BITMAPINFOHEADER_SIZE, 3, 0),
        color::ColorType::Rgba8 => (BITMAPV4HEADER_SIZE, 4, 0),
        color::ColorType::L8 => (BITMAPINFOHEADER_SIZE, 1, 256),
        color::ColorType::La8 => (BITMAPINFOHEADER_SIZE, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BmpDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BmpDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [1, 2, 3, 4];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(&decoded[..], &image[..]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<commit_msg>Fixes #1090. Adds checked_mul when computing img size.<commit_after>use byteorder::{LittleEndian, WriteBytesExt};
use std::io::{self, Write};

use color;
use image::{ImageEncoder, ImageError, ImageResult};

const BITMAPFILEHEADER_SIZE: u32 = 14;
const BITMAPINFOHEADER_SIZE: u32 = 40;
const BITMAPV4HEADER_SIZE: u32 = 108;

/// The representation of a BMP encoder.
pub struct BMPEncoder<'a, W: 'a> {
    writer: &'a mut W,
}

impl<'a, W: Write + 'a> BMPEncoder<'a, W> {
    /// Create a new encoder that writes its output to ```w```.
    pub fn new(w: &'a mut W) -> Self {
        BMPEncoder { writer: w }
    }

    /// Encodes the image ```image```
    /// that has dimensions ```width``` and ```height```
    /// and ```ColorType``` ```c```.
    pub fn encode(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        c: color::ColorType,
    ) -> ImageResult<()> {
        let bmp_header_size = BITMAPFILEHEADER_SIZE;

        let (dib_header_size, written_pixel_size, palette_color_count) = get_pixel_info(c)?;
        let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes
        let image_size = width.checked_mul(height);
        if image_size.is_none() {
            return Err(ImageError::DimensionError);
        }
        let image_size = image_size.unwrap().checked_mul(written_pixel_size);
        if image_size.is_none() {
            return Err(ImageError::DimensionError);
        }
        let image_size = image_size.unwrap() + (height * row_pad_size);
        let palette_size = palette_color_count * 4; // all palette colors are BGRA
        let file_size = bmp_header_size + dib_header_size + palette_size + image_size;

        // write BMP header
        self.writer.write_u8(b'B')?;
        self.writer.write_u8(b'M')?;
        self.writer.write_u32::<LittleEndian>(file_size)?; // file size
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
        self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
        self.writer
            .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)?; // image data offset

        // write DIB header
        self.writer.write_u32::<LittleEndian>(dib_header_size)?;
        self.writer.write_i32::<LittleEndian>(width as i32)?;
        self.writer.write_i32::<LittleEndian>(height as i32)?;
        self.writer.write_u16::<LittleEndian>(1)?; // color planes
        self.writer
            .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)?; // bits per pixel
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
        } else {
            self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
        }
        self.writer.write_u32::<LittleEndian>(image_size)?;
        self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
        self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
        self.writer.write_u32::<LittleEndian>(palette_color_count)?;
        self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
        if dib_header_size >= BITMAPV4HEADER_SIZE {
            // Assume BGRA32
            self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
            self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
            self.writer.write_u32::<LittleEndian>(0xff << 0)?; // blue mask
            self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
            self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB

            // endpoints (3x3) and gamma (3)
            for _ in 0..12 {
                self.writer.write_u32::<LittleEndian>(0)?;
            }
        }

        // write image data
        match c {
            color::ColorType::Rgb8 => {
                self.encode_rgb(image, width, height, row_pad_size, 3)?
            }
            color::ColorType::Rgba8 => {
                self.encode_rgba(image, width, height, row_pad_size, 4)?
            }
            color::ColorType::L8 => {
                self.encode_gray(image, width, height, row_pad_size, 1)?
            }
            color::ColorType::La8 => {
                self.encode_gray(image, width, height, row_pad_size, 2)?
            }
            _ => {
                return Err(ImageError::IoError(io::Error::new(
                    io::ErrorKind::InvalidInput,
                    &get_unsupported_error_message(c)[..],
                )))
            }
        }

        Ok(())
    }

    fn encode_rgb(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                // written as BGR
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_rgba(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                let r = image[pixel_start];
                let g = image[pixel_start + 1];
                let b = image[pixel_start + 2];
                let a = image[pixel_start + 3];
                // written as BGRA
                self.writer.write_u8(b)?;
                self.writer.write_u8(g)?;
                self.writer.write_u8(r)?;
                self.writer.write_u8(a)?;
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn encode_gray(
        &mut self,
        image: &[u8],
        width: u32,
        height: u32,
        row_pad_size: u32,
        bytes_per_pixel: u32,
    ) -> io::Result<()> {
        // write grayscale palette
        for val in 0..256 {
            // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
            let val = val as u8;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(val)?;
            self.writer.write_u8(0)?;
        }

        // write image data
        let x_stride = bytes_per_pixel;
        let y_stride = width * x_stride;
        for row in 0..height {
            // from the bottom up
            let row_start = (height - row - 1) * y_stride;
            for col in 0..width {
                let pixel_start = (row_start + (col * x_stride)) as usize;
                // color value is equal to the palette index
                self.writer.write_u8(image[pixel_start])?;
                // alpha is never written as it's not widely supported
            }

            self.write_row_pad(row_pad_size)?;
        }

        Ok(())
    }

    fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
        for _ in 0..row_pad_size {
            self.writer.write_u8(0)?;
        }

        Ok(())
    }
}

impl<'a, W: Write> ImageEncoder for BMPEncoder<'a, W> {
    fn write_image(
        mut self,
        buf: &[u8],
        width: u32,
        height: u32,
        color_type: color::ColorType,
    ) -> ImageResult<()> {
        self.encode(buf, width, height, color_type)
    }
}

fn get_unsupported_error_message(c: color::ColorType) -> String {
    format!(
        "Unsupported color type {:?}.  Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
        c
    )
}

/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
fn get_pixel_info(c: color::ColorType) -> io::Result<(u32, u32, u32)> {
    let sizes = match c {
        color::ColorType::Rgb8 => (BITMAPINFOHEADER_SIZE, 3, 0),
        color::ColorType::Rgba8 => (BITMAPV4HEADER_SIZE, 4, 0),
        color::ColorType::L8 => (BITMAPINFOHEADER_SIZE, 1, 256),
        color::ColorType::La8 => (BITMAPINFOHEADER_SIZE, 1, 256),
        _ => {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                &get_unsupported_error_message(c)[..],
            ))
        }
    };

    Ok(sizes)
}

#[cfg(test)]
mod tests {
    use super::super::BmpDecoder;
    use super::BMPEncoder;
    use color::ColorType;
    use image::ImageDecoder;
    use std::io::Cursor;

    fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
        let mut encoded_data = Vec::new();
        {
            let mut encoder = BMPEncoder::new(&mut encoded_data);
            encoder
                .encode(&image, width, height, c)
                .expect("could not encode image");
        }

        let decoder = BmpDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");

        let mut buf = vec![0; decoder.total_bytes() as usize];
        decoder.read_image(&mut buf).expect("failed to decode");
        buf
    }

    #[test]
    fn round_trip_single_pixel_rgb() {
        let image = [255u8, 0, 0]; // single red pixel
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
        assert_eq!(3, decoded.len());
        assert_eq!(255, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
    }

    #[test]
    fn huge_files_return_error() {
        let mut encoded_data = Vec::new();
        let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
        let mut encoder = BMPEncoder::new(&mut encoded_data);
        let result = encoder.encode(&image, 40_000, 40_000, ColorType::Rgb8);
        assert!(result.is_err());
    }

    #[test]
    fn round_trip_single_pixel_rgba() {
        let image = [1, 2, 3, 4];
        let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
        assert_eq!(&decoded[..], &image[..]);
    }

    #[test]
    fn round_trip_3px_rgb() {
        let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
        let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
    }

    #[test]
    fn round_trip_gray() {
        let image = [0u8, 1, 2]; // 3 pixels
        let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }

    #[test]
    fn round_trip_graya() {
        let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
        let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
        // should be read back as 3 RGB pixels
        assert_eq!(9, decoded.len());
        assert_eq!(0, decoded[0]);
        assert_eq!(0, decoded[1]);
        assert_eq!(0, decoded[2]);
        assert_eq!(1, decoded[3]);
        assert_eq!(1, decoded[4]);
        assert_eq!(1, decoded[5]);
        assert_eq!(2, decoded[6]);
        assert_eq!(2, decoded[7]);
        assert_eq!(2, decoded[8]);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Contains the struct `SubRegisterFile` which extends `PhiPlacer`s
//! functionality by reads and writes to partial registers.

use std::cmp::Ordering;
use std::collections::HashMap;
use std::convert::From;

use r2api::structs::LRegInfo;

use middle::ssa::ssa_traits::ValueType;

#[derive(Clone, Copy, Debug)]
pub struct SubRegister {
    pub base: usize,
    pub shift: usize,
    pub width: usize,
}

impl SubRegister {
    fn new(base: usize, shift: usize, width: usize) -> SubRegister {
        SubRegister {
            base: base,
            shift: shift,
            width: width,
        }
    }
}

/// A structure containing information about whole and partial registers of a platform.
/// Upon creation it builds a vector of `ValueType`s representing whole registers
/// to be added to a `PhiPlacer`.
///
/// It can then translate accesses to partial registers to accesses of whole registers.
/// Shifts and masks are added automatically.
#[derive(Clone, Debug)]
pub struct SubRegisterFile {
    /// `ValueType`s of whole registers ready to be added to a `PhiPlacer`.
    /// The index within `PhiPlacer` to the first register is needed
    /// as argument `base` to `read_register` and `write_register` later.
    pub whole_registers: Vec<ValueType>,
    /// Contains the respective names for the registers described in `whole_registers`
    pub whole_names: Vec<String>,
    named_registers: HashMap<String, SubRegister>,
}

impl SubRegisterFile {
    /// Creates a new SubRegisterFile based on a provided register profile.
    pub fn new(reg_info: &LRegInfo) -> SubRegisterFile {
        let mut slices = HashMap::new();
        let mut events: Vec<SubRegister> = Vec::new();
        for (i, reg) in reg_info.reg_info.iter().enumerate() {
            if reg.type_str == "fpu" {
                continue;
            } // st7 from "fpu" overlaps with zf from "gpr" (r2 bug?)
            if reg.name.ends_with("flags") {
                continue;
            } // HARDCODED x86
            events.push(SubRegister::new(i, reg.offset, reg.size));
        }

        events.sort_by(|a, b| {
            let o = a.shift.cmp(&b.shift);
            if let Ordering::Equal = o {
                (b.width + b.shift).cmp(&(a.width + a.shift))
            } else {
                o
            }
        });

        let mut current = SubRegister::new(0, 0, 0);
        let mut whole: Vec<ValueType> = Vec::new();
        let mut names: Vec<String> = Vec::new();
        for &ev in &events {
            let name = &reg_info.reg_info[ev.base].name;
            let cur_until = current.shift + current.width;
            if ev.shift >= cur_until {
                current = ev;

                radeco_trace!("regfile_mappings|{} -> {}", whole.len(), &name);

                whole.push(From::from(current.width));
                names.push(name.clone());
            } else {
                let ev_until = ev.width + ev.shift;
                assert!(ev_until <= cur_until);
            }

            let subreg = SubRegister::new(whole.len() - 1, ev.shift - current.shift, ev.width);

            slices.insert(name.clone(), subreg);
        }

        SubRegisterFile {
            whole_registers: whole,
            named_registers: slices,
            whole_names: names,
        }
    }

    pub fn get_info(&self, name: &str) -> Option<SubRegister> {
        self.named_registers.get(name).cloned()
    }

    pub fn get_name(&self, id: usize) -> Option<String> {
        Some(self.whole_names[id].clone())
    }

    // Emit code for setting the specified register to the specified value.
    // Will automatically insert code for shifting and masking in case of subregisters.
    // This implies that it also tries to read the old value of the whole register.
    //
    // # Arguments
    // * `phiplacer` - A PhiPlacer that has already been informed of our variables.
    //                 It will also give us access to the SSA to modify
    // * `base`      - Index of the PhiPlacer variable that corresponds to our first register.
    // * `block`     - Reference to the basic block to which operations will be appended.
    // * `var`       - Name of the register to write as a string.
    // * `value`     - An SSA node whose value shall be assigned to the register.
    //                 As with most APIs in radeco, we will not check if the value is reachable
    //                 from the position where the caller is trying to insert these operations.

    //pub fn write_register<'a, T>(&self,
                                 //phip: &mut PhiPlacer<'a, T>,
                                 //base: usize,
                                 //block: T::ActionRef,
                                 //var: &String,
                                 //mut value: T::ValueRef,
                                 //addr: u64)
        //where T: 'a + SSAMod<BBInfo = BBInfo> + VerifiedAdd
    //{
        //let info = &self.named_registers[var];
        //let id = info.base + base;

        //let width = match phip.variable_types[id] {
            //ValueType::Integer { width } => width,
        //};

        //if info.width >= width as usize {
            //phip.write_variable(block, id, value);
            //return;
        //}

        //// Need to add a cast.
        //let vt = From::from(width);
        //let opcode = MOpcode::OpWiden(width as WidthSpec);

        //if phip.ssa.get_node_data(&value).ok().map_or(0, |nd| {
            //match nd.vt {
                //ValueType::Integer{width} => width,
            //}
        //}) < width {
            //value = phip.ssa.verified_add_op(block, opcode, vt, &[value], Some(addr));
        //}

        //let mut new_value;

        //if info.shift > 0 {
            //let shift_amount_node = phip.add_const(block, info.shift as u64);
            //new_value = phip.ssa.verified_add_op(block,
                                                 //MOpcode::OpLsl,
                                                 //vt,
                                                 //&[value, shift_amount_node],
                                                 //Some(addr));
            //value = new_value;
        //}

        //let fullval: u64 = !((!1u64) << (width - 1));
        //let maskval: u64 = ((!((!1u64) << (info.width - 1))) << info.shift) ^ fullval;

        //if maskval == 0 {
            //phip.write_variable(block, id, value);
            //return;
        //}

        //let mut ov = phip.read_variable(block, id);
        //let maskvalue_node = phip.add_const(block, maskval);
        //new_value = phip.ssa.verified_add_op(block,
                                             //MOpcode::OpAnd,
                                             //vt,
                                             //&[ov, maskvalue_node],
                                             //Some(addr));

        //ov = new_value;
        //new_value = phip.ssa.verified_add_op(block, MOpcode::OpOr, vt, &[value, ov], Some(addr));
        //value = new_value;
        //phip.write_variable(block, id, value);
    //}

    // Emit code for reading the current value of the specified register.
    //
    // # Arguments
    // * `phiplacer` - A PhiPlacer that has already been informed of our variables.
    //                 It will also give us access to the SSA to modify
    // * `base`      - Index of the PhiPlacer variable that corresponds to our first register.
    // * `block`     - Reference to the basic block to which operations will be appended.
    // * `var`       - Name of the register to read as a string.
    //
    // # Return value
    // A SSA node representing the value of the register as seen by the current end of `block`.
    // Unless prior basic blocks are marked as sealed in the PhiPlacer this will always return
    // a reference to a Phi node.
    // Either way, once nodes are sealed redundant Phi nodes are eliminated by PhiPlacer.

    //pub fn read_register<'a, T>(&self,
                                //phiplacer: &mut PhiPlacer<'a, T>,
                                //base: usize,
                                //block: T::ActionRef,
                                //var: &String,
                                //addr: u64)
                                //-> T::ValueRef
        //where T: SSAMod<BBInfo = BBInfo> + VerifiedAdd + 'a
    //{
        //let info = &self.named_registers[var];
        //let id = info.base + base;
        //let mut value = phiplacer.read_variable(block, id);

        //let width = match phiplacer.variable_types[id] {
            //ValueType::Integer { width } => width,
        //};

        //if info.shift > 0 {
            //let shift_amount_node = phiplacer.add_const(block, info.shift as u64);
            //let opcode = MOpcode::OpLsr;
            //let vtype = From::from(width);
            //let new_value = phiplacer.ssa.verified_add_op(block,
                                                          //opcode,
                                                          //vtype,
                                                          //&[value, shift_amount_node],
                                                          //Some(addr));
            //value = new_value;
        //}

        //if info.width < (width as usize) {
            //let opcode = MOpcode::OpNarrow(info.width as WidthSpec);
            //let vtype = From::from(info.width);
            //let new_value = phiplacer.ssa
                                     //.verified_add_op(block, opcode, vtype, &[value], Some(addr));
            //value = new_value;
        //}
        //value
    //}
}
<commit_msg>add alias_info and type_info API for regfile<commit_after>// Copyright (c) 2015, The Radare Project. All rights reserved.
// See the COPYING file at the top-level directory of this distribution.
// Licensed under the BSD 3-Clause License:
// <http://opensource.org/licenses/BSD-3-Clause>
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Contains the struct `SubRegisterFile` which extends `PhiPlacer`s
//! functionality by reads and writes to partial registers.

use std::cmp::Ordering;
use std::collections::HashMap;
use std::convert::From;

use r2api::structs::LRegInfo;

use middle::ssa::ssa_traits::ValueType;

#[derive(Clone, Copy, Debug)]
pub struct SubRegister {
    pub base: usize,
    pub shift: usize,
    pub width: usize,
}

impl SubRegister {
    fn new(base: usize, shift: usize, width: usize) -> SubRegister {
        SubRegister {
            base: base,
            shift: shift,
            width: width,
        }
    }
}

/// A structure containing information about whole and partial registers of a platform.
/// Upon creation it builds a vector of `ValueType`s representing whole registers
/// to be added to a `PhiPlacer`.
///
/// It can then translate accesses to partial registers to accesses of whole registers.
/// Shifts and masks are added automatically.
#[derive(Clone, Debug)]
pub struct SubRegisterFile {
    /// `ValueType`s of whole registers ready to be added to a `PhiPlacer`.
    /// The index within `PhiPlacer` to the first register is needed
    /// as argument `base` to `read_register` and `write_register` later.
    pub whole_registers: Vec<ValueType>,
    /// Contains the respective names for the registers described in `whole_registers`
    pub whole_names: Vec<String>,
    named_registers: HashMap<String, SubRegister>,
    /// Contains the alias information for some registers.
    pub alias_info: HashMap<String, String>,
    /// Contains the type information for every registers.
    pub type_info: HashMap<String, String>,
}

impl SubRegisterFile {
    /// Creates a new SubRegisterFile based on a provided register profile.
    pub fn new(reg_info: &LRegInfo) -> SubRegisterFile {
        let mut aliases: HashMap<String, String> = HashMap::new();
        for reg in &reg_info.alias_info {
            aliases.insert(reg.reg.clone(), reg.role_str.clone());
        }

        let mut slices = HashMap::new();
        let mut events: Vec<SubRegister> = Vec::new();
        let mut types: HashMap<String, String> = HashMap::new();
        for (i, reg) in reg_info.reg_info.iter().enumerate() {
            types.insert(reg.name.clone(), reg.type_str.clone());
            if reg.type_str == "fpu" {
                continue;
            } // st7 from "fpu" overlaps with zf from "gpr" (r2 bug?)
            if reg.name.ends_with("flags") {
                continue;
            } // HARDCODED x86
            events.push(SubRegister::new(i, reg.offset, reg.size));
        }

        events.sort_by(|a, b| {
            let o = a.shift.cmp(&b.shift);
            if let Ordering::Equal = o {
                (b.width + b.shift).cmp(&(a.width + a.shift))
            } else {
                o
            }
        });

        let mut current = SubRegister::new(0, 0, 0);
        let mut whole: Vec<ValueType> = Vec::new();
        let mut names: Vec<String> = Vec::new();
        for &ev in &events {
            let name = &reg_info.reg_info[ev.base].name;
            let cur_until = current.shift + current.width;
            if ev.shift >= cur_until {
                current = ev;

                radeco_trace!("regfile_mappings|{} -> {}", whole.len(), &name);

                whole.push(From::from(current.width));
                names.push(name.clone());
            } else {
                let ev_until = ev.width + ev.shift;
                assert!(ev_until <= cur_until);
            }

            let subreg = SubRegister::new(whole.len() - 1, ev.shift - current.shift, ev.width);

            slices.insert(name.clone(), subreg);
        }

        SubRegisterFile {
            whole_registers: whole,
            named_registers: slices,
            whole_names: names,
            alias_info: aliases,
            type_info: types,
        }
    }

    pub fn get_info(&self, name: &str) -> Option<SubRegister> {
        self.named_registers.get(name).cloned()
    }

    pub fn get_name(&self, id: usize) -> Option<String> {
        Some(self.whole_names[id].clone())
    }

    // Emit code for setting the specified register to the specified value.
    // Will automatically insert code for shifting and masking in case of subregisters.
    // This implies that it also tries to read the old value of the whole register.
    //
    // # Arguments
    // * `phiplacer` - A PhiPlacer that has already been informed of our variables.
    //                 It will also give us access to the SSA to modify
    // * `base`      - Index of the PhiPlacer variable that corresponds to our first register.
    // * `block`     - Reference to the basic block to which operations will be appended.
    // * `var`       - Name of the register to write as a string.
    // * `value`     - An SSA node whose value shall be assigned to the register.
    //                 As with most APIs in radeco, we will not check if the value is reachable
    //                 from the position where the caller is trying to insert these operations.

    //pub fn write_register<'a, T>(&self,
                                 //phip: &mut PhiPlacer<'a, T>,
                                 //base: usize,
                                 //block: T::ActionRef,
                                 //var: &String,
                                 //mut value: T::ValueRef,
                                 //addr: u64)
        //where T: 'a + SSAMod<BBInfo = BBInfo> + VerifiedAdd
    //{
        //let info = &self.named_registers[var];
        //let id = info.base + base;

        //let width = match phip.variable_types[id] {
            //ValueType::Integer { width } => width,
        //};

        //if info.width >= width as usize {
            //phip.write_variable(block, id, value);
            //return;
        //}

        //// Need to add a cast.
        //let vt = From::from(width);
        //let opcode = MOpcode::OpWiden(width as WidthSpec);

        //if phip.ssa.get_node_data(&value).ok().map_or(0, |nd| {
            //match nd.vt {
                //ValueType::Integer{width} => width,
            //}
        //}) < width {
            //value = phip.ssa.verified_add_op(block, opcode, vt, &[value], Some(addr));
        //}

        //let mut new_value;

        //if info.shift > 0 {
            //let shift_amount_node = phip.add_const(block, info.shift as u64);
            //new_value = phip.ssa.verified_add_op(block,
                                                 //MOpcode::OpLsl,
                                                 //vt,
                                                 //&[value, shift_amount_node],
                                                 //Some(addr));
            //value = new_value;
        //}

        //let fullval: u64 = !((!1u64) << (width - 1));
        //let maskval: u64 = ((!((!1u64) << (info.width - 1))) << info.shift) ^ fullval;

        //if maskval == 0 {
            //phip.write_variable(block, id, value);
            //return;
        //}

        //let mut ov = phip.read_variable(block, id);
        //let maskvalue_node = phip.add_const(block, maskval);
        //new_value = phip.ssa.verified_add_op(block,
                                             //MOpcode::OpAnd,
                                             //vt,
                                             //&[ov, maskvalue_node],
                                             //Some(addr));

        //ov = new_value;
        //new_value = phip.ssa.verified_add_op(block, MOpcode::OpOr, vt, &[value, ov], Some(addr));
        //value = new_value;
        //phip.write_variable(block, id, value);
    //}

    // Emit code for reading the current value of the specified register.
    //
    // # Arguments
    // * `phiplacer` - A PhiPlacer that has already been informed of our variables.
    //                 It will also give us access to the SSA to modify
    // * `base`      - Index of the PhiPlacer variable that corresponds to our first register.
    // * `block`     - Reference to the basic block to which operations will be appended.
    // * `var`       - Name of the register to read as a string.
    //
    // # Return value
    // A SSA node representing the value of the register as seen by the current end of `block`.
    // Unless prior basic blocks are marked as sealed in the PhiPlacer this will always return
    // a reference to a Phi node.
    // Either way, once nodes are sealed redundant Phi nodes are eliminated by PhiPlacer.

    //pub fn read_register<'a, T>(&self,
                                //phiplacer: &mut PhiPlacer<'a, T>,
                                //base: usize,
                                //block: T::ActionRef,
                                //var: &String,
                                //addr: u64)
                                //-> T::ValueRef
        //where T: SSAMod<BBInfo = BBInfo> + VerifiedAdd + 'a
    //{
        //let info = &self.named_registers[var];
        //let id = info.base + base;
        //let mut value = phiplacer.read_variable(block, id);

        //let width = match phiplacer.variable_types[id] {
            //ValueType::Integer { width } => width,
        //};

        //if info.shift > 0 {
            //let shift_amount_node = phiplacer.add_const(block, info.shift as u64);
            //let opcode = MOpcode::OpLsr;
            //let vtype = From::from(width);
            //let new_value = phiplacer.ssa.verified_add_op(block,
                                                          //opcode,
                                                          //vtype,
                                                          //&[value, shift_amount_node],
                                                          //Some(addr));
            //value = new_value;
        //}

        //if info.width < (width as usize) {
            //let opcode = MOpcode::OpNarrow(info.width as WidthSpec);
            //let vtype = From::from(info.width);
            //let new_value = phiplacer.ssa
                                     //.verified_add_op(block, opcode, vtype, &[value], Some(addr));
            //value = new_value;
        //}
        //value
    //}
}
<|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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    fn has_events(&self) -> bool {
        !self.event_queue.borrow().is_empty() || self.window.has_events()
    }

    // This function decides whether the event should be handled during `run_forever`.
    fn winit_event_to_servo_event(&self, event: glutin::Event) -> glutin::ControlFlow {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    // Resize events need to be handled during run_forever
                    let cont = if let glutin::WindowEvent::Resized(_) = event {
                        glutin::ControlFlow::Continue
                    } else {
                        glutin::ControlFlow::Break
                    };
                    self.window.winit_event_to_servo_event(event);
                    return cont;
                }
            },
        }
        glutin::ControlFlow::Break
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    let cont = self.winit_event_to_servo_event(e);
                    if cont == glutin::ControlFlow::Continue {
                        // Note we need to be careful to make sure that any events
                        // that are handled during run_forever aren't re-entrant,
                        // since we are handling them while holding onto a mutable borrow
                        // of the events loop
                        self.handle_events();
                    }
                    cont
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<commit_msg>Dead code elimination<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 https://mozilla.org/MPL/2.0/. */

//! Application entry point, runs the event loop.

use crate::browser::Browser;
use crate::embedder::EmbedderCallbacks;
use crate::window_trait::WindowPortsMethods;
use crate::events_loop::EventsLoop;
use crate::{headed_window, headless_window};
use servo::compositing::windowing::WindowEvent;
use servo::config::opts::{self, parse_url_or_filename};
use servo::servo_config::pref;
use servo::servo_url::ServoUrl;
use servo::{BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::env;
use std::mem;
use std::rc::Rc;

pub struct App {
    events_loop: Rc<RefCell<EventsLoop>>,
    window: Rc<WindowPortsMethods>,
    servo: RefCell<Servo<WindowPortsMethods>>,
    browser: RefCell<Browser<WindowPortsMethods>>,
    event_queue: RefCell<Vec<WindowEvent>>,
    suspended: Cell<bool>,
}

impl App {
    pub fn run() {
        let events_loop = EventsLoop::new(opts::get().headless);

        // Implements window methods, used by compositor.
        let window = if opts::get().headless {
            headless_window::Window::new(opts::get().initial_window_size)
        } else {
            headed_window::Window::new(opts::get().initial_window_size, events_loop.borrow().as_winit())
        };

        // Implements embedder methods, used by libservo and constellation.
        let embedder = Box::new(EmbedderCallbacks::new(
            events_loop.clone(),
            window.gl(),
        ));

        // Handle browser state.
        let browser = Browser::new(window.clone());

        let mut servo = Servo::new(embedder, window.clone());
        let browser_id = BrowserId::new();
        servo.handle_events(vec![WindowEvent::NewBrowser(get_default_url(), browser_id)]);
        servo.setup_logging();

        let app = App {
            event_queue: RefCell::new(vec![]),
            events_loop,
            window: window,
            browser: RefCell::new(browser),
            servo: RefCell::new(servo),
            suspended: Cell::new(false),
        };

        app.run_loop();
    }

    fn get_events(&self) -> Vec<WindowEvent> {
        mem::replace(&mut *self.event_queue.borrow_mut(), Vec::new())
    }

    // This function decides whether the event should be handled during `run_forever`.
    fn winit_event_to_servo_event(&self, event: glutin::Event) -> glutin::ControlFlow {
        match event {
            // App level events
            glutin::Event::Suspended(suspended) => {
                self.suspended.set(suspended);
                if !suspended {
                    self.event_queue.borrow_mut().push(WindowEvent::Idle);
                }
            },
            glutin::Event::Awakened => {
                self.event_queue.borrow_mut().push(WindowEvent::Idle);
            },
            glutin::Event::DeviceEvent { .. } => {},

            // Window level events
            glutin::Event::WindowEvent {
                window_id, event, ..
            } => {
                if Some(window_id) != self.window.id() {
                    warn!("Got an event from unknown window");
                } else {
                    // Resize events need to be handled during run_forever
                    let cont = if let glutin::WindowEvent::Resized(_) = event {
                        glutin::ControlFlow::Continue
                    } else {
                        glutin::ControlFlow::Break
                    };
                    self.window.winit_event_to_servo_event(event);
                    return cont;
                }
            },
        }
        glutin::ControlFlow::Break
    }

    fn run_loop(self) {
        loop {
            if !self.window.is_animating()  || self.suspended.get() {
                // If there's no animations running then we block on the window event loop.
                self.events_loop.borrow_mut().run_forever(|e| {
                    let cont = self.winit_event_to_servo_event(e);
                    if cont == glutin::ControlFlow::Continue {
                        // Note we need to be careful to make sure that any events
                        // that are handled during run_forever aren't re-entrant,
                        // since we are handling them while holding onto a mutable borrow
                        // of the events loop
                        self.handle_events();
                    }
                    cont
                });
            }
            // Grab any other events that may have happened
            self.events_loop.borrow_mut().poll_events(|e| {
                self.winit_event_to_servo_event(e);
            });
            // If animations are running, we block on compositing
            // (self.handle_events() ends up calling swap_buffers)
            let stop = self.handle_events();
            if stop {
                break;
            }
        }

        self.servo.into_inner().deinit()
    }

    fn handle_events(&self) -> bool {
        let mut browser = self.browser.borrow_mut();
        let mut servo = self.servo.borrow_mut();

        let win_events = self.window.get_events();

        // FIXME: this could be handled by Servo. We don't need
        // a repaint_synchronously function exposed.
        let need_resize = win_events.iter().any(|e| match *e {
            WindowEvent::Resize => true,
            _ => false,
        });

        let mut app_events = self.get_events();
        app_events.extend(win_events);

        browser.handle_window_events(app_events);

        let mut servo_events = servo.get_events();
        loop {
            browser.handle_servo_events(servo_events);
            servo.handle_events(browser.get_events());
            if browser.shutdown_requested() {
                return true;
            }
            servo_events = servo.get_events();
            if servo_events.is_empty() {
                break;
            }
        }

        if need_resize {
            servo.repaint_synchronously();
        }
        false
    }
}

fn get_default_url() -> ServoUrl {
    // If the url is not provided, we fallback to the homepage in prefs,
    // or a blank page in case the homepage is not set either.
    let cwd = env::current_dir().unwrap();
    let cmdline_url = opts::get().url.clone();
    let pref_url = {
        let homepage_url = pref!(shell.homepage);
        parse_url_or_filename(&cwd, &homepage_url).ok()
    };
    let blank_url = ServoUrl::parse("about:blank").ok();

    cmdline_url.or(pref_url).or(blank_url).unwrap()
}

pub fn gl_version() -> glutin::GlRequest {
    if opts::get().angle {
        glutin::GlRequest::Specific(glutin::Api::OpenGlEs, (3, 0))
    } else {
        glutin::GlRequest::GlThenGles {
            opengl_version: (3, 2),
            opengles_version: (3, 0),
        }
    }
}
<|endoftext|>


<commit_before>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let mut wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            ::std::mem::transmute(&self.pointer)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<::std::io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(::std::io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_GetLastError() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError").unwrap();
    }
}

#[test]
fn works_GetLastError0() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError\0").unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<commit_msg>Remove useless mutability modifier<commit_after>/// Windows implementation of dynamic library loading.
///
/// This module should be expanded with more Windows-specific functionality in the future.
extern crate winapi;
extern crate kernel32;

use util::{CowCString, CStringAsRef};

use std::ffi::{OsStr, OsString};
use std::marker;
use std::mem;
use std::ptr;
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use std::os::windows::ffi::{OsStrExt, OsStringExt};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(winapi::HMODULE);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryW(filename)`.
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> ::Result<Library> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|| {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { kernel32::LoadLibraryW(wide_filename.as_ptr()) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("LoadLibraryW failed but GetLastError did not report the error")
        ));

        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
                             // inside the closure by mistake.
        ret
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> ::Result<Symbol<T>> {
        let symbol = try!(CowCString::from_bytes(symbol));
        with_get_last_error(|| {
            let symbol = kernel32::GetProcAddress(self.0, symbol.cstring_ref());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or_else(||
            panic!("GetProcAddress failed but GetLastError did not report the error")
        ))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        with_get_last_error(|| {
            if unsafe { kernel32::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).unwrap()
    }
}

impl ::std::fmt::Debug for Library {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        unsafe {
            let mut buf: [winapi::WCHAR; 1024] = mem::uninitialized();
            let len = kernel32::GetModuleFileNameW(self.0,
                                                   (&mut buf[..]).as_mut_ptr(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(&buf[..len]);
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: winapi::FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            ::std::mem::transmute(&self.pointer)
        }
    }
}

impl<T> ::std::fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = ATOMIC_BOOL_INIT;
struct ErrorModeGuard(winapi::DWORD);

impl ErrorModeGuard {
    fn new() -> ErrorModeGuard {
        let mut ret = ErrorModeGuard(0);

        if !USE_ERRORMODE.load(Ordering::Acquire) {
            if unsafe { kernel32::SetThreadErrorMode(1, &mut ret.0) == 0
                        && kernel32::GetLastError() == winapi::ERROR_CALL_NOT_IMPLEMENTED } {
                USE_ERRORMODE.store(true, Ordering::Release);
            } else {
                return ret;
            }
        }
        ret.0 = unsafe { kernel32::SetErrorMode(1) };
        ret
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                kernel32::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                kernel32::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(closure: F) -> Result<T, Option<::std::io::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { kernel32::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(::std::io::Error::from_raw_os_error(error as i32))
        }
    })
}

#[test]
fn works_GetLastError() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError").unwrap();
    }
}

#[test]
fn works_GetLastError0() {
    let that = Library::new("kernel32.dll").unwrap();
    unsafe {
        that.get::<*mut usize>(b"GetLastError\0").unwrap();
    }
}

#[test]
fn fails_new_kernel23() {
    Library::new("kernel23").err().unwrap();
}
<|endoftext|>


<commit_before>extern crate mp4parse;

use std::env;
use std::fs::File;

fn dump_file(filename: String) {
    let mut f = File::open(filename).unwrap();
    let h = mp4parse::read_box_header(&mut f).unwrap();
    println!("{}", h);
    mp4parse::skip_box_content(&mut f, &h).unwrap();
    let h = mp4parse::read_box_header(&mut f).unwrap();
    println!("{}", h);
}

fn main() {
    for filename in env::args().skip(1) {
        println!("-- dump of '{}' --", filename);
        dump_file(filename);
    }
}
<commit_msg>Loop over all top-level boxes.<commit_after>extern crate mp4parse;

use std::env;
use std::fs::File;
use std::thread;

fn dump_file(filename: String) {
    let mut f = File::open(filename).unwrap();
    let task = thread::spawn(move || {
        loop {
            match mp4parse::read_box_header(&mut f) {
                Some(h) => {
                    println!("{}", h);
                    mp4parse::skip_box_content(&mut f, &h).unwrap();
                },
                _ => break,
            }
        }
    });
    task.join();
}

fn main() {
    for filename in env::args().skip(1) {
        println!("-- dump of '{}' --", filename);
        dump_file(filename);
    }
}
<|endoftext|>