deft 0.15.0

Cross platform ui framework
use std::cell::Cell;
use std::error::Error;
use std::fmt::{Display, Formatter};
use std::ops::{Deref, DerefMut};
use std::panic::RefUnwindSafe;
use std::ptr::null_mut;

#[derive(Debug)]
pub struct UpgradeError {}

impl Display for UpgradeError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("failed to upgrade")
    }
}

impl Error for UpgradeError {}

struct MrcBox<T> {
    strong: Cell<usize>,
    weak: Cell<usize>,
    value: Option<T>,
}

impl<T> MrcBox<T> {
    pub fn dec_weak(&mut self) {
        self.weak.set(self.weak.get() - 1);
    }
    pub fn inc_weak(&mut self) {
        self.weak.set(self.strong.get() + 1);
    }

    pub fn inc_strong(&mut self) {
        self.strong.set(self.strong.get() + 1);
    }

    pub fn dec_strong(&mut self) {
        self.strong.set(self.strong.get() - 1);
    }
}

/// A single-threaded mutable reference-counting pointer.
pub struct Mrc<T> {
    ptr: *mut MrcBox<T>,
}

impl<T> PartialEq for Mrc<T> {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

/// MrcWeak is a version of Mrc that holds a non-owning reference to the managed allocation. The allocation is accessed by calling upgrade on the MrcWeak pointer, which returns an Option<Mrc<T>>.
pub struct MrcWeak<T> {
    ptr: *mut MrcBox<T>,
}

impl<T> PartialEq for MrcWeak<T> {
    fn eq(&self, other: &Self) -> bool {
        self.ptr == other.ptr
    }
}

//TODO should impl it?
impl<T> RefUnwindSafe for Mrc<T> {}

impl<T> Mrc<T> {
    pub fn new(value: T) -> Self {
        let ptr = Box::into_raw(Box::new(MrcBox {
            strong: Cell::new(1),
            // An implicit weak pointer owned by all the strong
            weak: Cell::new(1),
            value: Some(value),
        }));
        Mrc { ptr }
    }

    pub fn as_weak(&self) -> MrcWeak<T> {
        let weak = self.inner().weak.get();
        self.inner().weak.set(weak + 1);
        MrcWeak { ptr: self.ptr }
    }

    fn inner(&self) -> &mut MrcBox<T> {
        unsafe { &mut (*self.ptr) }
    }
}

impl<T> Deref for Mrc<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        unsafe { (*self.ptr).value.as_ref().unwrap() }
    }
}

impl<T> DerefMut for Mrc<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { (*self.ptr).value.as_mut().unwrap() }
    }
}

impl<T> Clone for Mrc<T> {
    fn clone(&self) -> Self {
        unsafe {
            let strong = &(*self.ptr).strong;
            strong.set(strong.get() + 1);
            Self { ptr: self.ptr }
        }
    }
}

impl<T> Drop for MrcWeak<T> {
    fn drop(&mut self) {
        if self.ptr.is_null() {
            return;
        }
        self.inner().dec_weak();

        if self.inner().weak.get() == 0 {
            unsafe {
                let _ = Box::from_raw(self.ptr);
            }
        }
    }
}

impl<T> MrcWeak<T> {
    pub fn new() -> Self {
        Self { ptr: null_mut() }
    }

    pub fn upgrade(&self) -> Result<Mrc<T>, UpgradeError> {
        if self.ptr.is_null() {
            return Err(UpgradeError {});
        }
        let strong = self.inner().strong.get();
        if strong == 0 {
            return Err(UpgradeError {});
        }
        self.inner().strong.set(strong + 1);
        Ok(Mrc { ptr: self.ptr })
    }

    fn inner(&self) -> &mut MrcBox<T> {
        unsafe { &mut (*self.ptr) }
    }
}

impl<T> Clone for MrcWeak<T> {
    fn clone(&self) -> Self {
        if !self.ptr.is_null() {
            let weak = self.inner().weak.get();
            self.inner().weak.set(weak + 1);
        }
        Self { ptr: self.ptr }
    }
}

impl<T> Drop for Mrc<T> {
    fn drop(&mut self) {
        let inner = self.inner();
        let strong = inner.strong.get() - 1;
        inner.strong.set(strong);
        if strong == 0 {
            unsafe {
                (*self.ptr).value.take();
                self.inner().dec_weak();

                if self.inner().weak.get() == 0 {
                    let _ = Box::from_raw(self.ptr);
                }
            }
        }
    }
}