use core::{iter::FusedIterator, ops::Not};
use fluent_result::bool::Then;
use crate::InvalidSizeHint;
use crate::size_hint::SizeHint;
#[cfg(doc)]
use crate::*;
#[derive(Debug, Default, Clone)]
#[readonly::make]
pub struct HintSize<I: Iterator> {
pub iterator: I,
pub hint: SizeHint,
}
impl<I: Iterator> HintSize<I> {
#[inline]
#[track_caller]
fn try_new_impl(iterator: I, hint: SizeHint) -> Result<Self, InvalidSizeHint> {
let wrapped: SizeHint = iterator.size_hint().try_into().expect("iterator's size hint should be valid");
SizeHint::overlaps(hint, wrapped).not().then_err(InvalidSizeHint)?;
Ok(Self { iterator, hint })
}
#[inline]
pub fn new<IntoIter>(iterator: IntoIter, lower: usize, upper: usize) -> Self
where
IntoIter: IntoIterator<IntoIter = I>,
I: FusedIterator,
{
Self::try_new(iterator, lower, upper).expect("Invalid size hint")
}
#[inline]
pub fn try_new<II>(iterator: II, lower: usize, upper: usize) -> Result<Self, InvalidSizeHint>
where
II: IntoIterator<IntoIter = I>,
I: FusedIterator,
{
let hint = SizeHint::try_bounded(lower, upper)?;
Self::try_new_impl(iterator.into_iter(), hint)
}
#[inline]
pub fn min(iterator: impl IntoIterator<IntoIter = I>, lower: usize) -> Self {
Self::try_min(iterator, lower).expect("Invalid size hint")
}
#[inline]
pub fn try_min(iterator: impl IntoIterator<IntoIter = I>, lower: usize) -> Result<Self, InvalidSizeHint> {
Self::try_new_impl(iterator.into_iter(), SizeHint::unbounded(lower))
}
#[inline]
pub fn hide(iterator: impl IntoIterator<IntoIter = I>) -> Self {
Self { iterator: iterator.into_iter(), hint: SizeHint::UNIVERSAL }
}
#[inline]
pub fn into_inner(self) -> I {
self.iterator
}
}
impl<I: Iterator> Iterator for HintSize<I> {
type Item = I::Item;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.hint = self.hint.decrement();
self.iterator.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.hint.into()
}
}
impl<I: DoubleEndedIterator> DoubleEndedIterator for HintSize<I> {
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.hint = self.hint.decrement();
self.iterator.next_back()
}
}
impl<I: Iterator + FusedIterator> FusedIterator for HintSize<I> {}