use core::convert::Infallible;
use crate::{
init::{
Init, InitError, InitPin, InitPinError, InitPinResult, InitResult, Initializer, IntoInitPin,
},
pin::DropSlot,
uninit::Uninit,
};
#[derive(Debug, PartialEq)]
pub struct Value<T>(T);
impl<T> Initializer for Value<T> {
type Error = Infallible;
}
impl<T> InitPin<T> for Value<T> {
#[inline]
fn init_pin<'a, 'b>(
self,
mut place: Uninit<'a, T>,
slot: DropSlot<'a, 'b, T>,
) -> InitPinResult<'a, 'b, T, Infallible> {
(*place).write(self.0);
Ok(unsafe { place.assume_init_pin(slot) })
}
}
impl<T> Init<T> for Value<T> {
#[inline]
fn init(self, mut place: Uninit<'_, T>) -> InitResult<'_, T, Infallible> {
(*place).write(self.0);
Ok(unsafe { place.assume_init() })
}
}
#[inline]
pub const fn value<T>(value: T) -> Value<T> {
Value(value)
}
impl<T: Clone> IntoInitPin<T, Value<T>> for T {
type Init = Value<T>;
type Error = Infallible;
#[inline]
fn into_init(self) -> Self::Init {
Value(self)
}
}
#[derive(Debug, PartialEq)]
pub struct TryWith<F>(F);
impl<T, E, F> Initializer for TryWith<F>
where
F: FnOnce() -> Result<T, E>,
{
type Error = E;
}
impl<T, E, F> InitPin<T> for TryWith<F>
where
F: FnOnce() -> Result<T, E>,
{
#[inline]
fn init_pin<'a, 'b>(
self,
mut place: Uninit<'a, T>,
slot: DropSlot<'a, 'b, T>,
) -> InitPinResult<'a, 'b, T, E> {
match (self.0)() {
Ok(value) => {
(*place).write(value);
Ok(unsafe { place.assume_init_pin(slot) })
}
Err(e) => Err(InitPinError { error: e, place, slot }),
}
}
}
impl<T, F, E> Init<T> for TryWith<F>
where
F: FnOnce() -> Result<T, E>,
{
#[inline]
fn init(self, mut place: Uninit<'_, T>) -> InitResult<'_, T, E> {
match (self.0)() {
Ok(value) => {
(*place).write(value);
Ok(unsafe { place.assume_init() })
}
Err(e) => Err(InitError { error: e, place }),
}
}
}
#[inline]
pub const fn try_with<T, F, E>(f: F) -> TryWith<F>
where
F: FnOnce() -> Result<T, E>,
{
TryWith(f)
}
impl<T, E, F> IntoInitPin<T, TryWith<F>> for F
where
F: FnOnce() -> Result<T, E>,
{
type Init = TryWith<F>;
type Error = E;
#[inline]
fn into_init(self) -> Self::Init {
TryWith(self)
}
}
#[derive(Debug, PartialEq)]
pub struct With<F>(F);
impl<F> Initializer for With<F> {
type Error = Infallible;
}
impl<T, F> InitPin<T> for With<F>
where
F: FnOnce() -> T,
{
#[inline]
fn init_pin<'a, 'b>(
self,
mut place: Uninit<'a, T>,
slot: DropSlot<'a, 'b, T>,
) -> InitPinResult<'a, 'b, T, Infallible> {
(*place).write((self.0)());
Ok(unsafe { place.assume_init_pin(slot) })
}
}
impl<T, F> Init<T> for With<F>
where
F: FnOnce() -> T,
{
#[inline]
fn init(self, mut place: Uninit<'_, T>) -> InitResult<'_, T, Infallible> {
(*place).write((self.0)());
Ok(unsafe { place.assume_init() })
}
}
#[inline]
pub const fn with<T, F>(f: F) -> With<F>
where
F: FnOnce() -> T,
{
With(f)
}
impl<T, F> IntoInitPin<T, With<F>> for F
where
F: FnOnce() -> T,
{
type Init = With<F>;
type Error = Infallible;
#[inline]
fn into_init(self) -> Self::Init {
With(self)
}
}