Skip to content

Commit 38c004e

Browse files
authored
Merge pull request #628 from therealbnut/more_into_iter_traits
Add ExactSizeIterator, FusedIterator, and DoubleEndedIterator on IntoIter types
2 parents 30e1494 + bd70229 commit 38c004e

File tree

5 files changed

+166
-2
lines changed

5 files changed

+166
-2
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
- Added `retain_mut` to `Deque`
2020
- Added `into_raw` to `Box`
2121
- Added `from_raw` to `Box`
22+
- Added `FusedIterator` to `vec::IntoIter`, `deque::IntoIter`, `index_map::IntoIter` and `linear_map::IntoIter`.
23+
- Added `ExactSizeIterator` to `vec::IntoIter`, `deque::IntoIter`, `index_map::IntoIter` and `linear_map::IntoIter`.
24+
- Added `DoubleEndedIterator` to `vec::IntoIter` and `deque::IntoIter`.
2225

2326
## [v0.9.1] - 2025-08-19
2427

src/deque.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,21 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
10951095
fn next(&mut self) -> Option<Self::Item> {
10961096
self.deque.pop_front()
10971097
}
1098+
fn size_hint(&self) -> (usize, Option<usize>) {
1099+
let len = self.len();
1100+
(len, Some(len))
1101+
}
1102+
}
1103+
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
1104+
fn next_back(&mut self) -> Option<Self::Item> {
1105+
self.deque.pop_back()
1106+
}
1107+
}
1108+
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
1109+
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
1110+
fn len(&self) -> usize {
1111+
self.deque.len()
1112+
}
10981113
}
10991114

