From f7eb0ca1e6b357a11175de8bcf45e7d3c3953c31 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 30 Nov 2017 13:46:30 -0800 Subject: [PATCH 1/2] Add views of OrderMap `OrderMap::view() -> OrderMapView` and `view_mut() -> OrderMapViewMut` provide access to items in the map, but no ability to add/remove items. These views can be sub-divided with `split_at` etc., which may be useful to enable parallelism. --- src/lib.rs | 49 ++--- src/macros.rs | 35 ++++ src/view.rs | 337 ++++++++++++++++++++++++++++++++++ src/view_mut.rs | 478 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 864 insertions(+), 35 deletions(-) create mode 100644 src/view.rs create mode 100644 src/view_mut.rs diff --git a/src/lib.rs b/src/lib.rs index 637a4a3b..f03e6c41 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,8 @@ mod serde; mod util; mod equivalent; mod mutable_keys; +mod view; +mod view_mut; pub mod set; @@ -32,6 +34,8 @@ use util::{third, ptrdistance, enumerate}; pub use equivalent::Equivalent; pub use mutable_keys::MutableKeys; pub use set::OrderSet; +pub use view::OrderMapView; +pub use view_mut::OrderMapViewMut; fn hash_elem_using(build: &B, k: &K) -> HashValue { let mut h = build.build_hasher(); @@ -328,20 +332,6 @@ fn to_raw_capacity(n: usize) -> usize { n + n / 3 } -// this could not be captured in an efficient iterator -macro_rules! probe_loop { - ($probe_var: ident < $len: expr, $body: expr) => { - loop { - if $probe_var < $len { - $body - $probe_var += 1; - } else { - $probe_var = 0; - } - } - } -} - impl OrderMap { /// Create a new map. (Does not allocate.) pub fn new() -> Self { @@ -431,6 +421,16 @@ impl OrderMap pub fn capacity(&self) -> usize { usable_capacity(self.raw_capacity()) } + + /// Creates a read-only view of the map. + pub fn view(&self) -> OrderMapView { + OrderMapView::new(self) + } + + /// Creates a mutable view of the map. + pub fn view_mut(&mut self) -> OrderMapViewMut { + OrderMapViewMut::new(self) + } } /// Trait for the "size class". Either u32 or u64 depending on the index @@ -452,27 +452,6 @@ impl Size for u64 { fn is_64_bit() -> bool { true } } -/// Call self.method(args) with `::` or `::` depending on `self` -/// size class. -/// -/// The u32 or u64 is *prepended* to the type parameter list! -macro_rules! dispatch_32_vs_64 { - ($self_:ident . $method:ident::<$($t:ty),*>($($arg:expr),*)) => { - if $self_.size_class_is_64bit() { - $self_.$method::($($arg),*) - } else { - $self_.$method::($($arg),*) - } - }; - ($self_:ident . $method:ident ($($arg:expr),*)) => { - if $self_.size_class_is_64bit() { - $self_.$method::($($arg),*) - } else { - $self_.$method::($($arg),*) - } - }; -} - /// FIXME: Remove dependence on the `S` parameter /// (to match HashMap). pub enum Entry<'a, K: 'a, V: 'a, S: 'a = RandomState> { diff --git a/src/macros.rs b/src/macros.rs index 27d7afec..bcd470c2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -120,3 +120,38 @@ macro_rules! double_ended_iterator_methods { } } } + +// this could not be captured in an efficient iterator +macro_rules! probe_loop { + ($probe_var: ident < $len: expr, $body: expr) => { + loop { + if $probe_var < $len { + $body + $probe_var += 1; + } else { + $probe_var = 0; + } + } + } +} + +/// Call self.method(args) with `::` or `::` depending on `self` +/// size class. +/// +/// The u32 or u64 is *prepended* to the type parameter list! +macro_rules! dispatch_32_vs_64 { + ($self_:ident . $method:ident::<$($t:ty),*>($($arg:expr),*)) => { + if $self_.size_class_is_64bit() { + $self_.$method::($($arg),*) + } else { + $self_.$method::($($arg),*) + } + }; + ($self_:ident . $method:ident ($($arg:expr),*)) => { + if $self_.size_class_is_64bit() { + $self_.$method::($($arg),*) + } else { + $self_.$method::($($arg),*) + } + }; +} diff --git a/src/view.rs b/src/view.rs new file mode 100644 index 00000000..f4803981 --- /dev/null +++ b/src/view.rs @@ -0,0 +1,337 @@ +use super::*; + +/// A read-only view of an `OrderMap`. +/// +/// Views are not just references into the map -- +/// they can also be split into smaller views! +pub struct OrderMapView<'a, K: 'a, V: 'a, S: 'a = RandomState> { + map: &'a OrderMap, + + /// the index range that's covered by this view + start: usize, + end: usize, +} + +impl<'a, K, V, S> Clone for OrderMapView<'a, K, V, S> { + fn clone(&self) -> Self { + *self + } +} + +impl<'a, K, V, S> Copy for OrderMapView<'a, K, V, S> {} + +impl<'a, K, V, S> fmt::Debug for OrderMapView<'a, K, V, S> + where K: fmt::Debug + Hash + Eq, + V: fmt::Debug, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +impl<'a, K, V, S> OrderMapView<'a, K, V, S> { + /// Creates a read-only view of a map. + pub fn new(map: &OrderMap) -> OrderMapView { + OrderMapView { + map: map, + + start: 0, + end: map.entries.len(), + } + } + + /// Return the number of key-value pairs in the map view. + /// + /// Computes in **O(1)** time. + pub fn len(&self) -> usize { self.end - self.start } + + /// Returns true if the map view contains no elements. + /// + /// Computes in **O(1)** time. + pub fn is_empty(&self) -> bool { self.len() == 0 } + + /// Return a reference to the map's `BuildHasher`. + pub fn hasher(&self) -> &'a S + where S: BuildHasher + { + self.map.hasher() + } + + fn entries_iter(&self) -> SliceIter<'a, Bucket> { + self.map.entries[self.start .. self.end].iter() + } + + fn contains_index(&self, index: usize) -> bool { + (self.start <= index) && (index < self.end) + } +} + +impl<'a, K, V, S> OrderMapView<'a, K, V, S> + where K: Hash + Eq, + S: BuildHasher, +{ + /// Return an iterator over the key-value pairs of the map view, in their order + pub fn iter(&self) -> Iter<'a, K, V> { + Iter { + iter: self.entries_iter(), + } + } + + /// Return an iterator over the keys of the map view, in their order + pub fn keys(&self) -> Keys<'a, K, V> { + Keys { + iter: self.entries_iter(), + } + } + + /// Return an iterator over the values of the map view, in their order + pub fn values(&self) -> Values<'a, K, V> { + Values { + iter: self.entries_iter(), + } + } + + /// Return `true` if and equivalent to `key` exists in the map view. + /// + /// Computes in **O(1)** time (average). + pub fn contains_key(&self, key: &Q) -> bool + where Q: Hash + Equivalent, + { + if let Some((_, found)) = self.map.find(key) { + self.contains_index(found) + } else { + false + } + } + + /// Return a reference to the value stored for `key`, if it is present in + /// this map view, else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get(&self, key: &Q) -> Option<&'a V> + where Q: Hash + Equivalent, + { + self.get_full(key).map(third) + } + + /// Return item index, key and value + pub fn get_full(&self, key: &Q) -> Option<(usize, &'a K, &'a V)> + where Q: Hash + Equivalent, + { + if let Some((index, key, value)) = self.map.get_full(key) { + if self.contains_index(index) { + return Some((index - self.start, key, value)); + } + } + None + } +} + +impl<'a, K, V, S> OrderMapView<'a, K, V, S> { + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index(&self, index: usize) -> Option<(&'a K, &'a V)> { + if index < self.len() { + self.map.get_index(self.start + index) + } else { + None + } + } + + /// Divides a view into two at an index. + /// + /// ***Panics*** if `mid > self.len()` + pub fn split_at(&self, mid: usize) -> (OrderMapView<'a, K, V, S>, OrderMapView<'a, K, V, S>) { + assert!(mid <= self.len()); + let mid = self.start + mid; + (OrderMapView { end: mid, ..*self }, + OrderMapView { start: mid, ..*self }) + } + + /// Returns the first key-value pair and a view of all the rest, + /// or `None` if it is empty. + pub fn split_first(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + if self.start < self.end { + self.map.get_index(self.start) + .map(|(k, v)| (k, v, OrderMapView { start: self.start + 1, ..*self })) + } else { + None + } + } + + /// Returns the last key-value pair and a view of all the rest, + /// or `None` if it is empty. + pub fn split_last(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + if self.start < self.end { + self.map.get_index(self.end - 1) + .map(|(k, v)| (k, v, OrderMapView { end: self.end - 1, ..*self })) + } else { + None + } + } +} + +impl<'a, K, V, S> IntoIterator for OrderMapView<'a, K, V, S> + where K: Hash + Eq, + S: BuildHasher, +{ + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} + +impl<'a, 'q, K, V, Q: ?Sized, S> Index<&'q Q> for OrderMapView<'a, K, V, S> + where Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + type Output = V; + + /// ***Panics*** if `key` is not present in the map view. + fn index(&self, key: &Q) -> &V { + if let Some(v) = self.get(key) { + v + } else { + panic!("OrderMap: key not found") + } + } +} + +impl<'a, 'b, K, V1, S1, V2, S2> PartialEq> for OrderMapView<'a, K, V1, S1> + where K: Hash + Eq, + V1: PartialEq, + S1: BuildHasher, + S2: BuildHasher +{ + fn eq(&self, other: &OrderMapView) -> bool { + if self.len() != other.len() { + return false; + } + + self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) + } +} + +impl<'a, K, V, S> Eq for OrderMapView<'a, K, V, S> + where K: Eq + Hash, + V: Eq, + S: BuildHasher +{ +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let mut map = OrderMap::new(); + assert_eq!(map.view().is_empty(), true); + map.insert(1, ()); + map.insert(1, ()); + let view = map.view(); + assert_eq!(view.len(), 1); + assert!(view.get(&1).is_some()); + assert_eq!(view.is_empty(), false); + } + + #[test] + fn new() { + let map = OrderMap::::new(); + let view = map.view(); + println!("{:?}", view); + assert_eq!(view.len(), 0); + assert_eq!(view.is_empty(), true); + } + + #[test] + fn insert_order() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut map = OrderMap::new(); + + for &elt in &insert { + map.insert(elt, ()); + } + + let view = map.view(); + assert_eq!(view.keys().count(), view.len()); + assert_eq!(view.keys().count(), insert.len()); + for (a, b) in insert.iter().zip(view.keys()) { + assert_eq!(a, b); + } + for (i, k) in (0..insert.len()).zip(view.keys()) { + assert_eq!(view.get_index(i).unwrap().0, k); + } + } + + #[test] + fn partial_eq_and_eq() { + let mut map_a = OrderMap::new(); + map_a.insert(1, "1"); + map_a.insert(2, "2"); + let mut map_b = map_a.clone(); + assert_eq!(map_a.view(), map_b.view()); + map_b.remove(&1); + assert_ne!(map_a.view(), map_b.view()); + + let map_c: OrderMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.to_owned())).collect(); + assert_ne!(map_a.view(), map_c.view()); + assert_ne!(map_c.view(), map_a.view()); + } + + #[test] + fn splits() { + fn check(view: OrderMapView, slice: &[i32], other: &[i32]) { + assert_eq!(view.len(), slice.len()); + assert_eq!(view.iter().count(), slice.len()); + assert_eq!(view.keys().count(), slice.len()); + assert_eq!(view.values().count(), slice.len()); + for (a, b) in view.keys().zip(slice) { + assert_eq!(a, b); + } + for x in slice { + assert!(view.contains_key(x)); + assert_eq!(view.get(x), Some(&())); + let _ = &view[x]; + } + for x in other { + assert!(!view.contains_key(x)); + } + } + + fn check_split_at(view: OrderMapView, slice: &[i32], index: usize) { + let (slice1, slice2) = slice.split_at(index); + let (view1, view2) = view.split_at(index); + check(view1, slice1, slice2); + check(view2, slice2, slice1); + } + + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + + let mut map = OrderMap::new(); + for &elt in &insert { + map.insert(elt, ()); + } + + let view = map.view(); + for i in 0..insert.len() + 1 { + check_split_at(view, &insert, i); + } + + let (first, slice) = insert.split_first().unwrap(); + let (k, &(), tail) = view.split_first().unwrap(); + assert_eq!(k, first); + check(tail, slice, &[*first]); + + let (last, slice) = insert.split_last().unwrap(); + let (k, &(), tail) = view.split_last().unwrap(); + assert_eq!(k, last); + check(tail, slice, &[*last]); + } +} diff --git a/src/view_mut.rs b/src/view_mut.rs new file mode 100644 index 00000000..0c3e9077 --- /dev/null +++ b/src/view_mut.rs @@ -0,0 +1,478 @@ +use super::*; + +/// A mutable view of an `OrderMap`. +/// +/// Mutable views are not just mutable references into the map -- +/// they can also be split into smaller views! +pub struct OrderMapViewMut<'a, K: 'a, V: 'a, S: 'a = RandomState> { + offset: usize, + mask: usize, + indices: &'a [Pos], + entries: &'a mut [Bucket], + hash_builder: &'a S, + size_class_is_64bit: bool, +} + +impl<'a, K, V, S> fmt::Debug for OrderMapViewMut<'a, K, V, S> + where K: fmt::Debug + Hash + Eq, + V: fmt::Debug, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_map().entries(self.iter()).finish() + } +} + +impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { + /// Creates a read-only view of a map. + pub fn new(map: &mut OrderMap) -> OrderMapViewMut { + OrderMapViewMut { + offset: 0, + mask: map.mask, + indices: &map.indices, + hash_builder: &map.hash_builder, + size_class_is_64bit: map.size_class_is_64bit(), + entries: &mut map.entries, + } + } + + /// Return the number of key-value pairs in the map view. + /// + /// Computes in **O(1)** time. + pub fn len(&self) -> usize { self.entries.len() } + + /// Returns true if the map view contains no elements. + /// + /// Computes in **O(1)** time. + pub fn is_empty(&self) -> bool { self.entries.is_empty() } + + /// Return a reference to the map's `BuildHasher`. + pub fn hasher(&self) -> &'a S + where S: BuildHasher + { + self.hash_builder + } + + #[inline(always)] + fn size_class_is_64bit(&self) -> bool { + self.size_class_is_64bit + } +} + +impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> + where K: Hash + Eq, + S: BuildHasher, +{ + /// Return an iterator over the key-value pairs of the map view, in their order + pub fn iter(&self) -> Iter { + Iter { + iter: self.entries.iter(), + } + } + + /// Return an iterator over the key-value pairs of the map, in their order + pub fn iter_mut(&mut self) -> IterMut { + IterMut { + iter: self.entries.iter_mut() + } + } + + /// Return an iterator over the keys of the map view, in their order + pub fn keys(&self) -> Keys { + Keys { + iter: self.entries.iter(), + } + } + + /// Return an iterator over the values of the map view, in their order + pub fn values(&self) -> Values { + Values { + iter: self.entries.iter(), + } + } + + /// Return an iterator over mutable references to the the values of the map, + /// in their order + pub fn values_mut(&mut self) -> ValuesMut { + ValuesMut { + iter: self.entries.iter_mut() + } + } + + /// Return `true` if and equivalent to `key` exists in the map view. + /// + /// Computes in **O(1)** time (average). + pub fn contains_key(&self, key: &Q) -> bool + where Q: Hash + Equivalent, + { + self.find(key).is_some() + } + + /// Return a reference to the value stored for `key`, if it is present in + /// this map view, else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get(&self, key: &Q) -> Option<&V> + where Q: Hash + Equivalent, + { + self.get_full(key).map(third) + } + + /// Return item index, key and value + pub fn get_full(&self, key: &Q) -> Option<(usize, &K, &V)> + where Q: Hash + Equivalent, + { + if let Some((_, found)) = self.find(key) { + let entry = &self.entries[found]; + Some((found, &entry.key, &entry.value)) + } else { + None + } + } + + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where Q: Hash + Equivalent, + { + self.get_full_mut(key).map(third) + } + + pub fn get_full_mut(&mut self, key: &Q) + -> Option<(usize, &K, &mut V)> + where Q: Hash + Equivalent, + { + if let Some((_, found)) = self.find(key) { + let entry = &mut self.entries[found]; + Some((found, &entry.key, &mut entry.value)) + } else { + None + } + } + + /// Return probe (indices) and position (entries) + fn find(&self, key: &Q) -> Option<(usize, usize)> + where Q: Hash + Equivalent, + { + if self.len() == 0 { return None; } + let h = hash_elem_using(self.hash_builder, key); + self.find_using(h, move |entry| { Q::equivalent(key, &entry.key) }) + } +} + +impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index(&self, index: usize) -> Option<(&K, &V)> { + self.entries.get(index).map(|ent| (&ent.key, &ent.value)) + } + + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> { + self.entries.get_mut(index).map(|ent| (&mut ent.key, &mut ent.value)) + } + + /// Divides a view into two at an index. + /// + /// ***Panics*** if `mid > self.len()` + // FIXME should downgrade to OrderMapView like: + // pub fn split_at(&self, mid: usize) -> (OrderMapView<'a, K, V, S>, OrderMapView<'a, K, V, S>) { + pub fn split_at(&mut self, mid: usize) -> (OrderMapViewMut, OrderMapViewMut) { + let (left, right) = self.entries.split_at_mut(mid); + (OrderMapViewMut { entries: left, ..*self }, + OrderMapViewMut { entries: right, offset: self.offset + mid, ..*self }) + } + + /// Divides a view into two at an index. + /// + /// ***Panics*** if `mid > self.len()` + pub fn split_at_mut(&mut self, mid: usize) -> (OrderMapViewMut, OrderMapViewMut) { + let (left, right) = self.entries.split_at_mut(mid); + (OrderMapViewMut { entries: left, ..*self }, + OrderMapViewMut { entries: right, offset: self.offset + mid, ..*self }) + } + + /// Returns the first key-value pair and a view of all the rest, + /// or `None` if it is empty. + // FIXME should downgrade to OrderMapView like: + // pub fn split_first(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + pub fn split_first(&mut self) -> Option<(&K, &V, OrderMapViewMut)> { + if let Some((ent, rest)) = self.entries.split_first_mut() { + Some((&ent.key, &ent.value, + OrderMapViewMut { offset: self.offset + 1, entries: rest, ..*self })) + } else { + None + } + } + + /// Returns the first key-value pair and a view of all the rest, + /// or `None` if it is empty. + pub fn split_first_mut(&mut self) -> Option<(&mut K, &mut V, OrderMapViewMut)> { + if let Some((ent, rest)) = self.entries.split_first_mut() { + Some((&mut ent.key, &mut ent.value, + OrderMapViewMut { offset: self.offset + 1, entries: rest, ..*self })) + } else { + None + } + } + + /// Returns the last key-value pair and a view of all the rest, + /// or `None` if it is empty. + // FIXME should downgrade to OrderMapView like: + // pub fn split_last(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + pub fn split_last(&mut self) -> Option<(&K, &V, OrderMapViewMut)> { + if let Some((ent, rest)) = self.entries.split_last_mut() { + Some((&ent.key, &ent.value, + OrderMapViewMut { entries: rest, ..*self })) + } else { + None + } + } + + /// Returns the last key-value pair and a view of all the rest, + /// or `None` if it is empty. + pub fn split_last_mut(&mut self) -> Option<(&mut K, &mut V, OrderMapViewMut)> { + if let Some((ent, rest)) = self.entries.split_last_mut() { + Some((&mut ent.key, &mut ent.value, + OrderMapViewMut { entries: rest, ..*self })) + } else { + None + } + } +} + +// Methods that don't use any properties (Hash / Eq) of K. +// +// It's cleaner to separate them out, then the compiler checks that we are not +// using Hash + Eq at all in these methods. +// +// However, we should probably not let this show in the public API or docs. +impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { + /// Return probe (indices) and position (entries) + fn find_using(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)> + where F: Fn(&Bucket) -> bool, + { + dispatch_32_vs_64!(self.find_using_impl::<_>(hash, key_eq)) + } + + fn find_using_impl(&self, hash: HashValue, key_eq: F) -> Option<(usize, usize)> + where F: Fn(&Bucket) -> bool, + Sz: Size, + { + debug_assert!(self.len() > 0); + let mut probe = desired_pos(self.mask, hash); + let mut dist = 0; + probe_loop!(probe < self.indices.len(), { + if let Some((i, hash_proxy)) = self.indices[probe].resolve::() { + // Unfortunately, we can only look at indexes within our slice + // of entries, which might mean we'll keep probing farther than + // it would be strictly necessary. + if (self.offset <= i) && (i < self.offset + self.entries.len()) { + let i = i - self.offset; + let entry_hash = hash_proxy.get_short_hash(&self.entries, i); + if dist > probe_distance(self.mask, entry_hash.into_hash(), probe) { + // give up when probe distance is too long + return None; + } else if entry_hash == hash && key_eq(&self.entries[i]) { + return Some((probe, i)); + } + } + } else { + return None; + } + dist += 1; + }); + } +} + +impl<'a, K, V, S> IntoIterator for OrderMapViewMut<'a, K, V, S> + where K: Hash + Eq, + S: BuildHasher, +{ + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + IterMut { + iter: self.entries.iter_mut() + } + } +} + +impl<'a, 'q, K, V, Q: ?Sized, S> Index<&'q Q> for OrderMapViewMut<'a, K, V, S> + where Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + type Output = V; + + /// ***Panics*** if `key` is not present in the map view. + fn index(&self, key: &Q) -> &V { + if let Some(v) = self.get(key) { + v + } else { + panic!("OrderMap: key not found") + } + } +} + +/// Mutable indexing allows changing / updating values of key-value +/// pairs that are already present. +/// +/// You can **not** insert new pairs with index syntax, use `.insert()`. +impl<'a, 'q, K, V, Q: ?Sized, S> IndexMut<&'q Q> for OrderMapViewMut<'a, K, V, S> + where Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + /// ***Panics*** if `key` is not present in the map view. + fn index_mut(&mut self, key: &Q) -> &mut V { + if let Some(v) = self.get_mut(key) { + v + } else { + panic!("OrderMap: key not found") + } + } +} + +impl<'a, 'b, K, V1, S1, V2, S2> PartialEq> for OrderMapViewMut<'a, K, V1, S1> + where K: Hash + Eq, + V1: PartialEq, + S1: BuildHasher, + S2: BuildHasher +{ + fn eq(&self, other: &OrderMapViewMut) -> bool { + if self.len() != other.len() { + return false; + } + + self.iter().all(|(key, value)| other.get(key).map_or(false, |v| *value == *v)) + } +} + +impl<'a, K, V, S> Eq for OrderMapViewMut<'a, K, V, S> + where K: Eq + Hash, + V: Eq, + S: BuildHasher +{ +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let mut map = OrderMap::new(); + assert_eq!(map.view_mut().is_empty(), true); + map.insert(1, ()); + map.insert(1, ()); + let view = map.view_mut(); + assert_eq!(view.len(), 1); + assert!(view.get(&1).is_some()); + assert_eq!(view.is_empty(), false); + } + + #[test] + fn new() { + let mut map = OrderMap::::new(); + let view = map.view_mut(); + println!("{:?}", view); + assert_eq!(view.len(), 0); + assert_eq!(view.is_empty(), true); + } + + #[test] + fn insert_order() { + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + let mut map = OrderMap::new(); + + for &elt in &insert { + map.insert(elt, ()); + } + + let view = map.view_mut(); + assert_eq!(view.keys().count(), view.len()); + assert_eq!(view.keys().count(), insert.len()); + for (a, b) in insert.iter().zip(view.keys()) { + assert_eq!(a, b); + } + for (i, k) in (0..insert.len()).zip(view.keys()) { + assert_eq!(view.get_index(i).unwrap().0, k); + } + } + + #[test] + fn partial_eq_and_eq() { + let mut map_a = OrderMap::new(); + map_a.insert(1, "1"); + map_a.insert(2, "2"); + let mut map_b = map_a.clone(); + assert_eq!(map_a.view_mut(), map_b.view_mut()); + map_b.remove(&1); + assert_ne!(map_a.view_mut(), map_b.view_mut()); + + let mut map_c: OrderMap<_, String> = map_b.into_iter().map(|(k, v)| (k, v.to_owned())).collect(); + assert_ne!(map_a.view_mut(), map_c.view_mut()); + assert_ne!(map_c.view_mut(), map_a.view_mut()); + } + + #[test] + fn splits() { + fn check(mut view: OrderMapViewMut, slice: &[i32], other: &[i32]) { + assert_eq!(view.len(), slice.len()); + assert_eq!(view.iter().count(), slice.len()); + assert_eq!(view.keys().count(), slice.len()); + assert_eq!(view.values().count(), slice.len()); + assert_eq!(view.values_mut().count(), slice.len()); + for (a, b) in view.keys().zip(slice) { + assert_eq!(a, b); + } + for x in slice { + assert!(view.contains_key(x)); + assert_eq!(view.get_mut(x), Some(&mut ())); + let _ = &mut view[x]; + } + for x in other { + assert!(!view.contains_key(x)); + } + } + + fn check_split_at(view: &mut OrderMapViewMut, slice: &[i32], index: usize) { + let (slice1, slice2) = slice.split_at(index); + let (view1, view2) = view.split_at_mut(index); + check(view1, slice1, slice2); + check(view2, slice2, slice1); + } + + let insert = [0, 4, 2, 12, 8, 7, 11, 5, 3, 17, 19, 22, 23]; + + let mut map = OrderMap::new(); + for &elt in &insert { + map.insert(elt, ()); + } + + let mut view = map.view_mut(); + for i in 0..insert.len() + 1 { + check_split_at(&mut view, &insert, i); + } + + { + let (first, slice) = insert.split_first().unwrap(); + let (k, &mut (), tail) = view.split_first_mut().unwrap(); + assert_eq!(k, first); + check(tail, slice, &[*first]); + } + + { + let (last, slice) = insert.split_last().unwrap(); + let (k, &mut (), tail) = view.split_last_mut().unwrap(); + assert_eq!(k, last); + check(tail, slice, &[*last]); + } + } +} From 7b4c9a96fb04a9d131cbf038e6ed8c9336cf32fe Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 1 Dec 2017 10:01:22 -0800 Subject: [PATCH 2/2] Split views by value --- src/view.rs | 14 +++++++------- src/view_mut.rs | 50 ++++++++++++++++++++++++------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/view.rs b/src/view.rs index f4803981..61bbaa38 100644 --- a/src/view.rs +++ b/src/view.rs @@ -145,19 +145,19 @@ impl<'a, K, V, S> OrderMapView<'a, K, V, S> { /// Divides a view into two at an index. /// /// ***Panics*** if `mid > self.len()` - pub fn split_at(&self, mid: usize) -> (OrderMapView<'a, K, V, S>, OrderMapView<'a, K, V, S>) { + pub fn split_at(self, mid: usize) -> (Self, Self) { assert!(mid <= self.len()); let mid = self.start + mid; - (OrderMapView { end: mid, ..*self }, - OrderMapView { start: mid, ..*self }) + (OrderMapView { end: mid, ..self }, + OrderMapView { start: mid, ..self }) } /// Returns the first key-value pair and a view of all the rest, /// or `None` if it is empty. - pub fn split_first(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + pub fn split_first(self) -> Option<(&'a K, &'a V, Self)> { if self.start < self.end { self.map.get_index(self.start) - .map(|(k, v)| (k, v, OrderMapView { start: self.start + 1, ..*self })) + .map(|(k, v)| (k, v, OrderMapView { start: self.start + 1, ..self })) } else { None } @@ -165,10 +165,10 @@ impl<'a, K, V, S> OrderMapView<'a, K, V, S> { /// Returns the last key-value pair and a view of all the rest, /// or `None` if it is empty. - pub fn split_last(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { + pub fn split_last(self) -> Option<(&'a K, &'a V, Self)> { if self.start < self.end { self.map.get_index(self.end - 1) - .map(|(k, v)| (k, v, OrderMapView { end: self.end - 1, ..*self })) + .map(|(k, v)| (k, v, OrderMapView { end: self.end - 1, ..self })) } else { None } diff --git a/src/view_mut.rs b/src/view_mut.rs index 0c3e9077..7cc8876a 100644 --- a/src/view_mut.rs +++ b/src/view_mut.rs @@ -36,6 +36,13 @@ impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { } } + // TODO pub fn view(&self) -> OrderMapView + + /// Reborrow the current view. + pub fn view_mut(&mut self) -> OrderMapViewMut { + OrderMapViewMut { entries: &mut *self.entries, ..*self } + } + /// Return the number of key-value pairs in the map view. /// /// Computes in **O(1)** time. @@ -180,31 +187,27 @@ impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { /// Divides a view into two at an index. /// /// ***Panics*** if `mid > self.len()` - // FIXME should downgrade to OrderMapView like: - // pub fn split_at(&self, mid: usize) -> (OrderMapView<'a, K, V, S>, OrderMapView<'a, K, V, S>) { - pub fn split_at(&mut self, mid: usize) -> (OrderMapViewMut, OrderMapViewMut) { + pub fn split_at(self, mid: usize) -> (Self, Self) { let (left, right) = self.entries.split_at_mut(mid); - (OrderMapViewMut { entries: left, ..*self }, - OrderMapViewMut { entries: right, offset: self.offset + mid, ..*self }) + (OrderMapViewMut { entries: left, ..self }, + OrderMapViewMut { entries: right, offset: self.offset + mid, ..self }) } /// Divides a view into two at an index. /// /// ***Panics*** if `mid > self.len()` - pub fn split_at_mut(&mut self, mid: usize) -> (OrderMapViewMut, OrderMapViewMut) { + pub fn split_at_mut(self, mid: usize) -> (Self, Self) { let (left, right) = self.entries.split_at_mut(mid); - (OrderMapViewMut { entries: left, ..*self }, - OrderMapViewMut { entries: right, offset: self.offset + mid, ..*self }) + (OrderMapViewMut { entries: left, ..self }, + OrderMapViewMut { entries: right, offset: self.offset + mid, ..self }) } /// Returns the first key-value pair and a view of all the rest, /// or `None` if it is empty. - // FIXME should downgrade to OrderMapView like: - // pub fn split_first(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { - pub fn split_first(&mut self) -> Option<(&K, &V, OrderMapViewMut)> { + pub fn split_first(self) -> Option<(&'a K, &'a V, Self)> { if let Some((ent, rest)) = self.entries.split_first_mut() { Some((&ent.key, &ent.value, - OrderMapViewMut { offset: self.offset + 1, entries: rest, ..*self })) + OrderMapViewMut { offset: self.offset + 1, entries: rest, ..self })) } else { None } @@ -212,10 +215,10 @@ impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { /// Returns the first key-value pair and a view of all the rest, /// or `None` if it is empty. - pub fn split_first_mut(&mut self) -> Option<(&mut K, &mut V, OrderMapViewMut)> { + pub fn split_first_mut(self) -> Option<(&'a mut K, &'a mut V, Self)> { if let Some((ent, rest)) = self.entries.split_first_mut() { Some((&mut ent.key, &mut ent.value, - OrderMapViewMut { offset: self.offset + 1, entries: rest, ..*self })) + OrderMapViewMut { offset: self.offset + 1, entries: rest, ..self })) } else { None } @@ -223,12 +226,10 @@ impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { /// Returns the last key-value pair and a view of all the rest, /// or `None` if it is empty. - // FIXME should downgrade to OrderMapView like: - // pub fn split_last(&self) -> Option<(&'a K, &'a V, OrderMapView<'a, K, V, S>)> { - pub fn split_last(&mut self) -> Option<(&K, &V, OrderMapViewMut)> { + pub fn split_last(self) -> Option<(&'a K, &'a V, Self)> { if let Some((ent, rest)) = self.entries.split_last_mut() { Some((&ent.key, &ent.value, - OrderMapViewMut { entries: rest, ..*self })) + OrderMapViewMut { entries: rest, ..self })) } else { None } @@ -236,10 +237,10 @@ impl<'a, K, V, S> OrderMapViewMut<'a, K, V, S> { /// Returns the last key-value pair and a view of all the rest, /// or `None` if it is empty. - pub fn split_last_mut(&mut self) -> Option<(&mut K, &mut V, OrderMapViewMut)> { + pub fn split_last_mut(self) -> Option<(&'a mut K, &'a mut V, Self)> { if let Some((ent, rest)) = self.entries.split_last_mut() { Some((&mut ent.key, &mut ent.value, - OrderMapViewMut { entries: rest, ..*self })) + OrderMapViewMut { entries: rest, ..self })) } else { None } @@ -442,7 +443,7 @@ mod tests { } } - fn check_split_at(view: &mut OrderMapViewMut, slice: &[i32], index: usize) { + fn check_split_at(view: OrderMapViewMut, slice: &[i32], index: usize) { let (slice1, slice2) = slice.split_at(index); let (view1, view2) = view.split_at_mut(index); check(view1, slice1, slice2); @@ -456,21 +457,20 @@ mod tests { map.insert(elt, ()); } - let mut view = map.view_mut(); for i in 0..insert.len() + 1 { - check_split_at(&mut view, &insert, i); + check_split_at(map.view_mut(), &insert, i); } { let (first, slice) = insert.split_first().unwrap(); - let (k, &mut (), tail) = view.split_first_mut().unwrap(); + let (k, &mut (), tail) = map.view_mut().split_first_mut().unwrap(); assert_eq!(k, first); check(tail, slice, &[*first]); } { let (last, slice) = insert.split_last().unwrap(); - let (k, &mut (), tail) = view.split_last_mut().unwrap(); + let (k, &mut (), tail) = map.view_mut().split_last_mut().unwrap(); assert_eq!(k, last); check(tail, slice, &[*last]); }