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())
}
}