pr47 0.0.3

A semi-experimental programming language. Still working in progress.
Documentation
use std::fmt::{Formatter, Debug, Display};

#[cfg(debug_assertions)]
use std::{
    sync::atomic::{
        AtomicBool,
        Ordering::Relaxed
    },
    rc::Rc,
    cell::{
        RefCell,
        Ref,
        RefMut
    }
};

#[cfg(debug_assertions)]
pub struct Repo<T> {
    dropped: Rc<AtomicBool>,
    data: Vec<*mut RefCell<T>>
}

#[cfg(debug_assertions)]
pub struct Ptr<T> {
    dropped: Rc<AtomicBool>,
    data: *mut RefCell<T>
}

#[cfg(debug_assertions)]
impl<'a, T> Ptr<T> {
    fn new(dropped: Rc<AtomicBool>, data: *mut RefCell<T>) -> Self {
        Self { dropped, data }
    }

    fn check_dropped(&self) {
        if self.dropped.load(Relaxed) {
            panic!("the belonging repository has been dropped!")
        }
    }

    pub fn get(&'a self) -> Ref<'a, T> {
        self.check_dropped();
        unsafe {
            (*self.data).borrow()
        }
    }

    pub fn get_mut(&'a self) -> RefMut<'a, T> {
        self.check_dropped();
        unsafe {
            (*self.data).borrow_mut()
        }
    }
}

#[cfg(debug_assertions)]
impl<T> Repo<T> {
    pub fn new() -> Self {
        Self {
            dropped: Rc::new(AtomicBool::new(false)),
            data: Vec::new()
        }
    }

    pub fn add(&mut self, t: T) -> Ptr<T> {
        let ptr = Box::into_raw(Box::new(RefCell::new(t)));
        self.data.push(ptr);
        Ptr::new(self.dropped.clone(), ptr)
    }
}

#[cfg(debug_assertions)]
impl<T> Drop for Repo<T> {
    fn drop(&mut self) {
        self.dropped.store(true, Relaxed);
        for data in self.data.iter() {
            unsafe {
                let _dropped = Box::from_raw(*data);
            }
        }
    }
}

#[cfg(not(debug_assertions))]
use unchecked_unwrap::UncheckedUnwrap;

#[cfg(not(debug_assertions))]
pub struct Repo<T> {
    data: Vec<*mut T>
}

#[cfg(not(debug_assertions))]
pub struct Ptr<T> {
    data: *mut T
}

#[cfg(not(debug_assertions))]
impl<T> Ptr<T> {
    fn new(data: *mut T) -> Self {
        Self { data }
    }

    pub fn get(&self) -> &T {
        unsafe {
            self.data.as_ref().unchecked_unwrap()
        }
    }

    pub fn get_mut(&self) -> &mut T {
        unsafe {
            self.data.as_mut().unchecked_unwrap()
        }
    }
}

#[cfg(not(debug_assertions))]
impl<T> Repo<T> {
    pub fn new() -> Self {
        Self { data: Vec::new() }
    }

    pub fn add(&mut self, t: T) -> Ptr<T> {
        let ptr = Box::into_raw(Box::new(t));
        self.data.push(ptr);
        Ptr::new(ptr)
    }
}

#[cfg(not(debug_assertions))]
impl<T> Drop for Repo<T> {
    fn drop(&mut self) {
        for ptr in self.data.iter() {
            unsafe {
                let _dropped = Box::from_raw(*ptr);
            }
        }
    }
}

impl<T> Debug for Ptr<T> where T: Debug {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", *self.get())
    }
}

impl<T> Display for Ptr<T> where T: Display {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", *self.get())
    }
}