use core::{fmt, marker::PhantomData};
use crate::prelude::*;
#[inline]
pub fn repeat_with<'a, L, E, F>(f: F) -> RepeatWith<'a, L, E, F>
where
L: ?Sized + CovariantFallibleLending + 'a,
F: FnMut() -> FallibleLend<'a, L>,
{
let _ = L::__check_covariance(crate::CovariantProof::new());
RepeatWith {
f,
_marker: PhantomData,
}
}
#[inline]
pub fn repeat_with_err<L, F>(f: F) -> RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
{
let _ = L::__check_covariance(crate::CovariantProof::new());
RepeatWithErr {
f,
_marker: PhantomData,
}
}
#[must_use = "lenders are lazy and do nothing unless consumed"]
pub struct RepeatWith<'a, L: ?Sized, E, F> {
f: F,
#[allow(clippy::type_complexity)]
_marker: core::marker::PhantomData<(&'a L, fn() -> E)>,
}
impl<L: ?Sized, E, F: Clone> Clone for RepeatWith<'_, L, E, F> {
#[inline]
fn clone(&self) -> Self {
Self {
f: self.f.clone(),
_marker: PhantomData,
}
}
}
impl<L: ?Sized, E, F> fmt::Debug for RepeatWith<'_, L, E, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FallibleRepeatWith").finish_non_exhaustive()
}
}
impl<'lend, 'a, L, E, F> FallibleLending<'lend> for RepeatWith<'a, L, E, F>
where
L: ?Sized + CovariantFallibleLending + 'a,
F: FnMut() -> FallibleLend<'a, L>,
{
type Lend = FallibleLend<'lend, L>;
}
impl<'a, L, E, F> FallibleLender for RepeatWith<'a, L, E, F>
where
L: ?Sized + CovariantFallibleLending + 'a,
F: FnMut() -> FallibleLend<'a, L>,
{
type Error = E;
crate::unsafe_assume_covariance_fallible!();
#[inline]
fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
Ok(Some(
unsafe { core::mem::transmute::<FallibleLend<'a, L>, FallibleLend<'_, L>>((self.f)()) },
))
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(usize::MAX, None)
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<Result<(), core::num::NonZeroUsize>, Self::Error> {
for _ in 0..n {
(self.f)();
}
Ok(Ok(()))
}
}
impl<'a, L, E, F> DoubleEndedFallibleLender for RepeatWith<'a, L, E, F>
where
L: ?Sized + CovariantFallibleLending + 'a,
F: FnMut() -> FallibleLend<'a, L>,
{
#[inline(always)]
fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.next()
}
#[inline]
fn advance_back_by(
&mut self,
n: usize,
) -> Result<Result<(), core::num::NonZeroUsize>, Self::Error> {
for _ in 0..n {
(self.f)();
}
Ok(Ok(()))
}
}
impl<'a, L, E, F> FusedFallibleLender for RepeatWith<'a, L, E, F>
where
L: ?Sized + CovariantFallibleLending + 'a,
F: FnMut() -> FallibleLend<'a, L>,
{
}
#[must_use = "lenders are lazy and do nothing unless consumed"]
pub struct RepeatWithErr<L: ?Sized, F> {
f: F,
_marker: PhantomData<fn() -> L>,
}
impl<L: ?Sized, F: Clone> Clone for RepeatWithErr<L, F> {
#[inline]
fn clone(&self) -> Self {
Self {
f: self.f.clone(),
_marker: PhantomData,
}
}
}
impl<L: ?Sized, F> fmt::Debug for RepeatWithErr<L, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FallibleRepeatWithErr")
.finish_non_exhaustive()
}
}
impl<'lend, L, E, F> FallibleLending<'lend> for RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
F: FnMut() -> E,
{
type Lend = FallibleLend<'lend, L>;
}
impl<L, E, F> FallibleLender for RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
F: FnMut() -> E,
{
type Error = E;
crate::unsafe_assume_covariance_fallible!();
#[inline]
fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
Err((self.f)())
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
#[inline]
fn advance_by(&mut self, n: usize) -> Result<Result<(), core::num::NonZeroUsize>, Self::Error> {
if n > 0 { Err((self.f)()) } else { Ok(Ok(())) }
}
}
impl<L, E, F> DoubleEndedFallibleLender for RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
F: FnMut() -> E,
{
#[inline(always)]
fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.next()
}
#[inline]
fn advance_back_by(
&mut self,
n: usize,
) -> Result<Result<(), core::num::NonZeroUsize>, Self::Error> {
if n > 0 { Err((self.f)()) } else { Ok(Ok(())) }
}
}
impl<L, E, F> FusedFallibleLender for RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
F: FnMut() -> E,
{
}
impl<L, E, F> ExactSizeFallibleLender for RepeatWithErr<L, F>
where
L: ?Sized + CovariantFallibleLending,
F: FnMut() -> E,
{
}