Skip to content

Commit

Permalink
auto merge of #15963 : nham/rust/moar_15294, r=alexcrichton
Browse files Browse the repository at this point in the history
Implements PartialEq/Eq/Clone/Hash/FromIterator/Extendable for SmallIntMap and Clone/Show for TrieMap/TrieSet. cc #15294
  • Loading branch information
bors committed Jul 27, 2014
2 parents 2de3fad + fadbc0b commit d114dda
Show file tree
Hide file tree
Showing 2 changed files with 194 additions and 2 deletions.
101 changes: 100 additions & 1 deletion src/libcollections/smallintmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -58,6 +60,7 @@ use vec::Vec;
/// months.clear();
/// assert!(months.is_empty());
/// ```
#[deriving(PartialEq, Eq)]
pub struct SmallIntMap<T> {
v: Vec<Option<T>>,
}
Expand Down Expand Up @@ -151,6 +154,27 @@ impl<V> Default for SmallIntMap<V> {
fn default() -> SmallIntMap<V> { SmallIntMap::new() }
}

impl<V:Clone> Clone for SmallIntMap<V> {
#[inline]
fn clone(&self) -> SmallIntMap<V> {
SmallIntMap { v: self.v.clone() }
}

#[inline]
fn clone_from(&mut self, source: &SmallIntMap<V>) {
self.v.reserve(source.v.len());
for (i, w) in self.v.mut_iter().enumerate() {
*w = source.v[i].clone();
}
}
}

impl <S: hash::Writer, T: Hash<S>> Hash<S> for SmallIntMap<T> {
fn hash(&self, state: &mut S) {
self.v.hash(state)
}
}

impl<V> SmallIntMap<V> {
/// Create an empty SmallIntMap.
///
Expand Down Expand Up @@ -362,6 +386,22 @@ impl<V: fmt::Show> fmt::Show for SmallIntMap<V> {
}
}

impl<V> FromIterator<(uint, V)> for SmallIntMap<V> {
fn from_iter<Iter: Iterator<(uint, V)>>(iter: Iter) -> SmallIntMap<V> {
let mut map = SmallIntMap::new();
map.extend(iter);
map
}
}

impl<V> Extendable<(uint, V)> for SmallIntMap<V> {
fn extend<Iter: Iterator<(uint, V)>>(&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> {
Expand Down Expand Up @@ -446,8 +486,10 @@ pub type Values<'a, T> =
#[cfg(test)]
mod test_map {
use std::prelude::*;
use vec::Vec;
use hash;

use {Map, MutableMap, Mutable};
use {Map, MutableMap, Mutable, MutableSeq};
use super::SmallIntMap;

#[test]
Expand Down Expand Up @@ -698,6 +740,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, 'x');
a.insert(4, 'y');
a.insert(6, 'z');

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<(uint, char)> = vec![(1u, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')];

let map: SmallIntMap<char> = xs.iter().map(|&x| x).collect();

for &(k, v) in xs.iter() {
assert_eq!(map.find(&k), Some(&v));
}
}
}

#[cfg(test)]
Expand Down
95 changes: 94 additions & 1 deletion src/libcollections/trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<T> {
Internal(Box<TrieNode<T>>),
External(uint, T),
Expand Down Expand Up @@ -75,6 +78,7 @@ enum Child<T> {
/// map.clear();
/// assert!(map.is_empty());
/// ```
#[deriving(Clone)]
pub struct TrieMap<T> {
root: TrieNode<T>,
length: uint
Expand All @@ -89,6 +93,19 @@ impl<T: PartialEq> PartialEq for TrieMap<T> {

impl<T: Eq> Eq for TrieMap<T> {}

impl<T: Show> Show for TrieMap<T> {
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<T> Collection for TrieMap<T> {
/// Return the number of elements in the map.
#[inline]
Expand Down Expand Up @@ -500,11 +517,24 @@ impl<S: Writer, T: Hash<S>> Hash<S> for TrieMap<T> {
/// 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]
Expand Down Expand Up @@ -673,6 +703,19 @@ struct TrieNode<T> {
children: [Child<T>, ..SIZE]
}

impl<T:Clone> Clone for TrieNode<T> {
#[inline]
fn clone(&self) -> TrieNode<T> {
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<T> TrieNode<T> {
#[inline]
fn new() -> TrieNode<T> {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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<uint> = 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)]
Expand Down Expand Up @@ -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);
}
}

0 comments on commit d114dda

Please sign in to comment.