Skip to main content

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                // The reference keeps the value alive, so it can be handed
152                // back: releasing the access and handing the count over is what
153                // dropping does, minus the count being given up.
154                into_value: Some(|shared: NonNull<()>| {
155                    let shared = shared.cast::<AnyObjData>();
156                    shared.as_ref().access.release();
157                    Value::from(AnyObj::from_raw(shared))
158                }),
159            };
160
161            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
162            Ok(Ref::new(data, guard))
163        }
164    }
165
166    /// Downcast into an owned value of type [`Mut<T>`].
167    ///
168    /// # Errors
169    ///
170    /// This errors in case the underlying value is not owned, non-owned
171    /// references cannot be coerced into [`Mut<T>`].
172    ///
173    /// # Examples
174    ///
175    /// ```
176    /// use rune::{Any, Value};
177    ///
178    /// #[derive(Any)]
179    /// struct Struct(u32);
180    ///
181    /// let value = Value::new(Struct(42))?;
182    /// let value = value.into_shared::<Struct>()?;
183    ///
184    /// let mut mutable = value.clone().into_mut()?;
185    /// assert!(value.borrow_ref().is_err());
186    /// mutable.0 += 1;
187    /// drop(mutable);
188    ///
189    /// assert_eq!(value.borrow_ref()?.0, 43);
190    /// # Ok::<_, rune::support::Error>(())
191    /// ```
192    pub fn into_mut(self) -> Result<Mut<T>, AnyObjError> {
193        let vtable = vtable(&self);
194
195        if !vtable.is_owned() {
196            return Err(AnyObjError::new(AnyObjErrorKind::NotOwned(
197                vtable.type_info(),
198            )));
199        }
200
201        // SAFETY: The appropriate type has been type checked for when the
202        // container was constructed.
203        unsafe {
204            self.shared.as_ref().access.try_exclusive()?;
205            let this = ManuallyDrop::new(self);
206            let data = vtable.as_ptr(this.shared);
207
208            let vtable = &RefVtable {
209                drop: |shared: NonNull<()>| {
210                    let shared = shared.cast::<AnyObjData>();
211                    shared.as_ref().access.release();
212                    AnyObjData::dec(shared)
213                },
214                // The reference keeps the value alive, so it can be handed
215                // back: releasing the access and handing the count over is what
216                // dropping does, minus the count being given up.
217                into_value: Some(|shared: NonNull<()>| {
218                    let shared = shared.cast::<AnyObjData>();
219                    shared.as_ref().access.release();
220                    Value::from(AnyObj::from_raw(shared))
221                }),
222            };
223
224            let guard = RawAnyGuard::new(this.shared.cast(), vtable);
225            Ok(Mut::new(data, guard))
226        }
227    }
228
229    /// Borrow a shared reference to the value while checking for shared access.
230    ///
231    /// This prevents other exclusive accesses from being performed while the
232    /// guard returned from this function is live.
233    ///
234    /// # Examples
235    ///
236    /// ```
237    /// use rune::{Any, Value};
238    ///
239    /// #[derive(Any)]
240    /// struct Struct(u32);
241    ///
242    /// let value = Value::new(Struct(42))?;
243    /// let value = value.into_shared::<Struct>()?;
244    ///
245    /// let borrowed = value.borrow_ref()?;
246    /// assert!(value.borrow_ref().is_ok());
247    /// drop(borrowed);
248    /// assert!(value.borrow_ref().is_ok());
249    /// # Ok::<_, rune::support::Error>(())
250    /// ```
251    pub fn borrow_ref(&self) -> Result<BorrowRef<'_, T>, AnyObjError> {
252        let vtable = vtable(self);
253
254        // SAFETY: The appropriate type has been type checked for when the
255        // container was constructed.
256        unsafe {
257            let guard = self.shared.as_ref().access.shared()?;
258            let data = vtable.as_ptr(self.shared);
259            Ok(BorrowRef::new(data, guard.into_raw()))
260        }
261    }
262
263    /// Borrow an exclusive reference to the value.
264    ///
265    /// This prevents other accesses from being performed while the guard
266    /// returned from this function is live.
267    ///
268    /// # Examples
269    ///
270    /// ```
271    /// use rune::{Any, Value};
272    ///
273    /// #[derive(Any)]
274    /// struct Struct(u32);
275    ///
276    /// let value = Value::new(Struct(42))?;
277    /// let value = value.into_shared::<Struct>()?;
278    ///
279    /// let borrowed = value.borrow_mut()?;
280    /// assert!(value.borrow_ref().is_err());
281    /// drop(borrowed);
282    /// assert!(value.borrow_ref().is_ok());
283    /// # Ok::<_, rune::support::Error>(())
284    /// ```
285    pub fn borrow_mut(&self) -> Result<BorrowMut<'_, T>, AnyObjError> {
286        let vtable = vtable(self);
287
288        if !vtable.is_mutable() {
289            return Err(AnyObjError::new(AnyObjErrorKind::Cast(
290                T::ANY_TYPE_INFO,
291                vtable.type_info(),
292            )));
293        }
294
295        // SAFETY: The appropriate type has been type checked for when the
296        // container was constructed.
297        unsafe {
298            let guard = self.shared.as_ref().access.exclusive()?;
299            let data = vtable.as_ptr(self.shared);
300            Ok(BorrowMut::new(data, guard.into_raw()))
301        }
302    }
303
304    /// Test if the value is sharable.
305    ///
306    /// # Examples
307    ///
308    /// ```
309    /// use rune::{Any, Value};
310    ///
311    /// #[derive(Any)]
312    /// struct Struct(u32);
313    ///
314    /// let value = Value::new(Struct(42))?;
315    /// let value = value.into_shared::<Struct>()?;
316    ///
317    /// {
318    ///     assert!(value.is_writable());
319    ///
320    ///     let borrowed = value.borrow_mut()?;
321    ///     assert!(!value.is_writable());
322    ///     drop(borrowed);
323    ///     assert!(value.is_writable());
324    /// }
325    ///
326    /// let foo = Struct(42);
327    ///
328    /// {
329    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
330    ///     let value = value.into_shared::<Struct>()?;
331    ///     assert!(value.is_readable());
332    ///     assert!(!value.is_writable());
333    /// }
334    ///
335    /// let mut foo = Struct(42);
336    ///
337    /// {
338    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
339    ///     let value = value.into_shared::<Struct>()?;
340    ///     assert!(value.is_readable());
341    ///     assert!(value.is_writable());
342    /// }
343    /// # Ok::<_, rune::support::Error>(())
344    /// ```
345    pub fn is_readable(&self) -> bool {
346        // Safety: Since we have a reference to this shared, we know that the
347        // inner is available.
348        unsafe { self.shared.as_ref().access.is_shared() }
349    }
350
351    /// Test if a value is writable.
352    ///
353    /// # Examples
354    ///
355    /// ```
356    /// use rune::{Any, Value};
357    ///
358    /// #[derive(Any)]
359    /// struct Struct(u32);
360    ///
361    /// let value = Value::new(Struct(42))?;
362    /// let value = value.into_shared::<Struct>()?;
363    ///
364    /// {
365    ///     assert!(value.is_writable());
366    ///
367    ///     let borrowed = value.borrow_mut()?;
368    ///     assert!(!value.is_writable());
369    ///     drop(borrowed);
370    ///     assert!(value.is_writable());
371    /// }
372    ///
373    /// let foo = Struct(42);
374    ///
375    /// {
376    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
377    ///     let value = value.into_shared::<Struct>()?;
378    ///     assert!(value.is_readable());
379    ///     assert!(!value.is_writable());
380    /// }
381    ///
382    /// let mut foo = Struct(42);
383    ///
384    /// {
385    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
386    ///     let value = value.into_shared::<Struct>()?;
387    ///     assert!(value.is_readable());
388    ///     assert!(value.is_writable());
389    /// }
390    /// # Ok::<_, rune::support::Error>(())
391    /// ```
392    pub fn is_writable(&self) -> bool {
393        unsafe {
394            let shared = self.shared.as_ref();
395            shared.vtable.is_mutable() && shared.access.is_exclusive()
396        }
397    }
398
399    /// Debug format the current any type.
400    pub(crate) fn debug(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
401        vtable(self).debug(f)
402    }
403
404    /// Access the underlying type id for the data.
405    pub fn type_hash(&self) -> Hash {
406        vtable(self).type_hash()
407    }
408
409    /// Access full type info for the underlying type.
410    pub fn type_info(&self) -> TypeInfo {
411        vtable(self).type_info()
412    }
413}
414
415impl<T> fmt::Debug for Shared<T>
416where
417    T: Any,
418{
419    #[inline]
420    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421        self.debug(f)
422    }
423}
424
425impl<T> Drop for Shared<T> {
426    fn drop(&mut self) {
427        // Safety: We know that the inner value is live in this instance.
428        unsafe {
429            AnyObjData::dec(self.shared);
430        }
431    }
432}
433
434#[inline]
435pub(super) fn vtable<T>(any: &Shared<T>) -> &'static AnyObjVtable {
436    unsafe { addr_of!((*any.shared.as_ptr()).vtable).read() }
437}
438
439impl<T> FromValue for Shared<T>
440where
441    T: AnyMarker,
442{
443    #[inline]
444    fn from_value(value: Value) -> Result<Self, RuntimeError> {
445        value.into_shared()
446    }
447}
448
449impl<T> ToValue for Shared<T>
450where
451    T: AnyMarker,
452{
453    #[inline]
454    fn to_value(self) -> Result<Value, RuntimeError> {
455        Ok(Value::from(self.into_any_obj()))
456    }
457}
458
459impl<T> MaybeTypeOf for Shared<T>
460where
461    T: MaybeTypeOf,
462{
463    #[inline]
464    fn maybe_type_of() -> alloc::Result<meta::DocType> {
465        T::maybe_type_of()
466    }
467}
468
469impl<T> TypeHash for Shared<T>
470where
471    T: TypeHash,
472{
473    const HASH: Hash = T::HASH;
474}
475
476impl<T> TypeOf for Shared<T>
477where
478    T: TypeOf,
479{
480    const PARAMETERS: Hash = T::PARAMETERS;
481    const STATIC_TYPE_INFO: AnyTypeInfo = T::STATIC_TYPE_INFO;
482}
483
484impl<T> Clone for Shared<T>
485where
486    T: Any,
487{
488    #[inline]
489    fn clone(&self) -> Self {
490        // SAFETY: We know that the inner value is live in this instance.
491        unsafe {
492            AnyObjData::inc(self.shared);
493        }
494
495        Self {
496            shared: self.shared,
497            _marker: PhantomData,
498        }
499    }
500
501    #[inline]
502    fn clone_from(&mut self, source: &Self) {
503        if ptr::eq(self.shared.as_ptr(), source.shared.as_ptr()) {
504            return;
505        }
506
507        let old = replace(&mut self.shared, source.shared);
508
509        // SAFETY: We know that the inner value is live in both instances.
510        unsafe {
511            AnyObjData::dec(old);
512            AnyObjData::inc(self.shared);
513        }
514    }
515}
516
517impl<T> TryClone for Shared<T>
518where
519    T: Any,
520{
521    #[inline]
522    fn try_clone(&self) -> alloc::Result<Self> {
523        Ok(self.clone())
524    }
525
526    #[inline]
527    fn try_clone_from(&mut self, source: &Self) -> alloc::Result<()> {
528        self.clone_from(source);
529        Ok(())
530    }
531}