From 1e997d62b7dc91779ace53cf18e31bc955a334f0 Mon Sep 17 00:00:00 2001 From: nham Date: Thu, 24 Jul 2014 17:50:21 -0400 Subject: [PATCH 1/3] Implement PartialEq/Eq/Clone/Hash/FromIterator/Extendable for SmallIntMap and Show/Clone for TrieMap and TrieSet --- src/libcollections/smallintmap.rs | 91 +++++++++++++++++++++++++++++ src/libcollections/trie.rs | 95 ++++++++++++++++++++++++++++++- 2 files changed, 185 insertions(+), 1 deletion(-) diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index e1980e1549a05..94aae9b008519 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -24,6 +24,7 @@ use core::mem::replace; use {Collection, Mutable, Map, MutableMap, MutableSeq}; use {vec, slice}; use vec::Vec; +use hash::Hash; /// A map optimized for small integer keys. /// @@ -58,6 +59,7 @@ use vec::Vec; /// months.clear(); /// assert!(months.is_empty()); /// ``` +#[deriving(PartialEq, Eq, Hash)] pub struct SmallIntMap { v: Vec>, } @@ -151,6 +153,21 @@ impl Default for SmallIntMap { fn default() -> SmallIntMap { SmallIntMap::new() } } +impl Clone for SmallIntMap { + #[inline] + fn clone(&self) -> SmallIntMap { + SmallIntMap { v: self.v.clone() } + } + + #[inline] + fn clone_from(&mut self, source: &SmallIntMap) { + self.v.reserve(source.v.len()); + for (i, w) in self.v.mut_iter().enumerate() { + *w = source.v[i].clone(); + } + } +} + impl SmallIntMap { /// Create an empty SmallIntMap. /// @@ -362,6 +379,22 @@ impl fmt::Show for SmallIntMap { } } +impl FromIterator<(uint, V)> for SmallIntMap { + fn from_iter>(iter: Iter) -> SmallIntMap { + let mut map = SmallIntMap::new(); + map.extend(iter); + map + } +} + +impl Extendable<(uint, V)> for SmallIntMap { + fn extend>(&mut self, mut iter: Iter) { + for (k, v) in iter { + self.insert(k, v); + } + } +} + macro_rules! iterator { (impl $name:ident -> $elem:ty, $getter:ident) => { impl<'a, T> Iterator<$elem> for $name<'a, T> { @@ -446,6 +479,7 @@ pub type Values<'a, T> = #[cfg(test)] mod test_map { use std::prelude::*; + use std::hash; use {Map, MutableMap, Mutable}; use super::SmallIntMap; @@ -698,6 +732,63 @@ mod test_map { assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}"); assert_eq!(format!("{}", empty), "{}".to_string()); } + + #[test] + fn test_clone() { + let mut a = SmallIntMap::new(); + + a.insert(1, vec!(4i, 5, 6)); + a.insert(4, vec!()); + a.insert(6, vec!(1, 3)); + + assert!(a.clone() == a); + } + + #[test] + fn test_eq() { + let mut a = SmallIntMap::new(); + let mut b = SmallIntMap::new(); + + assert!(a == b); + assert!(a.insert(0, 5i)); + assert!(a != b); + assert!(b.insert(0, 4i)); + assert!(a != b); + assert!(a.insert(5, 19)); + assert!(a != b); + assert!(!b.insert(0, 5)); + assert!(a != b); + assert!(b.insert(5, 19)); + assert!(a == b); + } + + #[test] + fn test_hash() { + let mut x = SmallIntMap::new(); + let mut y = SmallIntMap::new(); + + assert!(hash::hash(&x) == hash::hash(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); + + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); + + assert!(hash::hash(&x) == hash::hash(&y)); + } + + #[test] + fn test_from_iter() { + let xs = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]; + + let map: SmallIntMap = xs.iter().map(|&x| x).collect(); + + for &(k, v) in xs.iter() { + assert_eq!(map.find(&k), Some(&v)); + } + } } #[cfg(test)] diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 14ab122f0a43a..1fe8747dfa820 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -15,6 +15,8 @@ use core::prelude::*; use alloc::boxed::Box; use core::default::Default; +use core::fmt; +use core::fmt::Show; use core::mem::zeroed; use core::mem; use core::uint; @@ -31,6 +33,7 @@ static SIZE: uint = 1 << SHIFT; static MASK: uint = SIZE - 1; static NUM_CHUNKS: uint = uint::BITS / SHIFT; +#[deriving(Clone)] enum Child { Internal(Box>), External(uint, T), @@ -75,6 +78,7 @@ enum Child { /// map.clear(); /// assert!(map.is_empty()); /// ``` +#[deriving(Clone)] pub struct TrieMap { root: TrieNode, length: uint @@ -89,6 +93,19 @@ impl PartialEq for TrieMap { impl Eq for TrieMap {} +impl Show for TrieMap { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, (k, v)) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}: {}", k, *v)); + } + + write!(f, "}}") + } +} + impl Collection for TrieMap { /// Return the number of elements in the map. #[inline] @@ -500,11 +517,24 @@ impl> Hash for TrieMap { /// set.clear(); /// assert!(set.is_empty()); /// ``` -#[deriving(Hash, PartialEq, Eq)] +#[deriving(Clone, Hash, PartialEq, Eq)] pub struct TrieSet { map: TrieMap<()> } +impl Show for TrieSet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{{")); + + for (i, x) in self.iter().enumerate() { + if i != 0 { try!(write!(f, ", ")); } + try!(write!(f, "{}", x)); + } + + write!(f, "}}") + } +} + impl Collection for TrieSet { /// Return the number of elements in the set. #[inline] @@ -673,6 +703,19 @@ struct TrieNode { children: [Child, ..SIZE] } +impl Clone for TrieNode { + #[inline] + fn clone(&self) -> TrieNode { + let ch = &self.children; + TrieNode { + count: self.count, + children: [ch[0].clone(), ch[1].clone(), ch[2].clone(), ch[3].clone(), + ch[4].clone(), ch[5].clone(), ch[6].clone(), ch[7].clone(), + ch[8].clone(), ch[9].clone(), ch[10].clone(), ch[11].clone(), + ch[12].clone(), ch[13].clone(), ch[14].clone(), ch[15].clone()]} + } +} + impl TrieNode { #[inline] fn new() -> TrieNode { @@ -1237,6 +1280,17 @@ mod test_map { assert!(m_upper.iter().all(|(_, &x)| x == 0)); } + #[test] + fn test_clone() { + let mut a = TrieMap::new(); + + a.insert(1, 'a'); + a.insert(2, 'b'); + a.insert(3, 'c'); + + assert!(a.clone() == a); + } + #[test] fn test_eq() { let mut a = TrieMap::new(); @@ -1271,6 +1325,20 @@ mod test_map { assert!(hash::hash(&x) == hash::hash(&y)); } + + #[test] + fn test_show() { + let mut map = TrieMap::new(); + let empty = TrieMap::new(); + + map.insert(1, 'a'); + map.insert(2, 'b'); + + let map_str = format!("{}", map); + + assert!(map_str == "{1: a, 2: b}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } } #[cfg(test)] @@ -1420,4 +1488,29 @@ mod test_set { assert!(set.contains(x)); } } + + #[test] + fn test_show() { + let mut set = TrieSet::new(); + let empty = TrieSet::new(); + + set.insert(1); + set.insert(2); + + let set_str = format!("{}", set); + + assert!(set_str == "{1, 2}".to_string()); + assert_eq!(format!("{}", empty), "{}".to_string()); + } + + #[test] + fn test_clone() { + let mut a = TrieSet::new(); + + a.insert(1); + a.insert(2); + a.insert(3); + + assert!(a.clone() == a); + } } From 3f1c37e96da571e6eb8137aad1b5d65ea3f89a0b Mon Sep 17 00:00:00 2001 From: nham Date: Fri, 25 Jul 2014 21:35:58 -0400 Subject: [PATCH 2/3] Small fixes for tests --- src/libcollections/smallintmap.rs | 14 +++++++------- src/libcollections/trie.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index 94aae9b008519..56fb7e3632e0b 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -24,7 +24,6 @@ use core::mem::replace; use {Collection, Mutable, Map, MutableMap, MutableSeq}; use {vec, slice}; use vec::Vec; -use hash::Hash; /// A map optimized for small integer keys. /// @@ -59,7 +58,7 @@ use hash::Hash; /// months.clear(); /// assert!(months.is_empty()); /// ``` -#[deriving(PartialEq, Eq, Hash)] +#[deriving(Hash, PartialEq, Eq)] pub struct SmallIntMap { v: Vec>, } @@ -480,8 +479,9 @@ pub type Values<'a, T> = mod test_map { use std::prelude::*; use std::hash; + use vec::Vec; - use {Map, MutableMap, Mutable}; + use {Map, MutableMap, Mutable, MutableSeq}; use super::SmallIntMap; #[test] @@ -737,9 +737,9 @@ mod test_map { fn test_clone() { let mut a = SmallIntMap::new(); - a.insert(1, vec!(4i, 5, 6)); - a.insert(4, vec!()); - a.insert(6, vec!(1, 3)); + a.insert(1, 'x'); + a.insert(4, 'y'); + a.insert(6, 'z'); assert!(a.clone() == a); } @@ -781,7 +781,7 @@ mod test_map { #[test] fn test_from_iter() { - let xs = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]; + let xs: Vec<(uint, char)> = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]; let map: SmallIntMap = xs.iter().map(|&x| x).collect(); diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 1fe8747dfa820..1ac05fbd562ed 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -1329,7 +1329,7 @@ mod test_map { #[test] fn test_show() { let mut map = TrieMap::new(); - let empty = TrieMap::new(); + let empty: TrieMap = TrieMap::new(); map.insert(1, 'a'); map.insert(2, 'b'); From fadbc0b88bb39ac42aa4874e4a90df53a778ef59 Mon Sep 17 00:00:00 2001 From: nham Date: Sat, 26 Jul 2014 12:04:41 -0400 Subject: [PATCH 3/3] Manually implement Hash for SmallIntMap --- src/libcollections/smallintmap.rs | 32 +++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/libcollections/smallintmap.rs b/src/libcollections/smallintmap.rs index 56fb7e3632e0b..c6c55b55e332e 100644 --- a/src/libcollections/smallintmap.rs +++ b/src/libcollections/smallintmap.rs @@ -24,6 +24,8 @@ use core::mem::replace; use {Collection, Mutable, Map, MutableMap, MutableSeq}; use {vec, slice}; use vec::Vec; +use hash; +use hash::Hash; /// A map optimized for small integer keys. /// @@ -58,7 +60,7 @@ use vec::Vec; /// months.clear(); /// assert!(months.is_empty()); /// ``` -#[deriving(Hash, PartialEq, Eq)] +#[deriving(PartialEq, Eq)] pub struct SmallIntMap { v: Vec>, } @@ -167,6 +169,12 @@ impl Clone for SmallIntMap { } } +impl > Hash for SmallIntMap { + fn hash(&self, state: &mut S) { + self.v.hash(state) + } +} + impl SmallIntMap { /// Create an empty SmallIntMap. /// @@ -478,8 +486,8 @@ pub type Values<'a, T> = #[cfg(test)] mod test_map { use std::prelude::*; - use std::hash; use vec::Vec; + use hash; use {Map, MutableMap, Mutable, MutableSeq}; use super::SmallIntMap; @@ -764,19 +772,19 @@ mod test_map { #[test] fn test_hash() { - let mut x = SmallIntMap::new(); - let mut y = SmallIntMap::new(); + let mut x = SmallIntMap::new(); + let mut y = SmallIntMap::new(); - assert!(hash::hash(&x) == hash::hash(&y)); - x.insert(1, 'a'); - x.insert(2, 'b'); - x.insert(3, 'c'); + assert!(hash::hash(&x) == hash::hash(&y)); + x.insert(1, 'a'); + x.insert(2, 'b'); + x.insert(3, 'c'); - y.insert(3, 'c'); - y.insert(2, 'b'); - y.insert(1, 'a'); + y.insert(3, 'c'); + y.insert(2, 'b'); + y.insert(1, 'a'); - assert!(hash::hash(&x) == hash::hash(&y)); + assert!(hash::hash(&x) == hash::hash(&y)); } #[test]