Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement some missing traits for SmallIntMap and TrieMap/TrieSet. #15963

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}
}