pour 0.2.1

Optionally consed radix tries for fast set operations
Documentation
use super::*;

impl<K: RadixKey, V: Clone + Eq> PartialEq for IdMap<K, V> {
    fn eq(&self, other: &IdMap<K, V>) -> bool {
        match (&self.0, &other.0) {
            (Some(this), Some(other)) => this.rec_eq(other),
            (Some(_), None) => false,
            (None, Some(_)) => false,
            (None, None) => true,
        }
    }
}

impl<K: RadixKey, V: Clone + Eq> Eq for IdMap<K, V> {}

impl<K: RadixKey, V: Clone> ConsCtx<K, V> for () {
    fn cons(&mut self, inner: InnerMap<K, V>) -> Arc<InnerMap<K, V>> {
        Arc::new(inner)
    }
    fn cons_arc(&mut self, inner: &Arc<InnerMap<K, V>>) -> Arc<InnerMap<K, V>> {
        inner.clone()
    }
    fn cons_recursive(&mut self, inner: &Arc<InnerMap<K, V>>) -> Arc<InnerMap<K, V>> {
        inner.clone()
    }
}

impl<I> RadixKey for I
where
    I: Default + Hash + PrimInt + AsPrimitive<u8> + 'static,
    u8: AsPrimitive<I>,
{
    type PatternType = I;
    type DepthType = u8;
    #[inline(always)]
    fn pattern(&self, _depth: u8) -> I {
        *self
    }
    #[inline(always)]
    fn pattern_no(_depth: u8) -> usize {
        0
    }
}

impl<D, I> Pattern<D> for I
where
    I: Default + Hash + PrimInt + AsPrimitive<u8> + 'static,
    u8: AsPrimitive<I>,
    D: AsPrimitive<u32>,
    u8: AsPrimitive<D>,
{
    const MAX_BITS: usize = 64;
    fn max_bits() -> D {
        (64u8).as_()
    }
    fn byte(self, depth: D) -> u8 {
        let depth: u32 = depth.as_();
        let max_bits: u32 = <Self as Pattern<D>>::MAX_BITS as u32;
        let ix: u32 = (depth / 8) % max_bits;
        (self.unsigned_shr(ix * 8) & 0xFF.as_()).as_()
    }
    fn diff(self, other: I) -> D {
        let xor = self ^ other;
        let zeroes = xor.trailing_zeros() as u8;
        zeroes.as_()
    }
}

impl<K: RadixKey, V: Eq + Clone> PartialOrd for IdMap<K, V> {
    fn partial_cmp(&self, other: &IdMap<K, V>) -> Option<Ordering> {
        self.map_cmp(other, false)
    }
    fn lt(&self, other: &IdMap<K, V>) -> bool {
        self.len() < other.len() && self.is_submap(other, false)
    }
    fn gt(&self, other: &IdMap<K, V>) -> bool {
        self.len() > other.len() && other.is_submap(self, false)
    }
    fn le(&self, other: &IdMap<K, V>) -> bool {
        self.is_submap(other, false)
    }
    fn ge(&self, other: &IdMap<K, V>) -> bool {
        other.is_submap(self, false)
    }
}

impl<K: RadixKey, V: Clone> IntoIterator for IdMap<K, V> {
    type Item = (K, V);
    type IntoIter = IdMapIntoIter<K, V>;
    fn into_iter(self) -> IdMapIntoIter<K, V> {
        let mut result = IdMapIntoIter::empty();
        if let Some(inner) = self.0 {
            result.root(inner)
        }
        result
    }
}

impl<K: RadixKey, V: Clone> Default for IdMap<K, V> {
    fn default() -> IdMap<K, V> {
        IdMap(None)
    }
}

impl<K: RadixKey, V: Clone> FromIterator<(K, V)> for IdMap<K, V> {
    fn from_iter<I>(iter: I) -> IdMap<K, V>
    where
        I: IntoIterator<Item = (K, V)>,
    {
        //TODO: more efficient implementation...
        let mut result = IdMap::new();
        for (key, value) in iter {
            result.try_insert(key, value);
        }
        result
    }
}

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

    #[test]
    fn big_small_submap_check() {
        use Ordering::*;
        let mut small = IdMap::singleton(3, 12);
        let mut big = IdMap::new();

        for x in 0..1000 {
            big.try_insert(x, 4 * x);
        }
        assert_eq!(small.partial_cmp(&big), Some(Less));
        assert!(small.le(&big));
        assert!(!small.ge(&big));
        assert!(small.lt(&big));
        assert!(!small.gt(&big));
        assert_eq!(small.domain_cmp(&big), Some(Less));
        small.try_insert(4, 12);
        assert_eq!(small.partial_cmp(&big), None);
        assert!(!small.le(&big));
        assert!(!small.ge(&big));
        assert!(!small.lt(&big));
        assert!(!small.gt(&big));
        assert_eq!(small.domain_cmp(&big), Some(Less));
        small.try_insert(1000, 3);
        assert_eq!(small.partial_cmp(&big), None);
        assert!(!small.le(&big));
        assert!(!small.ge(&big));
        assert!(!small.lt(&big));
        assert!(!small.gt(&big));
        assert_eq!(small.domain_cmp(&big), None);
        let u1 = big.left_unioned(&small);
        assert_eq!(u1.len(), 1001);
        assert_eq!(u1.domain_cmp(&big), Some(Greater));
        assert_eq!(u1.domain_cmp(&small), Some(Greater));
        assert_eq!(u1.partial_cmp(&big), Some(Greater));
        assert_eq!(u1.partial_cmp(&small), None);

        let u2 = small.left_unioned(&big);
        assert_eq!(u2.len(), 1001);
        assert_eq!(u2.domain_cmp(&big), Some(Greater));
        assert_eq!(u2.domain_cmp(&small), Some(Greater));
        assert_eq!(u2.partial_cmp(&big), None);
        assert_eq!(u2.partial_cmp(&small), Some(Greater));
    }
}