Skip to main content

fantasy_craft/core/
resource.rs

1use std::any::{Any, TypeId};
2
3use parry2d::utils::hashmap::HashMap;
4
5type AnySend = dyn Any + Send;
6
7#[derive(Default)]
8pub struct ResourceMap {
9    storage: HashMap<TypeId, Box<AnySend>>
10}
11
12impl ResourceMap {
13    pub fn new() -> Self {
14        Self {
15            ..Default::default()
16        }
17    }
18
19    /// Inserts a resource into the map.
20    /// If a resource of this type already exists, it is overwritten.
21    ///
22    /// `T` must be `Any + 'static`
23    pub fn insert<T: Any + Send + 'static>(&mut self, resource: T) {
24        let type_id = TypeId::of::<T>();
25        self.storage.insert(type_id, Box::new(resource));
26    }
27
28    /// Gets an immutable reference to a resource of type `T`.
29    /// Returns `None` if the resource does not exist.
30    pub fn get<T: Any + 'static>(&self) -> Option<&T> {
31        let type_id = TypeId::of::<T>();
32        self.storage
33            .get(&type_id)
34            .and_then(|boxed_value| boxed_value.downcast_ref::<T>())
35    }
36
37    /// Gets a mutable reference to a resource of type `T`.
38    /// Returns `None` if the resource does not exist.
39    pub fn get_mut<T: Any + Send + 'static>(&mut self) -> Option<&mut T> {
40        let type_id = TypeId::of::<T>();
41        self.storage
42            .get_mut(&type_id)
43            .and_then(|boxed_value| boxed_value.downcast_mut::<T>())
44    }
45
46    /// Removes and returns a resource of type `T`.
47    /// Returns `None` if the resource does not exist.
48    pub fn remove<T: Any + Send + 'static>(&mut self) -> Option<T> {
49        let type_id = TypeId::of::<T>();
50        self.storage
51            .remove(&type_id)
52            .and_then(|boxed_value| boxed_value.downcast::<T>().ok())
53            .map(|unboxed_value| *unboxed_value)
54    }
55}