1use intuicio_core::{
2 registry::Registry,
3 types::{TypeHandle, TypeQuery},
4};
5use intuicio_data::{
6 managed::{
7 DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, ManagedLazy, ManagedRef,
8 ManagedRefMut,
9 },
10 type_hash::TypeHash,
11};
12use std::ops::{Deref, DerefMut};
13
14pub struct ObjectRef<T> {
15 actual_type_hash: TypeHash,
16 data: ManagedRef<T>,
17}
18
19impl<T> ObjectRef<T> {
20 pub fn new(data: ManagedRef<T>) -> Self {
21 Self {
22 actual_type_hash: TypeHash::of::<T>(),
23 data,
24 }
25 }
26
27 pub fn actual_type_hash(&self) -> TypeHash {
28 self.actual_type_hash
29 }
30
31 pub fn current_type_hash(&self) -> TypeHash {
32 TypeHash::of::<T>()
33 }
34
35 pub fn upcast<U>(self, registry: &Registry) -> Option<ObjectRef<U>> {
36 let offset = inheritance_offset(
37 self.current_type_hash(),
38 TypeHash::of::<U>(),
39 None,
40 registry,
41 )?;
42 let Self {
43 actual_type_hash,
44 data,
45 } = self;
46 let (lifetime, memory) = data.into_inner();
47 let data =
48 unsafe { ManagedRef::new_raw(memory.cast::<u8>().add(offset).cast::<U>(), lifetime)? };
49 Some(ObjectRef {
50 actual_type_hash,
51 data,
52 })
53 }
54
55 pub fn downcast<U>(self, registry: &Registry) -> Option<ObjectRef<U>> {
56 let offset = inheritance_offset(
57 TypeHash::of::<U>(),
58 self.current_type_hash(),
59 Some(self.actual_type_hash),
60 registry,
61 )?;
62 let Self {
63 actual_type_hash,
64 data,
65 } = self;
66 let (lifetime, memory) = data.into_inner();
67 let data =
68 unsafe { ManagedRef::new_raw(memory.cast::<u8>().sub(offset).cast::<U>(), lifetime)? };
69 Some(ObjectRef {
70 actual_type_hash,
71 data,
72 })
73 }
74
75 pub fn into_dynamic(self) -> DynamicObjectRef {
76 let Self {
77 actual_type_hash,
78 data,
79 } = self;
80 DynamicObjectRef {
81 actual_type_hash,
82 data: data.into_dynamic(),
83 }
84 }
85}
86
87impl<T> Deref for ObjectRef<T> {
88 type Target = ManagedRef<T>;
89
90 fn deref(&self) -> &Self::Target {
91 &self.data
92 }
93}
94
95impl<T> DerefMut for ObjectRef<T> {
96 fn deref_mut(&mut self) -> &mut Self::Target {
97 &mut self.data
98 }
99}
100
101pub struct ObjectRefMut<T> {
102 actual_type_hash: TypeHash,
103 data: ManagedRefMut<T>,
104}
105
106impl<T> ObjectRefMut<T> {
107 pub fn new(data: ManagedRefMut<T>) -> Self {
108 Self {
109 actual_type_hash: TypeHash::of::<T>(),
110 data,
111 }
112 }
113
114 pub fn actual_type_hash(&self) -> TypeHash {
115 self.actual_type_hash
116 }
117
118 pub fn current_type_hash(&self) -> TypeHash {
119 TypeHash::of::<T>()
120 }
121
122 pub fn upcast<U>(self, registry: &Registry) -> Option<ObjectRefMut<U>> {
123 let offset = inheritance_offset(
124 self.current_type_hash(),
125 TypeHash::of::<U>(),
126 None,
127 registry,
128 )?;
129 let Self {
130 actual_type_hash,
131 data,
132 } = self;
133 let (lifetime, memory) = data.into_inner();
134 let data = unsafe {
135 ManagedRefMut::new_raw(memory.cast::<u8>().add(offset).cast::<U>(), lifetime)?
136 };
137 Some(ObjectRefMut {
138 actual_type_hash,
139 data,
140 })
141 }
142
143 pub fn downcast<U>(self, registry: &Registry) -> Option<ObjectRefMut<U>> {
144 let offset = inheritance_offset(
145 TypeHash::of::<U>(),
146 self.current_type_hash(),
147 Some(self.actual_type_hash),
148 registry,
149 )?;
150 let Self {
151 actual_type_hash,
152 data,
153 } = self;
154 let (lifetime, memory) = data.into_inner();
155 let data = unsafe {
156 ManagedRefMut::new_raw(memory.cast::<u8>().sub(offset).cast::<U>(), lifetime)?
157 };
158 Some(ObjectRefMut {
159 actual_type_hash,
160 data,
161 })
162 }
163
164 pub fn into_dynamic(self) -> DynamicObjectRefMut {
165 let Self {
166 actual_type_hash,
167 data,
168 } = self;
169 DynamicObjectRefMut {
170 actual_type_hash,
171 data: data.into_dynamic(),
172 }
173 }
174}
175
176impl<T> Deref for ObjectRefMut<T> {
177 type Target = ManagedRefMut<T>;
178
179 fn deref(&self) -> &Self::Target {
180 &self.data
181 }
182}
183
184impl<T> DerefMut for ObjectRefMut<T> {
185 fn deref_mut(&mut self) -> &mut Self::Target {
186 &mut self.data
187 }
188}
189
190pub struct ObjectLazy<T> {
191 actual_type_hash: TypeHash,
192 data: ManagedLazy<T>,
193}
194
195impl<T> ObjectLazy<T> {
196 pub fn new(data: ManagedLazy<T>) -> Self {
197 Self {
198 actual_type_hash: TypeHash::of::<T>(),
199 data,
200 }
201 }
202
203 pub fn actual_type_hash(&self) -> TypeHash {
204 self.actual_type_hash
205 }
206
207 pub fn current_type_hash(&self) -> TypeHash {
208 TypeHash::of::<T>()
209 }
210
211 pub fn upcast<U>(self, registry: &Registry) -> Option<ObjectLazy<U>> {
212 let offset = inheritance_offset(
213 self.current_type_hash(),
214 TypeHash::of::<U>(),
215 None,
216 registry,
217 )?;
218 let Self {
219 actual_type_hash,
220 data,
221 } = self;
222 let (lifetime, memory) = data.into_inner();
223 let data =
224 unsafe { ManagedLazy::new_raw(memory.cast::<u8>().add(offset).cast::<U>(), lifetime)? };
225 Some(ObjectLazy {
226 actual_type_hash,
227 data,
228 })
229 }
230
231 pub fn downcast<U>(self, registry: &Registry) -> Option<ObjectLazy<U>> {
232 let offset = inheritance_offset(
233 TypeHash::of::<U>(),
234 self.current_type_hash(),
235 Some(self.actual_type_hash),
236 registry,
237 )?;
238 let Self {
239 actual_type_hash,
240 data,
241 } = self;
242 let (lifetime, memory) = data.into_inner();
243 let data =
244 unsafe { ManagedLazy::new_raw(memory.cast::<u8>().sub(offset).cast::<U>(), lifetime)? };
245 Some(ObjectLazy {
246 actual_type_hash,
247 data,
248 })
249 }
250
251 pub fn into_dynamic(self) -> DynamicObjectLazy {
252 let Self {
253 actual_type_hash,
254 data,
255 } = self;
256 DynamicObjectLazy {
257 actual_type_hash,
258 data: data.into_dynamic(),
259 }
260 }
261}
262
263impl<T> Deref for ObjectLazy<T> {
264 type Target = ManagedLazy<T>;
265
266 fn deref(&self) -> &Self::Target {
267 &self.data
268 }
269}
270
271impl<T> DerefMut for ObjectLazy<T> {
272 fn deref_mut(&mut self) -> &mut Self::Target {
273 &mut self.data
274 }
275}
276
277impl<T> Clone for ObjectLazy<T> {
278 fn clone(&self) -> Self {
279 Self {
280 actual_type_hash: self.actual_type_hash,
281 data: self.data.clone(),
282 }
283 }
284}
285
286pub struct DynamicObjectRef {
287 actual_type_hash: TypeHash,
288 data: DynamicManagedRef,
289}
290
291impl DynamicObjectRef {
292 pub fn new(data: DynamicManagedRef) -> Self {
293 Self {
294 actual_type_hash: *data.type_hash(),
295 data,
296 }
297 }
298
299 pub fn actual_type_hash(&self) -> TypeHash {
300 self.actual_type_hash
301 }
302
303 pub fn current_type_hash(&self) -> TypeHash {
304 *self.data.type_hash()
305 }
306
307 pub fn upcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
308 let offset = inheritance_offset(self.current_type_hash(), type_hash, None, registry)?;
309 let Self {
310 actual_type_hash,
311 data,
312 } = self;
313 let (_, lifetime, memory) = data.into_inner();
314 let data = unsafe { DynamicManagedRef::new_raw(type_hash, lifetime, memory.add(offset))? };
315 Some(Self {
316 actual_type_hash,
317 data,
318 })
319 }
320
321 pub fn downcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
322 let offset = inheritance_offset(
323 type_hash,
324 self.current_type_hash(),
325 Some(self.actual_type_hash),
326 registry,
327 )?;
328 let Self {
329 actual_type_hash,
330 data,
331 } = self;
332 let (_, lifetime, memory) = data.into_inner();
333 let data = unsafe { DynamicManagedRef::new_raw(type_hash, lifetime, memory.sub(offset))? };
334 Some(Self {
335 actual_type_hash,
336 data,
337 })
338 }
339
340 pub fn into_inner(self, registry: &Registry) -> Option<DynamicManagedRef> {
341 let type_hash = self.actual_type_hash;
342 Some(self.downcast(type_hash, registry)?.data)
343 }
344
345 pub fn into_typed<T>(self) -> Result<ObjectRef<T>, Self> {
346 let Self {
347 actual_type_hash,
348 data,
349 } = self;
350 match data.into_typed::<T>() {
351 Ok(data) => Ok(ObjectRef {
352 actual_type_hash,
353 data,
354 }),
355 Err(data) => Err(Self {
356 actual_type_hash,
357 data,
358 }),
359 }
360 }
361}
362
363impl Deref for DynamicObjectRef {
364 type Target = DynamicManagedRef;
365
366 fn deref(&self) -> &Self::Target {
367 &self.data
368 }
369}
370
371impl DerefMut for DynamicObjectRef {
372 fn deref_mut(&mut self) -> &mut Self::Target {
373 &mut self.data
374 }
375}
376
377pub struct DynamicObjectRefMut {
378 actual_type_hash: TypeHash,
379 data: DynamicManagedRefMut,
380}
381
382impl DynamicObjectRefMut {
383 pub fn new(data: DynamicManagedRefMut) -> Self {
384 Self {
385 actual_type_hash: *data.type_hash(),
386 data,
387 }
388 }
389
390 pub fn actual_type_hash(&self) -> TypeHash {
391 self.actual_type_hash
392 }
393
394 pub fn current_type_hash(&self) -> TypeHash {
395 *self.data.type_hash()
396 }
397
398 pub fn upcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
399 let offset = inheritance_offset(self.current_type_hash(), type_hash, None, registry)?;
400 let Self {
401 actual_type_hash,
402 data,
403 } = self;
404 let (_, lifetime, memory) = data.into_inner();
405 let data =
406 unsafe { DynamicManagedRefMut::new_raw(type_hash, lifetime, memory.add(offset))? };
407 Some(Self {
408 actual_type_hash,
409 data,
410 })
411 }
412
413 pub fn downcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
414 let offset = inheritance_offset(
415 type_hash,
416 self.current_type_hash(),
417 Some(self.actual_type_hash),
418 registry,
419 )?;
420 let Self {
421 actual_type_hash,
422 data,
423 } = self;
424 let (_, lifetime, memory) = data.into_inner();
425 let data =
426 unsafe { DynamicManagedRefMut::new_raw(type_hash, lifetime, memory.sub(offset))? };
427 Some(Self {
428 actual_type_hash,
429 data,
430 })
431 }
432
433 pub fn into_inner(self, registry: &Registry) -> Option<DynamicManagedRefMut> {
434 let type_hash = self.actual_type_hash;
435 Some(self.downcast(type_hash, registry)?.data)
436 }
437
438 pub fn into_typed<T>(self) -> Result<ObjectRefMut<T>, Self> {
439 let Self {
440 actual_type_hash,
441 data,
442 } = self;
443 match data.into_typed::<T>() {
444 Ok(data) => Ok(ObjectRefMut {
445 actual_type_hash,
446 data,
447 }),
448 Err(data) => Err(Self {
449 actual_type_hash,
450 data,
451 }),
452 }
453 }
454}
455
456impl Deref for DynamicObjectRefMut {
457 type Target = DynamicManagedRefMut;
458
459 fn deref(&self) -> &Self::Target {
460 &self.data
461 }
462}
463
464impl DerefMut for DynamicObjectRefMut {
465 fn deref_mut(&mut self) -> &mut Self::Target {
466 &mut self.data
467 }
468}
469
470pub struct DynamicObjectLazy {
471 actual_type_hash: TypeHash,
472 data: DynamicManagedLazy,
473}
474
475impl DynamicObjectLazy {
476 pub fn new(data: DynamicManagedLazy) -> Self {
477 Self {
478 actual_type_hash: *data.type_hash(),
479 data,
480 }
481 }
482
483 pub fn actual_type_hash(&self) -> TypeHash {
484 self.actual_type_hash
485 }
486
487 pub fn current_type_hash(&self) -> TypeHash {
488 *self.data.type_hash()
489 }
490
491 pub fn upcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
492 let offset = inheritance_offset(self.current_type_hash(), type_hash, None, registry)?;
493 let Self {
494 actual_type_hash,
495 data,
496 } = self;
497 let (_, lifetime, memory) = data.into_inner();
498 let data = unsafe { DynamicManagedLazy::new_raw(type_hash, lifetime, memory.add(offset))? };
499 Some(Self {
500 actual_type_hash,
501 data,
502 })
503 }
504
505 pub fn downcast(self, type_hash: TypeHash, registry: &Registry) -> Option<Self> {
506 let offset = inheritance_offset(
507 type_hash,
508 self.current_type_hash(),
509 Some(self.actual_type_hash),
510 registry,
511 )?;
512 let Self {
513 actual_type_hash,
514 data,
515 } = self;
516 let (_, lifetime, memory) = data.into_inner();
517 let data = unsafe { DynamicManagedLazy::new_raw(type_hash, lifetime, memory.sub(offset))? };
518 Some(Self {
519 actual_type_hash,
520 data,
521 })
522 }
523
524 pub fn into_inner(self, registry: &Registry) -> Option<DynamicManagedLazy> {
525 let type_hash = self.actual_type_hash;
526 Some(self.downcast(type_hash, registry)?.data)
527 }
528
529 pub fn into_typed<T>(self) -> Result<ObjectLazy<T>, Self> {
530 let Self {
531 actual_type_hash,
532 data,
533 } = self;
534 match data.into_typed::<T>() {
535 Ok(data) => Ok(ObjectLazy {
536 actual_type_hash,
537 data,
538 }),
539 Err(data) => Err(Self {
540 actual_type_hash,
541 data,
542 }),
543 }
544 }
545}
546
547impl Deref for DynamicObjectLazy {
548 type Target = DynamicManagedLazy;
549
550 fn deref(&self) -> &Self::Target {
551 &self.data
552 }
553}
554
555impl DerefMut for DynamicObjectLazy {
556 fn deref_mut(&mut self) -> &mut Self::Target {
557 &mut self.data
558 }
559}
560
561impl Clone for DynamicObjectLazy {
562 fn clone(&self) -> Self {
563 Self {
564 actual_type_hash: self.actual_type_hash,
565 data: self.data.clone(),
566 }
567 }
568}
569
570fn inheritance_offset(
571 source: TypeHash,
572 target: TypeHash,
573 limit: Option<TypeHash>,
574 registry: &Registry,
575) -> Option<usize> {
576 let source_type = registry.find_type(TypeQuery {
577 type_hash: Some(source),
578 ..Default::default()
579 })?;
580 inheritance_offset_inner(&source_type, target, limit)
581}
582
583fn inheritance_offset_inner(
584 source_type: &TypeHandle,
585 target: TypeHash,
586 limit: Option<TypeHash>,
587) -> Option<usize> {
588 if source_type.type_hash() == target {
589 return Some(0);
590 }
591 let source_type = source_type.as_struct()?;
592 for field in source_type.fields() {
593 if !field
594 .meta
595 .as_ref()
596 .map(|meta| meta.has_id("inherit"))
597 .unwrap_or_default()
598 {
599 continue;
600 }
601 if let Some(limit) = limit {
602 if field.type_handle().type_hash() == limit {
603 return None;
604 }
605 }
606 if field.type_handle().type_hash() == target {
607 return Some(field.address_offset());
608 }
609 if let Some(offset) = inheritance_offset_inner(field.type_handle(), target, limit) {
610 return Some(field.address_offset() + offset);
611 }
612 }
613 None
614}
615
616#[cfg(test)]
617mod tests {
618 use super::*;
619 use intuicio_core::IntuicioStruct;
620 use intuicio_data::managed::Managed;
621 use intuicio_derive::IntuicioStruct;
622
623 #[derive(IntuicioStruct, Default)]
624 struct A {
625 a: usize,
626 }
627
628 #[derive(IntuicioStruct, Default)]
629 struct B {
630 #[intuicio(meta = "inherit")]
631 a: A,
632 b: f32,
633 }
634
635 #[derive(IntuicioStruct, Default)]
636 struct C {
637 #[intuicio(meta = "inherit")]
638 b: B,
639 c: bool,
640 }
641
642 #[test]
643 fn test_simple() {
644 let mut registry = Registry::default().with_basic_types();
645 registry.add_type(A::define_struct(®istry));
646 registry.add_type(B::define_struct(®istry));
647 registry.add_type(C::define_struct(®istry));
648
649 let mut data = Managed::new(C {
650 b: B {
651 a: A { a: 42 },
652 b: 4.2,
653 },
654 c: true,
655 });
656
657 {
658 let c = ObjectRef::new(data.borrow().unwrap());
659 assert_eq!(c.read().unwrap().b.a.a, 42);
660
661 let a = c.upcast::<A>(®istry).unwrap();
662 assert_eq!(a.read().unwrap().a, 42);
663
664 let c = a.downcast::<C>(®istry).unwrap();
665 assert_eq!(c.read().unwrap().b.a.a, 42);
666 }
667
668 {
669 let c = ObjectRefMut::new(data.borrow_mut().unwrap());
670 assert_eq!(c.read().unwrap().b.a.a, 42);
671
672 let mut a = c.upcast::<A>(®istry).unwrap();
673 a.write().unwrap().a = 1;
674
675 let c = a.downcast::<C>(®istry).unwrap();
676 assert_eq!(c.read().unwrap().b.a.a, 1);
677 }
678
679 {
680 let c = ObjectLazy::new(data.lazy());
681 assert_eq!(c.read().unwrap().b.a.a, 1);
682
683 let a = c.upcast::<A>(®istry).unwrap();
684 a.write().unwrap().a = 42;
685
686 let c = a.downcast::<C>(®istry).unwrap();
687 assert_eq!(c.read().unwrap().b.a.a, 42);
688 }
689 }
690
691 #[test]
692 fn test_casting() {
693 let mut registry = Registry::default().with_basic_types();
694 registry.add_type(A::define_struct(®istry));
695 registry.add_type(B::define_struct(®istry));
696 registry.add_type(C::define_struct(®istry));
697
698 let mut data = Managed::new(C {
699 b: B {
700 a: A { a: 42 },
701 b: 4.2,
702 },
703 c: true,
704 });
705
706 {
707 let c = ObjectRef::new(data.borrow().unwrap());
708 assert_eq!(c.current_type_hash(), TypeHash::of::<C>());
709 assert_eq!(c.actual_type_hash(), TypeHash::of::<C>());
710 assert!(c.read().unwrap().c);
711 assert_eq!(c.read().unwrap().b.b, 4.2);
712 assert_eq!(c.read().unwrap().b.a.a, 42);
713
714 let b = c.upcast::<B>(®istry).unwrap();
715 assert_eq!(b.current_type_hash(), TypeHash::of::<B>());
716 assert_eq!(b.actual_type_hash(), TypeHash::of::<C>());
717 assert_eq!(b.read().unwrap().b, 4.2);
718 assert_eq!(b.read().unwrap().a.a, 42);
719
720 let a = b.upcast::<A>(®istry).unwrap();
721 assert_eq!(a.current_type_hash(), TypeHash::of::<A>());
722 assert_eq!(a.actual_type_hash(), TypeHash::of::<C>());
723 assert_eq!(a.read().unwrap().a, 42);
724
725 let b = a.downcast::<B>(®istry).unwrap();
726 assert_eq!(b.read().unwrap().b, 4.2);
727 assert_eq!(b.read().unwrap().a.a, 42);
728
729 let c = b.downcast::<C>(®istry).unwrap();
730 assert!(c.read().unwrap().c);
731 assert_eq!(c.read().unwrap().b.b, 4.2);
732 assert_eq!(c.read().unwrap().b.a.a, 42);
733 }
734
735 {
736 let c = ObjectRefMut::new(data.borrow_mut().unwrap());
737 assert_eq!(c.current_type_hash(), TypeHash::of::<C>());
738 assert_eq!(c.actual_type_hash(), TypeHash::of::<C>());
739 assert!(c.read().unwrap().c);
740 assert_eq!(c.read().unwrap().b.b, 4.2);
741 assert_eq!(c.read().unwrap().b.a.a, 42);
742
743 let b = c.upcast::<B>(®istry).unwrap();
744 assert_eq!(b.current_type_hash(), TypeHash::of::<B>());
745 assert_eq!(b.actual_type_hash(), TypeHash::of::<C>());
746 assert_eq!(b.read().unwrap().b, 4.2);
747 assert_eq!(b.read().unwrap().a.a, 42);
748
749 let a = b.upcast::<A>(®istry).unwrap();
750 assert_eq!(a.current_type_hash(), TypeHash::of::<A>());
751 assert_eq!(a.actual_type_hash(), TypeHash::of::<C>());
752 assert_eq!(a.read().unwrap().a, 42);
753
754 let b = a.downcast::<B>(®istry).unwrap();
755 assert_eq!(b.read().unwrap().b, 4.2);
756 assert_eq!(b.read().unwrap().a.a, 42);
757
758 let c = b.downcast::<C>(®istry).unwrap();
759 assert!(c.read().unwrap().c);
760 assert_eq!(c.read().unwrap().b.b, 4.2);
761 assert_eq!(c.read().unwrap().b.a.a, 42);
762 }
763
764 {
765 let c = ObjectLazy::new(data.lazy());
766 assert_eq!(c.current_type_hash(), TypeHash::of::<C>());
767 assert_eq!(c.actual_type_hash(), TypeHash::of::<C>());
768 assert!(c.read().unwrap().c);
769 assert_eq!(c.read().unwrap().b.b, 4.2);
770 assert_eq!(c.read().unwrap().b.a.a, 42);
771
772 let b = c.clone().upcast::<B>(®istry).unwrap();
773 assert_eq!(b.current_type_hash(), TypeHash::of::<B>());
774 assert_eq!(b.actual_type_hash(), TypeHash::of::<C>());
775 assert_eq!(b.read().unwrap().b, 4.2);
776 assert_eq!(b.read().unwrap().a.a, 42);
777
778 let a = b.clone().upcast::<A>(®istry).unwrap();
779 assert_eq!(a.current_type_hash(), TypeHash::of::<A>());
780 assert_eq!(a.actual_type_hash(), TypeHash::of::<C>());
781 assert_eq!(a.read().unwrap().a, 42);
782
783 let a = c.clone().upcast::<A>(®istry).unwrap();
784 assert_eq!(a.current_type_hash(), TypeHash::of::<A>());
785 assert_eq!(a.actual_type_hash(), TypeHash::of::<C>());
786 assert_eq!(a.read().unwrap().a, 42);
787
788 let b = a.clone().downcast::<B>(®istry).unwrap();
789 assert_eq!(b.read().unwrap().b, 4.2);
790 assert_eq!(b.read().unwrap().a.a, 42);
791
792 let c = a.clone().downcast::<C>(®istry).unwrap();
793 assert!(c.read().unwrap().c);
794 assert_eq!(c.read().unwrap().b.b, 4.2);
795 assert_eq!(c.read().unwrap().b.a.a, 42);
796
797 let c = b.clone().downcast::<C>(®istry).unwrap();
798 assert!(c.read().unwrap().c);
799 assert_eq!(c.read().unwrap().b.b, 4.2);
800 assert_eq!(c.read().unwrap().b.a.a, 42);
801 }
802
803 let mut data = Managed::new(B {
804 a: A { a: 42 },
805 b: 4.2,
806 });
807
808 {
809 let b = ObjectLazy::new(data.lazy());
810 assert_eq!(b.read().unwrap().b, 4.2);
811 assert_eq!(b.read().unwrap().a.a, 42);
812
813 let a = b.upcast::<A>(®istry).unwrap();
814 assert_eq!(a.read().unwrap().a, 42);
815 assert!(a.clone().downcast::<C>(®istry).is_none());
816
817 let b = a.downcast::<B>(®istry).unwrap();
818 assert_eq!(b.read().unwrap().b, 4.2);
819 assert_eq!(b.read().unwrap().a.a, 42);
820 assert!(b.clone().downcast::<C>(®istry).is_none());
821 }
822
823 let mut data = Managed::new(A { a: 42 });
824
825 {
826 let a = ObjectLazy::new(data.lazy());
827 assert_eq!(a.read().unwrap().a, 42);
828 assert!(a.clone().downcast::<B>(®istry).is_none());
829 assert!(a.clone().downcast::<C>(®istry).is_none());
830 }
831 }
832}