resman/
ref_mut.rs

1use std::{
2    cmp::PartialEq,
3    fmt,
4    marker::PhantomData,
5    ops::{Deref, DerefMut},
6};
7
8pub use crate::Resource;
9
10/// Mutable reference to a resource.
11pub struct RefMut<'a, R: 'a> {
12    inner: rt_map::RefMut<'a, Box<dyn Resource>>,
13    phantom: PhantomData<&'a R>,
14}
15
16impl<'a, R> fmt::Debug for RefMut<'a, R>
17where
18    R: Resource + fmt::Debug + 'a,
19{
20    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21        let inner: &R = self;
22        f.debug_struct("RefMut").field("inner", inner).finish()
23    }
24}
25
26impl<'a, R> PartialEq for RefMut<'a, R>
27where
28    R: Resource + PartialEq + 'a,
29{
30    fn eq(&self, other: &Self) -> bool {
31        let r_self: &R = self;
32        let r_other: &R = other;
33        r_self == r_other
34    }
35}
36
37impl<'a, R> RefMut<'a, R> {
38    pub fn new(inner: rt_map::RefMut<'a, Box<dyn Resource>>) -> Self {
39        Self {
40            inner,
41            phantom: PhantomData,
42        }
43    }
44}
45
46impl<R> Deref for RefMut<'_, R>
47where
48    R: Resource,
49{
50    type Target = R;
51
52    fn deref(&self) -> &R {
53        self.inner
54            .downcast_ref::<R>()
55            .unwrap_or_else(|| panic!("Failed to downcast to {}", std::any::type_name::<R>()))
56    }
57}
58
59impl<R> DerefMut for RefMut<'_, R>
60where
61    R: Resource,
62{
63    fn deref_mut(&mut self) -> &mut R {
64        self.inner
65            .downcast_mut::<R>()
66            .unwrap_or_else(|| panic!("Failed to downcast to {}", std::any::type_name::<R>()))
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use std::fmt::{self, Write};
73
74    use rt_map::Cell;
75
76    use crate::Resource;
77
78    use super::RefMut;
79
80    #[test]
81    fn debug_includes_inner_field() -> fmt::Result {
82        let value: Box<dyn Resource> = Box::new(A(1));
83        let cell = Cell::new(value);
84        let ref_mut = RefMut::<A>::new(rt_map::RefMut::new(cell.borrow_mut()));
85
86        let mut debug_string = String::with_capacity(64);
87        write!(&mut debug_string, "{:?}", ref_mut)?;
88        assert_eq!("RefMut { inner: A(1) }", debug_string.as_str());
89
90        Ok(())
91    }
92
93    #[test]
94    fn partial_eq_compares_value() -> fmt::Result {
95        let value_0: Box<dyn Resource> = Box::new(A(1));
96        let value_1: Box<dyn Resource> = Box::new(A(1));
97        let cell_0 = Cell::new(value_0);
98        let ref_mut_0 = RefMut::<A>::new(rt_map::RefMut::new(cell_0.borrow_mut()));
99        let cell_1 = Cell::new(value_1);
100        let ref_mut_1 = RefMut::<A>::new(rt_map::RefMut::new(cell_1.borrow_mut()));
101
102        assert_eq!(ref_mut_1, ref_mut_0);
103
104        Ok(())
105    }
106
107    #[test]
108    fn deref_mut_returns_value() -> fmt::Result {
109        let value: Box<dyn Resource> = Box::new(A(1));
110        let cell = Cell::new(value);
111        let mut ref_mut = RefMut::<A>::new(rt_map::RefMut::new(cell.borrow_mut()));
112
113        assert_eq!(&mut A(1), &*ref_mut);
114
115        ref_mut.0 = 2;
116
117        assert_eq!(&mut A(2), &*ref_mut);
118
119        Ok(())
120    }
121
122    #[derive(Debug, Clone, PartialEq)]
123    struct A(usize);
124}