1use std::{
2 cmp::PartialEq,
3 fmt,
4 marker::PhantomData,
5 ops::{Deref, DerefMut},
6};
7
8pub use crate::Resource;
9
10pub 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}