#![cfg_attr( feature = "nightly", feature( trusted_len, trusted_fused, min_specialization, trusted_random_access, inplace_iteration, doc_cfg, ) )] #![no_std] use core::iter::FusedIterator; #[cfg(feature = "nightly")] use core::iter::{ InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, }; /// Provides a hint for an iterator. #[derive(Clone, Debug)] pub struct Hinted { /// Wrapped iterator. iter: I, /// Size hint, decreased on every call to [`next()`](Iterator::next). hint: usize, } /// Set the size hint for an iterator. pub trait HintExt: Iterator where Self: Sized, { /// Sets the lower bound of [`Iterator::size_hint`]. Useful for collects etc. fn hinted(self, hint: usize) -> Hinted { Hinted { iter: self, hint } } /// Implements [`ExactSizeIterator`] for any iterator, with a len provided by you. /// This implements [`TrustedLen`](core::iter::TrustedLen) as well, so this function is unsafe. /// /// The resulting iterator will not return after the length has been reached. /// /// # Safety /// /// number of items *must* be `len`. unsafe fn has(self, len: usize) -> Exactly { Exactly { iter: self, len } } } impl HintExt for I {} impl Iterator for Hinted where I: Iterator + Sized, { type Item = ::Item; fn next(&mut self) -> Option { self.hint = self.hint.saturating_sub(1); self.iter.next() } fn size_hint(&self) -> (usize, Option) { (self.hint, self.iter.size_hint().1) } } impl DoubleEndedIterator for Hinted { fn next_back(&mut self) -> Option { self.hint = self.hint.saturating_sub(1); self.iter.next_back() } } impl FusedIterator for Hinted {} #[cfg(feature = "nightly")] unsafe impl TrustedRandomAccess for Hinted {} #[cfg(feature = "nightly")] unsafe impl TrustedRandomAccessNoCoerce for Hinted { const MAY_HAVE_SIDE_EFFECT: bool = true; } #[cfg(feature = "nightly")] unsafe impl SourceIter for Hinted { type Source = I::Source; #[inline] unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } } #[cfg(feature = "nightly")] unsafe impl InPlaceIterable for Hinted { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; } /// Provides a size for an iterator. #[derive(Clone, Debug)] pub struct Exactly { /// Wrapped iterator. iter: I, /// Exact size, decreased on every call to [`next()`](Iterator::next). len: usize, } /// Set the size hint for an iterator. impl Iterator for Exactly where I: Iterator + Sized, { type Item = ::Item; fn next(&mut self) -> Option { self.len = self.len.saturating_sub(1); self.iter.next() } fn size_hint(&self) -> (usize, Option) { (self.len, Some(self.len)) } } impl ExactSizeIterator for Exactly { fn len(&self) -> usize { self.len } } impl DoubleEndedIterator for Exactly { fn next_back(&mut self) -> Option { self.len = self.len.saturating_sub(1); self.iter.next_back() } } impl FusedIterator for Exactly {} // SAFETY: see [`HintExt::has`]. #[cfg(feature = "nightly")] unsafe impl TrustedLen for Exactly {} #[cfg(feature = "nightly")] unsafe impl TrustedRandomAccess for Exactly {} #[cfg(feature = "nightly")] unsafe impl TrustedRandomAccessNoCoerce for Exactly { const MAY_HAVE_SIDE_EFFECT: bool = true; } #[cfg(feature = "nightly")] unsafe impl SourceIter for Exactly { type Source = I::Source; #[inline] unsafe fn as_inner(&mut self) -> &mut I::Source { // SAFETY: unsafe function forwarding to unsafe function with the same requirements unsafe { SourceIter::as_inner(&mut self.iter) } } } #[cfg(feature = "nightly")] unsafe impl InPlaceIterable for Exactly { const EXPAND_BY: Option> = I::EXPAND_BY; const MERGE_BY: Option> = I::MERGE_BY; }