use std::sync::Arc;
use std::fmt::{self, Debug};
use dashmap::DashMap;
use crate::resource::Resource;
pub type ResourceId = String;
#[derive(Default)]
pub struct ResourceTable {
index: DashMap<ResourceId, Arc<dyn Resource>>,
}
impl Debug for ResourceTable {
fn fmt(
&self,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
write!(f, "ResourceTable {{ len: {} }}", self.index.len())
}
}
impl ResourceTable {
pub fn len(&self) -> usize {
self.index.len()
}
pub fn is_empty(&self) -> bool {
self.index.is_empty()
}
pub fn add<T: Resource>(
&self,
rid: ResourceId,
resource: T,
) {
self.add_arc(rid, Arc::new(resource));
}
pub fn add_arc<T: Resource>(
&self,
rid: ResourceId,
resource: Arc<T>,
) {
let resource = resource as Arc<dyn Resource>;
self.add_arc_dyn(rid, resource);
}
pub fn add_arc_dyn(
&self,
rid: ResourceId,
resource: Arc<dyn Resource>,
) {
self.index.insert(rid, resource);
}
pub fn has(
&self,
rid: ResourceId,
) -> bool {
self.index.contains_key(&rid)
}
pub fn get<T: Resource>(
&self,
rid: ResourceId,
) -> Option<Arc<T>> {
self.index
.get(&rid)
.map(|rc| rc.value().clone())
.and_then(|rc| rc.downcast_arc::<T>().cloned())
}
pub fn get_any(
&self,
rid: ResourceId,
) -> Option<Arc<dyn Resource>> {
self.index.get(&rid).map(|rc| rc.value().clone())
}
pub fn take<T: Resource>(
&self,
rid: ResourceId,
) -> Option<Arc<T>> {
let (_, resource) = self.index.remove(&rid)?;
resource.downcast_arc::<T>().cloned()
}
pub fn take_any(
&self,
rid: ResourceId,
) -> Option<Arc<dyn Resource>> {
self.index.remove(&rid).map(|rc| rc.1)
}
}
#[derive(Debug, thiserror::Error)]
pub enum ResourceError {
#[error("null or invalid handle")]
Reference,
#[error("Bad resource ID")]
BadResourceId,
#[error("Resource is unavailable because it is in use by a promise")]
Unavailable,
#[error("{0}")]
Other(String),
}