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}