<commit_before>//! A monotone priority queue implemented with a radix heap.
//!
//! A monotone priority queue is a priority queue that only allows keys to be
//! inserted if their priority is less than or equal to that of the last
//! extracted key.
//!
//! In this implementation, the last extracted value is known as the "top"
//! value. The top value does not necessarily have to be the last extracted key.
//! It can be lower, or initially it can be any value. Note that the constraint
//! above still applies in such a case.
//!
//! Insertion is O(1) time complexity, while popping is amortized O(log n).
//! More precisely, popping is O(d) where d is the radix distance from the key
//! to the top value at the time of insertion. This can give better asymptotic
//! running times for certain algorithms like for example Djikstra's algorithm.
//!
//! #Example
//!
//! ```
//! extern crate radix_heap;
//!
//! let mut heap = radix_heap::RadixHeapMap::new();
//! heap.push(7, 'a');
//! heap.push(2, 'b');
//! heap.push(9, 'c');
//!
//! assert!(heap.pop() == Some((9, 'c')));
//! assert!(heap.top() == 9);
//! assert!(heap.pop() == Some((7, 'a')));
//! assert!(heap.top() == 7);
//! assert!(heap.pop() == Some((2, 'b')));
//! assert!(heap.top() == 2);
//! assert!(heap.pop() == None);
//! ```

extern crate ieee754;
extern crate revord;
extern crate ordered_float;
extern crate num;

use std::fmt;
use std::iter::FromIterator;
use std::cmp::max;
use std::mem::swap;
use std::default::Default;
use revord::RevOrd;
use ieee754::Ieee754;
use ordered_float::NotNaN;
use num::Bounded;

#[derive(Clone)]
struct Bucket<K,V> {
    max: Option<K>,
    elems: Vec<(K,V)>,
}

/// A montone priority queue implemented with a radix heap.
///
/// This will be a max-heap.
///
/// It is a logic error for a key to be modified in such a way that the
/// item's ordering relative to any other item, as determined by the `Ord`
/// trait, changes while it is in the heap. This is normally only possible
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
#[derive(Clone)]
pub struct RadixHeapMap<K,V> {
    len: usize,
    top: K,
    buckets: Vec<Bucket<K,V>>,
}

impl<K: Radix + Ord + Copy + Bounded, V> RadixHeapMap<K,V> {
    /// Creates a new `RadixHeapMap` with the highest possible top value such
    /// that all keys are allowed.
    pub fn new() -> RadixHeapMap<K,V> {
        RadixHeapMap::new_at(K::max_value())
    }

    /// Clears a new `RadixHeapMap` and sets te top value as high as possible
    /// value, so all keys can be inserted into the heap.
    pub fn clear(&mut self) {
        self.clear_to(K::max_value());
    }
}

impl<K: Radix + Ord + Copy,V> RadixHeapMap<K,V> {

    /// Creates a new RadixHeapMap with a specific top value
    pub fn new_at(top: K) -> RadixHeapMap<K,V> {
        let maxdist = K::radix_dist_max();
        let mut buckets = Vec::with_capacity(maxdist as usize + 1);

        for _ in 0..maxdist + 1 {
            buckets.push(Bucket{
                max: None,
                elems: Vec::new()
            });
        }

        RadixHeapMap { len: 0, top: top, buckets: buckets }
    }

    /// Clears the elements in the heap and sets the top value to a new value
    pub fn clear_to(&mut self, top: K) {
        self.top = top;
        self.len = 0;

        for bucket in &mut self.buckets {
            bucket.elems.clear();
        }
    }

    fn push_nocheck(&mut self, key: K, value: V) {
        let bucket = &mut self.buckets[key.radix_dist(&self.top) as usize];

        bucket.max = Some(bucket.max.map_or(key, |m| max(m, key)));
        bucket.elems.push((key,value));
    }

    /// Pushes a new key value pair onto the heap.
    ///
    /// Panics
    /// ------
    /// Panics if the key is more than the current top value.
    pub fn push(&mut self, key: K, value: V) {
        assert!(key <= self.top);
        self.len += 1;
        self.push_nocheck(key, value);
    }

    /// Sets the top value to the current maximum key value in the heap
    pub fn constrain(&mut self) {
        if self.buckets[0].elems.is_empty() {
            let bucket = self.buckets[1..].iter()
                .enumerate()
                .filter_map(|(i, ref bucket)| bucket.max
                    .map(|max| (i + 1, max)))
                .next();

            if let Some((index,max)) = bucket {
                self.top = max;
                let mut repush = Vec::new();

                self.buckets[index].max = None;
                swap(&mut self.buckets[index].elems, &mut repush);

                for (k,v) in repush.drain(..) {
                    self.push_nocheck(k, v);
                }

                // Swap `repush` back again (purely to save memory allocation,
                // they are both empty at this point but `repush` has some
                // memory allocated)
                swap(&mut self.buckets[index].elems, &mut repush);
            }
        }
    }

    /// Pops the largest element of the heap. This might decrease the top value.
    pub fn pop(&mut self) -> Option<(K,V)> {
        self.constrain();

        let pop = self.buckets[0].elems.pop();

        if pop.is_some() {
            self.len -= 1;
        }

        pop
    }

    /// Returns the number of elements in the heap
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns true if there is no elements in the heap
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// The current top value. All keys pushed onto the heap must be smaller
    /// than this value.
    pub fn top(&self) -> K {
        self.top
    }

    /// Discards as much additional capacity as possible.
    pub fn shrink_to_fit(&mut self) {
        for bucket in &mut self.buckets {
            bucket.elems.shrink_to_fit();
        }
    }
}

impl<K: Radix + Ord + Copy + Bounded, V> Default for RadixHeapMap<K,V> {
    fn default() -> RadixHeapMap<K,V> {
        RadixHeapMap::new()
    }
}

impl<K: Radix + Ord + Copy + Bounded, V> FromIterator<(K,V)> for RadixHeapMap<K,V> {
    fn from_iter<I>(iter: I) -> RadixHeapMap<K,V> where
        I: IntoIterator<Item=(K,V)>
    {
        let mut heap = RadixHeapMap::new();
        heap.extend(iter);
        heap
    }
}

impl<K: Radix + Ord + Copy, V> Extend<(K,V)> for RadixHeapMap<K,V> {
    fn extend<I>(&mut self, iter: I) where
        I: IntoIterator<Item=(K,V)>
    {
        for (k,v) in iter {
            self.push(k,v);
        }
    }
}

impl<'a, K: Radix + Ord + Copy + 'a, V: Copy + 'a> Extend<&'a (K,V)> for RadixHeapMap<K,V> {
    fn extend<I>(&mut self, iter: I) where
        I: IntoIterator<Item=&'a (K,V)>
    {
        for &(k,v) in iter {
            self.push(k,v);
        }
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RadixHeapMap<K,V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let entries = self.buckets.iter().flat_map(|b| b.elems.iter());
        f.debug_list().entries(entries).finish()
    }
}

/// A number that can be compared using radix distance
pub trait Radix {
    /// The radix distance between this number and another number.
    ///
    /// The radix distance of n means that the n'th bit (1 indexed) is the
    /// highest bit in which `self` and `other` differ. It is 0 if they are
    /// equal, and M if they are bitwise complements to each other, where M is
    /// the number of bits.
    fn radix_dist(&self, other: &Self) -> u32;

    /// The maximum possible radix distance possible.
    fn radix_dist_max() -> u32;
}

impl<T: Radix> Radix for RevOrd<T> {
    fn radix_dist(&self, other: &RevOrd<T>) -> u32 {
        self.0.radix_dist(&other.0)
    }

    fn radix_dist_max() -> u32 {
        T::radix_dist_max()
    }
}

macro_rules! radix_int_impl {
    ($t:ty) => {
        impl Radix for $t {
            fn radix_dist(&self, other: &$t) -> u32 {
                Self::radix_dist_max() - (self ^ other).leading_zeros()
            }

            fn radix_dist_max() -> u32 {
                (std::mem::size_of::<$t>() * 8) as u32
            }
        }
    }
}

macro_rules! radix_float_impl {
    ($t:ty) => {
        impl Radix for NotNaN<$t> {
            fn radix_dist(&self, other: &NotNaN<$t>) -> u32 {
                self.0.bits().radix_dist(&other.0.bits())
            }

            fn radix_dist_max() -> u32 {
                <$t as Ieee754>::Bits::radix_dist_max()
            }
        }
    }
}

radix_int_impl!(i8);
radix_int_impl!(i16);
radix_int_impl!(i32);
radix_int_impl!(i64);
radix_int_impl!(isize);

radix_int_impl!(u8);
radix_int_impl!(u16);
radix_int_impl!(u32);
radix_int_impl!(u64);
radix_int_impl!(usize);

radix_float_impl!(f32);
radix_float_impl!(f64);

#[cfg(test)]
mod tests {
    extern crate quickcheck;

    use std::f32;
    use ordered_float::NotNaN;
    use super::Radix;
    use super::RadixHeapMap;
    use self::quickcheck::{TestResult, quickcheck};

    #[test]
    fn radix_dist() {
        assert!(4u32.radix_dist(&2) == 3);
        assert!(3u32.radix_dist(&2) == 1);
        assert!(2u32.radix_dist(&2) == 0);
        assert!(1u32.radix_dist(&2) == 2);
        assert!(0u32.radix_dist(&2) == 2);
    }

