use core::num::NonZeroUsize;
use core::ops::ControlFlow;
use fallible_iterator::{DoubleEndedFallibleIterator, FallibleIterator};
use crate::try_trait_v2::Try;
use crate::{DoubleEndedFallibleLender, FallibleLend, FallibleLender, FallibleLending};
#[inline]
pub fn from_iter_ref<I: FallibleIterator>(iter: I) -> FromIterRef<I> {
FromIterRef {
iter,
current: None,
}
}
#[derive(Clone, Debug)]
#[must_use = "lenders are lazy and do nothing unless consumed"]
pub struct FromIterRef<I: FallibleIterator> {
iter: I,
current: Option<I::Item>,
}
impl<'lend, I: FallibleIterator> FallibleLending<'lend> for FromIterRef<I> {
type Lend = &'lend I::Item;
}
impl<I: FallibleIterator> FallibleLender for FromIterRef<I> {
type Error = I::Error;
crate::check_covariance_fallible!();
#[inline]
fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.current = self.iter.next()?;
Ok(self.current.as_ref())
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
#[inline]
fn nth(&mut self, n: usize) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.current = self.iter.nth(n)?;
Ok(self.current.as_ref())
}
#[inline(always)]
fn count(self) -> Result<usize, Self::Error>
where
Self: Sized,
{
self.iter.count()
}
#[inline]
fn last<'call>(&'call mut self) -> Result<Option<FallibleLend<'call, Self>>, Self::Error>
where
Self: Sized,
{
self.current = None;
while let Some(item) = self.iter.next()? {
self.current = Some(item);
}
Ok(self.current.as_ref())
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<Result<(), NonZeroUsize>, Self::Error> {
for i in 0..n {
if self.iter.next()?.is_none() {
return Ok(Err(unsafe { NonZeroUsize::new_unchecked(n - i) }));
}
}
Ok(Ok(()))
}
#[inline]
fn try_fold<B, F, R>(&mut self, mut init: B, mut f: F) -> Result<R, Self::Error>
where
F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
R: Try<Output = B>,
{
while let Some(item) = self.iter.next()? {
match f(init, &item)?.branch() {
ControlFlow::Break(residual) => return Ok(R::from_residual(residual)),
ControlFlow::Continue(output) => init = output,
}
}
Ok(R::from_output(init))
}
#[inline]
fn fold<B, F>(self, init: B, mut f: F) -> Result<B, Self::Error>
where
Self: Sized,
F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
{
self.iter.fold(init, |acc, item| f(acc, &item))
}
}
impl<I: DoubleEndedFallibleIterator> DoubleEndedFallibleLender for FromIterRef<I> {
#[inline]
fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.current = self.iter.next_back()?;
Ok(self.current.as_ref())
}
#[inline]
fn advance_back_by(&mut self, n: usize) -> Result<Result<(), NonZeroUsize>, Self::Error> {
for i in 0..n {
if self.iter.next_back()?.is_none() {
return Ok(Err(unsafe { NonZeroUsize::new_unchecked(n - i) }));
}
}
Ok(Ok(()))
}
#[inline]
fn try_rfold<B, F, R>(&mut self, mut init: B, mut f: F) -> Result<R, Self::Error>
where
F: FnMut(B, FallibleLend<'_, Self>) -> Result<R, Self::Error>,
R: Try<Output = B>,
{
while let Some(item) = self.iter.next_back()? {
match f(init, &item)?.branch() {
ControlFlow::Break(residual) => return Ok(R::from_residual(residual)),
ControlFlow::Continue(output) => init = output,
}
}
Ok(R::from_output(init))
}
#[inline]
fn rfold<B, F>(self, init: B, mut f: F) -> Result<B, Self::Error>
where
Self: Sized,
F: FnMut(B, FallibleLend<'_, Self>) -> Result<B, Self::Error>,
{
self.iter.rfold(init, |acc, item| f(acc, &item))
}
}
impl<I: FallibleIterator> From<I> for FromIterRef<I> {
#[inline(always)]
fn from(iter: I) -> Self {
from_iter_ref(iter)
}
}