Skip to main content

intuicio_core/
transformer.rs

1//! How native function arguments are represented on the script side.
2//!
3//! A Rust function like `fn add(a: &i32, b: &mut i32) -> i32` cannot take
4//! plain references off a script stack, because nothing on that stack has a
5//! Rust lifetime. A [`ValueTransformer`] decides which box stands in for each
6//! position instead: what an owned value becomes, what a `&T` becomes, and
7//! what a `&mut T` becomes.
8//!
9//! The derive macros take the choice as an attribute:
10//!
11//! ```ignore
12//! #[intuicio_function(transformer = "ManagedValueTransformer")]
13//! fn add(a: &i32, b: &mut i32) -> i32 {
14//!     *a + *b
15//! }
16//! ```
17//!
18//! With that transformer the script side passes a `ManagedRef<i32>` and a
19//! `ManagedRefMut<i32>`, and gets back a `Managed<i32>`.
20//!
21//! # Which one to pick
22//!
23//! | Transformer | Owned | Shared | Exclusive |
24//! |---|---|---|---|
25//! | [`SharedValueTransformer`] | `Shared<T>` | `Shared<T>` | `Shared<T>` |
26//! | [`ManagedValueTransformer`] | `Managed<T>` | `ManagedRef<T>` | `ManagedRefMut<T>` |
27//! | [`ManagedGcValueTransformer`] | `ManagedGc<T>` | `ManagedRef<T>` | `ManagedRefMut<T>` |
28//! | [`DynamicManagedValueTransformer`] | `DynamicManaged` | `DynamicManagedRef` | `DynamicManagedRefMut` |
29//! | [`DynamicManagedGcValueTransformer`] | `DynamicManagedGc` | `DynamicManagedRef` | `DynamicManagedRefMut` |
30//!
31//! The `Shared` one clones instead of borrowing, so it never fails but never
32//! shares writes either. The `Dynamic` ones erase the type, which is what a
33//! dynamically typed frontend wants. The `Gc` ones survive reference cycles.
34use crate::registry::Registry;
35use intuicio_data::{
36    lifetime::*,
37    managed::{gc::*, *},
38    shared::*,
39};
40use std::{
41    cell::{Ref, RefMut},
42    marker::PhantomData,
43};
44
45/// Maps between a Rust type and the boxes that stand in for it on the script
46/// side.
47///
48/// See the [module docs](self) for the ready-made implementations.
49pub trait ValueTransformer {
50    /// The Rust type being wrapped.
51    type Type;
52    /// What reading through [`ValueTransformer::into_ref`] yields.
53    type Borrow<'r>
54    where
55        Self::Type: 'r;
56    /// What writing through [`ValueTransformer::into_ref_mut`] yields.
57    type BorrowMut<'r>
58    where
59        Self::Type: 'r;
60    /// Proof that the borrowed value stays alive, usually a borrow token taken
61    /// from the owner's lifetime.
62    type Dependency;
63    /// The box standing in for an owned `Type`.
64    type Owned;
65    /// The box standing in for a `&Type`.
66    type Ref;
67    /// The box standing in for a `&mut Type`.
68    type RefMut;
69
70    /// Wraps a value the native function produced.
71    fn from_owned(registry: &Registry, value: Self::Type) -> Self::Owned;
72    /// Wraps a shared reference, tying it to `dependency`.
73    fn from_ref(
74        registry: &Registry,
75        value: &Self::Type,
76        dependency: Option<Self::Dependency>,
77    ) -> Self::Ref;
78    /// Wraps an exclusive reference, tying it to `dependency`.
79    fn from_ref_mut(
80        registry: &Registry,
81        value: &mut Self::Type,
82        dependency: Option<Self::Dependency>,
83    ) -> Self::RefMut;
84    /// Unwraps a value for the native function to take.
85    fn into_owned(value: Self::Owned) -> Self::Type;
86    /// Opens a shared box for reading.
87    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_>;
88    /// Opens an exclusive box for writing.
89    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_>;
90}
91
92/// Produces the proof a transformer needs to hand out a reference.
93///
94/// Implemented for every box that can lend a borrow, so a method taking
95/// `&self` can tie its result to the receiver it came from.
96pub trait ValueDependency<T> {
97    /// Takes a shared borrow from `value`.
98    fn as_ref(value: &T) -> Self;
99    /// Takes an exclusive borrow from `value`.
100    ///
101    /// # Panics
102    ///
103    /// Panics for boxes that only hold a shared borrow themselves.
104    fn as_ref_mut(value: &mut T) -> Self;
105}
106
107/// Passes values as `Shared<T>`, cloning instead of borrowing.
108///
109/// Never fails to hand out a value, but a script writing through one does
110/// not affect the original.
111pub struct SharedValueTransformer<T: Default + Clone + 'static>(PhantomData<fn() -> T>);
112
113impl<T: Default + Clone + 'static> ValueTransformer for SharedValueTransformer<T> {
114    type Type = T;
115    type Borrow<'r> = Ref<'r, T>;
116    type BorrowMut<'r> = RefMut<'r, T>;
117    type Dependency = ();
118    type Owned = Shared<T>;
119    type Ref = Shared<T>;
120    type RefMut = Shared<T>;
121
122    fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
123        Shared::new(value)
124    }
125
126    fn from_ref(_: &Registry, value: &Self::Type, _: Option<Self::Dependency>) -> Self::Ref {
127        Shared::new(value.clone())
128    }
129
130    fn from_ref_mut(
131        _: &Registry,
132        value: &mut Self::Type,
133        _: Option<Self::Dependency>,
134    ) -> Self::RefMut {
135        Shared::new(value.clone())
136    }
137
138    fn into_owned(value: Self::Owned) -> Self::Type {
139        value.read().unwrap().clone()
140    }
141
142    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
143        value.read().unwrap()
144    }
145
146    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
147        value.write().unwrap()
148    }
149}
150
151/// Passes values as [`Managed`] boxes with real borrow checking.
152///
153/// The usual choice for a statically typed frontend.
154pub struct ManagedValueTransformer<T>(PhantomData<fn() -> T>);
155
156impl<T> ValueTransformer for ManagedValueTransformer<T> {
157    type Type = T;
158    type Borrow<'r>
159        = ValueReadAccess<'r, T>
160    where
161        Self::Type: 'r;
162    type BorrowMut<'r>
163        = ValueWriteAccess<'r, T>
164    where
165        Self::Type: 'r;
166    type Dependency = ManagedValueDependency;
167    type Owned = Managed<T>;
168    type Ref = ManagedRef<T>;
169    type RefMut = ManagedRefMut<T>;
170
171    fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
172        Managed::new(value)
173    }
174
175    fn from_ref(
176        _: &Registry,
177        value: &Self::Type,
178        dependency: Option<Self::Dependency>,
179    ) -> Self::Ref {
180        if let ManagedValueDependency::Ref(lifetime) =
181            dependency.expect("`ManagedRef` require dependency for lifetime bound!")
182        {
183            ManagedRef::new(value, lifetime)
184        } else {
185            panic!("Could not borrow lifetime to create `ManagedRef`!")
186        }
187    }
188
189    fn from_ref_mut(
190        _: &Registry,
191        value: &mut Self::Type,
192        dependency: Option<Self::Dependency>,
193    ) -> Self::RefMut {
194        if let ManagedValueDependency::RefMut(lifetime) =
195            dependency.expect("`ManagedRefMut` require dependency for lifetime bound!")
196        {
197            ManagedRefMut::new(value, lifetime)
198        } else {
199            panic!("Could not borrow lifetime mutably to create `ManagedRefMut`!")
200        }
201    }
202
203    fn into_owned(value: Self::Owned) -> Self::Type {
204        value.consume().ok().unwrap()
205    }
206
207    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
208        value.read().unwrap()
209    }
210
211    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
212        value.write().unwrap()
213    }
214}
215
216/// [`ManagedValueTransformer`] with [`ManagedGc`] ownership, for values that
217/// may take part in reference cycles.
218pub struct ManagedGcValueTransformer<T>(PhantomData<fn() -> T>);
219
220impl<T> ValueTransformer for ManagedGcValueTransformer<T> {
221    type Type = T;
222    type Borrow<'r>
223        = ValueReadAccess<'r, T>
224    where
225        Self::Type: 'r;
226    type BorrowMut<'r>
227        = ValueWriteAccess<'r, T>
228    where
229        Self::Type: 'r;
230    type Dependency = ManagedValueDependency;
231    type Owned = ManagedGc<T>;
232    type Ref = ManagedRef<T>;
233    type RefMut = ManagedRefMut<T>;
234
235    fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
236        ManagedGc::new(value)
237    }
238
239    fn from_ref(
240        _: &Registry,
241        value: &Self::Type,
242        dependency: Option<Self::Dependency>,
243    ) -> Self::Ref {
244        if let ManagedValueDependency::Ref(lifetime) =
245            dependency.expect("`ManagedRef` require dependency for lifetime bound!")
246        {
247            ManagedRef::new(value, lifetime)
248        } else {
249            panic!("Could not borrow lifetime to create `ManagedRef`!")
250        }
251    }
252
253    fn from_ref_mut(
254        _: &Registry,
255        value: &mut Self::Type,
256        dependency: Option<Self::Dependency>,
257    ) -> Self::RefMut {
258        if let ManagedValueDependency::RefMut(lifetime) =
259            dependency.expect("`ManagedRefMut` require dependency for lifetime bound!")
260        {
261            ManagedRefMut::new(value, lifetime)
262        } else {
263            panic!("Could not borrow lifetime mutably to create `ManagedRefMut`!")
264        }
265    }
266
267    fn into_owned(value: Self::Owned) -> Self::Type {
268        value.consume().ok().unwrap()
269    }
270
271    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
272        value.read().unwrap()
273    }
274
275    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
276        value.write().unwrap()
277    }
278}
279
280/// Passes values as type-erased [`DynamicManaged`] boxes.
281///
282/// The usual choice for a dynamically typed frontend.
283pub struct DynamicManagedValueTransformer<T: 'static>(PhantomData<fn() -> T>);
284
285impl<T: 'static> ValueTransformer for DynamicManagedValueTransformer<T> {
286    type Type = T;
287    type Borrow<'r>
288        = ValueReadAccess<'r, T>
289    where
290        Self::Type: 'r;
291    type BorrowMut<'r>
292        = ValueWriteAccess<'r, T>
293    where
294        Self::Type: 'r;
295    type Dependency = ManagedValueDependency;
296    type Owned = DynamicManaged;
297    type Ref = DynamicManagedRef;
298    type RefMut = DynamicManagedRefMut;
299
300    fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
301        DynamicManaged::new(value).ok().unwrap()
302    }
303
304    fn from_ref(
305        _: &Registry,
306        value: &Self::Type,
307        dependency: Option<Self::Dependency>,
308    ) -> Self::Ref {
309        if let ManagedValueDependency::Ref(lifetime) =
310            dependency.expect("`DynamicManagedRef` require dependency for lifetime bound!")
311        {
312            DynamicManagedRef::new(value, lifetime)
313        } else {
314            panic!("Could not borrow lifetime to create `DynamicManagedRef`!")
315        }
316    }
317
318    fn from_ref_mut(
319        _: &Registry,
320        value: &mut Self::Type,
321        dependency: Option<Self::Dependency>,
322    ) -> Self::RefMut {
323        if let ManagedValueDependency::RefMut(lifetime) =
324            dependency.expect("`DynamicManagedRefMut` require dependency for lifetime bound!")
325        {
326            DynamicManagedRefMut::new(value, lifetime)
327        } else {
328            panic!("Could not borrow lifetime mutably to create `DynamicManagedRefMut`!")
329        }
330    }
331
332    fn into_owned(value: Self::Owned) -> Self::Type {
333        value.consume().ok().unwrap()
334    }
335
336    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
337        value.read().unwrap()
338    }
339
340    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
341        value.write().unwrap()
342    }
343}
344
345/// [`DynamicManagedValueTransformer`] with [`DynamicManagedGc`] ownership,
346/// for values that may take part in reference cycles.
347pub struct DynamicManagedGcValueTransformer<T: 'static>(PhantomData<fn() -> T>);
348
349impl<T: 'static> ValueTransformer for DynamicManagedGcValueTransformer<T> {
350    type Type = T;
351    type Borrow<'r>
352        = ValueReadAccess<'r, T>
353    where
354        Self::Type: 'r;
355    type BorrowMut<'r>
356        = ValueWriteAccess<'r, T>
357    where
358        Self::Type: 'r;
359    type Dependency = ManagedValueDependency;
360    type Owned = DynamicManagedGc;
361    type Ref = DynamicManagedRef;
362    type RefMut = DynamicManagedRefMut;
363
364    fn from_owned(_: &Registry, value: Self::Type) -> Self::Owned {
365        DynamicManagedGc::new(value)
366    }
367
368    fn from_ref(
369        _: &Registry,
370        value: &Self::Type,
371        dependency: Option<Self::Dependency>,
372    ) -> Self::Ref {
373        if let ManagedValueDependency::Ref(lifetime) =
374            dependency.expect("`DynamicManagedRef` require dependency for lifetime bound!")
375        {
376            DynamicManagedRef::new(value, lifetime)
377        } else {
378            panic!("Could not borrow lifetime to create `DynamicManagedRef`!")
379        }
380    }
381
382    fn from_ref_mut(
383        _: &Registry,
384        value: &mut Self::Type,
385        dependency: Option<Self::Dependency>,
386    ) -> Self::RefMut {
387        if let ManagedValueDependency::RefMut(lifetime) =
388            dependency.expect("`DynamicManagedRefMut` require dependency for lifetime bound!")
389        {
390            DynamicManagedRefMut::new(value, lifetime)
391        } else {
392            panic!("Could not borrow lifetime mutably to create `DynamicManagedRefMut`!")
393        }
394    }
395
396    fn into_owned(value: Self::Owned) -> Self::Type {
397        value.consume().ok().unwrap()
398    }
399
400    fn into_ref(value: &Self::Ref) -> Self::Borrow<'_> {
401        value.read().unwrap()
402    }
403
404    fn into_ref_mut(value: &mut Self::RefMut) -> Self::BorrowMut<'_> {
405        value.write().unwrap()
406    }
407}
408
409/// A borrow token keeping a value alive while a reference to it is out.
410///
411/// This is the [`ValueTransformer::Dependency`] of every managed transformer.
412pub enum ManagedValueDependency {
413    /// A shared borrow of the owner.
414    Ref(LifetimeRef),
415    /// An exclusive borrow of the owner.
416    RefMut(LifetimeRefMut),
417}
418
419impl<T> ValueDependency<Managed<T>> for ManagedValueDependency {
420    fn as_ref(value: &Managed<T>) -> Self {
421        Self::Ref(value.lifetime().borrow().unwrap())
422    }
423
424    fn as_ref_mut(value: &mut Managed<T>) -> Self {
425        Self::RefMut(value.lifetime().borrow_mut().unwrap())
426    }
427}
428
429impl<T> ValueDependency<ManagedRef<T>> for ManagedValueDependency {
430    fn as_ref(value: &ManagedRef<T>) -> Self {
431        Self::Ref(value.lifetime().borrow().unwrap())
432    }
433
434    fn as_ref_mut(_: &mut ManagedRef<T>) -> Self {
435        panic!("Cannot borrow lifetime mutably from `ManagedRef`!");
436    }
437}
438
439impl<T> ValueDependency<ManagedRefMut<T>> for ManagedValueDependency {
440    fn as_ref(value: &ManagedRefMut<T>) -> Self {
441        Self::Ref(value.lifetime().borrow().unwrap())
442    }
443
444    fn as_ref_mut(value: &mut ManagedRefMut<T>) -> Self {
445        Self::RefMut(value.lifetime().borrow_mut().unwrap())
446    }
447}
448
449impl ValueDependency<DynamicManaged> for ManagedValueDependency {
450    fn as_ref(value: &DynamicManaged) -> Self {
451        Self::Ref(value.lifetime().borrow().unwrap())
452    }
453
454    fn as_ref_mut(value: &mut DynamicManaged) -> Self {
455        Self::RefMut(value.lifetime().borrow_mut().unwrap())
456    }
457}
458
459impl ValueDependency<DynamicManagedRef> for ManagedValueDependency {
460    fn as_ref(value: &DynamicManagedRef) -> Self {
461        Self::Ref(value.lifetime().borrow().unwrap())
462    }
463
464    fn as_ref_mut(_: &mut DynamicManagedRef) -> Self {
465        panic!("Cannot borrow lifetime mutably from `DynamicManagedRef`!");
466    }
467}
468
469impl ValueDependency<DynamicManagedRefMut> for ManagedValueDependency {
470    fn as_ref(value: &DynamicManagedRefMut) -> Self {
471        Self::Ref(value.lifetime().borrow().unwrap())
472    }
473
474    fn as_ref_mut(value: &mut DynamicManagedRefMut) -> Self {
475        Self::RefMut(value.lifetime().borrow_mut().unwrap())
476    }
477}
478
479#[cfg(test)]
480mod tests {
481    use super::*;
482    use crate::{self as intuicio_core, IntuicioStruct, context::Context, define_native_struct};
483    use intuicio_derive::*;
484
485    #[intuicio_function(transformer = "ManagedValueTransformer")]
486    fn add(a: &i32, b: &mut i32) -> i32 {
487        *a + *b
488    }
489
490    #[intuicio_function(transformer = "DynamicManagedValueTransformer")]
491    fn sub(a: &i32, b: &mut i32) -> i32 {
492        *a - *b
493    }
494
495    #[intuicio_function(transformer = "ManagedGcValueTransformer")]
496    fn mul(a: &i32, b: &mut i32) -> i32 {
497        *a * *b
498    }
499
500    #[intuicio_function(transformer = "DynamicManagedGcValueTransformer")]
501    fn div(a: &i32, b: &mut i32) -> i32 {
502        *a / *b
503    }
504
505    #[derive(IntuicioStruct, Default, Clone)]
506    #[intuicio(name = "Foo")]
507    struct Foo {
508        bar: i32,
509    }
510
511    #[intuicio_methods(transformer = "ManagedValueTransformer")]
512    impl Foo {
513        #[intuicio_method()]
514        fn new(bar: i32) -> Foo {
515            Foo { bar }
516        }
517
518        #[intuicio_method(dependency = "this")]
519        fn get(&self) -> &i32 {
520            &self.bar
521        }
522
523        #[intuicio_method(dependency = "this")]
524        fn get_mut(&mut self) -> &mut i32 {
525            &mut self.bar
526        }
527    }
528
529    #[derive(IntuicioStruct, Debug, Default, Clone)]
530    #[intuicio(name = "Bar")]
531    struct Bar {
532        foo: i32,
533    }
534
535    #[intuicio_methods(transformer = "DynamicManagedValueTransformer")]
536    impl Bar {
537        #[intuicio_method()]
538        fn new(foo: i32) -> Bar {
539            Bar { foo }
540        }
541
542        #[intuicio_method(dependency = "this")]
543        fn get(&self) -> &i32 {
544            &self.foo
545        }
546    }
547
548    #[test]
549    fn test_derive() {
550        let mut registry = Registry::default().with_basic_types();
551        registry.add_type(define_native_struct! {
552            registry => struct (Managed<Foo>) {}
553        });
554        registry.add_type(define_native_struct! {
555            registry => struct (ManagedRef<Foo>) {}
556            [uninitialized]
557        });
558        registry.add_type(define_native_struct! {
559            registry => struct (ManagedRefMut<Foo>) {}
560            [uninitialized]
561        });
562        registry.add_type(define_native_struct! {
563            registry => struct (Managed<i32>) {}
564        });
565        registry.add_type(define_native_struct! {
566            registry => struct (DynamicManaged) {}
567            [uninitialized]
568        });
569        registry.add_type(define_native_struct! {
570            registry => struct (ManagedRef<i32>) {}
571            [uninitialized]
572        });
573        registry.add_type(define_native_struct! {
574            registry => struct (DynamicManagedRef) {}
575            [uninitialized]
576        });
577        registry.add_type(define_native_struct! {
578            registry => struct (ManagedRefMut<i32>) {}
579            [uninitialized]
580        });
581        registry.add_type(define_native_struct! {
582            registry => struct (DynamicManagedRefMut) {}
583            [uninitialized]
584        });
585        registry.add_type(define_native_struct! {
586            registry => struct (ManagedGc<i32>) {}
587        });
588        registry.add_type(define_native_struct! {
589            registry => struct (DynamicManagedGc) {}
590            [uninitialized]
591        });
592        registry.add_type(Foo::define_struct(&registry));
593        registry.add_function(Foo::new__define_function(&registry));
594        registry.add_type(Bar::define_struct(&registry));
595        registry.add_function(Bar::new__define_function(&registry));
596        let mut context = Context::new(10240, 10240);
597
598        let a = Managed::new(40);
599        let mut b = Managed::new(2);
600        context.stack().push(b.borrow_mut().unwrap());
601        context.stack().push(a.borrow().unwrap());
602        add::intuicio_function(&mut context, &registry);
603        assert_eq!(
604            context
605                .stack()
606                .pop::<Managed<i32>>()
607                .unwrap()
608                .consume()
609                .ok()
610                .unwrap(),
611            42
612        );
613        assert_eq!(
614            add::define_function(&registry)
615                .call::<(Managed<i32>,), _>(
616                    &mut context,
617                    &registry,
618                    (a.borrow().unwrap(), b.borrow_mut().unwrap()),
619                    true
620                )
621                .0
622                .consume()
623                .ok()
624                .unwrap(),
625            42
626        );
627        assert_eq!(add(&40, &mut 2), 42);
628
629        let a = DynamicManaged::new(40).unwrap();
630        let mut b = DynamicManaged::new(2).unwrap();
631        context.stack().push(b.borrow_mut().unwrap());
632        context.stack().push(a.borrow().unwrap());
633        sub::intuicio_function(&mut context, &registry);
634        assert_eq!(
635            context
636                .stack()
637                .pop::<DynamicManaged>()
638                .unwrap()
639                .consume::<i32>()
640                .ok()
641                .unwrap(),
642            38
643        );
644        assert_eq!(
645            sub::define_function(&registry)
646                .call::<(DynamicManaged,), _>(
647                    &mut context,
648                    &registry,
649                    (a.borrow().unwrap(), b.borrow_mut().unwrap()),
650                    true
651                )
652                .0
653                .consume::<i32>()
654                .ok()
655                .unwrap(),
656            38
657        );
658        assert_eq!(sub(&40, &mut 2), 38);
659
660        let a = ManagedGc::new(40);
661        let mut b = ManagedGc::new(2);
662        context.stack().push(b.borrow_mut::<false>());
663        context.stack().push(a.borrow::<false>());
664        mul::intuicio_function(&mut context, &registry);
665        assert_eq!(
666            *context
667                .stack()
668                .pop::<ManagedGc<i32>>()
669                .unwrap()
670                .try_read()
671                .unwrap(),
672            80
673        );
674        assert_eq!(
675            *mul::define_function(&registry)
676                .call::<(ManagedGc<i32>,), _>(
677                    &mut context,
678                    &registry,
679                    (a.borrow::<false>(), b.borrow_mut::<false>()),
680                    true
681                )
682                .0
683                .try_read()
684                .unwrap(),
685            80
686        );
687        assert_eq!(mul(&40, &mut 2), 80);
688
689        let a = DynamicManagedGc::new(40);
690        let mut b = DynamicManagedGc::new(2);
691        context.stack().push(b.borrow_mut::<false>());
692        context.stack().push(a.borrow::<false>());
693        div::intuicio_function(&mut context, &registry);
694        assert_eq!(
695            *context
696                .stack()
697                .pop::<DynamicManagedGc>()
698                .unwrap()
699                .try_read::<i32>()
700                .unwrap(),
701            20
702        );
703        assert_eq!(
704            *div::define_function(&registry)
705                .call::<(DynamicManagedGc,), _>(
706                    &mut context,
707                    &registry,
708                    (a.borrow::<false>(), b.borrow_mut::<false>()),
709                    true
710                )
711                .0
712                .try_read::<i32>()
713                .unwrap(),
714            20
715        );
716        assert_eq!(div(&40, &mut 2), 20);
717
718        let foo = Managed::new(Foo::new(42));
719        context.stack().push(foo.borrow().unwrap());
720        Foo::get__intuicio_function(&mut context, &registry);
721        assert_eq!(
722            *context
723                .stack()
724                .pop::<ManagedRef<i32>>()
725                .unwrap()
726                .read()
727                .unwrap(),
728            42
729        );
730        assert_eq!(
731            *Foo::get__define_function(&registry)
732                .call::<(ManagedRef<i32>,), _>(
733                    &mut context,
734                    &registry,
735                    (foo.borrow().unwrap(),),
736                    true
737                )
738                .0
739                .read()
740                .unwrap(),
741            42
742        );
743        assert_eq!(*Foo::new(42).get(), 42);
744
745        let mut foo = Managed::new(Foo::new(42));
746        context.stack().push(foo.borrow_mut().unwrap());
747        Foo::get_mut__intuicio_function(&mut context, &registry);
748        {
749            let mut result = context.stack().pop::<ManagedRefMut<i32>>().unwrap();
750            let mut result = result.write().unwrap();
751            assert_eq!(*result, 42);
752            *result = 10;
753        }
754        assert_eq!(foo.read().unwrap().bar, 10);
755
756        let bar = DynamicManaged::new(Bar::new(42)).unwrap();
757        context.stack().push(bar.borrow().unwrap());
758        Bar::get__intuicio_function(&mut context, &registry);
759        assert_eq!(
760            *context
761                .stack()
762                .pop::<DynamicManagedRef>()
763                .unwrap()
764                .read::<i32>()
765                .unwrap(),
766            42
767        );
768        assert_eq!(
769            *Bar::get__define_function(&registry)
770                .call::<(DynamicManagedRef,), _>(
771                    &mut context,
772                    &registry,
773                    (bar.borrow().unwrap(),),
774                    true
775                )
776                .0
777                .read::<i32>()
778                .unwrap(),
779            42
780        );
781        assert_eq!(*Bar::new(42).get(), 42);
782    }
783
784    #[test]
785    fn test_shared_value_transformer() {
786        fn add_wrapped(
787            a: <SharedValueTransformer<i32> as ValueTransformer>::Ref,
788            mut b: <SharedValueTransformer<i32> as ValueTransformer>::RefMut,
789        ) -> <SharedValueTransformer<i32> as ValueTransformer>::Owned {
790            let a = SharedValueTransformer::into_ref(&a);
791            let mut b = SharedValueTransformer::into_ref_mut(&mut b);
792            let result = {
793                let a = &a;
794                let b = &mut b;
795                add(a, b)
796            };
797            let registry = Registry::default();
798            SharedValueTransformer::from_owned(&registry, result)
799        }
800
801        assert_eq!(
802            add(&40, &mut 2),
803            *add_wrapped(Shared::new(40), Shared::new(2)).read().unwrap(),
804        );
805
806        fn get_wrapped(
807            foo: <SharedValueTransformer<Foo> as ValueTransformer>::Ref,
808        ) -> <SharedValueTransformer<i32> as ValueTransformer>::Ref {
809            let foo = SharedValueTransformer::into_ref(&foo);
810            let result = {
811                let foo = &foo;
812                Foo::get(foo)
813            };
814            let registry = Registry::default();
815            SharedValueTransformer::from_ref(&registry, result, None)
816        }
817
818        let foo = Shared::new(Foo { bar: 42 });
819        let a = *Foo::get(&foo.read().unwrap());
820        let b = *get_wrapped(foo.clone()).read().unwrap();
821        assert_eq!(a, b,);
822    }
823
824    #[test]
825    fn test_managed_value_transformer() {
826        fn add_wrapped(
827            a: <ManagedValueTransformer<i32> as ValueTransformer>::Ref,
828            mut b: <ManagedValueTransformer<i32> as ValueTransformer>::RefMut,
829        ) -> <ManagedValueTransformer<i32> as ValueTransformer>::Owned {
830            let a = ManagedValueTransformer::into_ref(&a);
831            let mut b = ManagedValueTransformer::into_ref_mut(&mut b);
832            let result = {
833                let a = &a;
834                let b = &mut b;
835                add(a, b)
836            };
837            let registry = Registry::default();
838            ManagedValueTransformer::from_owned(&registry, result)
839        }
840
841        let a = Managed::new(40);
842        let mut b = Managed::new(2);
843        assert_eq!(
844            add(&40, &mut 2),
845            *add_wrapped(a.borrow().unwrap(), b.borrow_mut().unwrap())
846                .read()
847                .unwrap(),
848        );
849
850        fn get_wrapped(
851            foo: <ManagedValueTransformer<Foo> as ValueTransformer>::Ref,
852        ) -> <ManagedValueTransformer<i32> as ValueTransformer>::Ref {
853            let dependency =
854                Some(<ManagedValueTransformer<i32> as ValueTransformer>::Dependency::as_ref(&foo));
855            let foo = ManagedValueTransformer::into_ref(&foo);
856            let result = {
857                let foo = &foo;
858                Foo::get(foo)
859            };
860            let registry = Registry::default();
861            ManagedValueTransformer::from_ref(&registry, result, dependency)
862        }
863
864        let foo = Managed::new(Foo { bar: 42 });
865        let a = *Foo::get(&foo.read().unwrap());
866        let b = *get_wrapped(foo.borrow().unwrap()).read().unwrap();
867        assert_eq!(a, b,);
868    }
869}