#![allow(clippy::module_name_repetitions)] // SPDX-FileCopyrightText: 2017 - 2022 Kamila Borowska // SPDX-FileCopyrightText: 2020 Amanieu d'Antras // SPDX-FileCopyrightText: 2021 Bruno CorrĂȘa Zimmermann // // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::{EnumArray, EnumMap}; use core::iter::{Enumerate, FusedIterator}; use core::marker::PhantomData; use core::mem::ManuallyDrop; use core::ops::Range; use core::ptr; use core::slice; /// Immutable enum map iterator /// /// This struct is created by `iter` method or `into_iter` on a reference /// to `EnumMap`. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum)] /// enum Example { /// A, /// B, /// C, /// } /// /// let mut map = enum_map! { Example::A => 3, _ => 0 }; /// assert_eq!(map[Example::A], 3); /// for (key, &value) in &map { /// assert_eq!(value, match key { /// Example::A => 3, /// _ => 0, /// }); /// } /// ``` #[derive(Debug)] pub struct Iter<'a, K, V: 'a> { _phantom: PhantomData K>, iterator: Enumerate>, } impl<'a, K: EnumArray, V> Clone for Iter<'a, K, V> { fn clone(&self) -> Self { Iter { _phantom: PhantomData, iterator: self.iterator.clone(), } } } impl<'a, K: EnumArray, V> Iterator for Iter<'a, K, V> { type Item = (K, &'a V); #[inline] fn next(&mut self) -> Option { self.iterator .next() .map(|(index, item)| (K::from_usize(index), item)) } #[inline] fn size_hint(&self) -> (usize, Option) { self.iterator.size_hint() } fn fold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { self.iterator .map(|(index, item)| (K::from_usize(index), item)) .fold(init, f) } } impl<'a, K: EnumArray, V> DoubleEndedIterator for Iter<'a, K, V> { #[inline] fn next_back(&mut self) -> Option { self.iterator .next_back() .map(|(index, item)| (K::from_usize(index), item)) } } impl<'a, K: EnumArray, V> ExactSizeIterator for Iter<'a, K, V> {} impl<'a, K: EnumArray, V> FusedIterator for Iter<'a, K, V> {} impl<'a, K: EnumArray, V> IntoIterator for &'a EnumMap { type Item = (K, &'a V); type IntoIter = Iter<'a, K, V>; #[inline] fn into_iter(self) -> Self::IntoIter { Iter { _phantom: PhantomData, iterator: self.as_slice().iter().enumerate(), } } } /// Mutable map iterator /// /// This struct is created by `iter_mut` method or `into_iter` on a mutable /// reference to `EnumMap`. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Debug, Enum)] /// enum Example { /// A, /// B, /// C, /// } /// /// let mut map = enum_map! { Example::A => 3, _ => 0 }; /// for (_, value) in &mut map { /// *value += 1; /// } /// assert_eq!(map, enum_map! { Example::A => 4, _ => 1 }); /// ``` #[derive(Debug)] pub struct IterMut<'a, K, V: 'a> { _phantom: PhantomData K>, iterator: Enumerate>, } impl<'a, K: EnumArray, V> Iterator for IterMut<'a, K, V> { type Item = (K, &'a mut V); #[inline] fn next(&mut self) -> Option { self.iterator .next() .map(|(index, item)| (K::from_usize(index), item)) } #[inline] fn size_hint(&self) -> (usize, Option) { self.iterator.size_hint() } fn fold(self, init: B, f: F) -> B where F: FnMut(B, Self::Item) -> B, { self.iterator .map(|(index, item)| (K::from_usize(index), item)) .fold(init, f) } } impl<'a, K: EnumArray, V> DoubleEndedIterator for IterMut<'a, K, V> { #[inline] fn next_back(&mut self) -> Option { self.iterator .next_back() .map(|(index, item)| (K::from_usize(index), item)) } } impl<'a, K: EnumArray, V> ExactSizeIterator for IterMut<'a, K, V> {} impl<'a, K: EnumArray, V> FusedIterator for IterMut<'a, K, V> {} impl<'a, K: EnumArray, V> IntoIterator for &'a mut EnumMap { type Item = (K, &'a mut V); type IntoIter = IterMut<'a, K, V>; #[inline] fn into_iter(self) -> Self::IntoIter { IterMut { _phantom: PhantomData, iterator: self.as_mut_slice().iter_mut().enumerate(), } } } /// A map iterator that moves out of map. /// /// This struct is created by `into_iter` on `EnumMap`. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Debug, Enum)] /// enum Example { /// A, /// B, /// } /// /// let map = enum_map! { Example::A | Example::B => String::from("123") }; /// for (_, value) in map { /// assert_eq!(value + "4", "1234"); /// } /// ``` pub struct IntoIter, V> { map: ManuallyDrop>, alive: Range, } impl, V> Iterator for IntoIter { type Item = (K, V); fn next(&mut self) -> Option<(K, V)> { let position = self.alive.next()?; Some((K::from_usize(position), unsafe { ptr::read(&self.map.as_slice()[position]) })) } #[inline] fn size_hint(&self) -> (usize, Option) { self.alive.size_hint() } } impl, V> DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option<(K, V)> { let position = self.alive.next_back()?; Some((K::from_usize(position), unsafe { ptr::read(&self.map.as_slice()[position]) })) } } impl, V> ExactSizeIterator for IntoIter {} impl, V> FusedIterator for IntoIter {} impl, V> Drop for IntoIter { #[inline] fn drop(&mut self) { unsafe { ptr::drop_in_place(&mut self.map.as_mut_slice()[self.alive.clone()]); } } } impl, V> IntoIterator for EnumMap { type Item = (K, V); type IntoIter = IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { let len = self.len(); IntoIter { map: ManuallyDrop::new(self), alive: 0..len, } } } impl, V> EnumMap { /// An iterator visiting all values. The iterator type is `&V`. /// /// # Examples /// /// ``` /// use enum_map::enum_map; /// /// let map = enum_map! { false => 3, true => 4 }; /// let mut values = map.values(); /// assert_eq!(values.next(), Some(&3)); /// assert_eq!(values.next(), Some(&4)); /// assert_eq!(values.next(), None); /// ``` #[inline] pub fn values(&self) -> Values { Values(self.as_slice().iter()) } /// An iterator visiting all values mutably. The iterator type is `&mut V`. /// /// # Examples /// /// ``` /// use enum_map::enum_map; /// /// let mut map = enum_map! { _ => 2 }; /// for value in map.values_mut() { /// *value += 2; /// } /// assert_eq!(map[false], 4); /// assert_eq!(map[true], 4); /// ``` #[inline] pub fn values_mut(&mut self) -> ValuesMut { ValuesMut(self.as_mut_slice().iter_mut()) } /// Creates a consuming iterator visiting all the values. The map /// cannot be used after calling this. The iterator element type /// is `V`. /// /// # Examples /// /// ``` /// use enum_map::enum_map; /// /// let mut map = enum_map! { false => "hello", true => "goodbye" }; /// assert_eq!(map.into_values().collect::>(), ["hello", "goodbye"]); /// ``` #[inline] pub fn into_values(self) -> IntoValues { IntoValues { inner: self.into_iter(), } } } /// An iterator over the values of `EnumMap`. /// /// This `struct` is created by the `values` method of `EnumMap`. /// See its documentation for more. pub struct Values<'a, V: 'a>(slice::Iter<'a, V>); impl<'a, V> Clone for Values<'a, V> { fn clone(&self) -> Self { Values(self.0.clone()) } } impl<'a, V: 'a> Iterator for Values<'a, V> { type Item = &'a V; #[inline] fn next(&mut self) -> Option<&'a V> { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } impl<'a, V: 'a> DoubleEndedIterator for Values<'a, V> { #[inline] fn next_back(&mut self) -> Option<&'a V> { self.0.next_back() } } impl<'a, V: 'a> ExactSizeIterator for Values<'a, V> {} impl<'a, V: 'a> FusedIterator for Values<'a, V> {} /// A mutable iterator over the values of `EnumMap`. /// /// This `struct` is created by the `values_mut` method of `EnumMap`. /// See its documentation for more. pub struct ValuesMut<'a, V: 'a>(slice::IterMut<'a, V>); impl<'a, V: 'a> Iterator for ValuesMut<'a, V> { type Item = &'a mut V; #[inline] fn next(&mut self) -> Option<&'a mut V> { self.0.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.0.size_hint() } } impl<'a, V: 'a> DoubleEndedIterator for ValuesMut<'a, V> { #[inline] fn next_back(&mut self) -> Option<&'a mut V> { self.0.next_back() } } impl<'a, V: 'a> ExactSizeIterator for ValuesMut<'a, V> {} impl<'a, V: 'a> FusedIterator for ValuesMut<'a, V> {} /// An owning iterator over the values of an `EnumMap`. /// /// This `struct` is created by the `into_values` method of `EnumMap`. /// See its documentation for more. pub struct IntoValues, V> { inner: IntoIter, } impl Iterator for IntoValues where K: EnumArray, { type Item = V; fn next(&mut self) -> Option { Some(self.inner.next()?.1) } fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } } impl, V> DoubleEndedIterator for IntoValues { fn next_back(&mut self) -> Option { Some(self.inner.next_back()?.1) } } impl ExactSizeIterator for IntoValues where K: EnumArray {} impl FusedIterator for IntoValues where K: EnumArray {}