use core::{fmt, marker::PhantomData};
use crate::{
CovariantFallibleLending, DoubleEndedFallibleLender, ExactSizeFallibleLender, FallibleLend,
FallibleLender, FallibleLending, FusedFallibleLender,
};
#[inline]
pub fn once<'a, L: ?Sized + CovariantFallibleLending, E>(
value: FallibleLend<'a, L>,
) -> Once<'a, L, E> {
let _ = L::__check_covariance(crate::CovariantProof::new());
Once {
inner: Some(value),
_marker: PhantomData,
}
}
#[inline]
pub fn once_err<L: ?Sized + CovariantFallibleLending, E>(error: E) -> OnceErr<L, E> {
let _ = L::__check_covariance(crate::CovariantProof::new());
OnceErr {
inner: Some(error),
_marker: PhantomData,
}
}
#[must_use = "lenders are lazy and do nothing unless consumed"]
pub struct Once<'a, L, E>
where
L: ?Sized + CovariantFallibleLending,
{
inner: Option<FallibleLend<'a, L>>,
_marker: PhantomData<fn() -> E>,
}
impl<'a, L, E> Clone for Once<'a, L, E>
where
L: ?Sized + CovariantFallibleLending,
FallibleLend<'a, L>: Clone,
{
#[inline]
fn clone(&self) -> Self {
Once {
inner: self.inner.clone(),
_marker: PhantomData,
}
}
}
impl<'a, L, E> fmt::Debug for Once<'a, L, E>
where
L: ?Sized + CovariantFallibleLending,
FallibleLend<'a, L>: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FallibleOnce")
.field("inner", &self.inner)
.finish()
}
}
impl<'lend, L, E> FallibleLending<'lend> for Once<'_, L, E>
where
L: ?Sized + CovariantFallibleLending,
{
type Lend = FallibleLend<'lend, L>;
}
impl<'a, L, E> FallibleLender for Once<'a, L, E>
where
E: 'a,
L: ?Sized + CovariantFallibleLending,
{
type Error = E;
crate::unsafe_assume_covariance_fallible!();
#[inline]
fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
Ok(self.inner.take().map(|value| {
unsafe { core::mem::transmute::<FallibleLend<'a, Self>, FallibleLend<'_, Self>>(value) }
}))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.inner.is_some() {
(1, Some(1))
} else {
(0, Some(0))
}
}
}
impl<'a, L, E> DoubleEndedFallibleLender for Once<'a, L, E>
where
E: 'a,
L: ?Sized + CovariantFallibleLending,
{
#[inline(always)]
fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.next()
}
}
impl<'a, L, E> ExactSizeFallibleLender for Once<'a, L, E>
where
E: 'a,
L: ?Sized + CovariantFallibleLending,
{
}
impl<'a, L, E> FusedFallibleLender for Once<'a, L, E>
where
E: 'a,
L: ?Sized + CovariantFallibleLending,
{
}
#[must_use = "lenders are lazy and do nothing unless consumed"]
pub struct OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
inner: Option<E>,
_marker: PhantomData<fn() -> L>,
}
impl<L, E: Clone> Clone for OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
#[inline]
fn clone(&self) -> Self {
OnceErr {
inner: self.inner.clone(),
_marker: PhantomData,
}
}
}
impl<L, E: fmt::Debug> fmt::Debug for OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FallibleOnceErr")
.field("inner", &self.inner)
.finish()
}
}
impl<'lend, L, E> FallibleLending<'lend> for OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
type Lend = FallibleLend<'lend, L>;
}
impl<L, E> FallibleLender for OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
type Error = E;
crate::unsafe_assume_covariance_fallible!();
#[inline]
fn next(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
match self.inner.take() {
Some(err) => Err(err),
None => Ok(None),
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}
impl<L, E> DoubleEndedFallibleLender for OnceErr<L, E>
where
L: ?Sized + CovariantFallibleLending,
{
#[inline(always)]
fn next_back(&mut self) -> Result<Option<FallibleLend<'_, Self>>, Self::Error> {
self.next()
}
}
impl<L, E> FusedFallibleLender for OnceErr<L, E> where L: ?Sized + CovariantFallibleLending {}
impl<L, E> ExactSizeFallibleLender for OnceErr<L, E> where L: ?Sized + CovariantFallibleLending {}