async_ecs/resource/
entry.rs

1use std::marker::PhantomData;
2
3use hashbrown::hash_map::{DefaultHashBuilder, Entry as HbEntry};
4
5use super::{cell::Cell, RefMut, Resource, ResourceId};
6
7pub struct Entry<'a, T: 'a> {
8    inner: Inner<'a>,
9    marker: PhantomData<T>,
10}
11
12pub type Inner<'a> = HbEntry<'a, ResourceId, Cell<Box<dyn Resource>>, DefaultHashBuilder>;
13
14/// An entry to a resource container.
15/// This is similar to the Entry API found in the standard library.
16///
17/// ## Examples
18///
19/// ```
20/// use async_ecs::World;
21///
22/// #[derive(Debug)]
23/// struct Res(i32);
24///
25/// let mut world = World::default();
26///
27/// let value = world.entry().or_insert(Res(4));
28/// println!("{:?}", value.0 * 2);
29/// ```
30impl<'a, T> Entry<'a, T>
31where
32    T: Resource + 'a,
33{
34    /// Create new entry.
35    pub fn new(inner: Inner<'a>) -> Self {
36        Self {
37            inner,
38            marker: PhantomData,
39        }
40    }
41
42    /// Returns this entry's value, inserts and returns `v` otherwise.
43    ///
44    /// Please note that you should use `or_insert_with` in case the creation of
45    /// the value is expensive.
46    pub fn or_insert(self, v: T) -> RefMut<'a, T> {
47        self.or_insert_with(move || v)
48    }
49
50    /// Returns this entry's value, inserts and returns the return value of `f`
51    /// otherwise.
52    pub fn or_insert_with<F>(self, f: F) -> RefMut<'a, T>
53    where
54        F: FnOnce() -> T,
55    {
56        let inner = self.inner.or_insert_with(move || Cell::new(Box::new(f())));
57        let inner = inner.borrow_mut().map(Box::as_mut);
58
59        RefMut::new(inner)
60    }
61}