    #[test]
    fn push_pop() {
        let mut heap = RadixHeapMap::new();
        heap.push(0u32, 'a');
        heap.push(3, 'b');
        heap.push(2, 'c');

        assert!(heap.len() == 3);
        assert!(!heap.is_empty());

        assert!(heap.pop() == Some((3,'b')));
        assert!(heap.pop() == Some((2,'c')));
        assert!(heap.pop() == Some((0,'a')));
        assert!(heap.pop() == None);

        assert!(heap.len() == 0);
        assert!(heap.is_empty());
    }

    #[test]
    #[should_panic]
    fn push_pop_panic() {
        let mut heap = RadixHeapMap::new();
        heap.push(0u32, 'a');
        heap.push(3, 'b');

        assert!(heap.pop() == Some((3,'b')));
        heap.push(4, 'd');
    }

    #[test]
    fn sort() {
        fn prop(mut xs: Vec<u32>) -> bool {
            let mut heap = xs.iter().map(|&d| (d,())).collect::<RadixHeapMap<_,_>>();

            xs.sort();

            while xs.pop() == heap.pop().map(|(k,_)| k) {
                if xs.is_empty() {
                    return true;
                }
            }

            return false;
        }

        quickcheck(prop as fn(Vec<u32>) -> bool);
    }

    #[test]
    fn sort_float() {
        fn prop(xs: Vec<f32>) -> TestResult {
            if xs.iter().any(|x| x.is_nan()) {
                return TestResult::discard();
            }

            let mut xs: Vec<_> = xs.into_iter().map(|x| NotNaN(x)).collect();

            let mut heap = RadixHeapMap::new_at(NotNaN(f32::INFINITY));
            heap.extend(xs.iter().map(|&d| (d,())));

            xs.sort();

            while xs.pop() == heap.pop().map(|(k,_)| k) {
                if xs.is_empty() {
                    return TestResult::passed();
                }
            }

            return TestResult::failed();
        }

        quickcheck(prop as fn(Vec<f32>) -> TestResult);
    }
}
<commit_msg>Added impl for tuples and Wrapping<commit_after>//! A monotone priority queue implemented with a radix heap.
//!
//! A monotone priority queue is a priority queue that only allows keys to be
//! inserted if their priority is less than or equal to that of the last
//! extracted key.
//!
//! In this implementation, the last extracted value is known as the "top"
//! value. The top value does not necessarily have to be the last extracted key.
//! It can be lower, or initially it can be any value. Note that the constraint
//! above still applies in such a case.
//!
//! Insertion is O(1) time complexity, while popping is amortized O(log n).
//! More precisely, popping is O(d) where d is the radix distance from the key
//! to the top value at the time of insertion. This can give better asymptotic
//! running times for certain algorithms like for example Djikstra's algorithm.
//!
//! #Example
//!
//! ```
//! extern crate radix_heap;
//!
//! let mut heap = radix_heap::RadixHeapMap::new();
//! heap.push(7, 'a');
//! heap.push(2, 'b');
//! heap.push(9, 'c');
//!
//! assert!(heap.pop() == Some((9, 'c')));
//! assert!(heap.top() == 9);
//! assert!(heap.pop() == Some((7, 'a')));
//! assert!(heap.top() == 7);
//! assert!(heap.pop() == Some((2, 'b')));
//! assert!(heap.top() == 2);
//! assert!(heap.pop() == None);
//! ```

extern crate ieee754;
extern crate revord;
extern crate ordered_float;
extern crate num;

use std::fmt;
use std::iter::FromIterator;
use std::cmp::max;
use std::mem::swap;
use std::default::Default;
use std::num::Wrapping;
use revord::RevOrd;
use ieee754::Ieee754;
use ordered_float::NotNaN;
use num::Bounded;

#[derive(Clone)]
struct Bucket<K,V> {
    max: Option<K>,
    elems: Vec<(K,V)>,
}

/// A montone priority queue implemented with a radix heap.
///
/// This will be a max-heap.
///
/// It is a logic error for a key to be modified in such a way that the
/// item's ordering relative to any other item, as determined by the `Ord`
/// trait, changes while it is in the heap. This is normally only possible
/// through `Cell`, `RefCell`, global state, I/O, or unsafe code.
#[derive(Clone)]
pub struct RadixHeapMap<K,V> {
    len: usize,
    top: K,
    buckets: Vec<Bucket<K,V>>,
}

impl<K: Radix + Ord + Copy + Bounded, V> RadixHeapMap<K,V> {
    /// Creates a new `RadixHeapMap` with the highest possible top value such
    /// that all keys are allowed.
    pub fn new() -> RadixHeapMap<K,V> {
        RadixHeapMap::new_at(K::max_value())
    }

    /// Clears a new `RadixHeapMap` and sets te top value as high as possible
    /// value, so all keys can be inserted into the heap.
    pub fn clear(&mut self) {
        self.clear_to(K::max_value());
    }
}

impl<K: Radix + Ord + Copy,V> RadixHeapMap<K,V> {

    /// Creates a new RadixHeapMap with a specific top value
    pub fn new_at(top: K) -> RadixHeapMap<K,V> {
        let maxdist = K::radix_dist_max();
        let mut buckets = Vec::with_capacity(maxdist as usize + 1);

        for _ in 0..maxdist + 1 {
            buckets.push(Bucket{
                max: None,
                elems: Vec::new()
            });
        }

        RadixHeapMap { len: 0, top: top, buckets: buckets }
    }

    /// Clears the elements in the heap and sets the top value to a new value
    pub fn clear_to(&mut self, top: K) {
        self.top = top;
        self.len = 0;

        for bucket in &mut self.buckets {
            bucket.elems.clear();
        }
    }

    fn push_nocheck(&mut self, key: K, value: V) {
        let bucket = &mut self.buckets[key.radix_dist(&self.top) as usize];

        bucket.max = Some(bucket.max.map_or(key, |m| max(m, key)));
        bucket.elems.push((key,value));
    }

    /// Pushes a new key value pair onto the heap.
    ///
    /// Panics
    /// ------
    /// Panics if the key is more than the current top value.
    pub fn push(&mut self, key: K, value: V) {
        assert!(key <= self.top);
        self.len += 1;
        self.push_nocheck(key, value);
    }

    /// Sets the top value to the current maximum key value in the heap
    pub fn constrain(&mut self) {
        if self.buckets[0].elems.is_empty() {
            let bucket = self.buckets[1..].iter()
                .enumerate()
                .filter_map(|(i, ref bucket)| bucket.max
                    .map(|max| (i + 1, max)))
                .next();

            if let Some((index,max)) = bucket {
                self.top = max;
                let mut repush = Vec::new();

                self.buckets[index].max = None;
                swap(&mut self.buckets[index].elems, &mut repush);

                for (k,v) in repush.drain(..) {
                    self.push_nocheck(k, v);
                }

                // Swap `repush` back again (purely to save memory allocation,
                // they are both empty at this point but `repush` has some
                // memory allocated)
                swap(&mut self.buckets[index].elems, &mut repush);
            }
        }
    }

    /// Pops the largest element of the heap. This might decrease the top value.
    pub fn pop(&mut self) -> Option<(K,V)> {
        self.constrain();

        let pop = self.buckets[0].elems.pop();

        if pop.is_some() {
            self.len -= 1;
        }

        pop
    }

    /// Returns the number of elements in the heap
    pub fn len(&self) -> usize {
        self.len
    }

    /// Returns true if there is no elements in the heap
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// The current top value. All keys pushed onto the heap must be smaller
    /// than this value.
    pub fn top(&self) -> K {
        self.top
    }

    /// Discards as much additional capacity as possible.
    pub fn shrink_to_fit(&mut self) {
        for bucket in &mut self.buckets {
            bucket.elems.shrink_to_fit();
        }
    }
}

impl<K: Radix + Ord + Copy + Bounded, V> Default for RadixHeapMap<K,V> {
    fn default() -> RadixHeapMap<K,V> {
        RadixHeapMap::new()
    }
}

impl<K: Radix + Ord + Copy + Bounded, V> FromIterator<(K,V)> for RadixHeapMap<K,V> {
    fn from_iter<I>(iter: I) -> RadixHeapMap<K,V> where
        I: IntoIterator<Item=(K,V)>
    {
        let mut heap = RadixHeapMap::new();
        heap.extend(iter);
        heap
    }
}

impl<K: Radix + Ord + Copy, V> Extend<(K,V)> for RadixHeapMap<K,V> {
    fn extend<I>(&mut self, iter: I) where
        I: IntoIterator<Item=(K,V)>
    {
        for (k,v) in iter {
            self.push(k,v);
        }
    }
}

impl<'a, K: Radix + Ord + Copy + 'a, V: Copy + 'a> Extend<&'a (K,V)> for RadixHeapMap<K,V> {
    fn extend<I>(&mut self, iter: I) where
        I: IntoIterator<Item=&'a (K,V)>
    {
        for &(k,v) in iter {
            self.push(k,v);
        }
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for RadixHeapMap<K,V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let entries = self.buckets.iter().flat_map(|b| b.elems.iter());
        f.debug_list().entries(entries).finish()
    }
}

/// A number that can be compared using radix distance
pub trait Radix {
    /// The radix distance between this number and another number.
    ///
    /// The radix distance of n means that the n'th bit (1 indexed) is the
    /// highest bit in which `self` and `other` differ. It is 0 if they are
    /// equal, and M if they are bitwise complements to each other, where M is
    /// the number of bits.
    fn radix_dist(&self, other: &Self) -> u32;

    /// The maximum possible radix distance possible.
    fn radix_dist_max() -> u32;
}

