2024-04-27 04:21:26 +00:00
|
|
|
use std::{any::{Any, TypeId}, sync::Arc};
|
2024-03-31 02:12:00 +00:00
|
|
|
|
|
|
|
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
2023-11-29 04:25:47 +00:00
|
|
|
|
|
|
|
/// Shorthand for `Send + Sync + 'static`, so it never needs to be implemented manually.
|
2024-03-31 02:12:00 +00:00
|
|
|
pub trait ResourceObject: Send + Sync + Any {
|
|
|
|
fn as_any(&self) -> &dyn Any;
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn Any;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Send + Sync + Any> ResourceObject for T {
|
|
|
|
fn as_any(&self) -> &dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
fn as_any_mut(&mut self) -> &mut dyn Any {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
2023-11-29 04:25:47 +00:00
|
|
|
|
|
|
|
/// A type erased storage for a Resource.
|
2024-04-27 04:21:26 +00:00
|
|
|
#[derive(Clone)]
|
2023-11-29 04:25:47 +00:00
|
|
|
pub struct ResourceData {
|
2024-04-27 04:21:26 +00:00
|
|
|
pub(crate) data: Arc<AtomicRefCell<dyn ResourceObject>>,
|
2023-11-29 04:25:47 +00:00
|
|
|
type_id: TypeId,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ResourceData {
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn new<T: ResourceObject>(data: T) -> Self {
|
2023-11-29 04:25:47 +00:00
|
|
|
|
|
|
|
Self {
|
2024-04-27 04:21:26 +00:00
|
|
|
data: Arc::new(AtomicRefCell::new(data)),
|
2023-11-29 04:25:47 +00:00
|
|
|
type_id: TypeId::of::<T>(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-16 15:09:16 +00:00
|
|
|
/// Returns a boolean indicating whether or not `T`` is of the same type of the Resource
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn is<T: ResourceObject>(&self) -> bool {
|
2023-11-29 04:25:47 +00:00
|
|
|
self.type_id == TypeId::of::<T>()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Borrow the data inside of the resource.
|
|
|
|
///
|
2023-12-16 15:09:16 +00:00
|
|
|
/// # Panics
|
2023-11-29 04:25:47 +00:00
|
|
|
///
|
2023-12-16 15:09:16 +00:00
|
|
|
/// * If the data is already borrowed mutably, this will panic.
|
|
|
|
/// * If the type of `T` is not the same as the resource type.
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn get<T: ResourceObject>(&self) -> AtomicRef<T> {
|
|
|
|
AtomicRef::map(self.data.borrow(), |a| a.as_any().downcast_ref().unwrap())
|
2023-11-29 04:25:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Mutably borrow the data inside of the resource.
|
|
|
|
///
|
2023-11-30 04:21:27 +00:00
|
|
|
/// # Panics
|
2023-11-29 04:25:47 +00:00
|
|
|
///
|
2023-11-30 04:21:27 +00:00
|
|
|
/// * If the data is already borrowed mutably, this will panic.
|
2023-12-16 15:09:16 +00:00
|
|
|
/// * If the type of `T` is not the same as the resource type.
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn get_mut<T: ResourceObject>(&self) -> AtomicRefMut<T> {
|
|
|
|
AtomicRefMut::map(self.data.borrow_mut(), |a| a.as_any_mut().downcast_mut().unwrap())
|
2023-11-29 04:25:47 +00:00
|
|
|
}
|
2023-11-30 04:21:27 +00:00
|
|
|
|
|
|
|
/// Borrow the data inside of the resource.
|
|
|
|
///
|
2023-12-16 15:09:16 +00:00
|
|
|
/// # Panics
|
2023-11-30 04:21:27 +00:00
|
|
|
///
|
2023-12-16 15:09:16 +00:00
|
|
|
/// * If the type of `T` is not the same as the resource type.
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn try_get<T: ResourceObject>(&self) -> Option<AtomicRef<T>> {
|
2023-11-30 04:21:27 +00:00
|
|
|
self.data.try_borrow()
|
2024-03-31 02:12:00 +00:00
|
|
|
.map(|r| AtomicRef::map(r, |a| a.as_any().downcast_ref().unwrap()))
|
2023-11-30 04:21:27 +00:00
|
|
|
.ok()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Mutably borrow the data inside of the resource.
|
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
2023-12-16 15:09:16 +00:00
|
|
|
/// * If the type of `T` is not the same as the resource type.
|
2024-03-31 02:12:00 +00:00
|
|
|
pub fn try_get_mut<T: ResourceObject>(&self) -> Option<AtomicRefMut<T>> {
|
2023-11-30 04:21:27 +00:00
|
|
|
self.data.try_borrow_mut()
|
2024-03-31 02:12:00 +00:00
|
|
|
.map(|r| AtomicRefMut::map(r, |a| a.as_any_mut().downcast_mut().unwrap()))
|
2023-11-30 04:21:27 +00:00
|
|
|
.ok()
|
|
|
|
}
|
2023-11-29 04:25:47 +00:00
|
|
|
}
|