Skip to content

Commit 15fca4b

Browse files
committed
Return concrete types from LiteMap iter methods
impl Trait is limited to a single trait. But we'd like to expose iterators that implement more than DoubleEndedIterator (eg: ExactSize, Fused). This is why we return a concrete type now. This closes #8054. Considerations -------------- * No Copy derive, because that's against API guidelines for Iterators * Manual impl of `size_hint`, to be able to use ExactSizeIterator without panicking. * Manual impl of `nth` and `fold`, as other iterator methods tend to be implemented in term of those, and forwarding them to the inner iterator **might** avoid performance penalty of the default impl.
1 parent aef08cb commit 15fca4b

1 file changed

Lines changed: 89 additions & 7 deletions

File tree

utils/litemap/src/map.rs

Lines changed: 89 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use alloc::vec::Vec;
1010
use core::borrow::Borrow;
1111
use core::cmp::Ordering;
1212
use core::fmt::Debug;
13-
use core::iter::FromIterator;
13+
use core::iter::{FromIterator, FusedIterator};
1414
use core::marker::PhantomData;
1515
use core::mem;
1616
use core::ops::{Index, IndexMut, Range};
@@ -901,7 +901,7 @@ where
901901
S: StoreIterable<'a, K, V>,
902902
{
903903
/// Produce an ordered iterator over key-value pairs
904-
pub fn iter(&'a self) -> impl DoubleEndedIterator<Item = (&'a K, &'a V)> {
904+
pub fn iter(&'a self) -> S::KeyValueIter {
905905
self.values.lm_iter()
906906
}
907907

@@ -918,13 +918,17 @@ where
918918
}
919919

920920
/// Produce an ordered iterator over keys
921-
pub fn keys(&'a self) -> impl DoubleEndedIterator<Item = &'a K> {
922-
self.values.lm_iter().map(|val| val.0)
921+
pub fn keys(&'a self) -> KeysIter<S::KeyValueIter> {
922+
KeysIter {
923+
iter: self.values.lm_iter(),
924+
}
923925
}
924926

925927
/// Produce an iterator over values, ordered by their keys
926-
pub fn values(&'a self) -> impl DoubleEndedIterator<Item = &'a V> {
927-
self.values.lm_iter().map(|val| val.1)
928+
pub fn values(&'a self) -> ValuesIter<S::KeyValueIter> {
929+
ValuesIter {
930+
iter: self.values.lm_iter(),
931+
}
928932
}
929933
}
930934

@@ -933,7 +937,7 @@ where
933937
S: StoreIterableMut<'a, K, V>,
934938
{
935939
/// Produce an ordered mutable iterator over key-value pairs
936-
pub fn iter_mut(&'a mut self) -> impl DoubleEndedIterator<Item = (&'a K, &'a mut V)> {
940+
pub fn iter_mut(&'a mut self) -> S::KeyValueIterMut {
937941
self.values.lm_iter_mut()
938942
}
939943
}
@@ -1217,6 +1221,84 @@ impl_const_get_with_index_for_integer!(i64);
12171221
impl_const_get_with_index_for_integer!(i128);
12181222
impl_const_get_with_index_for_integer!(isize);
12191223

1224+
/// An [`Iterator`] adapter over the 0th element of a 2-tuple iterator.
1225+
#[derive(Debug, Clone)]
1226+
pub struct KeysIter<I> {
1227+
iter: I,
1228+
}
1229+
1230+
/// An [`Iterator`] adapter over the 1st element of a 2-tuple iterator.
1231+
#[derive(Debug, Clone)]
1232+
pub struct ValuesIter<I> {
1233+
iter: I,
1234+
}
1235+
1236+
impl<K, V, I: Iterator<Item = (K, V)>> Iterator for KeysIter<I> {
1237+
type Item = K;
1238+
1239+
#[inline]
1240+
fn size_hint(&self) -> (usize, Option<usize>) {
1241+
self.iter.size_hint()
1242+
}
1243+
#[inline]
1244+
fn next(&mut self) -> Option<Self::Item> {
1245+
self.iter.next().map(|val| val.0)
1246+
}
1247+
#[inline]
1248+
fn fold<B, F>(self, init: B, f: F) -> B
1249+
where
1250+
Self: Sized,
1251+
F: FnMut(B, Self::Item) -> B,
1252+
{
1253+
self.iter.map(|val| val.0).fold(init, f)
1254+
}
1255+
#[inline]
1256+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1257+
self.iter.nth(n).map(|val| val.0)
1258+
}
1259+
}
1260+
impl<K, V, I: ExactSizeIterator<Item = (K, V)>> ExactSizeIterator for KeysIter<I> {}
1261+
impl<K, V, I: FusedIterator<Item = (K, V)>> FusedIterator for KeysIter<I> {}
1262+
impl<K, V, I: DoubleEndedIterator<Item = (K, V)>> DoubleEndedIterator for KeysIter<I> {
1263+
#[inline]
1264+
fn next_back(&mut self) -> Option<Self::Item> {
1265+
self.iter.next_back().map(|val| val.0)
1266+
}
1267+
}
1268+
1269+
impl<K, V, I: Iterator<Item = (K, V)>> Iterator for ValuesIter<I> {
1270+
type Item = V;
1271+
1272+
#[inline]
1273+
fn size_hint(&self) -> (usize, Option<usize>) {
1274+
self.iter.size_hint()
1275+
}
1276+
#[inline]
1277+
fn next(&mut self) -> Option<Self::Item> {
1278+
self.iter.next().map(|val| val.1)
1279+
}
1280+
#[inline]
1281+
fn fold<B, F>(self, init: B, f: F) -> B
1282+
where
1283+
Self: Sized,
1284+
F: FnMut(B, Self::Item) -> B,
1285+
{
1286+
self.iter.map(|val| val.1).fold(init, f)
1287+
}
1288+
#[inline]
1289+
fn nth(&mut self, n: usize) -> Option<Self::Item> {
1290+
self.iter.nth(n).map(|val| val.1)
1291+
}
1292+
}
1293+
impl<K, V, I: ExactSizeIterator<Item = (K, V)>> ExactSizeIterator for ValuesIter<I> {}
1294+
impl<K, V, I: FusedIterator<Item = (K, V)>> FusedIterator for ValuesIter<I> {}
1295+
impl<K, V, I: DoubleEndedIterator<Item = (K, V)>> DoubleEndedIterator for ValuesIter<I> {
1296+
#[inline]
1297+
fn next_back(&mut self) -> Option<Self::Item> {
1298+
self.iter.next_back().map(|val| val.1)
1299+
}
1300+
}
1301+
12201302
/// An entry in a `LiteMap`, which may be either occupied or vacant.
12211303
#[allow(clippy::exhaustive_enums)]
12221304
pub enum Entry<'a, K, V, S> {

0 commit comments

Comments
 (0)