use std::cell::UnsafeCell;
use std::ptr::NonNull;
struct Inner<T> {
value: UnsafeCell<T>,
count: usize,
}
pub struct BiRc<T> {
inner: NonNull<Inner<T>>,
}
impl<T> BiRc<T> {
pub(crate) fn new(value: T) -> (Self, Self) {
let inner = NonNull::from(Box::leak(Box::new(Inner {
value: UnsafeCell::new(value),
count: 2,
})));
(Self { inner }, Self { inner })
}
pub unsafe fn get_mut_unchecked(&self) -> (&mut T, bool) {
let inner = unsafe { &mut (*self.inner.as_ptr()) };
(inner.value.get_mut(), inner.count == 2)
}
}
impl<T> Drop for BiRc<T> {
fn drop(&mut self) {
unsafe {
let inner = self.inner.as_ptr();
let count = (*inner).count.wrapping_sub(1);
(*inner).count = count;
if count == 0 {
let _ = Box::from_raw(inner);
}
}
}
}