Skip to main content

intuicio_data/managed/
mod.rs

1//! Value boxes with runtime checked borrowing.
2//!
3//! A managed box is an owner plus a [`Lifetime`],
4//! so handles to it can be handed to a script and still be checked at
5//! runtime. When the owner goes away, every handle reports it instead of
6//! dangling.
7//!
8//! # The four roles
9//!
10//! | Role | Typed | Type-erased |
11//! |------|-------|-------------|
12//! | owns the value | [`Managed`] | [`DynamicManaged`] |
13//! | shared handle | [`ManagedRef`] | [`DynamicManagedRef`] |
14//! | exclusive handle | [`ManagedRefMut`] | [`DynamicManagedRefMut`] |
15//! | unclaimed handle | [`ManagedLazy`] | [`DynamicManagedLazy`] |
16//!
17//! The typed boxes know their Rust type at compile time. The dynamic ones
18//! carry a [`TypeHash`] instead and check it on every access, which is what
19//! script values use. `into_dynamic` and `into_typed` convert between them.
20//!
21//! Two more shapes build on these: [`value`] wraps all roles in one enum, so
22//! code can accept a value without caring how it is held, and [`gc`] adds
23//! boxes that survive reference cycles.
24//!
25//! ```
26//! # use intuicio_data::managed::Managed;
27//! let mut value = Managed::new(42);
28//! let borrow = value.borrow().unwrap();
29//! // a shared handle is out, so an exclusive one is refused
30//! assert!(value.borrow_mut().is_none());
31//! assert_eq!(*borrow.read().unwrap(), 42);
32//! ```
33pub mod gc;
34pub mod value;
35
36use crate::{
37    Finalize, Finalizer,
38    lifetime::{
39        Lifetime, LifetimeLazy, LifetimeRef, LifetimeRefMut, ValueReadAccess, ValueWriteAccess,
40    },
41    managed::value::{DynamicManagedValue, ManagedValue},
42    non_zero_alloc, non_zero_dealloc,
43    type_hash::TypeHash,
44};
45use std::{alloc::Layout, mem::MaybeUninit};
46
47/// Owner of a value plus its runtime borrow state.
48///
49/// The value is stored inline, so this is just `T` with a lifetime attached.
50/// Handles taken from it go dead when it is dropped. See the
51/// [module docs](self).
52#[derive(Default)]
53pub struct Managed<T> {
54    lifetime: Lifetime,
55    data: T,
56}
57
58impl<T> Managed<T> {
59    /// Takes ownership of a value with a fresh lifetime.
60    pub fn new(data: T) -> Self {
61        Self {
62            lifetime: Default::default(),
63            data,
64        }
65    }
66
67    /// Takes ownership of a value with a lifetime prepared elsewhere.
68    pub fn new_raw(data: T, lifetime: Lifetime) -> Self {
69        Self { lifetime, data }
70    }
71
72    /// Splits into the lifetime and the value, dropping no handles.
73    pub fn into_inner(self) -> (Lifetime, T) {
74        (self.lifetime, self.data)
75    }
76
77    /// Moves the value into a type-erased box, giving `self` back when the
78    /// allocation fails.
79    ///
80    /// The lifetime is not carried over, so handles taken so far go dead.
81    pub fn into_dynamic(self) -> Result<DynamicManaged, Self> {
82        match DynamicManaged::new(self.data) {
83            Ok(value) => Ok(value),
84            Err(data) => Err(Managed {
85                lifetime: self.lifetime,
86                data,
87            }),
88        }
89    }
90
91    /// Replaces the lifetime, killing every handle taken so far.
92    pub fn renew(mut self) -> Self {
93        self.lifetime = Lifetime::default();
94        self
95    }
96
97    /// Returns the borrow state of this value.
98    pub fn lifetime(&self) -> &Lifetime {
99        &self.lifetime
100    }
101
102    /// Guards the value for reading, or returns [`None`] while it is written.
103    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
104        self.lifetime.read(&self.data)
105    }
106
107    /// Guards the value for writing, or returns [`None`] while it is accessed.
108    pub fn write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
109        self.lifetime.write(&mut self.data)
110    }
111
112    /// Takes the value out, or gives the box back while any access guard is
113    /// live.
114    pub fn consume(self) -> Result<T, Self> {
115        if self.lifetime.state().is_in_use() {
116            Err(self)
117        } else {
118            Ok(self.data)
119        }
120    }
121
122    /// Moves the value into the place `target` points at.
123    ///
124    /// # Panics
125    ///
126    /// Panics when `target` cannot be written.
127    pub fn move_into_ref(self, mut target: ManagedRefMut<T>) -> Result<(), Self> {
128        *target.write().unwrap() = self.consume()?;
129        Ok(())
130    }
131
132    /// Moves the value into the place `target` points at.
133    ///
134    /// # Panics
135    ///
136    /// Panics when `target` cannot be written.
137    pub fn move_into_lazy(self, target: ManagedLazy<T>) -> Result<(), Self> {
138        *target.write().unwrap() = self.consume()?;
139        Ok(())
140    }
141
142    /// Takes a shared handle, or returns [`None`] when an exclusive one is out.
143    pub fn borrow(&self) -> Option<ManagedRef<T>> {
144        Some(ManagedRef::new(&self.data, self.lifetime.borrow()?))
145    }
146
147    /// Takes an exclusive handle, or returns [`None`] when any handle is out.
148    pub fn borrow_mut(&mut self) -> Option<ManagedRefMut<T>> {
149        Some(ManagedRefMut::new(
150            &mut self.data,
151            self.lifetime.borrow_mut()?,
152        ))
153    }
154
155    /// Takes an unclaimed handle.
156    pub fn lazy(&mut self) -> ManagedLazy<T> {
157        ManagedLazy::new(&mut self.data, self.lifetime.lazy())
158    }
159
160    /// [`Managed::lazy`] from a shared reference.
161    ///
162    /// # Safety
163    ///
164    /// The returned handle can write to a value the caller only borrowed
165    /// immutably. Only use it when nothing else holds a `&T` to it.
166    pub unsafe fn lazy_immutable(&self) -> ManagedLazy<T> {
167        unsafe {
168            ManagedLazy::new_raw(&self.data as *const T as *mut T, self.lifetime.lazy()).unwrap()
169        }
170    }
171
172    /// Replaces the value with one built from it, under a fresh lifetime.
173    ///
174    /// # Safety
175    ///
176    /// Handles taken so far are not checked before the value is moved out, and
177    /// they go dead. Nothing may be accessing the value.
178    pub unsafe fn map<U>(self, f: impl FnOnce(T) -> U) -> Managed<U> {
179        Managed {
180            lifetime: Default::default(),
181            data: f(self.data),
182        }
183    }
184
185    /// [`Managed::map`] that can decline, dropping the value when it does.
186    ///
187    /// # Safety
188    ///
189    /// Same as [`Managed::map`].
190    pub unsafe fn try_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Managed<U>> {
191        f(self.data).map(|data| Managed {
192            lifetime: Default::default(),
193            data,
194        })
195    }
196
197    /// Returns a pointer to the value, bypassing the borrow state.
198    ///
199    /// # Safety
200    ///
201    /// The caller takes over checking for conflicting access, and must not
202    /// outlive this box.
203    pub unsafe fn as_ptr(&self) -> *const T {
204        &self.data as _
205    }
206
207    /// Returns a mutable pointer to the value, bypassing the borrow state.
208    ///
209    /// # Safety
210    ///
211    /// The caller takes over checking for conflicting access, and must not
212    /// outlive this box.
213    pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
214        &mut self.data as _
215    }
216}
217
218/// Shared handle to a value owned by a [`Managed`], the runtime `&T`.
219///
220/// Keeps its claim until dropped, and reports a dead owner by returning
221/// [`None`] from [`ManagedRef::read`].
222pub struct ManagedRef<T: ?Sized> {
223    lifetime: LifetimeRef,
224    data: *const T,
225}
226
227unsafe impl<T: ?Sized> Send for ManagedRef<T> where T: Send {}
228unsafe impl<T: ?Sized> Sync for ManagedRef<T> where T: Sync {}
229
230impl<T: ?Sized> ManagedRef<T> {
231    /// Pairs a reference with a shared borrow taken from its lifetime.
232    pub fn new(data: &T, lifetime: LifetimeRef) -> Self {
233        Self {
234            lifetime,
235            data: data as *const T,
236        }
237    }
238
239    /// [`ManagedRef::new`] over a raw pointer. A null pointer yields [`None`].
240    ///
241    /// # Safety
242    ///
243    /// `data` must stay valid for as long as `lifetime` says it does, and
244    /// `lifetime` must be the borrow state that guards it.
245    pub unsafe fn new_raw(data: *const T, lifetime: LifetimeRef) -> Option<Self> {
246        if data.is_null() {
247            None
248        } else {
249            Some(Self { lifetime, data })
250        }
251    }
252
253    /// Builds a handle to a plain reference along with the lifetime that backs
254    /// it.
255    ///
256    /// The caller has to keep the returned [`Lifetime`] alive for at least as
257    /// long as the handle.
258    pub fn make(data: &T) -> (Self, Lifetime) {
259        let result = Lifetime::default();
260        (Self::new(data, result.borrow().unwrap()), result)
261    }
262
263    /// [`ManagedRef::make`] over a raw pointer.
264    ///
265    /// # Safety
266    ///
267    /// `data` must stay valid for as long as the returned handle lives.
268    pub unsafe fn make_raw(data: *const T) -> Option<(Self, Lifetime)> {
269        let result = Lifetime::default();
270        Some((
271            unsafe { Self::new_raw(data, result.borrow().unwrap()) }?,
272            result,
273        ))
274    }
275
276    /// Splits into the borrow token and the pointer.
277    pub fn into_inner(self) -> (LifetimeRef, *const T) {
278        (self.lifetime, self.data)
279    }
280
281    /// Erases the type, keeping the same claim.
282    pub fn into_dynamic(self) -> DynamicManagedRef {
283        unsafe {
284            DynamicManagedRef::new_raw(TypeHash::of::<T>(), self.lifetime, self.data as *const u8)
285                .unwrap()
286        }
287    }
288
289    /// Returns the borrow token.
290    pub fn lifetime(&self) -> &LifetimeRef {
291        &self.lifetime
292    }
293
294    /// Takes another shared handle to the same value.
295    pub fn borrow(&self) -> Option<ManagedRef<T>> {
296        Some(ManagedRef {
297            lifetime: self.lifetime.borrow()?,
298            data: self.data,
299        })
300    }
301
302    /// Turns this shared handle into an unclaimed one that can also write.
303    ///
304    /// # Safety
305    ///
306    /// The value was only borrowed immutably, so writing through the result is
307    /// only sound when nothing else holds a `&T` to it.
308    pub unsafe fn lazy_immutable(&self) -> ManagedLazy<T> {
309        ManagedLazy {
310            lifetime: self.lifetime.lazy(),
311            data: self.data as *mut T,
312        }
313    }
314
315    /// Guards the value for reading, or returns [`None`] when it is written or
316    /// the owner is gone.
317    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
318        unsafe { self.lifetime.read_ptr(self.data) }
319    }
320
321    /// Narrows this handle down to a part of the value, such as one field.
322    ///
323    /// # Safety
324    ///
325    /// `f` must return a reference into the same value, and the owner must
326    /// still be alive.
327    pub unsafe fn map<U>(self, f: impl FnOnce(&T) -> &U) -> ManagedRef<U> {
328        unsafe {
329            let data = f(&*self.data);
330            ManagedRef {
331                lifetime: self.lifetime,
332                data: data as *const U,
333            }
334        }
335    }
336
337    /// [`ManagedRef::map`] that can decline.
338    ///
339    /// # Safety
340    ///
341    /// Same as [`ManagedRef::map`].
342    pub unsafe fn try_map<U>(self, f: impl FnOnce(&T) -> Option<&U>) -> Option<ManagedRef<U>> {
343        unsafe {
344            f(&*self.data).map(|data| ManagedRef {
345                lifetime: self.lifetime,
346                data: data as *const U,
347            })
348        }
349    }
350
351    /// Returns the pointer while the owner is alive, bypassing access checks.
352    ///
353    /// # Safety
354    ///
355    /// The caller takes over checking for conflicting access.
356    pub unsafe fn as_ptr(&self) -> Option<*const T> {
357        if self.lifetime.exists() {
358            Some(self.data)
359        } else {
360            None
361        }
362    }
363}
364
365impl<T> TryFrom<ManagedValue<T>> for ManagedRef<T> {
366    type Error = ();
367
368    fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
369        match value {
370            ManagedValue::Ref(value) => Ok(value),
371            _ => Err(()),
372        }
373    }
374}
375
376/// Exclusive handle to a value owned by a [`Managed`], the runtime `&mut T`.
377///
378/// Can be reborrowed, both shared and exclusive, one level deeper.
379pub struct ManagedRefMut<T: ?Sized> {
380    lifetime: LifetimeRefMut,
381    data: *mut T,
382}
383
384unsafe impl<T: ?Sized> Send for ManagedRefMut<T> where T: Send {}
385unsafe impl<T: ?Sized> Sync for ManagedRefMut<T> where T: Sync {}
386
387impl<T: ?Sized> ManagedRefMut<T> {
388    /// Pairs a mutable reference with an exclusive borrow of its lifetime.
389    pub fn new(data: &mut T, lifetime: LifetimeRefMut) -> Self {
390        Self {
391            lifetime,
392            data: data as *mut T,
393        }
394    }
395
396    /// [`ManagedRefMut::new`] over a raw pointer. A null pointer yields
397    /// [`None`].
398    ///
399    /// # Safety
400    ///
401    /// `data` must stay valid and unaliased for as long as `lifetime` says it
402    /// does, and `lifetime` must be the borrow state that guards it.
403    pub unsafe fn new_raw(data: *mut T, lifetime: LifetimeRefMut) -> Option<Self> {
404        if data.is_null() {
405            None
406        } else {
407            Some(Self { lifetime, data })
408        }
409    }
410
411    /// Builds a handle to a plain mutable reference along with the lifetime that
412    /// backs it.
413    ///
414    /// The caller has to keep the returned [`Lifetime`] alive for at least as
415    /// long as the handle.
416    pub fn make(data: &mut T) -> (Self, Lifetime) {
417        let result = Lifetime::default();
418        (Self::new(data, result.borrow_mut().unwrap()), result)
419    }
420
421    /// [`ManagedRefMut::make`] over a raw pointer.
422    ///
423    /// # Safety
424    ///
425    /// `data` must stay valid and unaliased for as long as the returned handle
426    /// lives.
427    pub unsafe fn make_raw(data: *mut T) -> Option<(Self, Lifetime)> {
428        let result = Lifetime::default();
429        Some((
430            unsafe { Self::new_raw(data, result.borrow_mut().unwrap()) }?,
431            result,
432        ))
433    }
434
435    /// Splits into the borrow token and the pointer.
436    pub fn into_inner(self) -> (LifetimeRefMut, *mut T) {
437        (self.lifetime, self.data)
438    }
439
440    /// Erases the type, keeping the same claim.
441    pub fn into_dynamic(self) -> DynamicManagedRefMut {
442        unsafe {
443            DynamicManagedRefMut::new_raw(TypeHash::of::<T>(), self.lifetime, self.data as *mut u8)
444                .unwrap()
445        }
446    }
447
448    /// Returns the borrow token.
449    pub fn lifetime(&self) -> &LifetimeRefMut {
450        &self.lifetime
451    }
452
453    /// Takes a shared handle nested under this one.
454    pub fn borrow(&self) -> Option<ManagedRef<T>> {
455        Some(ManagedRef {
456            lifetime: self.lifetime.borrow()?,
457            data: self.data,
458        })
459    }
460
461    /// Takes an exclusive handle nested under this one.
462    pub fn borrow_mut(&mut self) -> Option<ManagedRefMut<T>> {
463        Some(ManagedRefMut {
464            lifetime: self.lifetime.borrow_mut()?,
465            data: self.data,
466        })
467    }
468
469    /// Takes an unclaimed handle.
470    pub fn lazy(&self) -> ManagedLazy<T> {
471        ManagedLazy {
472            lifetime: self.lifetime.lazy(),
473            data: self.data,
474        }
475    }
476
477    /// Guards the value for reading, or returns [`None`] when it is written or
478    /// the owner is gone.
479    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
480        unsafe { self.lifetime.read_ptr(self.data) }
481    }
482
483    /// Guards the value for writing, or returns [`None`] when it is accessed or
484    /// the owner is gone.
485    pub fn write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
486        unsafe { self.lifetime.write_ptr(self.data) }
487    }
488
489    /// Narrows this handle down to a part of the value, such as one field.
490    ///
491    /// # Safety
492    ///
493    /// `f` must return a reference into the same value, and the owner must
494    /// still be alive.
495    pub unsafe fn map<U>(self, f: impl FnOnce(&mut T) -> &mut U) -> ManagedRefMut<U> {
496        unsafe {
497            let data = f(&mut *self.data);
498            ManagedRefMut {
499                lifetime: self.lifetime,
500                data: data as *mut U,
501            }
502        }
503    }
504
505    /// [`ManagedRefMut::map`] that can decline.
506    ///
507    /// # Safety
508    ///
509    /// Same as [`ManagedRefMut::map`].
510    pub unsafe fn try_map<U>(
511        self,
512        f: impl FnOnce(&mut T) -> Option<&mut U>,
513    ) -> Option<ManagedRefMut<U>> {
514        unsafe {
515            f(&mut *self.data).map(|data| ManagedRefMut {
516                lifetime: self.lifetime,
517                data: data as *mut U,
518            })
519        }
520    }
521
522    /// Returns the pointer while the owner is alive, bypassing access checks.
523    ///
524    /// # Safety
525    ///
526    /// The caller takes over checking for conflicting access.
527    pub unsafe fn as_ptr(&self) -> Option<*const T> {
528        if self.lifetime.exists() {
529            Some(self.data)
530        } else {
531            None
532        }
533    }
534
535    /// Returns the mutable pointer while the owner is alive, bypassing access
536    /// checks.
537    ///
538    /// # Safety
539    ///
540    /// The caller takes over checking for conflicting access.
541    pub unsafe fn as_mut_ptr(&mut self) -> Option<*mut T> {
542        if self.lifetime.exists() {
543            Some(self.data)
544        } else {
545            None
546        }
547    }
548}
549
550impl<T> TryFrom<ManagedValue<T>> for ManagedRefMut<T> {
551    type Error = ();
552
553    fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
554        match value {
555            ManagedValue::RefMut(value) => Ok(value),
556            _ => Err(()),
557        }
558    }
559}
560
561/// Unclaimed handle to a value owned by a [`Managed`].
562///
563/// Holding one blocks nobody, and it can be cloned freely. Every access is
564/// checked when it happens. This is the handle a script variable holds, because
565/// such a variable is read and written at any point, with no Rust borrow to
566/// model it.
567pub struct ManagedLazy<T: ?Sized> {
568    lifetime: LifetimeLazy,
569    data: *mut T,
570}
571
572unsafe impl<T: ?Sized> Send for ManagedLazy<T> where T: Send {}
573unsafe impl<T: ?Sized> Sync for ManagedLazy<T> where T: Sync {}
574
575impl<T: ?Sized> Clone for ManagedLazy<T> {
576    fn clone(&self) -> Self {
577        Self {
578            lifetime: self.lifetime.clone(),
579            data: self.data,
580        }
581    }
582}
583
584impl<T: ?Sized> ManagedLazy<T> {
585    /// Pairs a mutable reference with an unclaimed handle to its lifetime.
586    pub fn new(data: &mut T, lifetime: LifetimeLazy) -> Self {
587        Self {
588            lifetime,
589            data: data as *mut T,
590        }
591    }
592
593    /// [`ManagedLazy::new`] over a raw pointer. A null pointer yields [`None`].
594    ///
595    /// # Safety
596    ///
597    /// `data` must stay valid for as long as `lifetime` says it does, and
598    /// `lifetime` must be the borrow state that guards it.
599    pub unsafe fn new_raw(data: *mut T, lifetime: LifetimeLazy) -> Option<Self> {
600        if data.is_null() {
601            None
602        } else {
603            Some(Self { lifetime, data })
604        }
605    }
606
607    /// Builds a handle to a plain mutable reference along with the lifetime that
608    /// backs it.
609    ///
610    /// The caller has to keep the returned [`Lifetime`] alive for at least as
611    /// long as the handle.
612    pub fn make(data: &mut T) -> (Self, Lifetime) {
613        let result = Lifetime::default();
614        (Self::new(data, result.lazy()), result)
615    }
616
617    /// [`ManagedLazy::make`] over a raw pointer.
618    ///
619    /// # Safety
620    ///
621    /// `data` must stay valid for as long as the returned handle lives.
622    pub unsafe fn make_raw(data: *mut T) -> Option<(Self, Lifetime)> {
623        let result = Lifetime::default();
624        Some((unsafe { Self::new_raw(data, result.lazy()) }?, result))
625    }
626
627    /// Splits into the lifetime handle and the pointer.
628    pub fn into_inner(self) -> (LifetimeLazy, *mut T) {
629        (self.lifetime, self.data)
630    }
631
632    /// Erases the type, keeping the same handle.
633    pub fn into_dynamic(self) -> DynamicManagedLazy {
634        unsafe {
635            DynamicManagedLazy::new_raw(TypeHash::of::<T>(), self.lifetime, self.data as *mut u8)
636                .unwrap()
637        }
638    }
639
640    /// Returns the lifetime handle.
641    pub fn lifetime(&self) -> &LifetimeLazy {
642        &self.lifetime
643    }
644
645    /// Upgrades to a shared handle that holds its claim.
646    pub fn borrow(&self) -> Option<ManagedRef<T>> {
647        Some(ManagedRef {
648            lifetime: self.lifetime.borrow()?,
649            data: self.data,
650        })
651    }
652
653    /// Upgrades to an exclusive handle that holds its claim.
654    pub fn borrow_mut(&mut self) -> Option<ManagedRefMut<T>> {
655        Some(ManagedRefMut {
656            lifetime: self.lifetime.borrow_mut()?,
657            data: self.data,
658        })
659    }
660
661    /// Guards the value for reading, or returns [`None`] when it is written or
662    /// the owner is gone.
663    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
664        unsafe { self.lifetime.read_ptr(self.data) }
665    }
666
667    /// Guards the value for writing, or returns [`None`] when it is accessed or
668    /// the owner is gone.
669    ///
670    /// Takes `&self`, since a lazy handle claims nothing of its own.
671    pub fn write(&'_ self) -> Option<ValueWriteAccess<'_, T>> {
672        unsafe { self.lifetime.write_ptr(self.data) }
673    }
674
675    /// Narrows this handle down to a part of the value, such as one field.
676    ///
677    /// # Safety
678    ///
679    /// `f` must return a reference into the same value, and the owner must
680    /// still be alive.
681    pub unsafe fn map<U>(self, f: impl FnOnce(&mut T) -> &mut U) -> ManagedLazy<U> {
682        unsafe {
683            let data = f(&mut *self.data);
684            ManagedLazy {
685                lifetime: self.lifetime,
686                data: data as *mut U,
687            }
688        }
689    }
690
691    /// [`ManagedLazy::map`] that can decline.
692    ///
693    /// # Safety
694    ///
695    /// Same as [`ManagedLazy::map`].
696    pub unsafe fn try_map<U>(
697        self,
698        f: impl FnOnce(&mut T) -> Option<&mut U>,
699    ) -> Option<ManagedLazy<U>> {
700        unsafe {
701            f(&mut *self.data).map(|data| ManagedLazy {
702                lifetime: self.lifetime,
703                data: data as *mut U,
704            })
705        }
706    }
707
708    /// Returns the pointer while the owner is alive, bypassing access checks.
709    ///
710    /// # Safety
711    ///
712    /// The caller takes over checking for conflicting access.
713    pub unsafe fn as_ptr(&self) -> Option<*const T> {
714        if self.lifetime.exists() {
715            Some(self.data)
716        } else {
717            None
718        }
719    }
720
721    /// Returns the mutable pointer while the owner is alive, bypassing access
722    /// checks.
723    ///
724    /// # Safety
725    ///
726    /// The caller takes over checking for conflicting access.
727    pub unsafe fn as_mut_ptr(&self) -> Option<*mut T> {
728        if self.lifetime.exists() {
729            Some(self.data)
730        } else {
731            None
732        }
733    }
734}
735
736impl<T> TryFrom<ManagedValue<T>> for ManagedLazy<T> {
737    type Error = ();
738
739    fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
740        match value {
741            ManagedValue::Lazy(value) => Ok(value),
742            _ => Err(()),
743        }
744    }
745}
746
747/// Owner of a value whose type is only known at runtime.
748///
749/// The [`Managed`] counterpart for script values: the value lives in its own
750/// allocation, identified by a [`TypeHash`] and destroyed through a stored
751/// drop function. Every typed access checks the hash first.
752pub struct DynamicManaged {
753    type_hash: TypeHash,
754    lifetime: Lifetime,
755    memory: *mut u8,
756    layout: Layout,
757    finalizer: Finalizer,
758    drop: bool,
759}
760
761unsafe impl Send for DynamicManaged {}
762unsafe impl Sync for DynamicManaged {}
763
764impl Drop for DynamicManaged {
765    fn drop(&mut self) {
766        if self.drop {
767            unsafe {
768                if self.memory.is_null() {
769                    return;
770                }
771                let data_pointer = self.memory.cast::<()>();
772                self.finalizer.finalize(data_pointer);
773                non_zero_dealloc(self.memory, self.layout);
774                self.memory = std::ptr::null_mut();
775            }
776        }
777    }
778}
779
780impl DynamicManaged {
781    /// Moves a value into a new allocation, giving it back when the allocation
782    /// fails.
783    pub fn new<T: Finalize>(data: T) -> Result<Self, T> {
784        let layout = Layout::new::<T>().pad_to_align();
785        unsafe {
786            let memory = non_zero_alloc(layout);
787            if memory.is_null() {
788                Err(data)
789            } else {
790                memory.cast::<T>().write(data);
791                Ok(Self {
792                    type_hash: TypeHash::of::<T>(),
793                    lifetime: Default::default(),
794                    memory,
795                    layout,
796                    finalizer: Finalizer::of::<T>(),
797                    drop: true,
798                })
799            }
800        }
801    }
802
803    /// Takes ownership of an existing allocation.
804    ///
805    /// Returns [`None`] for a null pointer. The box will free `memory` and run
806    /// `finalizer` on drop.
807    pub fn new_raw(
808        type_hash: TypeHash,
809        lifetime: Lifetime,
810        memory: *mut u8,
811        layout: Layout,
812        finalizer: impl Into<Finalizer>,
813    ) -> Option<Self> {
814        if memory.is_null() {
815            None
816        } else {
817            Some(Self {
818                type_hash,
819                lifetime,
820                memory,
821                layout,
822                finalizer: finalizer.into(),
823                drop: true,
824            })
825        }
826    }
827
828    /// Allocates room for a value without writing one into it.
829    ///
830    /// Nothing stops the box from running its finalizer on drop, so the caller
831    /// must fill the memory before it is dropped or read.
832    pub fn new_uninitialized(
833        type_hash: TypeHash,
834        layout: Layout,
835        finalizer: impl Into<Finalizer>,
836    ) -> Self {
837        let layout = layout.pad_to_align();
838        let memory = unsafe { non_zero_alloc(layout) };
839        Self {
840            type_hash,
841            lifetime: Default::default(),
842            memory,
843            layout,
844            finalizer: finalizer.into(),
845            drop: true,
846        }
847    }
848
849    /// Builds a box by copying a byte image of a value into a new allocation.
850    ///
851    /// # Safety
852    ///
853    /// `bytes` must be a valid image of a value of the type named by
854    /// `type_hash`, matching `layout`, and it is moved, so the caller must not
855    /// drop the source afterwards.
856    pub unsafe fn from_bytes(
857        type_hash: TypeHash,
858        lifetime: Lifetime,
859        bytes: Vec<u8>,
860        layout: Layout,
861        finalizer: impl Into<Finalizer>,
862    ) -> Self {
863        let layout = layout.pad_to_align();
864        let memory = unsafe { non_zero_alloc(layout) };
865        unsafe { memory.copy_from(bytes.as_ptr(), bytes.len()) };
866        Self {
867            type_hash,
868            lifetime,
869            memory,
870            layout,
871            finalizer: finalizer.into(),
872            drop: true,
873        }
874    }
875
876    /// Splits into the parts the box was built from, and stops it from freeing
877    /// the allocation.
878    ///
879    /// The caller becomes responsible for running the finalizer and freeing the
880    /// memory.
881    #[allow(clippy::type_complexity)]
882    pub fn into_inner(mut self) -> (TypeHash, Lifetime, *mut u8, Layout, Finalizer) {
883        self.drop = false;
884        (
885            self.type_hash,
886            std::mem::take(&mut self.lifetime),
887            self.memory,
888            self.layout,
889            self.finalizer.clone(),
890        )
891    }
892
893    /// Moves the value into a typed box, giving `self` back on a type mismatch
894    /// or while it is accessed.
895    pub fn into_typed<T>(self) -> Result<Managed<T>, Self> {
896        Ok(Managed::new(self.consume()?))
897    }
898
899    /// Replaces the lifetime, killing every handle taken so far.
900    pub fn renew(mut self) -> Self {
901        self.lifetime = Lifetime::default();
902        self
903    }
904
905    /// Returns the type of the stored value.
906    pub fn type_hash(&self) -> &TypeHash {
907        &self.type_hash
908    }
909
910    /// Returns the borrow state of this value.
911    pub fn lifetime(&self) -> &Lifetime {
912        &self.lifetime
913    }
914
915    /// Returns the layout of the allocation.
916    pub fn layout(&self) -> &Layout {
917        &self.layout
918    }
919
920    /// Returns how the stored value is destroyed.
921    pub fn finalizer(&self) -> &Finalizer {
922        &self.finalizer
923    }
924
925    /// Returns the value as raw bytes.
926    ///
927    /// # Safety
928    ///
929    /// Bypasses the borrow state, so the caller must know that nothing is
930    /// writing the value.
931    pub unsafe fn memory(&self) -> &[u8] {
932        unsafe { std::slice::from_raw_parts(self.memory, self.layout.size()) }
933    }
934
935    /// Returns the value as mutable raw bytes.
936    ///
937    /// # Safety
938    ///
939    /// Bypasses the borrow state, and writing bytes that are not a valid value
940    /// of the stored type makes every later access undefined.
941    pub unsafe fn memory_mut(&mut self) -> &mut [u8] {
942        unsafe { std::slice::from_raw_parts_mut(self.memory, self.layout.size()) }
943    }
944
945    /// Returns `true` when the stored type is `T`.
946    pub fn is<T>(&self) -> bool {
947        self.type_hash == TypeHash::of::<T>()
948    }
949
950    /// Guards the value for reading, or returns [`None`] on a type mismatch or
951    /// while it is written.
952    pub fn read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
953        if self.type_hash == TypeHash::of::<T>() {
954            unsafe { self.lifetime.read_ptr(self.memory.cast::<T>()) }
955        } else {
956            None
957        }
958    }
959
960    /// Guards the value for writing, or returns [`None`] on a type mismatch or
961    /// while it is accessed.
962    pub fn write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
963        if self.type_hash == TypeHash::of::<T>() {
964            unsafe { self.lifetime.write_ptr(self.memory.cast::<T>()) }
965        } else {
966            None
967        }
968    }
969
970    /// Takes the value out and frees the allocation.
971    ///
972    /// Gives the box back on a type mismatch or while any access guard is live.
973    pub fn consume<T>(mut self) -> Result<T, Self> {
974        if self.type_hash == TypeHash::of::<T>() && !self.lifetime.state().is_in_use() {
975            if self.memory.is_null() {
976                return Err(self);
977            }
978            self.drop = false;
979            let mut result = MaybeUninit::<T>::uninit();
980            unsafe {
981                result.as_mut_ptr().copy_from(self.memory.cast::<T>(), 1);
982                non_zero_dealloc(self.memory, self.layout);
983                self.memory = std::ptr::null_mut();
984                Ok(result.assume_init())
985            }
986        } else {
987            Err(self)
988        }
989    }
990
991    /// Moves the value into the place `target` points at and frees this
992    /// allocation.
993    ///
994    /// Gives the box back when the types differ or both sides are the same
995    /// allocation.
996    pub fn move_into_ref(self, target: DynamicManagedRefMut) -> Result<(), Self> {
997        if self.type_hash == target.type_hash && self.memory != target.data {
998            if self.memory.is_null() {
999                return Err(self);
1000            }
1001            let (_, _, memory, layout, _) = self.into_inner();
1002            unsafe {
1003                target.data.copy_from(memory, layout.size());
1004                non_zero_dealloc(memory, layout);
1005            }
1006            Ok(())
1007        } else {
1008            Err(self)
1009        }
1010    }
1011
1012    /// Moves the value into the place `target` points at and frees this
1013    /// allocation.
1014    ///
1015    /// Gives the box back when the types differ or both sides are the same
1016    /// allocation.
1017    pub fn move_into_lazy(self, target: DynamicManagedLazy) -> Result<(), Self> {
1018        if self.type_hash == target.type_hash && self.memory != target.data {
1019            if self.memory.is_null() {
1020                return Err(self);
1021            }
1022            let (_, _, memory, layout, _) = self.into_inner();
1023            unsafe {
1024                target.data.copy_from(memory, layout.size());
1025                non_zero_dealloc(memory, layout);
1026            }
1027            Ok(())
1028        } else {
1029            Err(self)
1030        }
1031    }
1032
1033    /// Takes a shared handle, or returns [`None`] when an exclusive one is out.
1034    pub fn borrow(&self) -> Option<DynamicManagedRef> {
1035        unsafe { DynamicManagedRef::new_raw(self.type_hash, self.lifetime.borrow()?, self.memory) }
1036    }
1037
1038    /// Takes an exclusive handle, or returns [`None`] when any handle is out.
1039    pub fn borrow_mut(&mut self) -> Option<DynamicManagedRefMut> {
1040        unsafe {
1041            DynamicManagedRefMut::new_raw(self.type_hash, self.lifetime.borrow_mut()?, self.memory)
1042        }
1043    }
1044
1045    /// Takes an unclaimed handle.
1046    pub fn lazy(&self) -> DynamicManagedLazy {
1047        unsafe {
1048            DynamicManagedLazy::new_raw(self.type_hash, self.lifetime.lazy(), self.memory).unwrap()
1049        }
1050    }
1051
1052    /// Replaces the value with one built from it, in a new allocation.
1053    ///
1054    /// # Safety
1055    ///
1056    /// Handles taken so far are not checked before the value is moved out, and
1057    /// they go dead. Returns [`None`] when the stored type is not `T`.
1058    pub unsafe fn map<T, U: Finalize>(self, f: impl FnOnce(T) -> U) -> Option<Self> {
1059        let data = self.consume::<T>().ok()?;
1060        let data = f(data);
1061        Self::new(data).ok()
1062    }
1063
1064    /// [`DynamicManaged::map`] that can decline, dropping the value when it
1065    /// does.
1066    ///
1067    /// # Safety
1068    ///
1069    /// Same as [`DynamicManaged::map`].
1070    pub unsafe fn try_map<T, U: Finalize>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Self> {
1071        let data = self.consume::<T>().ok()?;
1072        let data = f(data)?;
1073        Self::new(data).ok()
1074    }
1075
1076    /// Returns a typed pointer while nothing is accessing the value.
1077    ///
1078    /// # Safety
1079    ///
1080    /// The caller takes over checking for conflicting access.
1081    pub unsafe fn as_ptr<T>(&self) -> Option<*const T> {
1082        if self.type_hash == TypeHash::of::<T>() && !self.lifetime.state().is_in_use() {
1083            Some(self.memory.cast::<T>())
1084        } else {
1085            None
1086        }
1087    }
1088
1089    /// Returns a typed mutable pointer while nothing is accessing the value.
1090    ///
1091    /// # Safety
1092    ///
1093    /// The caller takes over checking for conflicting access.
1094    pub unsafe fn as_mut_ptr<T>(&mut self) -> Option<*mut T> {
1095        if self.type_hash == TypeHash::of::<T>() && !self.lifetime.state().is_in_use() {
1096            Some(self.memory.cast::<T>())
1097        } else {
1098            None
1099        }
1100    }
1101
1102    /// Returns the allocation pointer, checking nothing at all.
1103    ///
1104    /// # Safety
1105    ///
1106    /// Neither the type nor the borrow state is checked.
1107    pub unsafe fn as_ptr_raw(&self) -> *const u8 {
1108        self.memory
1109    }
1110
1111    /// Returns the mutable allocation pointer, checking nothing at all.
1112    ///
1113    /// # Safety
1114    ///
1115    /// Neither the type nor the borrow state is checked.
1116    pub unsafe fn as_mut_ptr_raw(&mut self) -> *mut u8 {
1117        self.memory
1118    }
1119}
1120
1121impl TryFrom<DynamicManagedValue> for DynamicManaged {
1122    type Error = ();
1123
1124    fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1125        match value {
1126            DynamicManagedValue::Owned(value) => Ok(value),
1127            _ => Err(()),
1128        }
1129    }
1130}
1131
1132/// Shared handle to a value whose type is only known at runtime.
1133///
1134/// The [`ManagedRef`] counterpart for script values.
1135pub struct DynamicManagedRef {
1136    type_hash: TypeHash,
1137    lifetime: LifetimeRef,
1138    data: *const u8,
1139}
1140
1141unsafe impl Send for DynamicManagedRef {}
1142unsafe impl Sync for DynamicManagedRef {}
1143
1144impl DynamicManagedRef {
1145    /// Pairs a reference with a shared borrow taken from its lifetime.
1146    pub fn new<T: ?Sized>(data: &T, lifetime: LifetimeRef) -> Self {
1147        Self {
1148            type_hash: TypeHash::of::<T>(),
1149            lifetime,
1150            data: data as *const T as *const u8,
1151        }
1152    }
1153
1154    /// [`DynamicManagedRef::new`] for a type only known at runtime. A null
1155    /// pointer yields [`None`].
1156    ///
1157    /// # Safety
1158    ///
1159    /// `data` must point at a value of the type named by `type_hash`, and must
1160    /// stay valid for as long as `lifetime` says it does.
1161    pub unsafe fn new_raw(
1162        type_hash: TypeHash,
1163        lifetime: LifetimeRef,
1164        data: *const u8,
1165    ) -> Option<Self> {
1166        if data.is_null() {
1167            None
1168        } else {
1169            Some(Self {
1170                type_hash,
1171                lifetime,
1172                data,
1173            })
1174        }
1175    }
1176
1177    /// Builds a handle to a plain reference along with the lifetime that backs
1178    /// it.
1179    pub fn make<T: ?Sized>(data: &T) -> (Self, Lifetime) {
1180        let result = Lifetime::default();
1181        (Self::new(data, result.borrow().unwrap()), result)
1182    }
1183
1184    /// Splits into type, borrow token and pointer.
1185    pub fn into_inner(self) -> (TypeHash, LifetimeRef, *const u8) {
1186        (self.type_hash, self.lifetime, self.data)
1187    }
1188
1189    /// Recovers the typed handle, or gives `self` back on a type mismatch.
1190    pub fn into_typed<T>(self) -> Result<ManagedRef<T>, Self> {
1191        if self.type_hash == TypeHash::of::<T>() {
1192            unsafe { Ok(ManagedRef::new_raw(self.data.cast::<T>(), self.lifetime).unwrap()) }
1193        } else {
1194            Err(self)
1195        }
1196    }
1197
1198    /// Returns the type of the value.
1199    pub fn type_hash(&self) -> &TypeHash {
1200        &self.type_hash
1201    }
1202
1203    /// Returns the borrow token.
1204    pub fn lifetime(&self) -> &LifetimeRef {
1205        &self.lifetime
1206    }
1207
1208    /// Takes another shared handle to the same value.
1209    pub fn borrow(&self) -> Option<DynamicManagedRef> {
1210        Some(DynamicManagedRef {
1211            type_hash: self.type_hash,
1212            lifetime: self.lifetime.borrow()?,
1213            data: self.data,
1214        })
1215    }
1216
1217    /// Turns this shared handle into an unclaimed one that can also write.
1218    ///
1219    /// # Safety
1220    ///
1221    /// The value was only borrowed immutably, so writing through the result is
1222    /// only sound when nothing else holds a shared reference to it.
1223    pub unsafe fn lazy_immutable(&self) -> DynamicManagedLazy {
1224        DynamicManagedLazy {
1225            type_hash: self.type_hash,
1226            lifetime: self.lifetime.lazy(),
1227            data: self.data as *mut u8,
1228        }
1229    }
1230
1231    /// Returns `true` when the value is a `T`.
1232    pub fn is<T>(&self) -> bool {
1233        self.type_hash == TypeHash::of::<T>()
1234    }
1235
1236    /// Guards the value for reading, or returns [`None`] on a type mismatch or
1237    /// while it is written.
1238    pub fn read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
1239        if self.type_hash == TypeHash::of::<T>() {
1240            unsafe { self.lifetime.read_ptr(self.data.cast::<T>()) }
1241        } else {
1242            None
1243        }
1244    }
1245
1246    /// Narrows this handle down to a part of the value, retyping it to `U`.
1247    ///
1248    /// # Safety
1249    ///
1250    /// `f` must return a reference into the same value, and the owner must
1251    /// still be alive. Returns [`None`] when the value is not a `T`.
1252    pub unsafe fn map<T, U>(self, f: impl FnOnce(&T) -> &U) -> Option<Self> {
1253        if self.type_hash == TypeHash::of::<T>() {
1254            unsafe {
1255                let data = f(&*self.data.cast::<T>());
1256                Some(Self {
1257                    type_hash: TypeHash::of::<U>(),
1258                    lifetime: self.lifetime,
1259                    data: data as *const U as *const u8,
1260                })
1261            }
1262        } else {
1263            None
1264        }
1265    }
1266
1267    /// [`DynamicManagedRef::map`] that can decline.
1268    ///
1269    /// # Safety
1270    ///
1271    /// Same as [`DynamicManagedRef::map`].
1272    pub unsafe fn try_map<T, U>(self, f: impl FnOnce(&T) -> Option<&U>) -> Option<Self> {
1273        if self.type_hash == TypeHash::of::<T>() {
1274            unsafe {
1275                let data = f(&*self.data.cast::<T>())?;
1276                Some(Self {
1277                    type_hash: TypeHash::of::<U>(),
1278                    lifetime: self.lifetime,
1279                    data: data as *const U as *const u8,
1280                })
1281            }
1282        } else {
1283            None
1284        }
1285    }
1286
1287    /// Returns a typed pointer while the owner is alive.
1288    ///
1289    /// # Safety
1290    ///
1291    /// The caller takes over checking for conflicting access.
1292    pub unsafe fn as_ptr<T>(&self) -> Option<*const T> {
1293        if self.type_hash == TypeHash::of::<T>() && self.lifetime.exists() {
1294            Some(self.data.cast::<T>())
1295        } else {
1296            None
1297        }
1298    }
1299
1300    /// Returns the untyped pointer while the owner is alive.
1301    ///
1302    /// # Safety
1303    ///
1304    /// Neither the type nor conflicting access is checked.
1305    pub unsafe fn as_ptr_raw(&self) -> Option<*const u8> {
1306        if self.lifetime.exists() {
1307            Some(self.data)
1308        } else {
1309            None
1310        }
1311    }
1312}
1313
1314impl TryFrom<DynamicManagedValue> for DynamicManagedRef {
1315    type Error = ();
1316
1317    fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1318        match value {
1319            DynamicManagedValue::Ref(value) => Ok(value),
1320            _ => Err(()),
1321        }
1322    }
1323}
1324
1325/// Exclusive handle to a value whose type is only known at runtime.
1326///
1327/// The [`ManagedRefMut`] counterpart for script values.
1328pub struct DynamicManagedRefMut {
1329    type_hash: TypeHash,
1330    lifetime: LifetimeRefMut,
1331    data: *mut u8,
1332}
1333
1334unsafe impl Send for DynamicManagedRefMut {}
1335unsafe impl Sync for DynamicManagedRefMut {}
1336
1337impl DynamicManagedRefMut {
1338    /// Pairs a mutable reference with an exclusive borrow of its lifetime.
1339    pub fn new<T: ?Sized>(data: &mut T, lifetime: LifetimeRefMut) -> Self {
1340        Self {
1341            type_hash: TypeHash::of::<T>(),
1342            lifetime,
1343            data: data as *mut T as *mut u8,
1344        }
1345    }
1346
1347    /// [`DynamicManagedRefMut::new`] for a type only known at runtime. A null
1348    /// pointer yields [`None`].
1349    ///
1350    /// # Safety
1351    ///
1352    /// `data` must point at a value of the type named by `type_hash`, and must
1353    /// stay valid and unaliased for as long as `lifetime` says it does.
1354    pub unsafe fn new_raw(
1355        type_hash: TypeHash,
1356        lifetime: LifetimeRefMut,
1357        data: *mut u8,
1358    ) -> Option<Self> {
1359        if data.is_null() {
1360            None
1361        } else {
1362            Some(Self {
1363                type_hash,
1364                lifetime,
1365                data,
1366            })
1367        }
1368    }
1369
1370    /// Builds a handle to a plain mutable reference along with the lifetime that
1371    /// backs it.
1372    pub fn make<T: ?Sized>(data: &mut T) -> (Self, Lifetime) {
1373        let result = Lifetime::default();
1374        (Self::new(data, result.borrow_mut().unwrap()), result)
1375    }
1376
1377    /// Splits into type, borrow token and pointer.
1378    pub fn into_inner(self) -> (TypeHash, LifetimeRefMut, *mut u8) {
1379        (self.type_hash, self.lifetime, self.data)
1380    }
1381
1382    /// Recovers the typed handle, or gives `self` back on a type mismatch.
1383    pub fn into_typed<T>(self) -> Result<ManagedRefMut<T>, Self> {
1384        if self.type_hash == TypeHash::of::<T>() {
1385            unsafe { Ok(ManagedRefMut::new_raw(self.data.cast::<T>(), self.lifetime).unwrap()) }
1386        } else {
1387            Err(self)
1388        }
1389    }
1390
1391    /// Returns the type of the value.
1392    pub fn type_hash(&self) -> &TypeHash {
1393        &self.type_hash
1394    }
1395
1396    /// Returns the borrow token.
1397    pub fn lifetime(&self) -> &LifetimeRefMut {
1398        &self.lifetime
1399    }
1400
1401    /// Takes a shared handle nested under this one.
1402    pub fn borrow(&self) -> Option<DynamicManagedRef> {
1403        Some(DynamicManagedRef {
1404            type_hash: self.type_hash,
1405            lifetime: self.lifetime.borrow()?,
1406            data: self.data,
1407        })
1408    }
1409
1410    /// Takes an exclusive handle nested under this one.
1411    pub fn borrow_mut(&mut self) -> Option<DynamicManagedRefMut> {
1412        Some(DynamicManagedRefMut {
1413            type_hash: self.type_hash,
1414            lifetime: self.lifetime.borrow_mut()?,
1415            data: self.data,
1416        })
1417    }
1418
1419    /// Takes an unclaimed handle.
1420    pub fn lazy(&self) -> DynamicManagedLazy {
1421        DynamicManagedLazy {
1422            type_hash: self.type_hash,
1423            lifetime: self.lifetime.lazy(),
1424            data: self.data,
1425        }
1426    }
1427
1428    /// Returns `true` when the value is a `T`.
1429    pub fn is<T>(&self) -> bool {
1430        self.type_hash == TypeHash::of::<T>()
1431    }
1432
1433    /// Guards the value for reading, or returns [`None`] on a type mismatch or
1434    /// while it is written.
1435    pub fn read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
1436        if self.type_hash == TypeHash::of::<T>() {
1437            unsafe { self.lifetime.read_ptr(self.data.cast::<T>()) }
1438        } else {
1439            None
1440        }
1441    }
1442
1443    /// Guards the value for writing, or returns [`None`] on a type mismatch or
1444    /// while it is accessed.
1445    pub fn write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
1446        if self.type_hash == TypeHash::of::<T>() {
1447            unsafe { self.lifetime.write_ptr(self.data.cast::<T>()) }
1448        } else {
1449            None
1450        }
1451    }
1452
1453    /// Narrows this handle down to a part of the value, retyping it to `U`.
1454    ///
1455    /// # Safety
1456    ///
1457    /// `f` must return a reference into the same value, and the owner must
1458    /// still be alive. Returns [`None`] when the value is not a `T`.
1459    pub unsafe fn map<T, U>(self, f: impl FnOnce(&mut T) -> &mut U) -> Option<Self> {
1460        if self.type_hash == TypeHash::of::<T>() {
1461            unsafe {
1462                let data = f(&mut *self.data.cast::<T>());
1463                Some(Self {
1464                    type_hash: TypeHash::of::<U>(),
1465                    lifetime: self.lifetime,
1466                    data: data as *mut U as *mut u8,
1467                })
1468            }
1469        } else {
1470            None
1471        }
1472    }
1473
1474    /// [`DynamicManagedRefMut::map`] that can decline.
1475    ///
1476    /// # Safety
1477    ///
1478    /// Same as [`DynamicManagedRefMut::map`].
1479    pub unsafe fn try_map<T, U>(self, f: impl FnOnce(&mut T) -> Option<&mut U>) -> Option<Self> {
1480        if self.type_hash == TypeHash::of::<T>() {
1481            unsafe {
1482                let data = f(&mut *self.data.cast::<T>())?;
1483                Some(Self {
1484                    type_hash: TypeHash::of::<U>(),
1485                    lifetime: self.lifetime,
1486                    data: data as *mut U as *mut u8,
1487                })
1488            }
1489        } else {
1490            None
1491        }
1492    }
1493
1494    /// Returns a typed pointer while the owner is alive.
1495    ///
1496    /// # Safety
1497    ///
1498    /// The caller takes over checking for conflicting access.
1499    pub unsafe fn as_ptr<T>(&self) -> Option<*const T> {
1500        if self.type_hash == TypeHash::of::<T>() && self.lifetime.exists() {
1501            Some(self.data.cast::<T>())
1502        } else {
1503            None
1504        }
1505    }
1506
1507    /// Returns a typed mutable pointer while the owner is alive.
1508    ///
1509    /// # Safety
1510    ///
1511    /// The caller takes over checking for conflicting access.
1512    pub unsafe fn as_mut_ptr<T>(&mut self) -> Option<*mut T> {
1513        if self.type_hash == TypeHash::of::<T>() && self.lifetime.exists() {
1514            Some(self.data.cast::<T>())
1515        } else {
1516            None
1517        }
1518    }
1519
1520    /// Returns the untyped pointer while the owner is alive.
1521    ///
1522    /// # Safety
1523    ///
1524    /// Neither the type nor conflicting access is checked.
1525    pub unsafe fn as_ptr_raw(&self) -> Option<*const u8> {
1526        if self.lifetime.exists() {
1527            Some(self.data)
1528        } else {
1529            None
1530        }
1531    }
1532
1533    /// Returns the untyped mutable pointer while the owner is alive.
1534    ///
1535    /// # Safety
1536    ///
1537    /// Neither the type nor conflicting access is checked.
1538    pub unsafe fn as_mut_ptr_raw(&mut self) -> Option<*mut u8> {
1539        if self.lifetime.exists() {
1540            Some(self.data)
1541        } else {
1542            None
1543        }
1544    }
1545}
1546
1547impl TryFrom<DynamicManagedValue> for DynamicManagedRefMut {
1548    type Error = ();
1549
1550    fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1551        match value {
1552            DynamicManagedValue::RefMut(value) => Ok(value),
1553            _ => Err(()),
1554        }
1555    }
1556}
1557
1558/// Unclaimed handle to a value whose type is only known at runtime.
1559///
1560/// The [`ManagedLazy`] counterpart for script values, and the handle script
1561/// variables usually hold.
1562pub struct DynamicManagedLazy {
1563    type_hash: TypeHash,
1564    lifetime: LifetimeLazy,
1565    data: *mut u8,
1566}
1567
1568unsafe impl Send for DynamicManagedLazy {}
1569unsafe impl Sync for DynamicManagedLazy {}
1570
1571impl Clone for DynamicManagedLazy {
1572    fn clone(&self) -> Self {
1573        Self {
1574            type_hash: self.type_hash,
1575            lifetime: self.lifetime.clone(),
1576            data: self.data,
1577        }
1578    }
1579}
1580
1581impl DynamicManagedLazy {
1582    /// Pairs a mutable reference with an unclaimed handle to its lifetime.
1583    pub fn new<T: ?Sized>(data: &mut T, lifetime: LifetimeLazy) -> Self {
1584        Self {
1585            type_hash: TypeHash::of::<T>(),
1586            lifetime,
1587            data: data as *mut T as *mut u8,
1588        }
1589    }
1590
1591    /// [`DynamicManagedLazy::new`] for a type only known at runtime. A null
1592    /// pointer yields [`None`].
1593    ///
1594    /// # Safety
1595    ///
1596    /// `data` must point at a value of the type named by `type_hash`, and must
1597    /// stay valid for as long as `lifetime` says it does.
1598    pub unsafe fn new_raw(
1599        type_hash: TypeHash,
1600        lifetime: LifetimeLazy,
1601        data: *mut u8,
1602    ) -> Option<Self> {
1603        if data.is_null() {
1604            None
1605        } else {
1606            Some(Self {
1607                type_hash,
1608                lifetime,
1609                data,
1610            })
1611        }
1612    }
1613
1614    /// Builds a handle to a plain mutable reference along with the lifetime that
1615    /// backs it.
1616    pub fn make<T: ?Sized>(data: &mut T) -> (Self, Lifetime) {
1617        let result = Lifetime::default();
1618        (Self::new(data, result.lazy()), result)
1619    }
1620
1621    /// Splits into type, lifetime handle and pointer.
1622    pub fn into_inner(self) -> (TypeHash, LifetimeLazy, *mut u8) {
1623        (self.type_hash, self.lifetime, self.data)
1624    }
1625
1626    /// Recovers the typed handle, or gives `self` back on a type mismatch.
1627    pub fn into_typed<T>(self) -> Result<ManagedLazy<T>, Self> {
1628        if self.type_hash == TypeHash::of::<T>() {
1629            unsafe { Ok(ManagedLazy::new_raw(self.data.cast::<T>(), self.lifetime).unwrap()) }
1630        } else {
1631            Err(self)
1632        }
1633    }
1634
1635    /// Returns the type of the value.
1636    pub fn type_hash(&self) -> &TypeHash {
1637        &self.type_hash
1638    }
1639
1640    /// Returns the lifetime handle.
1641    pub fn lifetime(&self) -> &LifetimeLazy {
1642        &self.lifetime
1643    }
1644
1645    /// Returns `true` when the value is a `T`.
1646    pub fn is<T>(&self) -> bool {
1647        self.type_hash == TypeHash::of::<T>()
1648    }
1649
1650    /// Guards the value for reading, or returns [`None`] on a type mismatch or
1651    /// while it is written.
1652    pub fn read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
1653        if self.type_hash == TypeHash::of::<T>() {
1654            unsafe { self.lifetime.read_ptr(self.data.cast::<T>()) }
1655        } else {
1656            None
1657        }
1658    }
1659
1660    /// Guards the value for writing, or returns [`None`] on a type mismatch or
1661    /// while it is accessed.
1662    ///
1663    /// Takes `&self`, since a lazy handle claims nothing of its own.
1664    pub fn write<T>(&'_ self) -> Option<ValueWriteAccess<'_, T>> {
1665        if self.type_hash == TypeHash::of::<T>() {
1666            unsafe { self.lifetime.write_ptr(self.data.cast::<T>()) }
1667        } else {
1668            None
1669        }
1670    }
1671
1672    /// Upgrades to a shared handle that holds its claim.
1673    pub fn borrow(&self) -> Option<DynamicManagedRef> {
1674        Some(DynamicManagedRef {
1675            type_hash: self.type_hash,
1676            lifetime: self.lifetime.borrow()?,
1677            data: self.data,
1678        })
1679    }
1680
1681    /// Upgrades to an exclusive handle that holds its claim.
1682    pub fn borrow_mut(&mut self) -> Option<DynamicManagedRefMut> {
1683        Some(DynamicManagedRefMut {
1684            type_hash: self.type_hash,
1685            lifetime: self.lifetime.borrow_mut()?,
1686            data: self.data,
1687        })
1688    }
1689
1690    /// Narrows this handle down to a part of the value, retyping it to `U`.
1691    ///
1692    /// # Safety
1693    ///
1694    /// `f` must return a reference into the same value, and the owner must
1695    /// still be alive. Returns [`None`] when the value is not a `T`.
1696    pub unsafe fn map<T, U>(self, f: impl FnOnce(&mut T) -> &mut U) -> Option<Self> {
1697        if self.type_hash == TypeHash::of::<T>() {
1698            unsafe {
1699                let data = f(&mut *self.data.cast::<T>());
1700                Some(Self {
1701                    type_hash: TypeHash::of::<U>(),
1702                    lifetime: self.lifetime,
1703                    data: data as *mut U as *mut u8,
1704                })
1705            }
1706        } else {
1707            None
1708        }
1709    }
1710
1711    /// [`DynamicManagedLazy::map`] that can decline.
1712    ///
1713    /// # Safety
1714    ///
1715    /// Same as [`DynamicManagedLazy::map`].
1716    pub unsafe fn try_map<T, U>(self, f: impl FnOnce(&mut T) -> Option<&mut U>) -> Option<Self> {
1717        if self.type_hash == TypeHash::of::<T>() {
1718            unsafe {
1719                let data = f(&mut *self.data.cast::<T>())?;
1720                Some(Self {
1721                    type_hash: TypeHash::of::<U>(),
1722                    lifetime: self.lifetime,
1723                    data: data as *mut U as *mut u8,
1724                })
1725            }
1726        } else {
1727            None
1728        }
1729    }
1730
1731    /// Returns a typed pointer while the owner is alive.
1732    ///
1733    /// # Safety
1734    ///
1735    /// The caller takes over checking for conflicting access.
1736    pub unsafe fn as_ptr<T>(&self) -> Option<*const T> {
1737        if self.type_hash == TypeHash::of::<T>() && self.lifetime.exists() {
1738            Some(self.data.cast::<T>())
1739        } else {
1740            None
1741        }
1742    }
1743
1744    /// Returns a typed mutable pointer while the owner is alive.
1745    ///
1746    /// # Safety
1747    ///
1748    /// The caller takes over checking for conflicting access.
1749    pub unsafe fn as_mut_ptr<T>(&self) -> Option<*mut T> {
1750        if self.type_hash == TypeHash::of::<T>() && self.lifetime.exists() {
1751            Some(self.data.cast::<T>())
1752        } else {
1753            None
1754        }
1755    }
1756
1757    /// Returns the untyped pointer while the owner is alive.
1758    ///
1759    /// # Safety
1760    ///
1761    /// Neither the type nor conflicting access is checked.
1762    pub unsafe fn as_ptr_raw(&self) -> Option<*const u8> {
1763        if self.lifetime.exists() {
1764            Some(self.data)
1765        } else {
1766            None
1767        }
1768    }
1769
1770    /// Returns the untyped mutable pointer while the owner is alive.
1771    ///
1772    /// # Safety
1773    ///
1774    /// Neither the type nor conflicting access is checked.
1775    pub unsafe fn as_mut_ptr_raw(&mut self) -> Option<*mut u8> {
1776        if self.lifetime.exists() {
1777            Some(self.data)
1778        } else {
1779            None
1780        }
1781    }
1782}
1783
1784impl TryFrom<DynamicManagedValue> for DynamicManagedLazy {
1785    type Error = ();
1786
1787    fn try_from(value: DynamicManagedValue) -> Result<Self, Self::Error> {
1788        match value {
1789            DynamicManagedValue::Lazy(value) => Ok(value),
1790            _ => Err(()),
1791        }
1792    }
1793}
1794
1795#[cfg(test)]
1796mod tests {
1797    use super::*;
1798    use std::any::Any;
1799
1800    fn is_async<T: Send + Sync + ?Sized>() {}
1801
1802    #[test]
1803    fn test_managed() {
1804        is_async::<Managed<()>>();
1805        is_async::<ManagedRef<()>>();
1806        is_async::<ManagedRefMut<()>>();
1807        is_async::<ManagedLazy<()>>();
1808        is_async::<ManagedValue<()>>();
1809
1810        let mut value = Managed::new(42);
1811        let mut value_ref = value.borrow_mut().unwrap();
1812        assert!(value_ref.write().is_some());
1813        let mut value_ref2 = value_ref.borrow_mut().unwrap();
1814        assert!(value_ref.write().is_some());
1815        assert!(value_ref2.write().is_some());
1816        drop(value_ref);
1817        let value_ref = value.borrow().unwrap();
1818        assert!(value.borrow().is_some());
1819        assert!(value.borrow_mut().is_none());
1820        drop(value_ref);
1821        assert!(value.borrow().is_some());
1822        assert!(value.borrow_mut().is_some());
1823        *value.write().unwrap() = 40;
1824        assert_eq!(*value.read().unwrap(), 40);
1825        *value.borrow_mut().unwrap().write().unwrap() = 2;
1826        assert_eq!(*value.read().unwrap(), 2);
1827        let value_ref = value.borrow().unwrap();
1828        let value_ref2 = value_ref.borrow().unwrap();
1829        drop(value_ref);
1830        assert!(value_ref2.read().is_some());
1831        let value_ref = value.borrow().unwrap();
1832        let value_lazy = value.lazy();
1833        assert_eq!(*value_lazy.read().unwrap(), 2);
1834        *value_lazy.write().unwrap() = 42;
1835        assert_eq!(*value_lazy.read().unwrap(), 42);
1836        drop(value);
1837        assert!(value_ref.read().is_none());
1838        assert!(value_ref2.read().is_none());
1839        assert!(value_lazy.read().is_none());
1840    }
1841
1842    #[test]
1843    fn test_dynamic_managed() {
1844        is_async::<DynamicManaged>();
1845        is_async::<DynamicManagedRef>();
1846        is_async::<DynamicManagedRefMut>();
1847        is_async::<DynamicManagedLazy>();
1848        is_async::<DynamicManagedValue>();
1849
1850        let mut value = DynamicManaged::new(42).unwrap();
1851        let mut value_ref = value.borrow_mut().unwrap();
1852        assert!(value_ref.write::<i32>().is_some());
1853        let mut value_ref2 = value_ref.borrow_mut().unwrap();
1854        assert!(value_ref.write::<i32>().is_some());
1855        assert!(value_ref2.write::<i32>().is_some());
1856        drop(value_ref);
1857        let value_ref = value.borrow().unwrap();
1858        assert!(value.borrow().is_some());
1859        assert!(value.borrow_mut().is_none());
1860        drop(value_ref);
1861        assert!(value.borrow().is_some());
1862        assert!(value.borrow_mut().is_some());
1863        *value.write::<i32>().unwrap() = 40;
1864        assert_eq!(*value.read::<i32>().unwrap(), 40);
1865        *value.borrow_mut().unwrap().write::<i32>().unwrap() = 2;
1866        assert_eq!(*value.read::<i32>().unwrap(), 2);
1867        let value_ref = value.borrow().unwrap();
1868        let value_ref2 = value_ref.borrow().unwrap();
1869        drop(value_ref);
1870        assert!(value_ref2.read::<i32>().is_some());
1871        let value_ref = value.borrow().unwrap();
1872        let value_lazy = value.lazy();
1873        assert_eq!(*value_lazy.read::<i32>().unwrap(), 2);
1874        *value_lazy.write::<i32>().unwrap() = 42;
1875        assert_eq!(*value_lazy.read::<i32>().unwrap(), 42);
1876        drop(value);
1877        assert!(value_ref.read::<i32>().is_none());
1878        assert!(value_ref2.read::<i32>().is_none());
1879        assert!(value_lazy.read::<i32>().is_none());
1880        let value = DynamicManaged::new("hello".to_owned()).unwrap();
1881        let value = value.consume::<String>().ok().unwrap();
1882        assert_eq!(value.as_str(), "hello");
1883    }
1884
1885    #[test]
1886    fn test_conversion() {
1887        let value = Managed::new(42);
1888        assert_eq!(*value.read().unwrap(), 42);
1889        let value = value.into_dynamic().ok().unwrap();
1890        assert_eq!(*value.read::<i32>().unwrap(), 42);
1891        let mut value = value.into_typed::<i32>().ok().unwrap();
1892        assert_eq!(*value.read().unwrap(), 42);
1893
1894        let value_ref = value.borrow().unwrap();
1895        assert_eq!(*value.read().unwrap(), 42);
1896        let value_ref = value_ref.into_dynamic();
1897        assert_eq!(*value_ref.read::<i32>().unwrap(), 42);
1898        let value_ref = value_ref.into_typed::<i32>().ok().unwrap();
1899        assert_eq!(*value_ref.read().unwrap(), 42);
1900        drop(value_ref);
1901
1902        let value_ref_mut = value.borrow_mut().unwrap();
1903        assert_eq!(*value.read().unwrap(), 42);
1904        let value_ref_mut = value_ref_mut.into_dynamic();
1905        assert_eq!(*value_ref_mut.read::<i32>().unwrap(), 42);
1906        let value_ref_mut = value_ref_mut.into_typed::<i32>().ok().unwrap();
1907        assert_eq!(*value_ref_mut.read().unwrap(), 42);
1908
1909        let value_lazy = value.lazy();
1910        assert_eq!(*value.read().unwrap(), 42);
1911        let value_lazy = value_lazy.into_dynamic();
1912        assert_eq!(*value_lazy.read::<i32>().unwrap(), 42);
1913        let value_lazy = value_lazy.into_typed::<i32>().ok().unwrap();
1914        assert_eq!(*value_lazy.read().unwrap(), 42);
1915    }
1916
1917    #[test]
1918    fn test_unsized() {
1919        let lifetime = Lifetime::default();
1920        let mut data = 42usize;
1921        {
1922            let foo = ManagedRef::<dyn Any>::new(&data, lifetime.borrow().unwrap());
1923            assert_eq!(
1924                *foo.read().unwrap().downcast_ref::<usize>().unwrap(),
1925                42usize
1926            );
1927        }
1928        {
1929            let mut foo = ManagedRefMut::<dyn Any>::new(&mut data, lifetime.borrow_mut().unwrap());
1930            *foo.write().unwrap().downcast_mut::<usize>().unwrap() = 100;
1931        }
1932        {
1933            let foo = ManagedLazy::<dyn Any>::new(&mut data, lifetime.lazy());
1934            assert_eq!(
1935                *foo.read().unwrap().downcast_ref::<usize>().unwrap(),
1936                100usize
1937            );
1938        }
1939
1940        let lifetime = Lifetime::default();
1941        let mut data = [0, 1, 2, 3];
1942        {
1943            let foo = ManagedRef::<[i32]>::new(&data, lifetime.borrow().unwrap());
1944            assert_eq!(*foo.read().unwrap(), [0, 1, 2, 3]);
1945        }
1946        {
1947            let mut foo = ManagedRefMut::<[i32]>::new(&mut data, lifetime.borrow_mut().unwrap());
1948            foo.write().unwrap().sort_by(|a, b| a.cmp(b).reverse());
1949        }
1950        {
1951            let foo = ManagedLazy::<[i32]>::new(&mut data, lifetime.lazy());
1952            assert_eq!(*foo.read().unwrap(), [3, 2, 1, 0]);
1953        }
1954    }
1955
1956    #[test]
1957    fn test_moves() {
1958        let mut value = Managed::new(42);
1959        assert_eq!(*value.read().unwrap(), 42);
1960        {
1961            let value_ref = value.borrow_mut().unwrap();
1962            Managed::new(1).move_into_ref(value_ref).ok().unwrap();
1963            assert_eq!(*value.read().unwrap(), 1);
1964        }
1965        {
1966            let value_lazy = value.lazy();
1967            Managed::new(2).move_into_lazy(value_lazy).ok().unwrap();
1968            assert_eq!(*value.read().unwrap(), 2);
1969        }
1970
1971        let mut value = DynamicManaged::new(42).unwrap();
1972        assert_eq!(*value.read::<i32>().unwrap(), 42);
1973        {
1974            let value_ref = value.borrow_mut().unwrap();
1975            DynamicManaged::new(1)
1976                .unwrap()
1977                .move_into_ref(value_ref)
1978                .ok()
1979                .unwrap();
1980            assert_eq!(*value.read::<i32>().unwrap(), 1);
1981        }
1982        {
1983            let value_lazy = value.lazy();
1984            DynamicManaged::new(2)
1985                .unwrap()
1986                .move_into_lazy(value_lazy)
1987                .ok()
1988                .unwrap();
1989            assert_eq!(*value.read::<i32>().unwrap(), 2);
1990        }
1991    }
1992
1993    #[test]
1994    fn test_move_invalidation() {
1995        let value = Managed::new(42);
1996        let value_ref = value.borrow().unwrap();
1997        assert_eq!(value.lifetime().tag(), value_ref.lifetime().tag());
1998        assert!(value_ref.lifetime().exists());
1999        let value = Box::new(value);
2000        assert_ne!(value.lifetime().tag(), value_ref.lifetime().tag());
2001        assert!(!value_ref.lifetime().exists());
2002        let value = *value;
2003        assert_ne!(value.lifetime().tag(), value_ref.lifetime().tag());
2004        assert!(!value_ref.lifetime().exists());
2005    }
2006}