intuicio_framework_oop/
lib.rs

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(&registry));
646        registry.add_type(B::define_struct(&registry));
647        registry.add_type(C::define_struct(&registry));
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>(&registry).unwrap();
662            assert_eq!(a.read().unwrap().a, 42);
663
664            let c = a.downcast::<C>(&registry).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>(&registry).unwrap();
673            a.write().unwrap().a = 1;
674
675            let c = a.downcast::<C>(&registry).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>(&registry).unwrap();
684            a.write().unwrap().a = 42;
685
686            let c = a.downcast::<C>(&registry).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(&registry));
695        registry.add_type(B::define_struct(&registry));
696        registry.add_type(C::define_struct(&registry));
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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).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>(&registry).unwrap();
814            assert_eq!(a.read().unwrap().a, 42);
815            assert!(a.clone().downcast::<C>(&registry).is_none());
816
817            let b = a.downcast::<B>(&registry).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>(&registry).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>(&registry).is_none());
829            assert!(a.clone().downcast::<C>(&registry).is_none());
830        }
831    }
832}