#![no_std]
#![forbid(
clippy::pedantic,
rust_2018_idioms,
anonymous_parameters,
unused_qualifications,
missing_docs,
trivial_casts,
trivial_numeric_casts,
unstable_features,
unused_extern_crates,
unused_import_braces,
unused_results,
warnings
)]
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "alloc")]
extern crate alloc;
mod r#impl;
mod macros;
mod private;
use core::fmt::{self, Debug, Display};
use core::ops::Deref;
#[cfg(feature = "alloc")]
pub use aliasable;
#[cfg(feature = "derive")]
pub use zc_derive::Dependant;
use self::private::{Construct, TryConstruct};
pub struct Zc<O: Owner, D> {
value: D,
storage: O::Storage,
}
impl<O, D> Zc<O, D>
where
O: Owner,
D: Dependant<'static>,
{
pub fn new<C>(owner: O, constructor: C) -> Self
where
C: for<'o> Construct<'o, <O::Storage as Deref>::Target, Dependant = D>,
{
let storage = Owner::into_storage(owner);
let value = unsafe { constructor.construct(storage.deref()) };
Self { storage, value }
}
pub fn try_new<C, E>(owner: O, constructor: C) -> Result<Self, (E, O)>
where
E: 'static,
C: for<'o> TryConstruct<'o, <O::Storage as Deref>::Target, Error = E, Dependant = D>,
{
let storage = Owner::into_storage(owner);
match unsafe { constructor.try_construct(storage.deref()) } {
Ok(value) => Ok(Self { storage, value }),
Err(err) => Err((err, Owner::from_storage(storage))),
}
}
pub fn get<'a, T>(&'a self) -> &T
where
T: Dependant<'a, Static = D>,
{
let value_ptr: *const D = &self.value;
unsafe { &*value_ptr.cast::<T>() }
}
}
impl<O, D> Zc<O, D>
where
O: Owner,
{
pub fn as_owned(&self) -> &<O::Storage as Deref>::Target {
&*self.storage
}
pub fn into_owner(self) -> O {
Owner::from_storage(self.storage)
}
#[inline]
pub unsafe fn map_unchecked<F, U>(self, f: F) -> Zc<O, U>
where
F: FnOnce(D) -> U,
{
let Self { value, storage } = self;
let value = f(value);
Zc { value, storage }
}
#[inline]
pub unsafe fn try_map_unchecked<F, U, E>(self, f: F) -> Result<Zc<O, U>, E>
where
F: FnOnce(D) -> Result<U, E>,
{
let Self { value, storage } = self;
f(value).map(|value| Zc { value, storage })
}
}
impl<O, T> Zc<O, Option<T>>
where
O: Owner,
{
#[inline]
pub fn into_option(self) -> Option<Zc<O, T>> {
self.into()
}
}
impl<O, Ok, Err> Zc<O, Result<Ok, Err>>
where
O: Owner,
{
#[inline]
pub fn into_result(self) -> Result<Zc<O, Ok>, Zc<O, Err>> {
self.into()
}
}
impl<O, T> From<Zc<O, Option<T>>> for Option<Zc<O, T>>
where
O: Owner,
{
#[inline]
fn from(zc: Zc<O, Option<T>>) -> Self {
match zc.value {
None => None,
Some(value) => Some(Zc {
value,
storage: zc.storage,
}),
}
}
}
impl<O, Ok, Err> From<Zc<O, Result<Ok, Err>>> for Result<Zc<O, Ok>, Zc<O, Err>>
where
O: Owner,
{
#[inline]
fn from(zc: Zc<O, Result<Ok, Err>>) -> Self {
match zc.value {
Ok(value) => Ok(Zc {
value,
storage: zc.storage,
}),
Err(value) => Err(Zc {
value,
storage: zc.storage,
}),
}
}
}
impl<O, D> Display for Zc<O, D>
where
O: Owner,
D: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.value, f)
}
}
impl<O, D> Debug for Zc<O, D>
where
O: Owner,
O::Storage: Debug,
D: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Zc")
.field("storage", &self.storage)
.field("value", &self.value)
.finish()
}
}
pub unsafe trait Dependant<'o>: Sized + 'o {
type Static: Dependant<'static>;
}
pub trait Owner: Sized + 'static {
type Storage: Storage;
fn into_storage(self) -> Self::Storage;
fn from_storage(storage: Self::Storage) -> Self;
}
impl<T> Owner for T
where
T: Storage,
{
type Storage = T;
fn into_storage(self) -> Self::Storage {
self
}
fn from_storage(storage: Self::Storage) -> Self {
storage
}
}
pub unsafe trait Storage: Sized + Deref + 'static {}