macro_rules! radix_wrapper_impl {
    ($t:ident) => {
        impl<T: Radix> Radix for $t<T> {
            fn radix_dist(&self, other: &$t<T>) -> u32 {
                self.0.radix_dist(&other.0)
            }

            fn radix_dist_max() -> u32 {
                T::radix_dist_max()
            }
        }
    }
}

radix_wrapper_impl!(RevOrd);
radix_wrapper_impl!(Wrapping);

macro_rules! radix_int_impl {
    ($t:ty) => {
        impl Radix for $t {
            fn radix_dist(&self, other: &$t) -> u32 {
                Self::radix_dist_max() - (self ^ other).leading_zeros()
            }

            fn radix_dist_max() -> u32 {
                (std::mem::size_of::<$t>() * 8) as u32
            }
        }
    }
}

radix_int_impl!(i8);
radix_int_impl!(i16);
radix_int_impl!(i32);
radix_int_impl!(i64);
radix_int_impl!(isize);

radix_int_impl!(u8);
radix_int_impl!(u16);
radix_int_impl!(u32);
radix_int_impl!(u64);
radix_int_impl!(usize);

macro_rules! radix_float_impl {
    ($t:ty) => {
        impl Radix for NotNaN<$t> {
            fn radix_dist(&self, other: &NotNaN<$t>) -> u32 {
                self.0.bits().radix_dist(&other.0.bits())
            }

            fn radix_dist_max() -> u32 {
                <$t as Ieee754>::Bits::radix_dist_max()
            }
        }
    }
}

radix_float_impl!(f32);
radix_float_impl!(f64);

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

macro_rules! radix_tuple_impl {
    ($(
        $Tuple:ident {
            $(($idx:tt) -> $T:ident)+
        }
    )+) => {
        $(
            impl<$($T:Radix),+> Radix for ($($T,)+) {
                fn radix_dist(&self, other: &($($T,)+)) -> u32 {
                    let total_dist = 0 $(+e!(<$T as Radix>::radix_dist_max()))+;

                    $(
                        let total_dist = total_dist - e!(<$T as Radix>::radix_dist_max());
                        let d = e!(self.$idx.radix_dist(&other.$idx));
                        if d != 0 { return total_dist + d }
                    )+

                    return 0;
                }

                fn radix_dist_max() -> u32 {
                    0 $(+e!(<$T as Radix>::radix_dist_max()))+
                }
            }
        )+
    }
}

radix_tuple_impl! {
    Tuple1 {
        (0) -> A
    }
    Tuple2 {
        (0) -> A
        (1) -> B
    }
    Tuple3 {
        (0) -> A
        (1) -> B
        (2) -> C
    }
    Tuple4 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
    }
    Tuple5 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
    }
    Tuple6 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
    }
    Tuple7 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
    }
    Tuple8 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
    }
    Tuple9 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
    }
    Tuple10 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
    }
    Tuple11 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
    }
    Tuple12 {
        (0) -> A
        (1) -> B
        (2) -> C
        (3) -> D
        (4) -> E
        (5) -> F
        (6) -> G
        (7) -> H
        (8) -> I
        (9) -> J
        (10) -> K
        (11) -> L
    }
}

#[cfg(test)]
mod tests {
    extern crate quickcheck;

    use std::f32;
    use ordered_float::NotNaN;
    use super::Radix;
    use super::RadixHeapMap;
    use super::num::Bounded;
    use self::quickcheck::{TestResult, quickcheck};

    #[test]
    fn radix_dist() {
        assert!(4u32.radix_dist(&2) == 3);
        assert!(3u32.radix_dist(&2) == 1);
        assert!(2u32.radix_dist(&2) == 0);
        assert!(1u32.radix_dist(&2) == 2);
        assert!(0u32.radix_dist(&2) == 2);
    }

    #[test]
    fn push_pop() {
        let mut heap = RadixHeapMap::new();
        heap.push(0u32, 'a');
        heap.push(3, 'b');
        heap.push(2, 'c');

        assert!(heap.len() == 3);
        assert!(!heap.is_empty());

        assert!(heap.pop() == Some((3,'b')));
        assert!(heap.pop() == Some((2,'c')));
        assert!(heap.pop() == Some((0,'a')));
        assert!(heap.pop() == None);

        assert!(heap.len() == 0);
        assert!(heap.is_empty());
    }

    #[test]
    #[should_panic]
    fn push_pop_panic() {
        let mut heap = RadixHeapMap::new();
        heap.push(0u32, 'a');
        heap.push(3, 'b');

        assert!(heap.pop() == Some((3,'b')));
        heap.push(4, 'd');
    }

    #[test]
    fn sort() {
        fn prop<T: Ord + Radix + Copy + Bounded>(mut xs: Vec<T>) -> bool {
            let mut heap = xs.iter().map(|&d| (d,())).collect::<RadixHeapMap<_,_>>();

            xs.sort();

            while xs.pop() == heap.pop().map(|(k,_)| k) {
                if xs.is_empty() {
                    return true;
                }
            }

            return false;
        }

        quickcheck(prop as fn(Vec<u32>) -> bool);
        quickcheck(prop as fn(Vec<i32>) -> bool);
        quickcheck(prop as fn(Vec<(u32, i32)>) -> bool);
        quickcheck(prop as fn(Vec<u8>) -> bool);
        quickcheck(prop as fn(Vec<i16>) -> bool);
        quickcheck(prop as fn(Vec<(i64, usize)>) -> bool);
    }

