use std::{any::{TypeId, Any}, alloc::Layout, cell::{RefCell, Ref, RefMut}, ptr::NonNull, alloc}; /// Shorthand for `Send + Sync + 'static`, so it never needs to be implemented manually. pub trait ResourceObject: Send + Sync + 'static {} impl ResourceObject for T {} /// A type erased storage for a Resource. pub struct ResourceData { data: Box>, type_id: TypeId, } impl ResourceData { pub fn new(data: T) -> Self { Self { data: Box::new(RefCell::new(data)), type_id: TypeId::of::(), } } /// Returns a boolean indicating whether or not `T`` is of the same type of the Resource pub fn is(&self) -> bool { self.type_id == TypeId::of::() } /// Borrow the data inside of the resource. /// /// # Panics /// /// * If the data is already borrowed mutably, this will panic. /// * If the type of `T` is not the same as the resource type. pub fn get<'a, T: 'static>(&'a self) -> Ref<'a, T> { Ref::map(self.data.borrow(), |a| a.downcast_ref().unwrap()) } /// Mutably borrow the data inside of the resource. /// /// # Panics /// /// * If the data is already borrowed mutably, this will panic. /// * If the type of `T` is not the same as the resource type. pub fn get_mut<'a, T: 'static>(&'a self) -> RefMut<'a, T> { RefMut::map(self.data.borrow_mut(), |a| a.downcast_mut().unwrap()) } /// Borrow the data inside of the resource. /// /// # Panics /// /// * If the type of `T` is not the same as the resource type. pub fn try_get<'a, T: 'static>(&'a self) -> Option> { self.data.try_borrow() .map(|r| Ref::map(r, |a| a.downcast_ref().unwrap())) .ok() } /// Mutably borrow the data inside of the resource. /// /// # Panics /// /// * If the type of `T` is not the same as the resource type. pub fn try_get_mut<'a, T: 'static>(&'a self) -> Option> { self.data.try_borrow_mut() .map(|r| RefMut::map(r, |a| a.downcast_mut().unwrap())) .ok() } }