diff --git a/src/array.rs b/src/array.rs index d02d179..9813936 100644 --- a/src/array.rs +++ b/src/array.rs @@ -110,44 +110,47 @@ impl From<[T; N]> for IArray { } } -/// An iterator over the elements of an `IArray`. +/// An iterator over the cloned elements of an `IArray`. #[derive(Debug)] -pub struct Iter { +pub struct IArrayIntoIter { array: IArray, left: usize, right: usize, } -impl Iter { - fn new(array: IArray) -> Self { - Self { +impl IntoIterator for IArray { + type Item = T; + type IntoIter = IArrayIntoIter; + + fn into_iter(self) -> ::IntoIter { + IArrayIntoIter { left: 0, - right: array.len(), - array, + right: self.len(), + array: self, } } } -impl Iterator for Iter { +impl Iterator for IArrayIntoIter { type Item = T; fn next(&mut self) -> Option { if self.left >= self.right { return None; } - let item = self.array.get(self.left); + let item = &self.array[self.left]; self.left += 1; - item + Some(item.clone()) } } -impl DoubleEndedIterator for Iter { +impl DoubleEndedIterator for IArrayIntoIter { fn next_back(&mut self) -> Option { if self.left >= self.right { return None; } self.right -= 1; - self.array.get(self.right) + Some(self.array[self.right].clone()) } } @@ -155,29 +158,6 @@ impl IArray { /// An empty array without allocation. pub const EMPTY: Self = Self::Static(&[]); - /// Returns a double-ended iterator over the array. - /// - /// # Examples - /// - /// ``` - /// # use implicit_clone::unsync::*; - /// let x = IArray::::Static(&[1, 2, 3, 4, 5, 6]); - /// let mut iter = x.iter(); - /// - /// assert_eq!(Some(1), iter.next()); - /// assert_eq!(Some(6), iter.next_back()); - /// assert_eq!(Some(5), iter.next_back()); - /// assert_eq!(Some(2), iter.next()); - /// assert_eq!(Some(3), iter.next()); - /// assert_eq!(Some(4), iter.next()); - /// assert_eq!(None, iter.next()); - /// assert_eq!(None, iter.next_back()); - /// ``` - #[inline] - pub fn iter(&self) -> Iter { - Iter::new(self.clone()) - } - /// Returns the number of elements in the vector, also referred to /// as its 'length'. /// @@ -236,21 +216,21 @@ impl IArray { } } - /// Returns a clone of an element at a position or `None` if out of bounds. + /// Returns a reference of an element at a position or `None` if out of bounds. /// /// # Examples /// /// ``` /// # use implicit_clone::unsync::*; /// let v = IArray::::Static(&[10, 40, 30]); - /// assert_eq!(Some(40), v.get(1)); + /// assert_eq!(Some(&40), v.get(1)); /// assert_eq!(None, v.get(3)); /// ``` #[inline] - pub fn get(&self, index: usize) -> Option { + pub fn get(&self, index: usize) -> Option<&T> { match self { - Self::Static(a) => a.get(index).cloned(), - Self::Rc(a) => a.get(index).cloned(), + Self::Static(a) => a.get(index), + Self::Rc(a) => a.get(index), } } @@ -508,4 +488,11 @@ mod test_array { impl ImplicitClone for _Node {} } + + #[test] + fn into_iter() { + let array = IArray::Static(&[1, 2, 3]); + assert_eq!(array.iter().next().unwrap(), &1); + assert_eq!(array.into_iter().next().unwrap(), 1); + } } diff --git a/src/map.rs b/src/map.rs index b59b9ee..a49b261 100644 --- a/src/map.rs +++ b/src/map.rs @@ -298,12 +298,23 @@ pub enum IMapIter<'a, K, V> { impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator for IMapIter<'a, K, V> { - type Item = (K, V); + type Item = (&'a K, &'a V); fn next(&mut self) -> Option { match self { - Self::Slice(it) => it.next().map(|(k, v)| (k.clone(), v.clone())), - Self::Map(it) => it.next().map(|(k, v)| (k.clone(), v.clone())), + Self::Slice(it) => it.next().map(|(k, v)| (k, v)), + Self::Map(it) => it.next(), + } + } +} + +impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> + DoubleEndedIterator for IMapIter<'a, K, V> +{ + fn next_back(&mut self) -> Option { + match self { + Self::Slice(it) => it.next_back().map(|(k, v)| (k, v)), + Self::Map(it) => it.next_back(), } } } @@ -317,12 +328,23 @@ pub enum IMapKeys<'a, K, V> { impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator for IMapKeys<'a, K, V> { - type Item = K; + type Item = &'a K; fn next(&mut self) -> Option { match self { - Self::Slice(it) => it.next().map(|(k, _)| k.clone()), - Self::Map(it) => it.next().cloned(), + Self::Slice(it) => it.next().map(|(k, _)| k), + Self::Map(it) => it.next(), + } + } +} + +impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> + DoubleEndedIterator for IMapKeys<'a, K, V> +{ + fn next_back(&mut self) -> Option { + match self { + Self::Slice(it) => it.next_back().map(|(k, _)| k), + Self::Map(it) => it.next_back(), } } } @@ -336,12 +358,23 @@ pub enum IMapValues<'a, K, V> { impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> Iterator for IMapValues<'a, K, V> { - type Item = V; + type Item = &'a V; fn next(&mut self) -> Option { match self { - Self::Slice(it) => it.next().map(|(_, v)| v.clone()), - Self::Map(it) => it.next().cloned(), + Self::Slice(it) => it.next().map(|(_, v)| v), + Self::Map(it) => it.next(), + } + } +} + +impl<'a, K: Eq + Hash + ImplicitClone + 'static, V: PartialEq + ImplicitClone + 'static> + DoubleEndedIterator for IMapValues<'a, K, V> +{ + fn next_back(&mut self) -> Option { + match self { + Self::Slice(it) => it.next_back().map(|(_, v)| v), + Self::Map(it) => it.next_back(), } } } @@ -413,12 +446,12 @@ mod test_map { assert_eq!( flattened_vec, [ - (IString::from("foo1"), 1), - (IString::from("bar1"), 2), - (IString::from("baz1"), 3), - (IString::from("foo2"), 4), - (IString::from("bar2"), 5), - (IString::from("baz2"), 6), + (&IString::from("foo1"), &1), + (&IString::from("bar1"), &2), + (&IString::from("baz1"), &3), + (&IString::from("foo2"), &4), + (&IString::from("bar2"), &5), + (&IString::from("baz2"), &6), ] ); }