1use crate::*;
2pub use bytes::Bytes;
3pub use smol_str::SmolStr;
4use std::{collections::HashMap, fmt::Debug, hash::BuildHasher};
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 HashMapInstance<'s>: Instance<'s> + 's {
216 fn get_value<'a>(&'a self, key: &str) -> Option<Value<'a, 's>>
217 where
218 's: 'a;
219
220 fn is_empty(&self) -> bool;
221
222 fn len(&self) -> usize;
223
224 fn boxed_clone(&self) -> Box<dyn HashMapInstance<'s> + 's>;
226
227 fn update<'a>(
229 &'a mut self,
230 update: &'a (dyn HashMapInstance<'s> + 's),
231 field_mask: Option<&FieldMask>,
232 replace_repeated: bool,
233 ) -> Result<(), Error>;
234
235 fn values<'a>(&'a self) -> HashMap<String, CowValue<'a, 's>>
237 where
238 's: 'a;
239
240 fn hashmap_eq(&self, inst: &(dyn HashMapInstance<'s> + 's)) -> bool;
241
242 fn contains(&self, sub_inst: &(dyn HashMapInstance<'s> + 's)) -> bool {
243 sub_inst.values().into_iter().all(|(k, v)| {
244 self.get_value(&k).map_or(false, |sv| v.as_ref().slow_eq(&sv))
245 })
246 }
247
248 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's>;
249}
250
251impl<'s> std::fmt::Debug for dyn HashMapInstance<'s> + 's {
252 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
253 let mut builder = f.debug_map();
254 for (k, v) in self.values() {
255 builder.entry(&k, &v);
256 }
257 builder.finish()
258 }
259}
260
261impl<'s> PartialEq for dyn HashMapInstance<'s> + 's {
262 fn eq(&self, other: &Self) -> bool {
263 self.hashmap_eq(other)
264 }
265}
266
267impl<'s> Clone for Box<dyn HashMapInstance<'s> + 's> {
268 fn clone(&self) -> Self {
269 self.boxed_clone()
270 }
271}
272
273pub trait OptionInstance<'s>: Instance<'s> {
275 fn value<'a>(&'a self) -> Option<Value<'a, 's>>
277 where
278 's: 'a;
279
280 fn boxed_clone(&self) -> Box<dyn OptionInstance<'s> + 's>;
282
283 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's>;
284}
285
286impl<'s> std::fmt::Debug for dyn OptionInstance<'s> + 's {
287 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
288 let mut build = f.debug_tuple(&self.name());
289 if let Some(val) = self.value() {
290 build.field(&val);
291 }
292 build.finish()
293 }
294}
295
296impl<'s, T: Typed<'s> + Clone + 's> Typed<'s> for Option<T> {
297 fn ty() -> ValueTy {
298 ValueTy::Option(Box::new(T::ty()))
299 }
300
301 fn as_value<'a>(&'a self) -> Value<'a, 's>
302 where
303 's: 'a,
304 {
305 Value::from_option(self)
306 }
307}
308
309impl<'s> PartialEq for dyn OptionInstance<'s> + 's {
310 fn eq(&self, other: &Self) -> bool {
311 self.value() == other.value()
312 }
313}
314
315impl<'s> Clone for Box<dyn OptionInstance<'s> + 's> {
316 fn clone(&self) -> Self {
317 self.boxed_clone()
318 }
319}
320
321impl<'a, T: Typed<'a> + Clone + PartialEq + 'a> Instance<'a> for Vec<T> {
322 fn name(&self) -> SmolStr {
323 format!("Vec<{:?}>", T::ty()).into()
324 }
325
326 fn as_inst(&self) -> &(dyn Instance<'a> + 'a) {
327 self
328 }
329}
330
331impl<'s, T: Typed<'s> + Clone + 's + PartialEq> VecInstance<'s> for Vec<T> {
332 fn get_value<'a>(&'a self, i: usize) -> Option<Value<'a, 's>>
333 where
334 's: 'a,
335 {
336 let val = self.get(i)?.as_value();
337 Some(val)
338 }
339
340 fn values<'a>(&'a self) -> Vec<CowValue<'a, 's>>
341 where
342 's: 'a,
343 {
344 self.iter().map(|e| CowValue::Ref(e.as_value())).collect()
345 }
346
347 fn boxed_clone(&self) -> Box<dyn VecInstance<'s> + 's> {
348 Box::new(self.clone())
349 }
350
351 fn update<'a>(
352 &'a mut self,
353 update: &'a (dyn VecInstance<'s> + 's),
354 replace_repeated: bool,
355 ) -> Result<(), Error> {
356 if let Some(vec) = Value::from_vec(update).borrow::<&Vec<T>>() {
357 if replace_repeated {
358 let vec = vec.clone();
359 let _ = std::mem::replace(self as &mut Vec<T>, vec);
360 } else {
361 self.extend_from_slice(&vec[..]);
362 }
363 }
364 Ok(())
365 }
366
367 fn is_empty(&self) -> bool {
368 Vec::is_empty(self)
369 }
370
371 fn len(&self) -> usize {
372 Vec::len(self)
373 }
374
375 fn vec_eq(&self, inst: &(dyn VecInstance<'s> + 's)) -> bool {
376 inst.as_inst().downcast_ref::<Self>() == Some(self)
377 }
378
379 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's> {
380 self
381 }
382}
383
384impl<'s, T: Typed<'s> + Clone + 's + PartialEq> Typed<'s> for Vec<T> {
385 fn ty() -> ValueTy {
386 ValueTy::Vec(Box::new(T::ty()))
387 }
388
389 fn as_value<'a>(&'a self) -> Value<'a, 's>
390 where
391 's: 'a,
392 {
393 Value::from_vec(self)
394 }
395}
396
397impl<'s, T> Instance<'s> for HashMap<String, T>
398where
399 T: Typed<'s> + Clone + 's + PartialEq,
400{
401 fn name(&self) -> SmolStr {
402 format!("HashMap<String, {:?}>", T::ty()).into()
403 }
404
405 fn as_inst(&self) -> &(dyn Instance<'s> + 's) {
406 self
407 }
408}
409
410impl<'s, T> HashMapInstance<'s> for HashMap<String, T>
411where
412 T: Typed<'s> + Clone + 's + PartialEq,
413{
414 fn get_value<'a>(&'a self, key: &str) -> Option<Value<'a, 's>>
415 where
416 's: 'a,
417 {
418 let val = self.get(key)?.as_value();
419 Some(val)
420 }
421
422 fn update<'a>(
423 &'a mut self,
424 update: &'a (dyn HashMapInstance<'s> + 's),
425 field_mask: Option<&FieldMask>,
426 replace_repeated: bool,
427 ) -> Result<(), Error> {
428 if let Some(map) = Value::from_hashmap(update).borrow::<&HashMap<String, T>>() {
429 match (replace_repeated, field_mask) {
430 (true, None) => {
431 let _ = std::mem::replace(self as &mut HashMap<String, T>, map.clone());
432 }
433 (true, Some(mask)) => {
434 let masked_keys_to_remove: Vec<String> = self
435 .keys()
436 .filter(|k| {
437 let in_mask = mask.child(&SmolStr::new(k.as_str())).is_some();
438 let in_update = map.contains_key(k.as_str());
439 in_mask && !in_update
440 })
441 .cloned()
442 .collect();
443 for key in masked_keys_to_remove {
444 self.remove(&key);
445 }
446 for (key, value) in map.iter() {
447 if mask.child(&SmolStr::new(key.as_str())).is_some() {
448 self.insert(key.clone(), value.clone());
449 }
450 }
451 }
452 (false, None) => {
453 for (key, value) in map.iter() {
454 self.insert(key.clone(), value.clone());
455 }
456 }
457 (false, Some(mask)) => {
458 for (key, value) in map.iter() {
459 if mask.child(&SmolStr::new(key.as_str())).is_some() {
460 self.insert(key.clone(), value.clone());
461 }
462 }
463 }
464 }
465 }
466 Ok(())
467 }
468
469 fn values<'a>(&'a self) -> HashMap<String, CowValue<'a, 's>>
470 where
471 's: 'a,
472 {
473 self.iter()
474 .map(|(k, v)| {
475 let key_str = k.clone();
476 let cow_val = CowValue::Ref(v.as_value());
477 (key_str, cow_val)
478 })
479 .collect()
480 }
481
482 fn boxed_clone(&self) -> Box<dyn HashMapInstance<'s> + 's> {
483 Box::new(self.clone())
484 }
485
486 fn is_empty(&self) -> bool {
487 HashMap::is_empty(self)
488 }
489
490 fn len(&self) -> usize {
491 HashMap::len(self)
492 }
493
494 fn hashmap_eq(&self, inst: &(dyn HashMapInstance<'s> + 's)) -> bool {
495 inst.as_inst().downcast_ref::<Self>() == Some(self)
496 }
497
498 fn contains(&self, sub_inst: &(dyn HashMapInstance<'s> + 's)) -> bool {
499 if let Some(other) = sub_inst.as_inst().downcast_ref::<Self>() {
500 return other.iter().all(|(k, v)| self.get(k) == Some(v));
501 }
502
503 sub_inst.values().into_iter().all(|(field, sub_inst_value)| {
504 self.get(&field)
505 .map_or(false, |self_value| sub_inst_value.as_ref().slow_eq(&self_value.as_value()))
506 })
507 }
508
509 fn into_boxed_instance(self: Box<Self>) -> Box<dyn Instance<'s> + 's> {
510 self
511 }
512}
513
514impl<'s, T> Typed<'s> for HashMap<String, T>
515where
516 T: Typed<'s> + Clone + 's + PartialEq,
517{
518 fn ty() -> ValueTy {
519 ValueTy::HashMap(Box::new(T::ty()))
520 }
521
522 fn as_value<'a>(&'a self) -> Value<'a, 's>
523 where
524 's: 'a,
525 {
526 Value::from_hashmap(self)
527 }
528}
529
530impl<'s> Instance<'s> for String {
531 fn name(&self) -> SmolStr {
532 "String".into()
533 }
534
535 fn as_inst(&self) -> &(dyn Instance<'s> + 's) {
536 self
537 }
538}
539
540impl<'s> Instance<'s> for Bytes {
541 fn name(&self) -> SmolStr {
542 "Bytes".into()
543 }
544
545 fn as_inst(&self) -> &(dyn Instance<'s> + 's) {
546 self
547 }
548}