Skip to content

Commit

Permalink
Merge pull request #108 from Zefick/10
Browse files Browse the repository at this point in the history
Values, ValuesMut and IntoValues.
  • Loading branch information
yegor256 committed May 3, 2023
2 parents 2d01c6f + e88a33f commit 63f294c
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 8 deletions.
71 changes: 65 additions & 6 deletions src/iterators.rs
Expand Up @@ -19,6 +19,8 @@
// SOFTWARE.

use crate::{IntoIter, Iter, IterMut, Map};
use std::mem;
use std::mem::MaybeUninit;

impl<K: PartialEq, V, const N: usize> Map<K, V, N> {
/// Make an iterator over all pairs.
Expand Down Expand Up @@ -76,24 +78,54 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
}
}

impl<'a, K: Clone, V: Clone, const N: usize> Iterator for IntoIter<'a, K, V, N> {
impl<K: PartialEq, V, const N: usize> Iterator for IntoIter<K, V, N> {
type Item = (K, V);

#[inline]
#[must_use]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|p| (p.0.clone(), p.1.clone()))
while self.pos < self.map.next {
let p = &mut self.map.pairs[self.pos];
self.pos += 1;
unsafe {
if p.assume_init_ref().is_some() {
return mem::replace(p, MaybeUninit::new(None)).assume_init();
}
}
}
None
}
}

impl<'a, K: PartialEq, V, const N: usize> IntoIterator for &'a Map<K, V, N> {
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V, N>;

#[inline]
#[must_use]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}

impl<'a, K: PartialEq, V, const N: usize> IntoIterator for &'a mut Map<K, V, N> {
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;

#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}

impl<'a, K: Clone + PartialEq, V: Clone, const N: usize> IntoIterator for &'a Map<K, V, N> {
impl<K: PartialEq, V, const N: usize> IntoIterator for Map<K, V, N> {
type Item = (K, V);
type IntoIter = IntoIter<'a, K, V, N>;
type IntoIter = IntoIter<K, V, N>;

#[inline]
#[must_use]
fn into_iter(self) -> Self::IntoIter {
IntoIter { iter: self.iter() }
IntoIter { pos: 0, map: self }
}
}

Expand Down Expand Up @@ -158,7 +190,7 @@ fn into_iterate_with_blanks() {
m.insert("three", 5);
m.remove(&"two");
let mut sum = 0;
for (_k, v) in m.into_iter() {
for (_k, v) in m {
sum += v;
}
assert_eq!(6, sum);
Expand Down Expand Up @@ -188,3 +220,30 @@ fn iter_mut_with_blanks() {
assert_eq!(m.iter_mut().count(), 2);
assert_eq!(m.iter_mut().last().unwrap().1, &5);
}

#[test]
fn into_iter_mut() {
let mut m: Map<&str, i32, 10> = Map::new();
m.insert("one", 2);
m.insert("two", 3);
m.insert("three", 5);
for (_k, v) in &mut m {
*v *= 2;
}
let sum = m.iter().map(|p| p.1).sum::<i32>();
assert_eq!(20, sum);
}

#[test]
fn into_iter_drop() {
use std::rc::Rc;
let mut m: Map<i32, Rc<()>, 8> = Map::new();
let v = Rc::new(());
let n = 8;
for i in 0..n {
m.insert(i, Rc::clone(&v));
}
assert_eq!(Rc::strong_count(&v), (n + 1) as usize);
let _p = m.into_iter().nth(3);
assert_eq!(Rc::strong_count(&v), 2); // v & p
}
20 changes: 18 additions & 2 deletions src/lib.rs
Expand Up @@ -47,7 +47,6 @@
#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
#![allow(clippy::multiple_inherent_impl)]
#![allow(clippy::multiple_crate_versions)]

mod clone;
mod ctors;
mod debug;
Expand All @@ -58,6 +57,7 @@ mod iterators;
mod map;
#[cfg(feature = "serde")]
mod serialization;
mod values;

use std::mem::MaybeUninit;

Expand Down Expand Up @@ -110,6 +110,22 @@ pub struct IterMut<'a, K, V> {
}

/// Into-iterator over the [`Map`].
pub struct IntoIter<'a, K, V, const N: usize> {
pub struct IntoIter<K: PartialEq, V, const N: usize> {
pos: usize,
map: Map<K, V, N>,
}

/// An iterator over the values of the [`Map`].
pub struct Values<'a, K: PartialEq, V, const N: usize> {
iter: Iter<'a, K, V, N>,
}

/// Mutable iterator over the values of the [`Map`].
pub struct ValuesMut<'a, K: PartialEq, V> {
iter: IterMut<'a, K, V>,
}

/// Consuming iterator over the values of the [`Map`].
pub struct IntoValues<K: PartialEq, V, const N: usize> {
iter: IntoIter<K, V, N>,
}
112 changes: 112 additions & 0 deletions src/values.rs
@@ -0,0 +1,112 @@
// Copyright (c) 2023 Yegor Bugayenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

use crate::{IntoValues, Map, Values, ValuesMut};

impl<K: PartialEq, V, const N: usize> Map<K, V, N> {
/// An iterator visiting all values in arbitrary order.
#[inline]
pub const fn values(&self) -> Values<'_, K, V, N> {
Values { iter: self.iter() }
}

/// An iterator visiting all values mutably in arbitrary order.
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
ValuesMut {
iter: self.iter_mut(),
}
}

/// Consuming iterator visiting all the values in arbitrary order.
#[inline]
pub fn into_values(self) -> IntoValues<K, V, N> {
IntoValues {
iter: self.into_iter(),
}
}
}

impl<'a, K: PartialEq, V, const N: usize> Iterator for Values<'a, K, V, N> {
type Item = &'a V;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|p| p.1)
}
}

impl<'a, K: PartialEq, V> Iterator for ValuesMut<'a, K, V> {
type Item = &'a mut V;

#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|p| p.1)
}
}

impl<K: PartialEq, V, const N: usize> Iterator for IntoValues<K, V, N> {
type Item = V;

#[inline]
fn next(&mut self) -> Option<V> {
self.iter.next().map(|p| p.1)
}
}

#[test]
fn iterate_values() {
let mut m: Map<&str, i32, 10> = Map::new();
m.insert("one", 42);
m.insert("two", 16);
assert_eq!(58, m.values().sum());
}

#[test]
fn iterate_values_mut() {
let mut m: Map<&str, i32, 10> = Map::new();
m.insert("one", 42);
m.insert("two", 16);
m.values_mut().for_each(|v| *v *= 2);
assert_eq!(116, m.values().sum());
}

#[test]
fn iterate_values_with_blanks() {
let mut m: Map<&str, i32, 10> = Map::new();
m.insert("one", 1);
m.insert("two", 3);
m.insert("three", 5);
m.remove(&"two");
assert_eq!(m.values().collect::<Vec<_>>(), [&1, &5]);
}

#[test]
fn into_values_drop() {
use std::rc::Rc;
let mut m: Map<i32, Rc<()>, 8> = Map::new();
let v = Rc::new(());
for i in 0..8 {
m.insert(i, Rc::clone(&v));
}
assert_eq!(9, Rc::strong_count(&v));
m.into_values();
assert_eq!(1, Rc::strong_count(&v));
}

0 comments on commit 63f294c

Please sign in to comment.