use core::marker::PhantomData;
use core::ops::Deref;
use core::ops::DerefMut;
#[repr(transparent)]
pub struct BOption<'id, T>(Option<T>, PhantomData<fn(&'id ())->&'id ()>);
impl<T: Copy> Copy for BOption<'static, T> {}
impl<T: Clone> Clone for BOption<'static, T> {
fn clone(&self) -> Self {
let Self(option, id) = self;
Self(option.clone(), *id)
}
}
pub trait Wrapper {
type Kind<'a>;
}
pub struct Factory<'id> {
count: usize,
id: PhantomData<fn(&'id ())->&'id ()>,
}
impl<'id> Factory<'id> {
pub fn new_none<T>(&mut self) -> BOption<'id, T> {
self.count += 1;
BOption(None, self.id)
}
pub fn init<'a, T>(
&mut self,
boption: &'a mut BOption<'id, T>,
value: T,
) -> &'a mut T {
let was_none = boption.0.is_none();
let value = boption.0.insert(value);
if was_none {
self.count -= 1;
}
value
}
}
impl BOption<'static, ()> {
pub fn factory<T, F>(f: F) -> T::Kind<'static>
where
T: Wrapper,
F: for<'id> FnOnce(&mut Factory<'id>) -> T::Kind<'id>,
{
let mut factory = Factory {
count: 0,
id: PhantomData, };
let res = f(&mut factory);
assert_eq!(factory.count, 0);
res
}
}
impl<T> BOption<'static, T> {
pub fn new_init(t: T) -> Self {
Self(Some(t), PhantomData)
}
}
impl<T> Deref for BOption<'static, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe {
self.0.as_ref().unwrap_unchecked()
}
}
}
impl<T> DerefMut for BOption<'static, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe {
self.0.as_mut().unwrap_unchecked()
}
}
}