use super::iterators::slice_iter;
use super::iterators::{IntoIter, Iter, IterMut};
use super::Map;
use core::{fmt, iter::FusedIterator};
impl<K, V, const N: usize> Map<K, V, N> {
#[inline]
pub fn values(&self) -> Values<'_, K, V> {
Values { iter: self.iter() }
}
#[inline]
pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
ValuesMut {
iter: self.iter_mut(),
}
}
#[inline]
pub fn into_values(self) -> IntoValues<K, V, N> {
IntoValues {
iter: self.into_iter(),
}
}
}
#[repr(transparent)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Values<'a, K, V> {
iter: Iter<'a, K, V>,
}
#[repr(transparent)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct ValuesMut<'a, K, V> {
iter: IterMut<'a, K, V>,
}
#[repr(transparent)]
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct IntoValues<K, V, const N: usize> {
iter: IntoIter<K, V, N>,
}
impl<K, V> Clone for Values<'_, K, V> {
#[inline]
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
}
}
}
impl<K, V> Default for Values<'_, K, V> {
#[inline]
fn default() -> Self {
Self {
iter: Iter::default(),
}
}
}
impl<K, V> Default for ValuesMut<'_, K, V> {
#[inline]
fn default() -> Self {
Self {
iter: IterMut::default(),
}
}
}
impl<K, V, const N: usize> Default for IntoValues<K, V, N> {
#[inline]
fn default() -> Self {
Self {
iter: IntoIter::default(),
}
}
}
impl<K, V: fmt::Debug> fmt::Debug for Values<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(self.iter.clone().map(|(_, v)| v))
.finish()
}
}
impl<K, V: fmt::Debug> fmt::Debug for ValuesMut<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list()
.entries(slice_iter(self.iter.iter.as_slice()).map(|(_, v)| v))
.finish()
}
}
impl<K, V: fmt::Debug, const N: usize> fmt::Debug for IntoValues<K, V, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter.map.values()).finish()
}
}
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|p| p.1)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a, K, 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)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<K, 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)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<K, V> ExactSizeIterator for Values<'_, K, V> {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<K, V> ExactSizeIterator for ValuesMut<'_, K, V> {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<K, V, const N: usize> ExactSizeIterator for IntoValues<K, V, N> {
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<K, V> FusedIterator for Values<'_, K, V> {}
impl<K, V> FusedIterator for ValuesMut<'_, K, V> {}
impl<K: PartialEq, V, const N: usize> FusedIterator for IntoValues<K, V, N> {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn iterate_values() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 42);
m.insert("two".to_string(), 16);
let it = m.values();
assert_eq!(it.len(), 2);
assert_eq!(58, it.sum::<i32>());
}
#[test]
fn iterate_values_mut() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 42);
m.insert("two".to_string(), 16);
let it_mut = m.values_mut();
assert_eq!(it_mut.len(), 2);
assert_eq!(it_mut.len(), it_mut.size_hint().0);
assert_eq!(it_mut.len(), it_mut.size_hint().1.unwrap());
it_mut.for_each(|v| *v *= 2);
assert_eq!(116, m.values().sum::<i32>());
}
#[test]
fn iterate_values_with_blanks() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 1);
m.insert("two".to_string(), 3);
m.insert("three".to_string(), 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));
let mut values = m.into_values();
assert!(values.next().is_some());
assert_eq!(values.len(), 7);
assert!(values.next().is_some());
assert_eq!(values.len(), values.size_hint().0);
drop(values);
assert_eq!(1, Rc::strong_count(&v));
}
#[test]
fn values_clone() {
let mut m: Map<i32, String, 10> = Map::new();
m.insert(1, "foo".to_string());
m.insert(2, "bar".to_string());
let values = m.values();
let cloned_values = values.clone();
assert_eq!(
values.collect::<Vec<_>>(),
cloned_values.collect::<Vec<_>>()
);
}
#[test]
fn values_default() {
let values: Values<'_, String, i32> = Values::default();
assert_eq!(values.len(), 0);
assert_eq!(values.size_hint(), (0, Some(0)));
}
#[test]
fn values_mut_default() {
let values_mut: ValuesMut<'_, String, i32> = ValuesMut::default();
assert_eq!(values_mut.len(), 0);
assert_eq!(values_mut.size_hint(), (0, Some(0)));
}
#[test]
fn into_values_default() {
let into_values: IntoValues<String, i32, 10> = IntoValues::default();
assert_eq!(into_values.len(), 0);
assert_eq!(into_values.size_hint(), (0, Some(0)));
}
#[test]
fn values_debug() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 42);
m.insert("two".to_string(), 16);
let values = m.values();
let debug_str = format!("{:?}", values);
assert!(debug_str.contains("42"));
assert!(debug_str.contains("16"));
}
#[test]
fn values_mut_debug() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 42);
m.insert("two".to_string(), 16);
let values_mut = m.values_mut();
let debug_str = format!("{:?}", values_mut);
assert!(debug_str.contains("42"));
assert!(debug_str.contains("16"));
}
#[test]
fn into_values_debug() {
let mut m: Map<String, i32, 10> = Map::new();
m.insert("one".to_string(), 42);
m.insert("two".to_string(), 16);
let into_values = m.into_values();
let debug_str = format!("{:?}", into_values);
assert!(debug_str.contains("42"));
assert!(debug_str.contains("16"));
}
}