    #[test]
    fn sort_float() {
        fn prop(xs: Vec<f32>) -> TestResult {
            if xs.iter().any(|x| x.is_nan()) {
                return TestResult::discard();
            }

            let mut xs: Vec<_> = xs.into_iter().map(|x| NotNaN(x)).collect();

            let mut heap = RadixHeapMap::new_at(NotNaN(f32::INFINITY));
            heap.extend(xs.iter().map(|&d| (d,())));

            xs.sort();

            while xs.pop() == heap.pop().map(|(k,_)| k) {
                if xs.is_empty() {
                    return TestResult::passed();
                }
            }

            return TestResult::failed();
        }

        quickcheck(prop as fn(Vec<f32>) -> TestResult);
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

#[cfg(test)]
extern crate test;

pub use blake2b::Blake2b;
pub use blake2s::Blake2s;

mod blake2b;
mod blake2s;
#[cfg(test)] mod kat;
<commit_msg>Remove deprecated feature flag<commit_after>#[cfg(test)]
extern crate test;

pub use blake2b::Blake2b;
pub use blake2s::Blake2s;

mod blake2b;
mod blake2s;
#[cfg(test)] mod kat;
<|endoftext|>


<commit_before>//
// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
pub use ffi as rocksdb_ffi;
pub use ffi::{DBCompactionStyle, DBComparator, new_bloom_filter};
pub use rocksdb::{DB, DBIterator, DBVector, Direction, Writable, WriteBatch, IteratorMode};
pub use rocksdb_options::{BlockBasedOptions, Options};
pub use merge_operator::MergeOperands;
pub mod rocksdb;
pub mod ffi;
pub mod rocksdb_options;
pub mod merge_operator;
pub mod comparator;
<commit_msg>Export WriteOptions.<commit_after>//
// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
pub use ffi as rocksdb_ffi;
pub use ffi::{DBCompactionStyle, DBComparator, new_bloom_filter};
pub use rocksdb::{DB, DBIterator, DBVector, Direction, Writable, WriteBatch, IteratorMode};
pub use rocksdb_options::{BlockBasedOptions, Options, WriteOptions};
pub use merge_operator::MergeOperands;
pub mod rocksdb;
pub mod ffi;
pub mod rocksdb_options;
pub mod merge_operator;
pub mod comparator;
<|endoftext|>


<commit_before>#![feature(associated_types, macro_rules)]

//! Machine scalar casting that meets your expectations

/// Overflow error
pub struct Overflow;

/// Underflow error
pub struct Underflow;

/// Errors that may arise when casting from integers
pub enum FromInteger {
    Overflow,
    Underflow,
}

/// Errors that may arise when casting from floats
pub enum FromFloat {
    NaN,
    Overflow,
    Underflow,
}

/// The "casting from" operation
pub trait CastFrom<Src> {
    type Output;

    fn from(src: Src) -> Output;
}

/// The "casting to" operation
pub trait CastTo {
    fn to<Dst: CastFrom<Self>>(self) -> Dst::Output {
        Dst::from(self)
    }
}

macro_rules! impl_cast_to {
    ($($ty:ty),+) => {$(
        impl CastTo for $ty {})+
    }
}

impl_cast_to!(int, i8, i16, i32, i64, uint, u8, u16, u32, u64, f32, f64)

macro_rules! promotion {
    ($($src:ty -> $($dst: ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = $dst;

            #[inline(always)]
            fn from(src: $src) -> $dst {
                 // NB Sanity check
                debug_assert!(mem::size_of::<$src>() <= mem::size_of::<$dst>());

                src as $dst
            }
        })+)+
    }
}

macro_rules! half_promotion {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, Underflow>;

            fn from(src: $src) -> Result<$dst, Underflow> {
                 // NB Sanity check
                debug_assert!(mem::size_of::<$src>() <= mem::size_of::<$dst>());

                if self < 0 {
                    Err(Underflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_unsigned {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, Overflow>;

            fn from(src: $src) -> Result<$dst, Overflow> {
                // NB Sanity check
                debug_assert!(mem::size_of::<$src>() >= mem::size_of::<$dst>());

                if self > $dst::max_value() as $src {
                    Err(Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_signed {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, FromInteger>;

            fn cast(self) -> Result<$dst, FromInteger> {
                // NB Sanity check
                debug_assert!(mem::size_of::<$src>() > mem::size_of::<$dst>());

                if src < $dst::min_value() as $src {
                    Err(FromInteger::Underflow)
                } else if src > $dst::max_value() as $src {
                    Err(FromInteger::Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_float {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, FromFloat>;

            fn from(src: $src) -> Result<$dst, FromFloat> {
                if src.is_nan() {
                    Err(FromFloat::Nan)
                } else if src < $dst::min_value() as $src {
                    Err(FromFloat::Underflow)
                } else if src > $dst::max_value() as $src {
                    Err(FromFloat::Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

// Signed
promotion!{
    i8   -> f32, f64, i8, i16, i32, i64;
    i16  -> f32, f64,     i16, i32, i64;
    i32  -> f32, f64,          i32, i64;
    i64  -> f32, f64,               i64;
}

half_promotion!{
    i8   ->                              u8, u16, u32, u64;
    i16  ->                                  u16, u32, u64;
    i32  ->                                       u32, u64;
    i64  ->                                            u64;
}

from_signed!{

    i16  ->           i8,                u8;
    i32  ->           i8, i16,           u8, u16;
    i64  ->           i8, i16, i32,      u8, u16, u32;
}

// Unsigned
promotion!{
    u8   -> f32, f64,     i16, i32, i64, u8, u16, u32, u64;
    u16  -> f32, f64,          i32, i64,     u16, u32, u64;
    u32  -> f32, f64,               i64,          u32, u64;
    u64  -> f32, f64,                                  u64;
}

from_unsigned!{
    u8   ->           i8;
    u16  ->           i8, i16,           u8;
    u32  ->           i8, i16, i32,      u8, u16;
    u64  ->           i8, i16, i32, i64, u8, u16, u32;
}

// Float
promotion!{
    f32  -> f32, f64;
    f64  ->      f64;
}

from_float!{
    f32  ->           i8, i16, i32, i64, u8, u16, u32, u64;
    f64  -> f32,      i8, i16, i32, i64, u8, u16, u32, u64;
}

// Machine dependent scalars
#[cfg(any(target_arch = "x86", target_arch = "arm"))]
promotion!{
    int  -> f32, f64,          i32, i64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
half_promotion!{
    int  ->                                       u32, u64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
from_signed!{
    int  ->           i8, i16,           u8, u16;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
promotion!{
    uint -> f32, f64,               i64,          u32, u64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
from_unsigned!{
    uint ->           i8, i16, i32,      u8, u16;
}

#[cfg(any(target_arch = "x86_64"))]
promotion!{
    int  -> f32, f64,               i64;
}

#[cfg(any(target_arch = "x86_64"))]
half_promotion!{
    int  ->                                            u64;
}

#[cfg(any(target_arch = "x86_64"))]
from_signed!{
    int  ->           i8, i16, i32,      u8, u16, u32;
}

#[cfg(any(target_arch = "x86_64"))]
promotion!{
    uint -> f32, f64,                                  u64;
}

#[cfg(any(target_arch = "x86_64"))]
from_unsigned!{
    uint ->           i8, i16, i32, i64, u8, u16, u32;
}
<commit_msg>refactor(CastTo): move bound from parameter list to where clause<commit_after>#![feature(associated_types, macro_rules)]

//! Machine scalar casting that meets your expectations

/// Overflow error
pub struct Overflow;

/// Underflow error
pub struct Underflow;

/// Errors that may arise when casting from integers
pub enum FromInteger {
    Overflow,
    Underflow,
}

/// Errors that may arise when casting from floats
pub enum FromFloat {
    NaN,
    Overflow,
    Underflow,
}

/// The "casting from" operation
pub trait CastFrom<Src> {
    type Output;

    fn from(src: Src) -> Output;
}

/// The "casting to" operation
pub trait CastTo {
    fn to<Dst>(self) -> Dst::Output where Dst: CastFrom<Self> {
        Dst::from(self)
    }
}

macro_rules! impl_cast_to {
    ($($ty:ty),+) => {$(
        impl CastTo for $ty {})+
    }
}

impl_cast_to!(int, i8, i16, i32, i64, uint, u8, u16, u32, u64, f32, f64)

macro_rules! promotion {
    ($($src:ty -> $($dst: ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = $dst;

            #[inline(always)]
            fn from(src: $src) -> $dst {
                 // NB Sanity check
                debug_assert!(mem::size_of::<$src>() <= mem::size_of::<$dst>());

                src as $dst
            }
        })+)+
    }
}

macro_rules! half_promotion {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, Underflow>;

            fn from(src: $src) -> Result<$dst, Underflow> {
                 // NB Sanity check
                debug_assert!(mem::size_of::<$src>() <= mem::size_of::<$dst>());

                if self < 0 {
                    Err(Underflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_unsigned {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, Overflow>;

            fn from(src: $src) -> Result<$dst, Overflow> {
                // NB Sanity check
                debug_assert!(mem::size_of::<$src>() >= mem::size_of::<$dst>());

                if self > $dst::max_value() as $src {
                    Err(Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_signed {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, FromInteger>;

            fn cast(self) -> Result<$dst, FromInteger> {
                // NB Sanity check
                debug_assert!(mem::size_of::<$src>() > mem::size_of::<$dst>());

                if src < $dst::min_value() as $src {
                    Err(FromInteger::Underflow)
                } else if src > $dst::max_value() as $src {
                    Err(FromInteger::Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

macro_rules! from_float {
    ($($src:ty -> $($dst:ty),+);+;) => {$($(
        impl CastFrom<$src> for $dst {
            type Output = Result<$dst, FromFloat>;

            fn from(src: $src) -> Result<$dst, FromFloat> {
                if src.is_nan() {
                    Err(FromFloat::Nan)
                } else if src < $dst::min_value() as $src {
                    Err(FromFloat::Underflow)
                } else if src > $dst::max_value() as $src {
                    Err(FromFloat::Overflow)
                } else {
                    Ok(src as $dst)
                }
            }
        })+)+
    }
}

// Signed
promotion!{
    i8   -> f32, f64, i8, i16, i32, i64;
    i16  -> f32, f64,     i16, i32, i64;
    i32  -> f32, f64,          i32, i64;
    i64  -> f32, f64,               i64;
}

half_promotion!{
    i8   ->                              u8, u16, u32, u64;
    i16  ->                                  u16, u32, u64;
    i32  ->                                       u32, u64;
    i64  ->                                            u64;
}

from_signed!{

    i16  ->           i8,                u8;
    i32  ->           i8, i16,           u8, u16;
    i64  ->           i8, i16, i32,      u8, u16, u32;
}

// Unsigned
promotion!{
    u8   -> f32, f64,     i16, i32, i64, u8, u16, u32, u64;
    u16  -> f32, f64,          i32, i64,     u16, u32, u64;
    u32  -> f32, f64,               i64,          u32, u64;
    u64  -> f32, f64,                                  u64;
}

from_unsigned!{
    u8   ->           i8;
    u16  ->           i8, i16,           u8;
    u32  ->           i8, i16, i32,      u8, u16;
    u64  ->           i8, i16, i32, i64, u8, u16, u32;
}

// Float
promotion!{
    f32  -> f32, f64;
    f64  ->      f64;
}

from_float!{
    f32  ->           i8, i16, i32, i64, u8, u16, u32, u64;
    f64  -> f32,      i8, i16, i32, i64, u8, u16, u32, u64;
}

// Machine dependent scalars
#[cfg(any(target_arch = "x86", target_arch = "arm"))]
promotion!{
    int  -> f32, f64,          i32, i64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
half_promotion!{
    int  ->                                       u32, u64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
from_signed!{
    int  ->           i8, i16,           u8, u16;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
promotion!{
    uint -> f32, f64,               i64,          u32, u64;
}

#[cfg(any(target_arch = "x86", target_arch = "arm"))]
from_unsigned!{
    uint ->           i8, i16, i32,      u8, u16;
}

#[cfg(any(target_arch = "x86_64"))]
promotion!{
    int  -> f32, f64,               i64;
}

#[cfg(any(target_arch = "x86_64"))]
half_promotion!{
    int  ->                                            u64;
}

#[cfg(any(target_arch = "x86_64"))]
from_signed!{
    int  ->           i8, i16, i32,      u8, u16, u32;
}

#[cfg(any(target_arch = "x86_64"))]
promotion!{
    uint -> f32, f64,                                  u64;
}

#[cfg(any(target_arch = "x86_64"))]
from_unsigned!{
    uint ->           i8, i16, i32, i64, u8, u16, u32;
}
<|endoftext|>


<commit_before>// This file is part of Caribon.
//
// Caribon is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Caribon.  If not, see <http://www.gnu.org/licenses/>.

/*! Repetition detector library

Detects the repetitions in an input file, using a stemming library in order to detect
words that are not technically identical but are quite the same, such as `cat` and `cats`.

Here's a short example (more details below):
```
use Caribon::Parser;
let parser = Parser::new("English").unwrap();
let words = parser.tokenize("Some text where you want to detect repetitions");
let mut repetitions = parser.detect_local(words, 1.5);
repetitions = parser.detect_global(words, 0.01);
let html = parser.words_to_html(&repetitions);
println!("{}", html);
```

Since this stemming is dependent on the language, you must first create a new `Parser` with the
appropriate language. `Parser::new` returns a `caribon::Result<Parser>`, which will contain `Ok(Parser)`
if the language is implemented, `Err(caribon::Error)` else:

```
use caribon::Parser;
let result = Parser::new("foo");
assert!(result.is_err());
```

Once you have a parser, you can then configure it with various options:

```
use caribon::Parser;
let parser = Parser::new("english").unwrap()
                                            .with_html(true)
                                            .with_ignore_proper(true)
                                            .with_max_distance(20)
                                            .with_ignored("some, words, to, ignore");
```

The next step is to read some string and convert it to some inner format (currently `Vec<Word>`
but it is possible that it will change):

```ignore
let words = parser.tokenize(some_string).unwrap();
```

As `new`, this method can fail, so it returns a `Result`.

You then have a choice between multiple repetition detection algorithms. `detect_local` is probably
the one you want to use:

```ignore
let repetitions = parser.detect_local(words, 1.5);
```

There is also `detect_leak`, which is a particular algorithm which probably will be removed at some
point:

```ignore
let repetitions = parser.detect_leak(words, 1.5);
```

The last one is `detect_global`, which detects repetiion in the whole file:

```ignore
let repetitions = parser.detect_global(words, 0.01);
```

Once you have detected those repetitions, the final step is to print them.
`words_to_html` does this. Besides a reference to a <Vec<Word>>, it takes two arguments:
a threshold (basically, the number of repetitions to trigger underlining in HTML), and a
boolean that tests whether the HTML code must be a standalone file or not (you will probably
want to set it to true).

```ignore
let html = parser.words_to_html(&repetitions, true):
```
*/

// Uncomment this if you use nightly and want to run benchmarks
#![feature(test)]
mod bench;
mod word;
mod parser;

pub use parser::Error;
pub use parser::Result;
pub use word::Word;
pub use parser::Parser;
<commit_msg>commented benchmark call for lib.rs<commit_after>// This file is part of Caribon.
//
// Caribon is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// Caribon is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Caribon.  If not, see <http://www.gnu.org/licenses/>.

/*! Repetition detector library

Detects the repetitions in an input file, using a stemming library in order to detect
words that are not technically identical but are quite the same, such as `cat` and `cats`.

Here's a short example (more details below):
```
use Caribon::Parser;
let parser = Parser::new("English").unwrap();
let words = parser.tokenize("Some text where you want to detect repetitions");
let mut repetitions = parser.detect_local(words, 1.5);
repetitions = parser.detect_global(words, 0.01);
let html = parser.words_to_html(&repetitions);
println!("{}", html);
```

Since this stemming is dependent on the language, you must first create a new `Parser` with the
appropriate language. `Parser::new` returns a `caribon::Result<Parser>`, which will contain `Ok(Parser)`
if the language is implemented, `Err(caribon::Error)` else:

```
use caribon::Parser;
let result = Parser::new("foo");
assert!(result.is_err());
```

Once you have a parser, you can then configure it with various options:

```
use caribon::Parser;
let parser = Parser::new("english").unwrap()
                                            .with_html(true)
                                            .with_ignore_proper(true)
                                            .with_max_distance(20)
                                            .with_ignored("some, words, to, ignore");
```

The next step is to read some string and convert it to some inner format (currently `Vec<Word>`
but it is possible that it will change):

```ignore
let words = parser.tokenize(some_string).unwrap();
```

As `new`, this method can fail, so it returns a `Result`.

You then have a choice between multiple repetition detection algorithms. `detect_local` is probably
the one you want to use:

```ignore
let repetitions = parser.detect_local(words, 1.5);
```

There is also `detect_leak`, which is a particular algorithm which probably will be removed at some
point:

```ignore
let repetitions = parser.detect_leak(words, 1.5);
```

The last one is `detect_global`, which detects repetiion in the whole file:

```ignore
let repetitions = parser.detect_global(words, 0.01);
```

Once you have detected those repetitions, the final step is to print them.
`words_to_html` does this. Besides a reference to a <Vec<Word>>, it takes two arguments:
a threshold (basically, the number of repetitions to trigger underlining in HTML), and a
boolean that tests whether the HTML code must be a standalone file or not (you will probably
want to set it to true).

```ignore
let html = parser.words_to_html(&repetitions, true):
```
*/

// Uncomment this if you use nightly and want to run benchmarks
//#![feature(test)]
//mod bench;
mod word;
mod parser;

pub use parser::Error;
pub use parser::Result;
pub use word::Word;
pub use parser::Parser;
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(cargo_c)]
mod capi;

mod dist;
mod ec;
mod partition;
mod transform;
mod quantize;
mod predict;
mod rdo;
mod rdo_tables;
#[macro_use]
mod util;
mod context;
mod entropymode;
mod token_cdfs;
mod deblock;
mod segmentation;
mod cdef;
mod lrf;
mod encoder;
mod mc;
mod me;
mod metrics;
mod scan_order;
mod scenechange;
mod rate;
mod tiling;

mod api;
mod header;
mod frame;

use crate::encoder::*;

pub use crate::api::{Context, Config, Packet, EncoderStatus};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel};

pub mod prelude {
  pub use crate::api::*;
  pub use crate::frame::Frame;
  pub use crate::frame::Plane;
  pub use crate::encoder::Tune;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Basic data structures
pub mod data {
  pub use crate::frame::Frame;
  pub use crate::api::{
    Packet, Point, Rational, FrameType, EncoderStatus
  };
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Color model information
pub mod color {
  pub use crate::api::{
    ChromaSamplePosition,
    ChromaSampling,
    ColorPrimaries,
    TransferCharacteristics,
    PixelRange,
    ContentLight,
    ColorDescription,
    MasteringDisplay,
    MatrixCoefficients,
  };
}

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, SpeedSettings, PredictionModesSetting,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
///```
///
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature="decode_test", feature="decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature="bench")]
pub mod bench {
  pub mod api { pub use crate::api::*; }
  pub mod cdef { pub use crate::cdef::*; }
  pub mod context { pub use crate::context::*; }
  pub mod dist { pub use crate::dist::*; }
  pub mod ec { pub use crate::ec::*; }
  pub mod encoder { pub use crate::encoder::*; }
  pub mod partition { pub use crate::partition::*; }
  pub mod frame { pub use crate::frame::*; }
  pub mod predict { pub use crate::predict::*; }
  pub mod rdo { pub use crate::rdo::*; }
  pub mod transform { pub use crate::transform::*; }
  pub mod util { pub use crate::util::*; }
}
<commit_msg>Add PlaneConfig to the public API<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

#![allow(safe_extern_statics)]
#![deny(bare_trait_objects)]

// Override assert! and assert_eq! in tests
#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

#[cfg(cargo_c)]
mod capi;

mod dist;
mod ec;
mod partition;
mod transform;
mod quantize;
mod predict;
mod rdo;
mod rdo_tables;
#[macro_use]
mod util;
mod context;
mod entropymode;
mod token_cdfs;
mod deblock;
mod segmentation;
mod cdef;
mod lrf;
mod encoder;
mod mc;
mod me;
mod metrics;
mod scan_order;
mod scenechange;
mod rate;
mod tiling;

mod api;
mod header;
mod frame;

use crate::encoder::*;

pub use crate::api::{Context, Config, Packet, EncoderStatus};
pub use crate::frame::Frame;
pub use crate::util::{CastFromPrimitive, Pixel};

pub mod prelude {
  pub use crate::api::*;
  pub use crate::frame::Frame;
  pub use crate::frame::Plane;
  pub use crate::frame::PlaneConfig;
  pub use crate::encoder::Tune;
  pub use crate::partition::BlockSize;
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Basic data structures
pub mod data {
  pub use crate::frame::Frame;
  pub use crate::api::{
    Packet, Point, Rational, FrameType, EncoderStatus
  };
  pub use crate::util::{CastFromPrimitive, Pixel};
}

/// Color model information
pub mod color {
  pub use crate::api::{
    ChromaSamplePosition,
    ChromaSampling,
    ColorPrimaries,
    TransferCharacteristics,
    PixelRange,
    ContentLight,
    ColorDescription,
    MasteringDisplay,
    MatrixCoefficients,
  };
}

/// Encoder configuration and settings
pub mod config {
  pub use crate::api::{
    Config, EncoderConfig, SpeedSettings, PredictionModesSetting,
  };
}

/// Version information
///
/// The information is recovered from `Cargo.toml` and `git describe`, when available.
///
/// ```
/// use rav1e::version;
/// use semver::Version;
///
/// let major = version::major();
/// let minor = version::minor();
/// let patch = version::patch();
///
/// let short = version::short();
///
/// let v1 = Version::new(major, minor, patch);
/// let v2 = Version::parse(&short).unwrap();
///
/// assert_eq!(v1, v2);
///```
///
pub mod version {
  /// Major version component
  ///
  /// It is increased every time a release presents a incompatible API change.
  pub fn major() -> u64 {
    env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap()
  }
  /// Minor version component
  ///
  /// It is increased every time a release presents new functionalities are added
  /// in a backwards-compatible manner.
  pub fn minor() -> u64 {
    env!("CARGO_PKG_VERSION_MINOR").parse().unwrap()
  }
  /// Patch version component
  ///
  /// It is increased every time a release provides only backwards-compatible bugfixes.
  pub fn patch() -> u64 {
    env!("CARGO_PKG_VERSION_PATCH").parse().unwrap()
  }

  /// Version information as presented in `[package]` `version`.
  ///
  /// e.g. `0.1.0``
  ///
  /// Can be parsed by [semver](https://crates.io/crates/semver).
  pub fn short() -> String {
    env!("CARGO_PKG_VERSION").to_string()
  }

  /// Version information as presented in `[package] version` followed by the
  /// short commit hash if present.
  ///
  /// e.g. `0.1.0 - g743d464`
  ///
  pub fn long() -> String {
    let s = short();
    let hash = hash();

    if hash.is_empty() {
      s
    } else {
      format!("{} - {}", s, hash)
    }
  }

  /// Commit hash (short)
  ///
  /// Short hash of the git commit used by this build
  ///
  /// e.g. `g743d464`
  ///
  pub fn hash() -> String {
    env!("VERGEN_SHA_SHORT").to_string()
  }

  /// Version information with the information
  /// provided by `git describe --tags`.
  ///
  /// e.g. `0.1.0 (v0.1.0-1-g743d464)`
  ///
  pub fn full() -> String {
    let semver = env!("VERGEN_SEMVER_LIGHTWEIGHT");
    format!("{} ({})", short(), semver)
  }
}
#[cfg(all(test, any(feature="decode_test", feature="decode_test_dav1d")))]
mod test_encode_decode;

#[cfg(feature="bench")]
pub mod bench {
  pub mod api { pub use crate::api::*; }
  pub mod cdef { pub use crate::cdef::*; }
  pub mod context { pub use crate::context::*; }
  pub mod dist { pub use crate::dist::*; }
  pub mod ec { pub use crate::ec::*; }
  pub mod encoder { pub use crate::encoder::*; }
  pub mod partition { pub use crate::partition::*; }
  pub mod frame { pub use crate::frame::*; }
  pub mod predict { pub use crate::predict::*; }
  pub mod rdo { pub use crate::rdo::*; }
  pub mod transform { pub use crate::transform::*; }
  pub mod util { pub use crate::util::*; }
}
<|endoftext|>


<commit_before>//! [![Crates.io](https://img.shields.io/crates/v/inflector.svg)](https://crates.io/crates/inflector)
//!
//! Adds String based inflections for Rust. Snake, kebab, camel,
//! sentence, class, title, upper, and lower cases as well as ordinalize,
//! deordinalize, demodulize, deconstantize, and foreign key are supported as both traits and pure functions
//! acting on String types.
//!
//! ```rust
//! use inflector::Inflector;
//! #[test]
//! fn should_convert_to_and_verify_camel_cased_string() {
//!   let camel_case_string: String = "some_string".to_camel_case();
//!   let is_camel_cased: bool= camel_case_string.is_camel_case();
//!   assert!(is_camel_cased == true);
//! }
//! ```
extern crate regex;
/// Provides case inflections
/// - Camel case
/// - Class case
/// - Kebab case
/// - Lower case
/// - Screaming snake case
/// - Sentence case
/// - Snake case
/// - Upper case
pub mod cases;
/// Provides number inflections
/// - Ordinalize
/// - Deordinalize
pub mod numbers;
/// Provides suffix inflections
/// - Foreign key
pub mod suffix;
/// Provides string inflections
/// - Deconstantize
/// - Demodulize
pub mod string;

use cases::classcase::to_class_case;
use cases::classcase::is_class_case;

use cases::camelcase::to_camel_case;
use cases::camelcase::is_camel_case;

use cases::snakecase::to_snake_case;
use cases::snakecase::is_snake_case;

use cases::screamingsnakecase::to_screaming_snake_case;
use cases::screamingsnakecase::is_screaming_snake_case;

use cases::kebabcase::to_kebab_case;
use cases::kebabcase::is_kebab_case;

use cases::sentencecase::to_sentence_case;
use cases::sentencecase::is_sentence_case;

use cases::titlecase::to_title_case;
use cases::titlecase::is_title_case;

use cases::uppercase::to_upper_case;
use cases::uppercase::is_upper_case;

use cases::lowercase::to_lower_case;
use cases::lowercase::is_lower_case;

use numbers::ordinalize::ordinalize;
use numbers::deordinalize::deordinalize;

use suffix::foreignkey::to_foreign_key;
use suffix::foreignkey::is_foreign_key;

use string::demodulize::demodulize;
use string::deconstantize::deconstantize;

use string::pluralize::to_plural;

pub trait Inflector {
    fn to_class_case<'a>(&self) -> String;
    fn is_class_case<'a>(&self) -> bool;

    fn to_camel_case<'a>(&self) -> String;
    fn is_camel_case<'a>(&self) -> bool;

    fn to_snake_case<'a>(&self) -> String;
    fn is_snake_case<'a>(&self) -> bool;

    fn to_screaming_snake_case<'a>(&self) -> String;
    fn is_screaming_snake_case<'a>(&self) -> bool;

    fn to_kebab_case<'a>(&self) -> String;
    fn is_kebab_case<'a>(&self) -> bool;

    fn to_sentence_case<'a>(&self) -> String;
    fn is_sentence_case<'a>(&self) -> bool;

    fn to_title_case<'a>(&self) -> String;
    fn is_title_case<'a>(&self) -> bool;

    fn to_upper_case<'a>(&self) -> String;
    fn is_upper_case<'a>(&self) -> bool;

    fn to_lower_case<'a>(&self) -> String;
    fn is_lower_case<'a>(&self) -> bool;

    fn ordinalize<'a>(&self) -> String;
    fn deordinalize<'a>(&self) -> String;

    fn to_foreign_key<'a>(&self) -> String;
    fn is_foreign_key<'a>(&self) -> bool;

    fn demodulize<'a>(&self) -> String;
    fn deconstantize<'a>(&self) -> String;

    fn to_plural<'a>(&self) -> String;
}

impl<'c> Inflector for String {
    fn to_class_case(&self) -> String{
        return to_class_case(self.to_string());
    }
    fn is_class_case(&self) -> bool{
        return is_class_case(self.to_string());
    }
    fn to_camel_case(&self) -> String{
        return to_camel_case(self.to_string());
    }
    fn is_camel_case(&self) -> bool{
        return is_camel_case(self.to_string());
    }
    fn to_screaming_snake_case(&self) -> String{
        return to_screaming_snake_case(self.to_string());
    }
    fn is_screaming_snake_case(&self) -> bool{
        return is_screaming_snake_case(self.to_string());
    }
    fn to_snake_case(&self) -> String{
        return to_snake_case(self.to_string());
    }
    fn is_snake_case(&self) -> bool{
        return is_snake_case(self.to_string());
    }
    fn to_kebab_case(&self) -> String{
        return to_kebab_case(self.to_string());
    }
    fn is_kebab_case(&self) -> bool{
        return is_kebab_case(self.to_string());
    }
    fn to_sentence_case(&self) -> String{
        return to_sentence_case(self.to_string());
    }
    fn is_sentence_case(&self) -> bool{
        return is_sentence_case(self.to_string());
    }
    fn to_title_case(&self) -> String{
        return to_title_case(self.to_string());
    }
    fn is_title_case(&self) -> bool{
        return is_title_case(self.to_string());
    }
    fn to_upper_case(&self) -> String{
        return to_upper_case(self.to_string());
    }
    fn is_upper_case(&self) -> bool{
        return is_upper_case(self.to_string());
    }
    fn to_lower_case(&self) -> String{
        return to_lower_case(self.to_string());
    }
    fn is_lower_case(&self) -> bool{
        return is_lower_case(self.to_string());
    }
    fn ordinalize(&self) -> String{
        return ordinalize(self.to_string());
    }
    fn deordinalize(&self) -> String{
        return deordinalize(self.to_string());
    }
    fn to_foreign_key(&self) -> String{
        return to_foreign_key(self.to_string());
    }
    fn is_foreign_key(&self) -> bool{
        return is_foreign_key(self.to_string());
    }
    fn demodulize(&self) -> String{
        return demodulize(self.to_string());
    }
    fn deconstantize(&self) -> String{
        return deconstantize(self.to_string());
    }
    fn to_plural(&self) -> String{
        return to_plural(self.to_string());
    }
}

impl<'c> Inflector for str {
    fn to_class_case(&self) -> String{
        return to_class_case(self.to_string());
    }
    fn is_class_case(&self) -> bool{
        return is_class_case(self.to_string());
    }
    fn to_camel_case(&self) -> String{
        return to_camel_case(self.to_string());
    }
    fn is_camel_case(&self) -> bool{
        return is_camel_case(self.to_string());
    }
    fn to_screaming_snake_case(&self) -> String{
        return to_screaming_snake_case(self.to_string());
    }
    fn is_screaming_snake_case(&self) -> bool{
        return is_screaming_snake_case(self.to_string());
    }
    fn to_snake_case(&self) -> String{
        return to_snake_case(self.to_string());
    }
    fn is_snake_case(&self) -> bool{
        return is_snake_case(self.to_string());
    }
    fn to_kebab_case(&self) -> String{
        return to_kebab_case(self.to_string());
    }
    fn is_kebab_case(&self) -> bool{
        return is_kebab_case(self.to_string());
    }
    fn to_sentence_case(&self) -> String{
        return to_sentence_case(self.to_string());
    }
    fn is_sentence_case(&self) -> bool{
        return is_sentence_case(self.to_string());
    }
    fn to_title_case(&self) -> String{
        return to_title_case(self.to_string());
    }
    fn is_title_case(&self) -> bool{
        return is_title_case(self.to_string());
    }
    fn to_upper_case(&self) -> String{
        return to_upper_case(self.to_string());
    }
    fn is_upper_case(&self) -> bool{
        return is_upper_case(self.to_string());
    }
    fn to_lower_case(&self) -> String{
        return to_lower_case(self.to_string());
    }
    fn is_lower_case(&self) -> bool{
        return is_lower_case(self.to_string());
    }
    fn ordinalize(&self) -> String{
        return ordinalize(self.to_string());
    }
    fn deordinalize(&self) -> String{
        return deordinalize(self.to_string());
    }
    fn to_foreign_key(&self) -> String{
        return to_foreign_key(self.to_string());
    }
    fn is_foreign_key(&self) -> bool{
        return is_foreign_key(self.to_string());
    }
    fn demodulize(&self) -> String{
        return demodulize(self.to_string());
    }
    fn deconstantize(&self) -> String{
        return deconstantize(self.to_string());
    }

    fn to_plural(&self) -> String{
        return to_plural(self.to_string());
    }
}
<commit_msg>Removed ability to pass with warnings<commit_after>#![deny(warnings)]
//! [![Crates.io](https://img.shields.io/crates/v/inflector.svg)](https://crates.io/crates/inflector)
//!
//! Adds String based inflections for Rust. Snake, kebab, camel,
//! sentence, class, title, upper, and lower cases as well as ordinalize,
//! deordinalize, demodulize, deconstantize, and foreign key are supported as both traits and pure functions
//! acting on String types.
//!
//! ```rust
//! use inflector::Inflector;
//! #[test]
//! fn should_convert_to_and_verify_camel_cased_string() {
//!   let camel_case_string: String = "some_string".to_camel_case();
//!   let is_camel_cased: bool= camel_case_string.is_camel_case();
//!   assert!(is_camel_cased == true);
//! }
//! ```
extern crate regex;
/// Provides case inflections
/// - Camel case
/// - Class case
/// - Kebab case
/// - Lower case
/// - Screaming snake case
/// - Sentence case
/// - Snake case
/// - Upper case
pub mod cases;
/// Provides number inflections
/// - Ordinalize
/// - Deordinalize
pub mod numbers;
/// Provides suffix inflections
/// - Foreign key
pub mod suffix;
/// Provides string inflections
/// - Deconstantize
/// - Demodulize
pub mod string;

use cases::classcase::to_class_case;
use cases::classcase::is_class_case;

use cases::camelcase::to_camel_case;
use cases::camelcase::is_camel_case;

use cases::snakecase::to_snake_case;
use cases::snakecase::is_snake_case;

use cases::screamingsnakecase::to_screaming_snake_case;
use cases::screamingsnakecase::is_screaming_snake_case;

use cases::kebabcase::to_kebab_case;
use cases::kebabcase::is_kebab_case;

use cases::sentencecase::to_sentence_case;
use cases::sentencecase::is_sentence_case;

use cases::titlecase::to_title_case;
use cases::titlecase::is_title_case;

use cases::uppercase::to_upper_case;
use cases::uppercase::is_upper_case;

use cases::lowercase::to_lower_case;
use cases::lowercase::is_lower_case;

use numbers::ordinalize::ordinalize;
use numbers::deordinalize::deordinalize;

use suffix::foreignkey::to_foreign_key;
use suffix::foreignkey::is_foreign_key;

use string::demodulize::demodulize;
use string::deconstantize::deconstantize;

use string::pluralize::to_plural;

pub trait Inflector {
    fn to_class_case<'a>(&self) -> String;
    fn is_class_case<'a>(&self) -> bool;

    fn to_camel_case<'a>(&self) -> String;
    fn is_camel_case<'a>(&self) -> bool;

    fn to_snake_case<'a>(&self) -> String;
    fn is_snake_case<'a>(&self) -> bool;

    fn to_screaming_snake_case<'a>(&self) -> String;
    fn is_screaming_snake_case<'a>(&self) -> bool;

    fn to_kebab_case<'a>(&self) -> String;
    fn is_kebab_case<'a>(&self) -> bool;

    fn to_sentence_case<'a>(&self) -> String;
    fn is_sentence_case<'a>(&self) -> bool;

    fn to_title_case<'a>(&self) -> String;
    fn is_title_case<'a>(&self) -> bool;

    fn to_upper_case<'a>(&self) -> String;
    fn is_upper_case<'a>(&self) -> bool;

    fn to_lower_case<'a>(&self) -> String;
    fn is_lower_case<'a>(&self) -> bool;

    fn ordinalize<'a>(&self) -> String;
    fn deordinalize<'a>(&self) -> String;

    fn to_foreign_key<'a>(&self) -> String;
    fn is_foreign_key<'a>(&self) -> bool;

    fn demodulize<'a>(&self) -> String;
    fn deconstantize<'a>(&self) -> String;

    fn to_plural<'a>(&self) -> String;
}

impl<'c> Inflector for String {
    fn to_class_case(&self) -> String{
        return to_class_case(self.to_string());
    }
    fn is_class_case(&self) -> bool{
        return is_class_case(self.to_string());
    }
    fn to_camel_case(&self) -> String{
        return to_camel_case(self.to_string());
    }
    fn is_camel_case(&self) -> bool{
        return is_camel_case(self.to_string());
    }
    fn to_screaming_snake_case(&self) -> String{
        return to_screaming_snake_case(self.to_string());
    }
    fn is_screaming_snake_case(&self) -> bool{
        return is_screaming_snake_case(self.to_string());
    }
    fn to_snake_case(&self) -> String{
        return to_snake_case(self.to_string());
    }
    fn is_snake_case(&self) -> bool{
        return is_snake_case(self.to_string());
    }
    fn to_kebab_case(&self) -> String{
        return to_kebab_case(self.to_string());
    }
    fn is_kebab_case(&self) -> bool{
        return is_kebab_case(self.to_string());
    }
    fn to_sentence_case(&self) -> String{
        return to_sentence_case(self.to_string());
    }
    fn is_sentence_case(&self) -> bool{
        return is_sentence_case(self.to_string());
    }
    fn to_title_case(&self) -> String{
        return to_title_case(self.to_string());
    }
    fn is_title_case(&self) -> bool{
        return is_title_case(self.to_string());
    }
    fn to_upper_case(&self) -> String{
        return to_upper_case(self.to_string());
    }
    fn is_upper_case(&self) -> bool{
        return is_upper_case(self.to_string());
    }
    fn to_lower_case(&self) -> String{
        return to_lower_case(self.to_string());
    }
    fn is_lower_case(&self) -> bool{
        return is_lower_case(self.to_string());
    }
    fn ordinalize(&self) -> String{
        return ordinalize(self.to_string());
    }
    fn deordinalize(&self) -> String{
        return deordinalize(self.to_string());
    }
    fn to_foreign_key(&self) -> String{
        return to_foreign_key(self.to_string());
    }
    fn is_foreign_key(&self) -> bool{
        return is_foreign_key(self.to_string());
    }
    fn demodulize(&self) -> String{
        return demodulize(self.to_string());
    }
    fn deconstantize(&self) -> String{
        return deconstantize(self.to_string());
    }
    fn to_plural(&self) -> String{
        return to_plural(self.to_string());
    }
}

impl<'c> Inflector for str {
    fn to_class_case(&self) -> String{
        return to_class_case(self.to_string());
    }
    fn is_class_case(&self) -> bool{
        return is_class_case(self.to_string());
    }
    fn to_camel_case(&self) -> String{
        return to_camel_case(self.to_string());
    }
    fn is_camel_case(&self) -> bool{
        return is_camel_case(self.to_string());
    }
    fn to_screaming_snake_case(&self) -> String{
        return to_screaming_snake_case(self.to_string());
    }
    fn is_screaming_snake_case(&self) -> bool{
        return is_screaming_snake_case(self.to_string());
    }
    fn to_snake_case(&self) -> String{
        return to_snake_case(self.to_string());
    }
    fn is_snake_case(&self) -> bool{
        return is_snake_case(self.to_string());
    }
    fn to_kebab_case(&self) -> String{
        return to_kebab_case(self.to_string());
    }
    fn is_kebab_case(&self) -> bool{
        return is_kebab_case(self.to_string());
    }
    fn to_sentence_case(&self) -> String{
        return to_sentence_case(self.to_string());
    }
    fn is_sentence_case(&self) -> bool{
        return is_sentence_case(self.to_string());
    }
    fn to_title_case(&self) -> String{
        return to_title_case(self.to_string());
    }
    fn is_title_case(&self) -> bool{
        return is_title_case(self.to_string());
    }
    fn to_upper_case(&self) -> String{
        return to_upper_case(self.to_string());
    }
    fn is_upper_case(&self) -> bool{
        return is_upper_case(self.to_string());
    }
    fn to_lower_case(&self) -> String{
        return to_lower_case(self.to_string());
    }
    fn is_lower_case(&self) -> bool{
        return is_lower_case(self.to_string());
    }
    fn ordinalize(&self) -> String{
        return ordinalize(self.to_string());
    }
    fn deordinalize(&self) -> String{
        return deordinalize(self.to_string());
    }
    fn to_foreign_key(&self) -> String{
        return to_foreign_key(self.to_string());
    }
    fn is_foreign_key(&self) -> bool{
        return is_foreign_key(self.to_string());
    }
    fn demodulize(&self) -> String{
        return demodulize(self.to_string());
    }
    fn deconstantize(&self) -> String{
        return deconstantize(self.to_string());
    }

    fn to_plural(&self) -> String{
        return to_plural(self.to_string());
    }
}
<|endoftext|>


<commit_before>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::io::{Error, ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new().unwrap();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Couldn't parse socket address"))
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, i32)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            let _ = socket.setsockopt(socket_option.0, socket_option.1, socket_option.2);
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: HashSet<IpAddr> = Discovery::new().unwrap().start(None, Some(3)).unwrap();
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<HashSet<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: HashSet<IpAddr> = HashSet::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<commit_msg>[Improved] Return sockopt result from create_socket<commit_after>extern crate socket;

use socket::{AF_INET, Socket, SOCK_DGRAM, IP_MULTICAST_TTL, IPPROTO_IP};
use std::collections::HashSet;
use std::io::{Error, ErrorKind, Result};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use std::sync::{Arc, mpsc};
use std::thread;
use std::time::Instant;

#[derive(Debug)]
/// `Discover` type
///
/// Used for discovering sonos devices in the local network via the simple service discovery protocol (ssdp).
/// The ssd-protocol works via udp sockets. First a certain search-message is sent to the multicast address (239.255.255.250:1900).
///
/// All answer from upnp (universal plug and play) ready devices are processed and filtered ("Sonos" is in the reply).
pub struct Discover {
    /// Multicast address in the local network
    multicast_addr: SocketAddr,
    /// Socket implementation
    /// INFO: The socket type will likely change in the future due to cross platform compatability
    socket: Arc<Socket>
}

impl Discover {
    /// Creates a new `Discovery`. Uses the default socket on the default ipv4 multicast address (239.255.255.250:1900).
    ///
    /// # Examples
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let discovery: Discovery = Discovery::new().unwrap();
    /// ```
    pub fn new() -> Result<Self> {
        let multicast_address = match SocketAddr::from_str("239.255.255.250:1900") {
            Ok(address) => address,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Couldn't parse socket address"))
        };

        Discover::with_address(multicast_address)
    }

    /// Creates a new `Discovery` with a custom multicast address.
    pub fn with_address(address: SocketAddr) -> Result<Self> {
        let socket = Discover::create_default_socket()?;
        Ok(Discover {
            multicast_addr: address,
            socket: socket
        })
    }

    /// Create a default socket
    /// socket option: AF_INET - SOCK_DGRAM - 0 // Automatically discover the protocol (IPPROTO_UDP)
    /// socket option: IPPROTO_IP - IP_MULTICAST_TTL - 4 // UPnP 1.0 needs a TTL of 4
    fn create_default_socket() -> Result<Arc<Socket>> {
        let socket_family = AF_INET;
        let socket_level = SOCK_DGRAM;
        let protocol = 0; // auto discover
        let socket_options = vec![(IPPROTO_IP, IP_MULTICAST_TTL, 4)];

        Discover::create_socket(socket_family, socket_level, protocol, &socket_options)
    }

    fn create_socket(socket_family: i32, socket_type: i32, protocol: i32, socket_options: &Vec<(i32, i32, i32)>) -> Result<Arc<Socket>> {
        let socket = Socket::new(socket_family, socket_type, protocol)?;
        for socket_option in socket_options {
            // TODO: Use result, allow to fail, panic or return a result?
            socket.setsockopt(socket_option.0, socket_option.1, socket_option.2)?
        }

        Ok(Arc::new(socket))
    }

    /// Sends the search message to the defined socket.
    /// Message can't have leading/trailing whitespaces (\s).
    ///
    /// # Message
    /// ```
    /// M-SEARCH * HTTP/1.1
    /// HOST: 239.255.255.250:1900
    /// MAN: "ssdp:discover"
    /// MX: 1
    /// ST: urn:schemas-upnp-org:device:ZonePlayer:1```
    fn send_search(&self) -> Result<usize> {
        let player_search = r#"M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
MX: 1
ST: urn:schemas-upnp-org:device:ZonePlayer:1"#.as_bytes();

        self.socket.sendto(player_search, 0, &self.multicast_addr)
    }

    /// Start discovering devices.
    ///
    /// # Examples
    /// In this example the search will stop if3 devices have been discovered or the default timeout (5s) is reached.
    /// This is useful if you know the amount of speakers you have and want to reduce the search time.
    ///
    /// ```
    /// use sonos_discovery::Discovery;
    ///
    /// let devices: HashSet<IpAddr> = Discovery::new().unwrap().start(None, Some(3)).unwrap();
    /// ```
    pub fn start(&self, timeout: Option<u32>, device_count: Option<usize>) -> Result<HashSet<IpAddr>> {
        let timeout = match timeout {
            Some(value) => { value }
            None => 5
        };
        let device_count = match device_count {
            Some(value) => { value }
            None => std::u32::MAX as usize
        };

        let time = Instant::now();

        self.send_search()?;
        // There's probably a better way than a double clone
        let socket = self.socket.clone();
        let mut devices: HashSet<IpAddr> = HashSet::new();
        while time.elapsed().as_secs() < timeout as u64 && devices.len() < device_count {
            let socket = socket.clone();
            let (sender, receiver) = mpsc::channel();
            thread::spawn(move ||
                {
                    // TODO: Add logging
                    match socket.recvfrom(1024, 0) {
                        Ok((__addr, _data)) => {
                            // TODO: Add logging, fail on multiple send errors?
                            match sender.send((__addr, _data)) {
                                Ok(_) => {}
                                Err(_) => {}
                            };
                        }
                        Err(_) => {}
                    }
                }
            );

            // TODO: Add logging, change
            let (_addr, data) = match receiver.recv_timeout(std::time::Duration::new(0, 500000000)) {
                Ok((_addr, data)) => (_addr, data),
                Err(_) => continue
            };

            // Skip from_utf8_lossy
            // Due to the usual small size of `devices`, this is faster than decoding a potentially large response
            if devices.contains(&_addr.ip()) || data.is_empty() {
                println!("{:?}", &_addr.ip());
                continue
            }

            let data = String::from_utf8_lossy(&data);
            if data.contains("Sonos") {
                devices.insert(_addr.ip());
            }
        }

        Ok(devices)
    }
}

/// Drop internal socket on going out of scope
impl Drop for Discover {
    fn drop(&mut self) {
        // Socket closes on drop automatically, better safe than sorry
        // Log failure for debugging
        let _ = self.socket.close();
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde_json;

pub mod diagnostics;
use diagnostics::{Diagnostic, DiagnosticSpan};

#[derive(Debug, Copy, Clone, Hash, PartialEq)]
pub struct LinePosition {
    pub line: usize,
    pub column: usize,
}

impl std::fmt::Display for LinePosition {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}:{}", self.line, self.column)
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq)]
pub struct LineRange {
    pub start: LinePosition,
    pub end: LinePosition,
}

impl std::fmt::Display for LineRange {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}

#[derive(Debug, Clone, Hash, PartialEq)]
pub struct Suggestion {
    pub message: String,
    pub file_name: String,
    pub line_range: LineRange,
    pub text: String,
    pub replacement: String,
}

fn collect_span(message: &str, span: &DiagnosticSpan) -> Option<Suggestion> {
    if let Some(replacement) = span.suggested_replacement.clone() {
        Some(Suggestion {
            message: message.into(),
            file_name: span.file_name.clone(),
            line_range: LineRange {
                start: LinePosition {
                    line: span.line_start,
                    column: span.column_start,
                },
                end: LinePosition {
                    line: span.line_end,
                    column: span.column_end,
                },
            },
            text: span.text.iter().map(|ref x| x.text.clone()).collect::<Vec<_>>().join("\n"),
            replacement: replacement,
        })
    } else {
        None
    }
}

pub fn collect_suggestions(diagnostic: &Diagnostic,
                           parent_message: Option<String>)
                           -> Vec<Suggestion> {
    let message = parent_message.unwrap_or(diagnostic.message.clone());
    let mut suggestions = vec![];

    suggestions.extend(diagnostic.spans
        .iter()
        .flat_map(|span| collect_span(&message, span)));

    suggestions.extend(diagnostic.children
        .iter()
        .flat_map(|children| collect_suggestions(children, Some(message.clone()))));

    suggestions
}
<commit_msg>Fix a clippy suggestion<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

extern crate serde_json;

pub mod diagnostics;
use diagnostics::{Diagnostic, DiagnosticSpan};

#[derive(Debug, Copy, Clone, Hash, PartialEq)]
pub struct LinePosition {
    pub line: usize,
    pub column: usize,
}

impl std::fmt::Display for LinePosition {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}:{}", self.line, self.column)
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq)]
pub struct LineRange {
    pub start: LinePosition,
    pub end: LinePosition,
}

impl std::fmt::Display for LineRange {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}-{}", self.start, self.end)
    }
}

#[derive(Debug, Clone, Hash, PartialEq)]
pub struct Suggestion {
    pub message: String,
    pub file_name: String,
    pub line_range: LineRange,
    pub text: String,
    pub replacement: String,
}

fn collect_span(message: &str, span: &DiagnosticSpan) -> Option<Suggestion> {
    if let Some(replacement) = span.suggested_replacement.clone() {
        Some(Suggestion {
            message: message.into(),
            file_name: span.file_name.clone(),
            line_range: LineRange {
                start: LinePosition {
                    line: span.line_start,
                    column: span.column_start,
                },
                end: LinePosition {
                    line: span.line_end,
                    column: span.column_end,
                },
            },
            text: span.text.iter().map(|x| x.text.clone()).collect::<Vec<_>>().join("\n"),
            replacement: replacement,
        })
    } else {
        None
    }
}

pub fn collect_suggestions(diagnostic: &Diagnostic,
                           parent_message: Option<String>)
                           -> Vec<Suggestion> {
    let message = parent_message.unwrap_or(diagnostic.message.clone());
    let mut suggestions = vec![];

    suggestions.extend(diagnostic.spans
        .iter()
        .flat_map(|span| collect_span(&message, span)));

    suggestions.extend(diagnostic.children
        .iter()
        .flat_map(|children| collect_suggestions(children, Some(message.clone()))));

    suggestions
}
<|endoftext|>