1use std::{fmt, marker::PhantomData, ops::Deref};
2
3use crate::Resource;
4
5#[derive(Clone)]
7pub struct Ref<'a, R: 'a> {
8 inner: rt_map::Ref<'a, Box<dyn Resource>>,
9 phantom: PhantomData<&'a R>,
10}
11
12impl<'a, R> Ref<'a, R> {
13 pub fn new(inner: rt_map::Ref<'a, Box<dyn Resource>>) -> Self {
14 Self {
15 inner,
16 phantom: PhantomData,
17 }
18 }
19}
20
21impl<R> Deref for Ref<'_, R>
22where
23 R: Resource,
24{
25 type Target = R;
26
27 fn deref(&self) -> &R {
28 (*self.inner)
29 .downcast_ref::<R>()
30 .unwrap_or_else(|| panic!("Failed to downcast to {}", std::any::type_name::<R>()))
31 }
32}
33
34impl<'a, R> fmt::Debug for Ref<'a, R>
35where
36 R: Resource + fmt::Debug + 'a,
37{
38 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
39 let inner: &R = self;
40 f.debug_struct("Ref").field("inner", inner).finish()
41 }
42}
43
44impl<'a, R> PartialEq for Ref<'a, R>
45where
46 R: Resource + PartialEq + 'a,
47{
48 fn eq(&self, other: &Self) -> bool {
49 let r_self: &R = self;
50 let r_other: &R = other;
51 r_self == r_other
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use std::fmt::{self, Write};
58
59 use rt_map::Cell;
60
61 use crate::Resource;
62
63 use super::Ref;
64
65 #[test]
66 fn debug_includes_inner_field() -> fmt::Result {
67 let value: Box<dyn Resource> = Box::new(A(1));
68 let cell = Cell::new(value);
69 let r#ref = Ref::<A>::new(rt_map::Ref::new(cell.borrow()));
70
71 let mut debug_string = String::with_capacity(64);
72 write!(&mut debug_string, "{:?}", r#ref)?;
73 assert_eq!("Ref { inner: A(1) }", debug_string.as_str());
74
75 Ok(())
76 }
77
78 #[test]
79 fn partial_eq_compares_value() -> fmt::Result {
80 let value_0: Box<dyn Resource> = Box::new(A(1));
81 let cell_0 = Cell::new(value_0);
82 let ref_0 = Ref::<A>::new(rt_map::Ref::new(cell_0.borrow()));
83
84 let value_1: Box<dyn Resource> = Box::new(A(1));
85 let cell_1 = Cell::new(value_1);
86 let ref_1 = Ref::<A>::new(rt_map::Ref::new(cell_1.borrow()));
87
88 assert_eq!(ref_1, ref_0);
89 assert_eq!(Ref::<A>::new(rt_map::Ref::new(cell_0.borrow())), ref_0);
90
91 Ok(())
92 }
93
94 #[derive(Debug, Clone, PartialEq)]
95 struct A(usize);
96}