looking_glass/
instance.rs1use crate::*;
2pub use bytes::Bytes;
3pub use smol_str::SmolStr;
4use std::collections::HashMap;
5
6pub trait Instance<'ty>: TypedObj + Send + Sync {
8 fn name(&self) -> SmolStr;
10
11 fn as_inst(&self) -> &(dyn Instance<'ty> + 'ty);
12}
13
14impl<'ty> dyn Instance<'ty> + 'ty {
15 #[inline]
17 pub fn downcast_ref<'val, 't, T: Typed<'ty> + 'ty>(&'val self) -> Option<&'val T>
18 where
19 'ty: 'val,
20 {
21 if self.inst_ty() == T::ty() {
22 Some(unsafe { &*(self as *const dyn Instance<'ty> as *const T) })
30 } else {
31 None
32 }
33 }
34}
35
36pub trait DowncastExt<'ty> {
38 fn downcast<T: Typed<'ty> + 'ty>(self) -> Option<Box<T>>;
40}
41impl<'ty> DowncastExt<'ty> for Box<dyn Instance<'ty> + 'ty> {
42 fn downcast<T: Typed<'ty> + 'ty>(self) -> Option<Box<T>> {
43 if self.inst_ty() == T::ty() {
44 unsafe {
45 let raw: *mut (dyn Instance<'ty> + 'ty) = Box::into_raw(self);
48 Some(Box::from_raw(raw as *mut T))
49 }
50 } else {
51 None
52 }
53 }
54}
55
56pub trait StructInstance<'s>: Instance<'s> {
58 fn get_value<'a>(&'a self, field: &str) -> Option<CowValue<'a, 's>>
60 where
61 's: 'a;
62
63 fn update<'a>(
65 &'a mut self,
66 update: &'a (dyn StructInstance<'s> + 's),
67 field_mask: Option<&FieldMask>,
68 replace_repeated: bool,
69 ) -> Result<(), Error>;
70
71 fn values<'a>(&'a self) -> HashMap<SmolStr, CowValue<'a, 's>>;
73
74 fn boxed_clone(&self) -> Box<dyn StructInstance<'s> + 's>;
76
77 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's>;
79}
80
81impl<'s> std::fmt::Debug for dyn StructInstance<'s> + 's {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 let mut builder = f.debug_struct(&self.name());
84 for (name, val) in self.values() {
85 builder.field(&name, &val);
86 }
87 builder.finish()
88 }
89}
90
91impl<'s> PartialEq for dyn StructInstance<'s> + 's {
92 fn eq(&self, other: &Self) -> bool {
93 self.values() == other.values()
94 }
95}
96
97impl<'s> Clone for Box<dyn StructInstance<'s> + 's> {
98 fn clone(&self) -> Self {
99 self.boxed_clone()
100 }
101}
102
103pub trait EnumInstance<'s>: Instance<'s> {
105 fn boxed_clone(&self) -> Box<dyn EnumInstance<'s> + 's>;
107 fn field<'a>(&'a self) -> EnumField<'a, 's>
109 where
110 's: 'a;
111
112 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s>>;
113}
114
115#[derive(PartialEq, Clone, Debug)]
117pub enum EnumField<'a, 's> {
118 Unit(SmolStr),
119 Tuple {
120 name: SmolStr,
121 fields: Vec<CowValue<'a, 's>>,
122 },
123 Struct {
124 name: SmolStr,
125 fields: HashMap<SmolStr, CowValue<'a, 's>>,
126 },
127}
128
129impl<'s> PartialEq for dyn EnumInstance<'s> + 's {
130 fn eq(&self, other: &Self) -> bool {
131 self.field() == other.field()
132 }
133}
134
135impl<'s> std::fmt::Debug for dyn EnumInstance<'s> + 's {
136 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137 match self.field() {
138 EnumField::Unit(name) => f.write_str(name.as_str()),
139 EnumField::Tuple { name, fields } => {
140 let mut tuple = f.debug_tuple(name.as_str());
141 for field in fields {
142 tuple.field(&field);
143 }
144 tuple.finish()
145 }
146 EnumField::Struct { name, fields } => {
147 let mut s = f.debug_struct(&name);
148 for (name, field) in fields {
149 s.field(&name, &field);
150 }
151 s.finish()
152 }
153 }
154 }
155}
156
157impl<'s> Clone for Box<dyn EnumInstance<'s> + 's> {
158 fn clone(&self) -> Self {
159 self.boxed_clone()
160 }
161}
162
163pub trait VecInstance<'s>: Instance<'s> + 's {
165 fn get_value<'a>(&'a self, i: usize) -> Option<Value<'a, 's>>
167 where
168 's: 'a;
169
170 fn values<'a>(&'a self) -> Vec<CowValue<'a, 's>>
172 where
173 's: 'a;
174
175 fn boxed_clone(&self) -> Box<dyn VecInstance<'s> + 's>;
177
178 fn update<'a>(
180 &'a mut self,
181 update: &'a (dyn VecInstance<'s> + 's),
182 replace_repeated: bool,
183 ) -> Result<(), Error>;
184
185 fn is_empty(&self) -> bool;
187
188 fn len(&self) -> usize;
190
191 fn vec_eq(&self, inst: &(dyn VecInstance<'s> + 's)) -> bool;
192
193 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's>;
194}
195
196impl<'s> std::fmt::Debug for dyn VecInstance<'s> {
197 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198 f.debug_list().entries(self.values().iter()).finish()
199 }
200}
201
202impl<'s> PartialEq for dyn VecInstance<'s> + 's {
203 fn eq(&self, other: &Self) -> bool {
204 self.vec_eq(other)
205 }
206}
207
208impl<'s> Clone for Box<dyn VecInstance<'s> + 's> {
209 fn clone(&self) -> Self {
210 self.boxed_clone()
211 }
212}
213
214pub trait OptionInstance<'s>: Instance<'s> {
216 fn value<'a>(&'a self) -> Option<Value<'a, 's>>
218 where
219 's: 'a;
220
221 fn boxed_clone(&self) -> Box<dyn OptionInstance<'s> + 's>;
223
224 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's>;
225}
226
227impl<'s> std::fmt::Debug for dyn OptionInstance<'s> + 's {
228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229 let mut build = f.debug_tuple(&self.name());
230 if let Some(val) = self.value() {
231 build.field(&val);
232 }
233 build.finish()
234 }
235}
236
237impl<'s, T: Typed<'s> + Clone + 's> Typed<'s> for Option<T> {
238 fn ty() -> ValueTy {
239 ValueTy::Option(Box::new(T::ty()))
240 }
241
242 fn as_value<'a>(&'a self) -> Value<'a, 's>
243 where
244 's: 'a,
245 {
246 Value::from_option(self)
247 }
248}
249
250impl<'s> PartialEq for dyn OptionInstance<'s> + 's {
251 fn eq(&self, other: &Self) -> bool {
252 self.value() == other.value()
253 }
254}
255
256impl<'s> Clone for Box<dyn OptionInstance<'s> + 's> {
257 fn clone(&self) -> Self {
258 self.boxed_clone()
259 }
260}
261
262impl<'a, T: Typed<'a> + Clone + PartialEq + 'a> Instance<'a> for Vec<T> {
263 fn name(&self) -> SmolStr {
264 format!("Vec<{:?}>", T::ty()).into()
265 }
266
267 fn as_inst(&self) -> &(dyn Instance<'a> + 'a) {
268 self
269 }
270}
271
272impl<'s, T: Typed<'s> + Clone + 's + PartialEq> VecInstance<'s> for Vec<T> {
273 fn get_value<'a>(&'a self, i: usize) -> Option<Value<'a, 's>>
274 where
275 's: 'a,
276 {
277 let val = self.get(i)?.as_value();
278 Some(val)
279 }
280
281 fn values<'a>(&'a self) -> Vec<CowValue<'a, 's>>
282 where
283 's: 'a,
284 {
285 self.iter().map(|e| CowValue::Ref(e.as_value())).collect()
286 }
287
288 fn boxed_clone(&self) -> Box<dyn VecInstance<'s> + 's> {
289 Box::new(self.clone())
290 }
291
292 fn update<'a>(
293 &'a mut self,
294 update: &'a (dyn VecInstance<'s> + 's),
295 replace_repeated: bool,
296 ) -> Result<(), Error> {
297 if let Some(vec) = Value::from_vec(update).borrow::<&Vec<T>>() {
298 if replace_repeated {
299 let vec = vec.clone();
300 let _ = std::mem::replace(self as &mut Vec<T>, vec);
301 } else {
302 self.extend_from_slice(&vec[..]);
303 }
304 }
305 Ok(())
306 }
307
308 fn is_empty(&self) -> bool {
309 Vec::is_empty(self)
310 }
311
312 fn len(&self) -> usize {
313 Vec::len(self)
314 }
315
316 fn vec_eq(&self, inst: &(dyn VecInstance<'s> + 's)) -> bool {
317 inst.as_inst().downcast_ref::<Self>() == Some(self)
318 }
319
320 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's> {
321 self
322 }
323}
324
325impl<'s, T: Typed<'s> + Clone + 's + PartialEq> Typed<'s> for Vec<T> {
326 fn ty() -> ValueTy {
327 ValueTy::Vec(Box::new(T::ty()))
328 }
329
330 fn as_value<'a>(&'a self) -> Value<'a, 's>
331 where
332 's: 'a,
333 {
334 Value::from_vec(self)
335 }
336}
337
338impl<'s> Instance<'s> for String {
339 fn name(&self) -> SmolStr {
340 "String".into()
341 }
342
343 fn as_inst(&self) -> &(dyn Instance<'s> + 's) {
344 self
345 }
346}
347
348impl<'s> Instance<'s> for Bytes {
349 fn name(&self) -> SmolStr {
350 "Bytes".into()
351 }
352
353 fn as_inst(&self) -> &(dyn Instance<'s> + 's) {
354 self
355 }
356}