ferrin_spec/dynamic/
model_ref.rs1use std::sync::Arc;
4
5pub struct ModelRef<D: ?Sized>(Inner<D>);
13
14enum Inner<D: ?Sized> {
15 Model(Arc<D>),
16 Id(String),
17}
18
19impl<D: ?Sized> ModelRef<D> {
20 #[must_use]
22 pub fn from_arc(model: Arc<D>) -> Self {
23 Self(Inner::Model(model))
24 }
25
26 #[must_use]
28 pub fn from_id(id: impl Into<String>) -> Self {
29 Self(Inner::Id(id.into()))
30 }
31
32 #[must_use]
34 pub fn model(&self) -> Option<&Arc<D>> {
35 match &self.0 {
36 Inner::Model(model) => Some(model),
37 Inner::Id(_) => None,
38 }
39 }
40
41 #[must_use]
43 pub fn unresolved_id(&self) -> Option<&str> {
44 match &self.0 {
45 Inner::Model(_) => None,
46 Inner::Id(id) => Some(id),
47 }
48 }
49
50 #[must_use]
52 pub fn is_resolved(&self) -> bool {
53 matches!(self.0, Inner::Model(_))
54 }
55
56 pub fn into_model(self) -> Result<Arc<D>, String> {
62 match self.0 {
63 Inner::Model(model) => Ok(model),
64 Inner::Id(id) => Err(id),
65 }
66 }
67}
68
69impl<D: ?Sized> Clone for ModelRef<D> {
70 fn clone(&self) -> Self {
71 Self(match &self.0 {
72 Inner::Model(model) => Inner::Model(Arc::clone(model)),
73 Inner::Id(id) => Inner::Id(id.clone()),
74 })
75 }
76}
77
78impl<D: ?Sized> std::fmt::Debug for ModelRef<D> {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match &self.0 {
81 Inner::Model(_) => f.write_str("ModelRef::Model(..)"),
82 Inner::Id(id) => f.debug_tuple("ModelRef::Id").field(id).finish(),
83 }
84 }
85}
86
87impl<D: ?Sized> From<Arc<D>> for ModelRef<D> {
88 fn from(model: Arc<D>) -> Self {
89 Self::from_arc(model)
90 }
91}
92
93impl<D: ?Sized> From<String> for ModelRef<D> {
94 fn from(id: String) -> Self {
95 Self::from_id(id)
96 }
97}
98
99impl<D: ?Sized> From<&str> for ModelRef<D> {
100 fn from(id: &str) -> Self {
101 Self::from_id(id)
102 }
103}
104
105pub struct ServiceRef<D: ?Sized>(Arc<D>);
108
109impl<D: ?Sized> ServiceRef<D> {
110 #[must_use]
112 pub fn from_arc(service: Arc<D>) -> Self {
113 Self(service)
114 }
115
116 #[must_use]
118 pub fn inner(&self) -> &Arc<D> {
119 &self.0
120 }
121
122 #[must_use]
124 pub fn into_inner(self) -> Arc<D> {
125 self.0
126 }
127}
128
129impl<D: ?Sized> Clone for ServiceRef<D> {
130 fn clone(&self) -> Self {
131 Self(Arc::clone(&self.0))
132 }
133}
134
135impl<D: ?Sized> std::fmt::Debug for ServiceRef<D> {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 f.write_str("ServiceRef(..)")
138 }
139}
140
141impl<D: ?Sized> std::ops::Deref for ServiceRef<D> {
142 type Target = D;
143
144 fn deref(&self) -> &D {
145 &self.0
146 }
147}
148
149impl<D: ?Sized> From<Arc<D>> for ServiceRef<D> {
150 fn from(service: Arc<D>) -> Self {
151 Self::from_arc(service)
152 }
153}
154
155macro_rules! ref_conversions {
157 ($alias:ident, $trait_:ident, $dyn_trait:ident) => {
158 impl<T: $trait_> From<T> for $alias {
159 fn from(model: T) -> Self {
160 Self::from_arc(::std::sync::Arc::new(model))
161 }
162 }
163
164 impl<T: $trait_> From<::std::sync::Arc<T>> for $alias {
165 fn from(model: ::std::sync::Arc<T>) -> Self {
166 Self::from_arc(model)
167 }
168 }
169 };
170}
171
172pub(crate) use ref_conversions;