use itertools::ProcessResults;
pub unsafe trait TrustedLen: Iterator {}
pub struct TrustedLenAdapter<I> {
inner: I,
len: usize,
#[cfg(debug_assertions)]
count: usize,
}
impl<I: Iterator> Iterator for TrustedLenAdapter<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
None => {
#[cfg(debug_assertions)]
{
assert_eq!(
self.len, self.count,
"TrustedLenAdapter: iterator ended early"
);
}
None
}
Some(item) => {
#[cfg(debug_assertions)]
{
self.count += 1;
assert!(
self.count <= self.len,
"TrustedLenAdapter: iterator yielded more items than promised"
);
}
Some(item)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
unsafe impl<I: Iterator> TrustedLen for TrustedLenAdapter<I> {}
pub trait TrustedLenExt: Iterator + Sized {
unsafe fn trusted_len(self) -> TrustedLenAdapter<Self> {
let (lower_bound, upper_bound_opt) = self.size_hint();
if let Some(upper_bound) = upper_bound_opt {
assert_eq!(
lower_bound, upper_bound,
"TrustedLenExt: iterator size hints must match if upper bound is given"
);
}
TrustedLenAdapter {
inner: self,
len: lower_bound,
#[cfg(debug_assertions)]
count: 0,
}
}
}
impl<I: Iterator> TrustedLenExt for I {}
macro_rules! impl_for_range {
($($typ:ty),*) => {
$(
unsafe impl TrustedLen for std::ops::Range<$typ> {}
unsafe impl TrustedLen for std::ops::RangeInclusive<$typ> {}
unsafe impl TrustedLen for std::iter::StepBy<std::ops::Range<$typ>> {}
unsafe impl TrustedLen for std::iter::StepBy<std::ops::RangeInclusive<$typ>> {}
)*
};
}
impl_for_range!(u8, u16, u32, u64, i8, i16, i32, i64, usize);
unsafe impl<T> TrustedLen for std::slice::Iter<'_, T> {}
unsafe impl<T> TrustedLen for std::slice::IterMut<'_, T> {}
unsafe impl<B, I, F> TrustedLen for std::iter::Map<I, F>
where
I: TrustedLen,
F: FnMut(I::Item) -> B,
{
}
unsafe impl<I> TrustedLen for std::iter::Skip<I> where I: TrustedLen {}
unsafe impl<'a, I, T: 'a> TrustedLen for std::iter::Copied<I>
where
I: TrustedLen<Item = &'a T>,
T: Copy,
{
}
unsafe impl<'a, I, T: 'a> TrustedLen for std::iter::Cloned<I>
where
I: TrustedLen<Item = &'a T>,
T: Clone,
{
}
unsafe impl<T> TrustedLen for std::vec::IntoIter<T> {}
unsafe impl<T, const N: usize> TrustedLen for std::array::IntoIter<T, N> {}
unsafe impl<T> TrustedLen for crate::Iter<'_, T> {}
unsafe impl<T: Copy> TrustedLen for crate::BufferIterator<T> {}
unsafe impl<'a, I, T: 'a, E: 'a> TrustedLen for ProcessResults<'a, I, E> where
I: TrustedLen<Item = Result<T, E>>
{
}
unsafe impl<I, T> TrustedLen for std::iter::Enumerate<I> where I: TrustedLen<Item = T> {}
unsafe impl<T, U> TrustedLen for std::iter::Zip<T, U>
where
T: TrustedLen,
U: TrustedLen,
{
}
unsafe impl<T: Clone> TrustedLen for std::iter::RepeatN<T> {}
unsafe impl<'a> TrustedLen for crate::bit::BitIterator<'a> {}
unsafe impl<'a> TrustedLen for crate::bit::BitChunkIterator<'a> {}
unsafe impl<'a> TrustedLen for crate::bit::UnalignedBitChunkIterator<'a> {}