use core::{convert::Infallible, fmt, pin::Pin};
use crate::{
owned::Own,
pin::{DropSlot, POwn},
uninit::Uninit,
};
#[diagnostic::on_unimplemented(
message = "`{Self}` is not an initializer",
label = "`{Self}` is not an initializer"
)]
pub trait Initializer: Sized {
type Error;
#[inline]
fn map_err<F, E2>(self, f: F) -> MapErr<Self, F>
where
F: FnOnce(Self::Error) -> E2,
{
map_err(self, f)
}
#[inline]
fn adapt_err<E2>(self) -> MapErr<Self, impl FnOnce(Self::Error) -> E2>
where
Self: Initializer<Error = Infallible>,
{
adapt_err(self)
}
}
#[derive(thiserror::Error)]
#[error("failed to initialize in pinned place: {error}")]
pub struct InitPinError<'a, 'b, T: ?Sized, E> {
#[source]
pub error: E,
pub place: Uninit<'a, T>,
pub slot: DropSlot<'a, 'b, T>,
}
impl<'a, 'b, T: ?Sized, E> InitPinError<'a, 'b, T, E> {
#[inline]
pub const fn new(error: E, place: Uninit<'a, T>, slot: DropSlot<'a, 'b, T>) -> Self {
InitPinError { error, place, slot }
}
#[inline]
pub fn map<F, E2>(self, f: F) -> InitPinError<'a, 'b, T, E2>
where
F: FnOnce(E) -> E2,
{
InitPinError {
error: f(self.error),
place: self.place,
slot: self.slot,
}
}
}
impl<'a, 'b, T: ?Sized, E: fmt::Debug> fmt::Debug for InitPinError<'a, 'b, T, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("error", &self.error)
.field("place", &self.place)
.field("slot", &self.slot)
.finish()
}
}
pub type InitPinResult<'a, 'b, T, E> = Result<POwn<'b, T>, InitPinError<'a, 'b, T, E>>;
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a pin-initializer for places of type `{T}`",
label = "`{Self}` is not a pin-initializer for type `{T}`"
)]
pub trait InitPin<T: ?Sized>: Initializer {
fn init_pin<'a, 'b>(
self,
place: Uninit<'a, T>,
slot: DropSlot<'a, 'b, T>,
) -> InitPinResult<'a, 'b, T, Self::Error>;
#[inline]
fn and_pin<F: FnOnce(Pin<&mut T>)>(self, f: F) -> AndPin<Self, F> {
and_pin(self, f)
}
#[inline]
fn or<M, I2>(self, other: I2) -> Or<Self, I2, M>
where
I2: IntoInitPin<T, M, Error: Into<Self::Error>>,
{
or(self, other)
}
#[inline]
fn or_else<F, I2>(self, f: F) -> OrElse<Self, F>
where
F: FnOnce(Self::Error) -> I2,
I2: InitPin<T, Error: Into<Self::Error>>,
{
or_else(self, f)
}
#[inline]
fn unwrap_or<M, I2>(self, other: I2) -> UnwrapOr<Self, I2, M>
where
I2: IntoInitPin<T, M, Error = Infallible>,
{
unwrap_or(self, other)
}
#[inline]
fn unwrap_or_else<F, I2>(self, f: F) -> UnwrapOrElse<Self, F>
where
F: FnOnce(Self::Error) -> I2,
I2: InitPin<T, Error = Infallible>,
{
unwrap_or_else(self, f)
}
}
#[derive(thiserror::Error)]
#[error("failed to initialize in place: {error}")]
pub struct InitError<'a, T: ?Sized, E> {
#[source]
pub error: E,
pub place: Uninit<'a, T>,
}
impl<'a, T: ?Sized, E> InitError<'a, T, E> {
#[inline]
pub const fn new(error: E, place: Uninit<'a, T>) -> Self {
InitError { error, place }
}
#[inline]
pub fn into_pin<'b>(self, slot: DropSlot<'a, 'b, T>) -> InitPinError<'a, 'b, T, E> {
InitPinError {
error: self.error,
place: self.place,
slot,
}
}
#[inline]
pub fn map<F, E2>(self, f: F) -> InitError<'a, T, E2>
where
F: FnOnce(E) -> E2,
{
InitError {
error: f(self.error),
place: self.place,
}
}
}
impl<'a, 'b, T: ?Sized, E> From<InitPinError<'a, 'b, T, E>> for InitError<'a, T, E> {
#[inline]
fn from(err: InitPinError<'a, 'b, T, E>) -> Self {
InitError {
error: err.error,
place: err.place,
}
}
}
impl<'a, T: ?Sized, E: fmt::Debug> fmt::Debug for InitError<'a, T, E> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("error", &self.error)
.field("place", &self.place)
.finish()
}
}
pub type InitResult<'a, T, E> = Result<Own<'a, T>, InitError<'a, T, E>>;
#[diagnostic::on_unimplemented(
message = "`{Self}` is not an initializer for places of type `{T}`",
label = "`{Self}` is not an initializer for type `{T}`"
)]
pub trait Init<T: ?Sized>: InitPin<T> {
fn init(self, place: Uninit<'_, T>) -> InitResult<'_, T, Self::Error>;
#[inline]
fn and<F: FnOnce(&mut T)>(self, f: F) -> And<Self, F> {
and(self, f)
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not a pin-initializer for places of type `{T}`",
label = "`{Self}` is not a pin-initializer for type `{T}`"
)]
pub trait IntoInitPin<T: ?Sized, Marker = ()>: Sized {
type Init: InitPin<T, Error = Self::Error>;
type Error;
fn into_init(self) -> Self::Init;
}
impl<T: ?Sized, I: InitPin<T>> IntoInitPin<T> for I {
type Init = I;
type Error = I::Error;
#[inline]
fn into_init(self) -> Self::Init {
self
}
}
#[diagnostic::on_unimplemented(
message = "`{Self}` is not an initializer for places of type `{T}`",
label = "`{Self}` is not an initializer for type `{T}`"
)]
pub trait IntoInit<T: ?Sized, Marker = ()>:
IntoInitPin<T, Marker, Init: Init<T, Error = Self::Error>>
{
}
impl<T, Marker, I> IntoInit<T, Marker> for I
where
T: ?Sized,
I: IntoInitPin<T, Marker, Init: Init<T, Error = Self::Error>>,
{
}
mod and;
pub use self::and::{And, AndPin, and, and_pin};
mod or;
pub use self::or::{
MapErr, Or, OrElse, UnwrapOr, UnwrapOrElse, adapt_err, map_err, or, or_else, unwrap_or,
unwrap_or_else,
};
mod raw;
pub use self::raw::{Raw, RawPin, TryRaw, TryRawPin, raw, raw_pin, try_raw, try_raw_pin};
mod slice;
pub use self::slice::{
Repeat, RepeatWith, Slice, SliceError, Str, repeat, repeat_with, slice, str,
};
mod value;
pub use self::value::{TryWith, Value, With, try_with, value, with};
mod imp;
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be structurally pin-initialized",
label = "`{Self}` cannot be structurally pin-initialized",
note = "`#[derive(InitPin)]` to enable structural pin-initialization for this type"
)]
pub trait StructuralInitPin<'b> {
#[doc(hidden)]
type __BuilderInitPin<'a: 'b>
where
Self: 'a;
#[doc(hidden)]
fn __builder_init_pin<'a>(
place: Uninit<'a, Self>,
slot: DropSlot<'a, 'b, Self>,
) -> Self::__BuilderInitPin<'a>
where
Self: 'a;
}
#[diagnostic::on_unimplemented(
message = "`{Self}` cannot be structurally initialized",
label = "`{Self}` cannot be structurally initialized",
note = "`#[derive(Init)]` to enable structural initialization for this type"
)]
pub trait StructuralInit<'b>: StructuralInitPin<'b> {
#[doc(hidden)]
type __BuilderInit;
#[doc(hidden)]
fn __builder_init(place: Uninit<'b, Self>) -> Self::__BuilderInit;
}
pub use placid_macro::Init;
pub use placid_macro::InitPin;
pub use placid_macro::init;
pub use placid_macro::init_pin;