Skip to main content

intuicio_data/managed/
value.rs

1//! One enum over every way a value can be held.
2//!
3//! A script does not care whether a value is owned, borrowed or garbage
4//! collected, it just wants to read or write it. [`ManagedValue`] and
5//! [`DynamicManagedValue`] wrap all of those roles and forward the common
6//! operations to whichever one is inside.
7//!
8//! Operations that the role cannot support return [`None`], so for example
9//! writing through a shared handle simply fails.
10use crate::{
11    lifetime::{ValueReadAccess, ValueWriteAccess},
12    managed::{
13        DynamicManaged, DynamicManagedLazy, DynamicManagedRef, DynamicManagedRefMut, Managed,
14        ManagedLazy, ManagedRef, ManagedRefMut,
15        gc::{DynamicManagedGc, ManagedGc},
16    },
17};
18
19/// A typed value held in any of the possible ways.
20///
21/// See the [module docs](self).
22pub enum ManagedValue<T> {
23    /// The value itself.
24    Owned(Managed<T>),
25    /// A shared handle to someone else's value.
26    Ref(ManagedRef<T>),
27    /// An exclusive handle to someone else's value.
28    RefMut(ManagedRefMut<T>),
29    /// An unclaimed handle to someone else's value.
30    Lazy(ManagedLazy<T>),
31    /// A garbage collected handle, owning or referencing.
32    Gc(ManagedGc<T>),
33}
34
35impl<T> ManagedValue<T> {
36    /// Returns the owned value, or [`None`] for any other role.
37    pub fn as_owned(&self) -> Option<&Managed<T>> {
38        match self {
39            Self::Owned(value) => Some(value),
40            _ => None,
41        }
42    }
43
44    /// Returns the owned value mutably, or [`None`] for any other role.
45    pub fn as_mut_owned(&mut self) -> Option<&mut Managed<T>> {
46        match self {
47            Self::Owned(value) => Some(value),
48            _ => None,
49        }
50    }
51
52    /// Returns the shared handle, or [`None`] for any other role.
53    pub fn as_ref(&self) -> Option<&ManagedRef<T>> {
54        match self {
55            Self::Ref(value) => Some(value),
56            _ => None,
57        }
58    }
59
60    /// Returns the shared handle mutably, or [`None`] for any other role.
61    pub fn as_mut_ref(&mut self) -> Option<&mut ManagedRef<T>> {
62        match self {
63            Self::Ref(value) => Some(value),
64            _ => None,
65        }
66    }
67
68    /// Returns the exclusive handle, or [`None`] for any other role.
69    pub fn as_ref_mut(&self) -> Option<&ManagedRefMut<T>> {
70        match self {
71            Self::RefMut(value) => Some(value),
72            _ => None,
73        }
74    }
75
76    /// Returns the exclusive handle mutably, or [`None`] for any other role.
77    pub fn as_mut_ref_mut(&mut self) -> Option<&mut ManagedRefMut<T>> {
78        match self {
79            Self::RefMut(value) => Some(value),
80            _ => None,
81        }
82    }
83
84    /// Returns the unclaimed handle, or [`None`] for any other role.
85    pub fn as_lazy(&self) -> Option<&ManagedLazy<T>> {
86        match self {
87            Self::Lazy(value) => Some(value),
88            _ => None,
89        }
90    }
91
92    /// Returns the unclaimed handle mutably, or [`None`] for any other role.
93    pub fn as_mut_lazy(&mut self) -> Option<&mut ManagedLazy<T>> {
94        match self {
95            Self::Lazy(value) => Some(value),
96            _ => None,
97        }
98    }
99
100    /// Returns the garbage collected handle, or [`None`] for any other role.
101    pub fn as_gc(&self) -> Option<&ManagedGc<T>> {
102        match self {
103            Self::Gc(value) => Some(value),
104            _ => None,
105        }
106    }
107
108    /// Returns the garbage collected handle mutably, or [`None`] for any other role.
109    pub fn as_mut_gc(&mut self) -> Option<&mut ManagedGc<T>> {
110        match self {
111            Self::Gc(value) => Some(value),
112            _ => None,
113        }
114    }
115
116    /// Guards the value for reading, whichever role holds it.
117    pub fn read(&'_ self) -> Option<ValueReadAccess<'_, T>> {
118        match self {
119            Self::Owned(value) => value.read(),
120            Self::Ref(value) => value.read(),
121            Self::RefMut(value) => value.read(),
122            Self::Lazy(value) => value.read(),
123            Self::Gc(value) => value.try_read(),
124        }
125    }
126
127    /// Guards the value for writing.
128    ///
129    /// Always [`None`] for a shared handle.
130    pub fn write(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
131        match self {
132            Self::Owned(value) => value.write(),
133            Self::RefMut(value) => value.write(),
134            Self::Lazy(value) => value.write(),
135            Self::Gc(value) => value.try_write(),
136            _ => None,
137        }
138    }
139
140    /// Takes a shared handle to the value.
141    ///
142    /// Always [`None`] for an unclaimed handle, which cannot lend its claim.
143    pub fn borrow(&self) -> Option<ManagedRef<T>> {
144        match self {
145            Self::Owned(value) => value.borrow(),
146            Self::Ref(value) => value.borrow(),
147            Self::RefMut(value) => value.borrow(),
148            Self::Gc(value) => value.try_borrow(),
149            _ => None,
150        }
151    }
152
153    /// Takes an exclusive handle to the value.
154    ///
155    /// Always [`None`] for shared and unclaimed handles.
156    pub fn borrow_mut(&mut self) -> Option<ManagedRefMut<T>> {
157        match self {
158            Self::Owned(value) => value.borrow_mut(),
159            Self::RefMut(value) => value.borrow_mut(),
160            Self::Gc(value) => value.try_borrow_mut(),
161            _ => None,
162        }
163    }
164
165    /// Takes an unclaimed handle to the value.
166    ///
167    /// Always [`None`] for a shared handle. See
168    /// [`ManagedValue::lazy_immutable`].
169    pub fn lazy(&mut self) -> Option<ManagedLazy<T>> {
170        match self {
171            Self::Owned(value) => Some(value.lazy()),
172            Self::Lazy(value) => Some(value.clone()),
173            Self::RefMut(value) => Some(value.lazy()),
174            Self::Gc(value) => Some(value.lazy()),
175            _ => None,
176        }
177    }
178
179    /// [`ManagedValue::lazy`] that also works for a shared handle.
180    ///
181    /// # Safety
182    ///
183    /// For a shared handle, the result can write to a value that was only
184    /// borrowed immutably.
185    pub unsafe fn lazy_immutable(&self) -> ManagedLazy<T> {
186        unsafe {
187            match self {
188                Self::Owned(value) => value.lazy_immutable(),
189                Self::Lazy(value) => value.clone(),
190                Self::Ref(value) => value.lazy_immutable(),
191                Self::RefMut(value) => value.lazy(),
192                Self::Gc(value) => value.lazy(),
193            }
194        }
195    }
196
197    /// Erases the type, giving `self` back when an owned value cannot be moved
198    /// into its own allocation.
199    pub fn into_dynamic(self) -> Result<DynamicManagedValue, Self> {
200        match self {
201            Self::Owned(value) => match value.into_dynamic() {
202                Ok(dynamic) => Ok(DynamicManagedValue::Owned(dynamic)),
203                Err(original) => Err(Self::Owned(original)),
204            },
205            Self::Ref(value) => Ok(DynamicManagedValue::Ref(value.into_dynamic())),
206            Self::RefMut(value) => Ok(DynamicManagedValue::RefMut(value.into_dynamic())),
207            Self::Lazy(value) => Ok(DynamicManagedValue::Lazy(value.into_dynamic())),
208            Self::Gc(value) => Ok(DynamicManagedValue::Gc(value.into_dynamic())),
209        }
210    }
211}
212
213impl<T> From<Managed<T>> for ManagedValue<T> {
214    fn from(value: Managed<T>) -> Self {
215        Self::Owned(value)
216    }
217}
218
219impl<T> TryFrom<ManagedValue<T>> for Managed<T> {
220    type Error = ();
221
222    fn try_from(value: ManagedValue<T>) -> Result<Self, Self::Error> {
223        match value {
224            ManagedValue::Owned(value) => Ok(value),
225            _ => Err(()),
226        }
227    }
228}
229
230impl<T> From<ManagedRef<T>> for ManagedValue<T> {
231    fn from(value: ManagedRef<T>) -> Self {
232        Self::Ref(value)
233    }
234}
235
236impl<T> From<ManagedRefMut<T>> for ManagedValue<T> {
237    fn from(value: ManagedRefMut<T>) -> Self {
238        Self::RefMut(value)
239    }
240}
241
242impl<T> From<ManagedLazy<T>> for ManagedValue<T> {
243    fn from(value: ManagedLazy<T>) -> Self {
244        Self::Lazy(value)
245    }
246}
247
248impl<T> From<ManagedGc<T>> for ManagedValue<T> {
249    fn from(value: ManagedGc<T>) -> Self {
250        Self::Gc(value)
251    }
252}
253
254/// A value of a runtime known type, held in any of the possible ways.
255///
256/// The [`ManagedValue`] counterpart for script values.
257pub enum DynamicManagedValue {
258    /// The value itself.
259    Owned(DynamicManaged),
260    /// A shared handle to someone else's value.
261    Ref(DynamicManagedRef),
262    /// An exclusive handle to someone else's value.
263    RefMut(DynamicManagedRefMut),
264    /// An unclaimed handle to someone else's value.
265    Lazy(DynamicManagedLazy),
266    /// A garbage collected handle, owning or referencing.
267    Gc(DynamicManagedGc),
268}
269
270impl DynamicManagedValue {
271    /// Returns the owned value, or [`None`] for any other role.
272    pub fn as_owned(&self) -> Option<&DynamicManaged> {
273        match self {
274            Self::Owned(value) => Some(value),
275            _ => None,
276        }
277    }
278
279    /// Returns the owned value mutably, or [`None`] for any other role.
280    pub fn as_mut_owned(&mut self) -> Option<&mut DynamicManaged> {
281        match self {
282            Self::Owned(value) => Some(value),
283            _ => None,
284        }
285    }
286
287    /// Returns the shared handle, or [`None`] for any other role.
288    pub fn as_ref(&self) -> Option<&DynamicManagedRef> {
289        match self {
290            Self::Ref(value) => Some(value),
291            _ => None,
292        }
293    }
294
295    /// Returns the shared handle mutably, or [`None`] for any other role.
296    pub fn as_mut_ref(&mut self) -> Option<&mut DynamicManagedRef> {
297        match self {
298            Self::Ref(value) => Some(value),
299            _ => None,
300        }
301    }
302
303    /// Returns the exclusive handle, or [`None`] for any other role.
304    pub fn as_ref_mut(&self) -> Option<&DynamicManagedRefMut> {
305        match self {
306            Self::RefMut(value) => Some(value),
307            _ => None,
308        }
309    }
310
311    /// Returns the exclusive handle mutably, or [`None`] for any other role.
312    pub fn as_mut_ref_mut(&mut self) -> Option<&mut DynamicManagedRefMut> {
313        match self {
314            Self::RefMut(value) => Some(value),
315            _ => None,
316        }
317    }
318
319    /// Returns the unclaimed handle, or [`None`] for any other role.
320    pub fn as_lazy(&self) -> Option<&DynamicManagedLazy> {
321        match self {
322            Self::Lazy(value) => Some(value),
323            _ => None,
324        }
325    }
326
327    /// Returns the unclaimed handle mutably, or [`None`] for any other role.
328    pub fn as_mut_lazy(&mut self) -> Option<&mut DynamicManagedLazy> {
329        match self {
330            Self::Lazy(value) => Some(value),
331            _ => None,
332        }
333    }
334
335    /// Returns the garbage collected handle, or [`None`] for any other role.
336    pub fn as_gc(&self) -> Option<&DynamicManagedGc> {
337        match self {
338            Self::Gc(value) => Some(value),
339            _ => None,
340        }
341    }
342
343    /// Returns the garbage collected handle mutably, or [`None`] for any other role.
344    pub fn as_mut_gc(&mut self) -> Option<&mut DynamicManagedGc> {
345        match self {
346            Self::Gc(value) => Some(value),
347            _ => None,
348        }
349    }
350
351    /// Guards the value for reading, whichever role holds it.
352    ///
353    /// Returns [`None`] when the value is not a `T`.
354    pub fn read<T>(&'_ self) -> Option<ValueReadAccess<'_, T>> {
355        match self {
356            Self::Owned(value) => value.read::<T>(),
357            Self::Ref(value) => value.read::<T>(),
358            Self::RefMut(value) => value.read::<T>(),
359            Self::Lazy(value) => value.read::<T>(),
360            Self::Gc(value) => value.try_read::<T>(),
361        }
362    }
363
364    /// Guards the value for writing.
365    ///
366    /// Always [`None`] for a shared handle, or when the value is not a `T`.
367    pub fn write<T>(&'_ mut self) -> Option<ValueWriteAccess<'_, T>> {
368        match self {
369            Self::Owned(value) => value.write::<T>(),
370            Self::RefMut(value) => value.write::<T>(),
371            Self::Lazy(value) => value.write::<T>(),
372            Self::Gc(value) => value.try_write::<T>(),
373            _ => None,
374        }
375    }
376
377    /// Takes a shared handle to the value.
378    ///
379    /// Always [`None`] for an unclaimed handle, which cannot lend its claim.
380    pub fn borrow(&self) -> Option<DynamicManagedRef> {
381        match self {
382            Self::Owned(value) => value.borrow(),
383            Self::Ref(value) => value.borrow(),
384            Self::RefMut(value) => value.borrow(),
385            Self::Gc(value) => value.try_borrow(),
386            _ => None,
387        }
388    }
389
390    /// Takes an exclusive handle to the value.
391    ///
392    /// Always [`None`] for shared and unclaimed handles.
393    pub fn borrow_mut(&mut self) -> Option<DynamicManagedRefMut> {
394        match self {
395            Self::Owned(value) => value.borrow_mut(),
396            Self::RefMut(value) => value.borrow_mut(),
397            Self::Gc(value) => value.try_borrow_mut(),
398            _ => None,
399        }
400    }
401
402    /// Takes an unclaimed handle to the value.
403    ///
404    /// Always [`None`] for a shared handle. See
405    /// [`DynamicManagedValue::lazy_immutable`].
406    pub fn lazy(&self) -> Option<DynamicManagedLazy> {
407        match self {
408            Self::Owned(value) => Some(value.lazy()),
409            Self::Lazy(value) => Some(value.clone()),
410            Self::RefMut(value) => Some(value.lazy()),
411            Self::Gc(value) => Some(value.lazy()),
412            _ => None,
413        }
414    }
415
416    /// [`DynamicManagedValue::lazy`] that also works for a shared handle.
417    ///
418    /// # Safety
419    ///
420    /// For a shared handle, the result can write to a value that was only
421    /// borrowed immutably.
422    pub unsafe fn lazy_immutable(&self) -> DynamicManagedLazy {
423        unsafe {
424            match self {
425                Self::Owned(value) => value.lazy(),
426                Self::Lazy(value) => value.clone(),
427                Self::Ref(value) => value.lazy_immutable(),
428                Self::RefMut(value) => value.lazy(),
429                Self::Gc(value) => value.lazy(),
430            }
431        }
432    }
433
434    /// Recovers the typed value, giving `self` back on a type mismatch.
435    pub fn into_typed<T>(self) -> Result<ManagedValue<T>, Self> {
436        match self {
437            Self::Owned(value) => match value.into_typed() {
438                Ok(typed) => Ok(ManagedValue::Owned(typed)),
439                Err(original) => Err(Self::Owned(original)),
440            },
441            Self::Ref(value) => match value.into_typed() {
442                Ok(typed) => Ok(ManagedValue::Ref(typed)),
443                Err(original) => Err(Self::Ref(original)),
444            },
445            Self::RefMut(value) => match value.into_typed() {
446                Ok(typed) => Ok(ManagedValue::RefMut(typed)),
447                Err(original) => Err(Self::RefMut(original)),
448            },
449            Self::Lazy(value) => match value.into_typed() {
450                Ok(typed) => Ok(ManagedValue::Lazy(typed)),
451                Err(original) => Err(Self::Lazy(original)),
452            },
453            Self::Gc(value) => Ok(ManagedValue::Gc(value.into_typed())),
454        }
455    }
456}
457
458impl From<DynamicManaged> for DynamicManagedValue {
459    fn from(value: DynamicManaged) -> Self {
460        Self::Owned(value)
461    }
462}
463
464impl From<DynamicManagedRef> for DynamicManagedValue {
465    fn from(value: DynamicManagedRef) -> Self {
466        Self::Ref(value)
467    }
468}
469
470impl From<DynamicManagedRefMut> for DynamicManagedValue {
471    fn from(value: DynamicManagedRefMut) -> Self {
472        Self::RefMut(value)
473    }
474}
475
476impl From<DynamicManagedLazy> for DynamicManagedValue {
477    fn from(value: DynamicManagedLazy) -> Self {
478        Self::Lazy(value)
479    }
480}
481
482impl From<DynamicManagedGc> for DynamicManagedValue {
483    fn from(value: DynamicManagedGc) -> Self {
484        Self::Gc(value)
485    }
486}