11001115
impl<T, const N: usize> IntoIterator for Deque<T, N> {
@@ -1421,6 +1436,41 @@ mod tests {
14211436
assert_eq!(items.next(), None);
14221437
}
14231438

1439+
#[test]
1440+
fn iter_move_back() {
1441+
let mut v: Deque<i32, 4> = Deque::new();
1442+
1443+
v.push_back(0).unwrap();
1444+
v.push_back(1).unwrap();
1445+
v.push_back(2).unwrap();
1446+
v.push_back(3).unwrap();
1447+
1448+
let mut items = v.into_iter();
1449+
assert_eq!(items.next_back(), Some(3));
1450+
assert_eq!(items.next_back(), Some(2));
1451+
assert_eq!(items.next_back(), Some(1));
1452+
assert_eq!(items.next_back(), Some(0));
1453+
assert_eq!(items.next_back(), None);
1454+
}
1455+
1456+
#[test]
1457+
fn iter_move_len() {
1458+
let mut v: Deque<i32, 3> = Deque::new();
1459+
1460+
v.push_back(0).unwrap();
1461+
v.push_back(1).unwrap();
1462+
v.push_back(2).unwrap();
1463+
1464+
let mut items = v.into_iter();
1465+
assert_eq!(items.len(), 3);
1466+
let _ = items.next();
1467+
assert_eq!(items.len(), 2);
1468+
let _ = items.next_back();
1469+
assert_eq!(items.len(), 1);
1470+
let _ = items.next();
1471+
assert_eq!(items.len(), 0);
1472+
}
1473+
14241474
#[test]
14251475
fn iter_move_drop() {
14261476
droppable!();

src/index_map.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use core::{
33
borrow::Borrow,
44
fmt,
55
hash::{BuildHasher, Hash},
6+
iter::FusedIterator,
67
mem,
78
num::NonZeroU32,
89
ops, slice,
@@ -1471,6 +1472,19 @@ impl<K, V, const N: usize> Iterator for IntoIter<K, V, N> {
14711472
fn next(&mut self) -> Option<Self::Item> {
14721473
self.entries.pop().map(|bucket| (bucket.key, bucket.value))
14731474
}
1475+
1476+
fn size_hint(&self) -> (usize, Option<usize>) {
1477+
let len = self.len();
1478+
(len, Some(len))
1479+
}
1480+
}
1481+
1482+
impl<K, V, const N: usize> FusedIterator for IntoIter<K, V, N> {}
1483+
1484+
impl<K, V, const N: usize> ExactSizeIterator for IntoIter<K, V, N> {
1485+
fn len(&self) -> usize {
1486+
self.entries.len()
1487+
}
14741488
}
14751489

14761490
impl<K, V, S, const N: usize> IntoIterator for IndexMap<K, V, S, N> {
@@ -1744,8 +1758,23 @@ mod tests {
17441758
src.insert("k4", "v4").unwrap();
17451759
let clone = src.clone();
17461760
for (k, v) in clone.into_iter() {
1747-
assert_eq!(v, *src.get(k).unwrap());
1761+
assert_eq!(v, src.remove(k).unwrap());
17481762
}
1763+
assert!(src.is_empty());
1764+
}
1765+
1766+
#[test]
1767+
fn into_iter_len() {
1768+
let mut src: FnvIndexMap<_, _, 2> = FnvIndexMap::new();
1769+
src.insert("k1", "v1").unwrap();
1770+
src.insert("k2", "v2").unwrap();
1771+
1772+
let mut items = src.into_iter();
1773+
assert_eq!(items.len(), 2);
1774+
let _ = items.next();
1775+
assert_eq!(items.len(), 1);
1776+
let _ = items.next();
1777+
assert_eq!(items.len(), 0);
17491778
}
17501779

17511780
#[test]

src/linear_map.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//!
33
//! Note that as this map doesn't use hashing so most operations are *O*(n) instead of *O*(1).
44
5-
use core::{borrow::Borrow, fmt, mem, ops, slice};
5+
use core::{borrow::Borrow, fmt, iter::FusedIterator, mem, ops, slice};
66

77
#[cfg(feature = "zeroize")]
88
use zeroize::Zeroize;
@@ -606,6 +606,22 @@ where
606606
fn next(&mut self) -> Option<Self::Item> {
607607
self.inner.next()
608608
}
609+
610+
fn size_hint(&self) -> (usize, Option<usize>) {
611+
let len = self.len();
612+
(len, Some(len))
613+
}
614+
}
615+
616+
impl<K, V, const N: usize> FusedIterator for IntoIter<K, V, N> where K: Eq {}
617+
618+
impl<K, V, const N: usize> ExactSizeIterator for IntoIter<K, V, N>
619+
where
620+
K: Eq,
621+
{
622+
fn len(&self) -> usize {
623+
self.inner.len()
624+
}
609625
}
610626

611627
impl<K, V, const N: usize> IntoIterator for LinearMap<K, V, N>
@@ -877,6 +893,20 @@ mod test {
877893
for (k, v) in clone.into_iter() {
878894
assert_eq!(v, src.remove(k).unwrap());
879895
}
896+
assert!(src.is_empty());
897+
}
898+
899+
#[test]
900+
fn into_iter_len() {
901+
let mut src: LinearMap<_, _, 2> = LinearMap::new();
902+
src.insert("k1", "v1").unwrap();
903+
src.insert("k2", "v2").unwrap();
904+
let mut items = src.into_iter();
905+
assert_eq!(items.len(), 2);
906+
let _ = items.next();
907+
assert_eq!(items.len(), 1);
908+
let _ = items.next();
909+
assert_eq!(items.len(), 0);
880910
}
881911

882912
fn _test_variance_value<'a: 'b, 'b>(

src/vec/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! A fixed capacity [`Vec`](https://doc.rust-lang.org/std/vec/struct.Vec.html).
22
33
use core::borrow;
4+
use core::iter::FusedIterator;
45
use core::marker::PhantomData;
56
use core::{
67
cmp::Ordering,
@@ -1472,6 +1473,31 @@ impl<T, LenT: LenType, const N: usize> Iterator for IntoIter<T, N, LenT> {
14721473
None
14731474
}
14741475
}
1476+
1477+
fn size_hint(&self) -> (usize, Option<usize>) {
1478+
let len = self.len();
1479+
(len, Some(len))
1480+
}
1481+
}
1482+
1483+
impl<T, LenT: LenType, const N: usize> DoubleEndedIterator for IntoIter<T, N, LenT> {
1484+
fn next_back(&mut self) -> Option<Self::Item> {
1485+
if self.next < self.vec.len {
1486+
// SAFETY: len must be non-zero as next is less than len.
1487+
let item = unsafe { self.vec.pop_unchecked() };
1488+
Some(item)
1489+
} else {
1490+
None
1491+
}
1492+
}
1493+
}
1494+
1495+
impl<T, LenT: LenType, const N: usize> FusedIterator for IntoIter<T, N, LenT> {}
1496+
1497+
impl<T, LenT: LenType, const N: usize> ExactSizeIterator for IntoIter<T, N, LenT> {
1498+
fn len(&self) -> usize {
1499+
(self.vec.len - self.next).into_usize()
1500+
}
14751501
}
14761502

14771503
impl<T, LenT: LenType, const N: usize> Clone for IntoIter<T, N, LenT>
@@ -2034,6 +2060,32 @@ mod tests {
20342060
assert_eq!(Droppable::count(), 0);
20352061
}
20362062

2063+
#[test]
2064+
fn iter_move_next_back() {
2065+
let mut vec: Vec<&str, 3> = Vec::new();
2066+
vec.push("a").unwrap();
2067+
vec.push("b").unwrap();
2068+
vec.push("c").unwrap();
2069+
let mut items = vec.into_iter();
2070+
let _ = items.next(); // Remove the first item.
2071+
assert_eq!(items.next_back(), Some("c"));
2072+
assert_eq!(items.next_back(), Some("b"));
2073+
assert_eq!(items.next_back(), None);
2074+
}
2075+
2076+
#[test]
2077+
fn iter_move_len() {
2078+
let mut vec: Vec<&str, 2> = Vec::new();
2079+
vec.push("a").unwrap();
2080+
vec.push("b").unwrap();
2081+
let mut items = vec.into_iter();
2082+
assert_eq!(items.len(), 2);
2083+
let _ = items.next(); // Remove the first item.
2084+
assert_eq!(items.len(), 1);
2085+
let _ = items.next_back(); // Remove the last item.
2086+
assert_eq!(items.len(), 0);
2087+
}
2088+
20372089
#[test]
20382090
fn push_and_pop() {
20392091
let mut v: Vec<i32, 4> = Vec::new();

0 commit comments

Comments
 (0)