rune/runtime/
shared.rs

1use core::fmt;
2use core::marker::PhantomData;
3use core::mem::{replace, ManuallyDrop};
4use core::ptr::{self, addr_of, NonNull};
5
6use crate::alloc;
7use crate::alloc::clone::TryClone;
8use crate::any::AnyMarker;
9use crate::compile::meta;
10use crate::{Any, Hash};
11
12use super::{
13    AnyObj, AnyObjData, AnyObjError, AnyObjErrorKind, AnyObjVtable, AnyTypeInfo, BorrowMut,
14    BorrowRef, FromValue, MaybeTypeOf, Mut, RawAnyGuard, Ref, RefVtable, RuntimeError, ToValue,
15    TypeHash, TypeInfo, TypeOf, Value,
16};
17
18/// A typed wrapper for a reference.
19///
20/// This is identical in layout to [`AnyObj`], but provides a statically
21/// type-checked container.
22///
23/// [`AnyObj`]: super::AnyObj
24pub struct Shared<T> {
25    /// The shared value.
26    shared: NonNull<AnyObjData>,
27    /// The statically known type of the value.
28    _marker: PhantomData<T>,
29}
30
31impl<T> Shared<T>
32where
33    T: Any,
34{
35    /// Construct a new typed shared value.
36    ///
37    /// # Examples
38    ///
39    /// ```
40    /// use rune::Value;
41    /// use rune::runtime::Shared;
42    /// use rune::alloc::String;
43    ///
44    /// let string = String::try_from("Hello World")?;
45    /// let string = Shared::new(string)?;
46    /// let string = Value::from(string);
47    ///
48    /// let string = string.into_any_obj()?;
49    /// assert_eq!(string.borrow_ref::<String>()?.as_str(), "Hello World");
50    /// # Ok::<_, rune::support::Error>(())
51    /// ```
52    #[inline]
53    pub fn new(value: T) -> alloc::Result<Self> {
54        let any = AnyObj::new(value)?;
55        // SAFETY: We know that the value is valid.
56        unsafe { Ok(any.unsafe_into_shared()) }
57    }
58
59    /// Construct a new typed object.
60    ///
61    /// # Safety
62    ///
63    /// Caller must ensure that the type is of the value `T`.
64    #[inline]
65    pub(super) unsafe fn from_raw(shared: NonNull<AnyObjData<T>>) -> Self {
66        Self {
67            shared: shared.cast(),
68            _marker: PhantomData,
69        }
70    }
71
72    /// Coerce into a type-erased [`AnyObj`].
73    #[inline]
74    pub(crate) fn into_any_obj(self) -> AnyObj {
75        let this = ManuallyDrop::new(self);
76        // SAFETY: We know that the shared value is valid.
77        unsafe { AnyObj::from_raw(this.shared.cast()) }
78    }
79
80    /// Take the owned value of type `T`.
81    ///
82    /// This consumes any live references of the value and accessing them in the
83    /// future will result in an error.
84    ///
85    /// # Errors
86    ///
87    /// This errors if the underlying value is not owned.
88    pub fn take(self) -> Result<T, AnyObjError> {
89        let vtable = vtable(&self);
90
91        if !vtable.is_owned() {
92            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
93                vtable.type_info(),
94            )));
95        }
96
97        // SAFETY: The appropriate type has been type checked for when the
98        // container was constructed.
99        unsafe {
100            self.shared.as_ref().access.try_take()?;
101            let data = vtable.as_ptr::<T>(self.shared);
102            Ok(data.read())
103        }
104    }
105
106    /// Downcast into an owned value of type [`Ref<T>`].
107    ///
108    /// # Errors
109    ///
110    /// This errors in case the underlying value is not owned, non-owned
111    /// references cannot be coerced into [`Ref<T>`].
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// use rune::{Any, Value};
117    ///
118    /// #[derive(Any)]
119    /// struct Struct(u32);
120    ///
121    /// let value = Value::new(Struct(42))?;
122    /// let value = value.into_shared::<Struct>()?;
123    ///
124    /// let reference = value.clone().into_ref()?;
125    /// assert!(value.borrow_ref().is_ok());
126    /// assert_eq!(reference.0, 42);
127    /// # Ok::<_, rune::support::Error>(())
128    /// ```
129    pub fn into_ref(self) -> Result<Ref<T>, AnyObjError> {
130        let vtable = vtable(&self);
131
132        if !vtable.is_owned() {
133            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
134                vtable.type_info(),
135            )));
136        }
137
138        // SAFETY: The appropriate type has been type checked for when the
139        // container was constructed.
140        unsafe {
141            self.shared.as_ref().access.try_shared()?;
142            let this = ManuallyDrop::new(self);
143            let data = vtable.as_ptr(this.shared);
144
145            let vtable = &RefVtable {
146                drop: |shared: NonNull<()>| {
147                    let shared = shared.cast::<AnyObjData>();
148                    shared.as_ref().access.release();
149                    AnyObjData::dec(shared)
150                },
151            };
152
153            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
154            Ok(Ref::new(data, guard))
155        }
156    }
157
158    /// Downcast into an owned value of type [`Mut<T>`].
159    ///
160    /// # Errors
161    ///
162    /// This errors in case the underlying value is not owned, non-owned
163    /// references cannot be coerced into [`Mut<T>`].
164    ///
165    /// # Examples
166    ///
167    /// ```
168    /// use rune::{Any, Value};
169    ///
170    /// #[derive(Any)]
171    /// struct Struct(u32);
172    ///
173    /// let value = Value::new(Struct(42))?;
174    /// let value = value.into_shared::<Struct>()?;
175    ///
176    /// let mut mutable = value.clone().into_mut()?;
177    /// assert!(value.borrow_ref().is_err());
178    /// mutable.0 += 1;
179    /// drop(mutable);
180    ///
181    /// assert_eq!(value.borrow_ref()?.0, 43);
182    /// # Ok::<_, rune::support::Error>(())
183    /// ```
184    pub fn into_mut(self) -> Result<Mut<T>, AnyObjError> {
185        let vtable = vtable(&self);
186
187        if !vtable.is_owned() {
188            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
189                vtable.type_info(),
190            )));
191        }
192
193        // SAFETY: The appropriate type has been type checked for when the
194        // container was constructed.
195        unsafe {
196            self.shared.as_ref().access.try_exclusive()?;
197            let this = ManuallyDrop::new(self);
198            let data = vtable.as_ptr(this.shared);
199
200            let vtable = &RefVtable {
201                drop: |shared: NonNull<()>| {
202                    let shared = shared.cast::<AnyObjData>();
203                    shared.as_ref().access.release();
204                    AnyObjData::dec(shared)
205                },
206            };
207
208            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
209            Ok(Mut::new(data, guard))
210        }
211    }
212
213    /// Borrow a shared reference to the value while checking for shared access.
214    ///
215    /// This prevents other exclusive accesses from being performed while the
216    /// guard returned from this function is live.
217    ///
218    /// # Examples
219    ///
220    /// ```
221    /// use rune::{Any, Value};
222    ///
223    /// #[derive(Any)]
224    /// struct Struct(u32);
225    ///
226    /// let value = Value::new(Struct(42))?;
227    /// let value = value.into_shared::<Struct>()?;
228    ///
229    /// let borrowed = value.borrow_ref()?;
230    /// assert!(value.borrow_ref().is_ok());
231    /// drop(borrowed);
232    /// assert!(value.borrow_ref().is_ok());
233    /// # Ok::<_, rune::support::Error>(())
234    /// ```
235    pub fn borrow_ref(&self) -> Result<BorrowRef<'_, T>, AnyObjError> {
236        let vtable = vtable(self);
237
238        // SAFETY: The appropriate type has been type checked for when the
239        // container was constructed.
240        unsafe {
241            let guard = self.shared.as_ref().access.shared()?;
242            let data = vtable.as_ptr(self.shared);
243            Ok(BorrowRef::new(data, guard.into_raw()))
244        }
245    }
246
247    /// Borrow an exclusive reference to the value.
248    ///
249    /// This prevents other accesses from being performed while the guard
250    /// returned from this function is live.
251    ///
252    /// # Examples
253    ///
254    /// ```
255    /// use rune::{Any, Value};
256    ///
257    /// #[derive(Any)]
258    /// struct Struct(u32);
259    ///
260    /// let value = Value::new(Struct(42))?;
261    /// let value = value.into_shared::<Struct>()?;
262    ///
263    /// let borrowed = value.borrow_mut()?;
264    /// assert!(value.borrow_ref().is_err());
265    /// drop(borrowed);
266    /// assert!(value.borrow_ref().is_ok());
267    /// # Ok::<_, rune::support::Error>(())
268    /// ```
269    pub fn borrow_mut(&self) -> Result<BorrowMut<'_, T>, AnyObjError> {
270        let vtable = vtable(self);
271
272        if !vtable.is_mutable() {
273            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
274                T::ANY_TYPE_INFO,
275                vtable.type_info(),
276            )));
277        }
278
279        // SAFETY: The appropriate type has been type checked for when the
280        // container was constructed.
281        unsafe {
282            let guard = self.shared.as_ref().access.exclusive()?;
283            let data = vtable.as_ptr(self.shared);
284            Ok(BorrowMut::new(data, guard.into_raw()))
285        }
286    }
287
288    /// Test if the value is sharable.
289    ///
290    /// # Examples
291    ///
292    /// ```
293    /// use rune::{Any, Value};
294    ///
295    /// #[derive(Any)]
296    /// struct Struct(u32);
297    ///
298    /// let value = Value::new(Struct(42))?;
299    /// let value = value.into_shared::<Struct>()?;
300    ///
301    /// {
302    ///     assert!(value.is_writable());
303    ///
304    ///     let borrowed = value.borrow_mut()?;
305    ///     assert!(!value.is_writable());
306    ///     drop(borrowed);
307    ///     assert!(value.is_writable());
308    /// }
309    ///
310    /// let foo = Struct(42);
311    ///
312    /// {
313    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
314    ///     let value = value.into_shared::<Struct>()?;
315    ///     assert!(value.is_readable());
316    ///     assert!(!value.is_writable());
317    /// }
318    ///
319    /// let mut foo = Struct(42);
320    ///
321    /// {
322    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
323    ///     let value = value.into_shared::<Struct>()?;
324    ///     assert!(value.is_readable());
325    ///     assert!(value.is_writable());
326    /// }
327    /// # Ok::<_, rune::support::Error>(())
328    /// ```
329    pub fn is_readable(&self) -> bool {
330        // Safety: Since we have a reference to this shared, we know that the
331        // inner is available.
332        unsafe { self.shared.as_ref().access.is_shared() }
333    }
334
335    /// Test if a value is writable.
336    ///
337    /// # Examples
338    ///
339    /// ```
340    /// use rune::{Any, Value};
341    ///
342    /// #[derive(Any)]
343    /// struct Struct(u32);
344    ///
345    /// let value = Value::new(Struct(42))?;
346    /// let value = value.into_shared::<Struct>()?;
347    ///
348    /// {
349    ///     assert!(value.is_writable());
350    ///
351    ///     let borrowed = value.borrow_mut()?;
352    ///     assert!(!value.is_writable());
353    ///     drop(borrowed);
354    ///     assert!(value.is_writable());
355    /// }
356    ///
357    /// let foo = Struct(42);
358    ///
359    /// {
360    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
361    ///     let value = value.into_shared::<Struct>()?;
362    ///     assert!(value.is_readable());
363    ///     assert!(!value.is_writable());
364    /// }
365    ///
366    /// let mut foo = Struct(42);
367    ///
368    /// {
369    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
370    ///     let value = value.into_shared::<Struct>()?;
371    ///     assert!(value.is_readable());
372    ///     assert!(value.is_writable());
373    /// }
374    /// # Ok::<_, rune::support::Error>(())
375    /// ```
376    pub fn is_writable(&self) -> bool {
377        unsafe {
378            let shared = self.shared.as_ref();
379            shared.vtable.is_mutable() && shared.access.is_exclusive()
380        }
381    }
382
383    /// Debug format the current any type.
384    pub(crate) fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
385        vtable(self).debug(f)
386    }
387
388    /// Access the underlying type id for the data.
389    pub fn type_hash(&self) -> Hash {
390        vtable(self).type_hash()
391    }
392
393    /// Access full type info for the underlying type.
394    pub fn type_info(&self) -> TypeInfo {
395        vtable(self).type_info()
396    }
397}
398
399impl<T> fmt::Debug for Shared<T>
400where
401    T: Any,
402{
403    #[inline]
404    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405        self.debug(f)
406    }
407}
408
409impl<T> Drop for Shared<T> {
410    fn drop(&mut self) {
411        // Safety: We know that the inner value is live in this instance.
412        unsafe {
413            AnyObjData::dec(self.shared);
414        }
415    }
416}
417
418#[inline]
419pub(super) fn vtable<T>(any: &Shared<T>) -> &'static AnyObjVtable {
420    unsafe { addr_of!((*any.shared.as_ptr()).vtable).read() }
421}
422
423impl<T> FromValue for Shared<T>
424where
425    T: AnyMarker,
426{
427    #[inline]
428    fn from_value(value: Value) -> Result<Self, RuntimeError> {
429        value.into_shared()
430    }
431}
432
433impl<T> ToValue for Shared<T>
434where
435    T: AnyMarker,
436{
437    #[inline]
438    fn to_value(self) -> Result<Value, RuntimeError> {
439        Ok(Value::from(self.into_any_obj()))
440    }
441}
442
443impl<T> MaybeTypeOf for Shared<T>
444where
445    T: MaybeTypeOf,
446{
447    #[inline]
448    fn maybe_type_of() -> alloc::Result<meta::DocType> {
449        T::maybe_type_of()
450    }
451}
452
453impl<T> TypeHash for Shared<T>
454where
455    T: TypeHash,
456{
457    const HASH: Hash = T::HASH;
458}
459
460impl<T> TypeOf for Shared<T>
461where
462    T: TypeOf,
463{
464    const PARAMETERS: Hash = T::PARAMETERS;
465    const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
466}
467
468impl<T> Clone for Shared<T>
469where
470    T: Any,
471{
472    #[inline]
473    fn clone(&self) -> Self {
474        // SAFETY: We know that the inner value is live in this instance.
475        unsafe {
476            AnyObjData::inc(self.shared);
477        }
478
479        Self {
480            shared: self.shared,
481            _marker: PhantomData,
482        }
483    }
484
485    #[inline]
486    fn clone_from(&mut self, source: &Self) {
487        if ptr::eq(self.shared.as_ptr(), source.shared.as_ptr()) {
488            return;
489        }
490
491        let old = replace(&mut self.shared, source.shared);
492
493        // SAFETY: We know that the inner value is live in both instances.
494        unsafe {
495            AnyObjData::dec(old);
496            AnyObjData::inc(self.shared);
497        }
498    }
499}
500
501impl<T> TryClone for Shared<T>
502where
503    T: Any,
504{
505    #[inline]
506    fn try_clone(&self) -> alloc::Result<Self> {
507        Ok(self.clone())
508    }
509
510    #[inline]
511    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
512        self.clone_from(source);
513        Ok(())
514    }
515}