Skip to content

Commit 8d2bdb0

Browse files
committed
Implement peekable for slice::iter
1 parent 38e446a commit 8d2bdb0

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

library/core/src/slice/iter.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ mod macros;
66
use super::{from_raw_parts, from_raw_parts_mut};
77
use crate::hint::assert_unchecked;
88
use crate::iter::{
9-
FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator,
9+
FusedIterator, PeekableIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
10+
UncheckedIterator,
1011
};
1112
use crate::marker::PhantomData;
1213
use crate::mem::{self, SizedTypeProperties};

library/core/src/slice/iter/macros.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,34 @@ macro_rules! iterator {
468468
}
469469
}
470470

471+
#[unstable(feature = "peekable_iterator", issue = "132973")]
472+
impl<'a, T> PeekableIterator for $name<'a, T> {
473+
fn peek(&mut self) -> Option<&$elem> {
474+
let ptr = self.ptr;
475+
let end_or_len = self.end_or_len;
476+
477+
// SAFETY: See inner comments.
478+
unsafe {
479+
if T::IS_ZST {
480+
let len = end_or_len.addr();
481+
if len == 0 {
482+
return None;
483+
}
484+
} else {
485+
// SAFETY: by type invariant, the `end_or_len` field is always
486+
// non-null for a non-ZST pointee. (This transmute ensures we
487+
// get `!nonnull` metadata on the load of the field.)
488+
if ptr == crate::intrinsics::transmute::<$ptr, NonNull<T>>(end_or_len) {
489+
return None;
490+
}
491+
}
492+
// SAFETY: Now that we know it wasn't empty and we've moved past
493+
// the first one (to avoid giving a duplicate `&mut` next time),
494+
// we can give out a reference to it.
495+
Some(core::mem::transmute(&self.ptr))
496+
}
497+
}
498+
}
471499
#[stable(feature = "default_iters", since = "1.70.0")]
472500
impl<T> Default for $name<'_, T> {
473501
/// Creates an empty slice iterator.

0 commit comments

Comments
 (0)