Skip to main content

rune/runtime/
value.rs

1#[macro_use]
2mod macros;
3
4#[cfg(test)]
5mod tests;
6
7mod inline;
8pub use self::inline::Inline;
9
10#[cfg(feature = "serde")]
11mod serde;
12
13mod rtti;
14pub(crate) use self::rtti::RttiKind;
15pub use self::rtti::{Accessor, Rtti};
16
17mod data;
18pub use self::data::{EmptyStruct, Struct, TupleStruct};
19
20mod any_sequence;
21pub use self::any_sequence::AnySequence;
22pub(crate) use self::any_sequence::AnySequenceTakeError;
23
24mod dismantle;
25pub(crate) use self::dismantle::Worklist;
26pub use self::dismantle::{Dismantle, Handover};
27
28use core::any;
29use core::cmp::Ordering;
30use core::fmt;
31use core::mem::replace;
32use core::ptr::NonNull;
33
34use crate::alloc::fmt::TryWrite;
35use crate::alloc::prelude::*;
36use crate::alloc::{self, String};
37use crate::compile::meta;
38use crate::runtime::{budget, env};
39use crate::sync::Arc;
40use crate::{Any, Hash, TypeHash};
41
42use super::{
43    AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, CallResultOnly, ConstNodeKind,
44    ConstValueBuf, DynGuardedArgs, EnvProtocolCaller, Formatter, FromValue, Future, Hasher,
45    Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol, ProtocolCaller, RawAnyObjGuard, Ref,
46    RuntimeError, Shared, Snapshot, Tuple, Type, TypeInfo, Vec, VmError, VmErrorKind,
47    VmIntegerRepr,
48};
49
50/// Defined guard for a reference value.
51///
52/// See [`Value::from_ref`].
53pub struct ValueRefGuard {
54    #[allow(unused)]
55    guard: AnyObjDrop,
56}
57
58/// Defined guard for a reference value.
59///
60/// See [`Value::from_mut`].
61pub struct ValueMutGuard {
62    #[allow(unused)]
63    guard: AnyObjDrop,
64}
65
66/// The guard returned by [`Value::into_any_mut_ptr`].
67pub struct RawValueGuard {
68    #[allow(unused)]
69    guard: RawAnyObjGuard,
70}
71
72#[derive(Clone)]
73pub(crate) enum Repr {
74    Inline(Inline),
75    Dynamic(AnySequence<Arc<Rtti>, Value>),
76    Any(AnyObj),
77}
78
79impl Repr {
80    #[inline]
81    pub(crate) fn type_info(&self) -> TypeInfo {
82        match self {
83            Repr::Inline(value) => value.type_info(),
84            Repr::Dynamic(value) => value.type_info(),
85            Repr::Any(value) => value.type_info(),
86        }
87    }
88}
89
90/// An entry on the stack.
91pub struct Value {
92    repr: Repr,
93}
94
95impl Value {
96    /// Take a mutable value, replacing the original location with an empty value.
97    #[inline]
98    pub fn take(value: &mut Self) -> Self {
99        replace(value, Self::empty())
100    }
101
102    /// Construct a value from a type that implements [`Any`] which owns the
103    /// underlying value.
104    pub fn new<T>(data: T) -> alloc::Result<Self>
105    where
106        T: Any,
107    {
108        Ok(Self {
109            repr: Repr::Any(AnyObj::new(data)?),
110        })
111    }
112
113    /// Construct an Any that wraps a pointer.
114    ///
115    /// # Safety
116    ///
117    /// Caller must ensure that the returned `Value` doesn't outlive the
118    /// reference it is wrapping.
119    ///
120    /// This would be an example of incorrect use:
121    ///
122    /// ```no_run
123    /// use rune::Any;
124    /// use rune::runtime::Value;
125    ///
126    /// #[derive(Any)]
127    /// struct Foo(u32);
128    ///
129    /// let mut v = Foo(1u32);
130    ///
131    /// unsafe {
132    ///     let (any, guard) = unsafe { Value::from_ref(&v)? };
133    ///     drop(v);
134    ///     // any use of `any` beyond here is undefined behavior.
135    /// }
136    /// # Ok::<_, rune::support::Error>(())
137    /// ```
138    ///
139    /// # Examples
140    ///
141    /// ```
142    /// use rune::Any;
143    /// use rune::runtime::Value;
144    ///
145    /// #[derive(Any)]
146    /// struct Foo(u32);
147    ///
148    /// let mut v = Foo(1u32);
149    ///
150    /// unsafe {
151    ///     let (any, guard) = Value::from_ref(&mut v)?;
152    ///     let b = any.borrow_ref::<Foo>()?;
153    ///     assert_eq!(b.0, 1u32);
154    /// }
155    /// # Ok::<_, rune::support::Error>(())
156    /// ```
157    pub unsafe fn from_ref<T>(data: &T) -> alloc::Result<(Self, ValueRefGuard)>
158    where
159        T: Any,
160    {
161        let value = AnyObj::from_ref(data)?;
162        let (value, guard) = AnyObj::into_drop_guard(value);
163
164        let guard = ValueRefGuard { guard };
165
166        Ok((
167            Self {
168                repr: Repr::Any(value),
169            },
170            guard,
171        ))
172    }
173
174    /// Construct a value that wraps a mutable pointer.
175    ///
176    /// # Safety
177    ///
178    /// Caller must ensure that the returned `Value` doesn't outlive the
179    /// reference it is wrapping.
180    ///
181    /// This would be an example of incorrect use:
182    ///
183    /// ```no_run
184    /// use rune::Any;
185    /// use rune::runtime::Value;
186    ///
187    /// #[derive(Any)]
188    /// struct Foo(u32);
189    ///
190    /// let mut v = Foo(1u32);
191    /// unsafe {
192    ///     let (any, guard) = Value::from_mut(&mut v)?;
193    ///     drop(v);
194    ///     // any use of value beyond here is undefined behavior.
195    /// }
196    /// # Ok::<_, rune::support::Error>(())
197    /// ```
198    ///
199    /// # Examples
200    ///
201    /// ```
202    /// use rune::Any;
203    /// use rune::runtime::Value;
204    ///
205    /// #[derive(Any)]
206    /// struct Foo(u32);
207    ///
208    /// let mut v = Foo(1u32);
209    ///
210    /// unsafe {
211    ///     let (any, guard) = Value::from_mut(&mut v)?;
212    ///
213    ///     if let Ok(mut v) = any.borrow_mut::<Foo>() {
214    ///         v.0 += 1;
215    ///     }
216    ///
217    ///     drop(guard);
218    ///     assert!(any.borrow_mut::<Foo>().is_err());
219    ///     drop(any);
220    /// }
221    ///
222    /// assert_eq!(v.0, 2);
223    /// # Ok::<_, rune::support::Error>(())
224    /// ```
225    pub unsafe fn from_mut<T>(data: &mut T) -> alloc::Result<(Self, ValueMutGuard)>
226    where
227        T: Any,
228    {
229        let value = AnyObj::from_mut(data)?;
230        let (value, guard) = AnyObj::into_drop_guard(value);
231
232        let guard = ValueMutGuard { guard };
233
234        Ok((
235            Self {
236                repr: Repr::Any(value),
237            },
238            guard,
239        ))
240    }
241
242    /// Optionally get the snapshot of the value if available.
243    pub(crate) fn snapshot(&self) -> Option<Snapshot> {
244        match &self.repr {
245            Repr::Dynamic(value) => Some(value.snapshot()),
246            Repr::Any(value) => Some(value.snapshot()),
247            _ => None,
248        }
249    }
250
251    /// Test if the value is writable.
252    ///
253    /// # Examples
254    ///
255    /// ```
256    /// use rune::{Any, Value};
257    ///
258    /// #[derive(Any)]
259    /// struct Struct(u32);
260    ///
261    /// let value = Value::new(Struct(42))?;
262    ///
263    /// {
264    ///     assert!(value.is_writable());
265    ///
266    ///     let borrowed = value.borrow_mut::<Struct>()?;
267    ///     assert!(!value.is_writable());
268    ///     drop(borrowed);
269    ///     assert!(value.is_writable());
270    /// }
271    ///
272    /// let foo = Struct(42);
273    ///
274    /// {
275    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
276    ///     assert!(value.is_readable());
277    ///     assert!(!value.is_writable());
278    /// }
279    ///
280    /// let mut foo = Struct(42);
281    ///
282    /// {
283    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
284    ///     assert!(value.is_readable());
285    ///     assert!(value.is_writable());
286    /// }
287    /// # Ok::<_, rune::support::Error>(())
288    /// ```
289    pub fn is_writable(&self) -> bool {
290        match self.repr {
291            Repr::Inline(Inline::Empty) => false,
292            Repr::Inline(..) => true,
293            Repr::Dynamic(ref value) => value.is_writable(),
294            Repr::Any(ref any) => any.is_writable(),
295        }
296    }
297
298    /// Test if a value is readable.
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// use rune::{Any, Value};
304    ///
305    /// #[derive(Any)]
306    /// struct Struct(u32);
307    ///
308    /// let value = Value::new(Struct(42))?;
309    ///
310    /// {
311    ///     assert!(value.is_writable());
312    ///
313    ///     let borrowed = value.borrow_mut::<Struct>()?;
314    ///     assert!(!value.is_writable());
315    ///     drop(borrowed);
316    ///     assert!(value.is_writable());
317    /// }
318    ///
319    /// let foo = Struct(42);
320    ///
321    /// {
322    ///     let (value, guard) = unsafe { Value::from_ref(&foo)? };
323    ///     assert!(value.is_readable());
324    ///     assert!(!value.is_writable());
325    /// }
326    ///
327    /// let mut foo = Struct(42);
328    ///
329    /// {
330    ///     let (value, guard) = unsafe { Value::from_mut(&mut foo)? };
331    ///     assert!(value.is_readable());
332    ///     assert!(value.is_writable());
333    /// }
334    /// # Ok::<_, rune::support::Error>(())
335    /// ```
336    pub fn is_readable(&self) -> bool {
337        match &self.repr {
338            Repr::Inline(Inline::Empty) => false,
339            Repr::Inline(..) => true,
340            Repr::Dynamic(ref value) => value.is_readable(),
341            Repr::Any(ref any) => any.is_readable(),
342        }
343    }
344
345    /// Test if this is the empty placeholder value.
346    ///
347    /// This is what [`Value::take`] leaves behind, and what marks a static item
348    /// slot as uninitialized in [`Globals`].
349    ///
350    /// [`Globals`]: crate::runtime::Globals
351    #[inline]
352    pub(crate) fn is_empty(&self) -> bool {
353        matches!(self.repr, Repr::Inline(Inline::Empty))
354    }
355
356    /// Construct a unit value.
357    pub(crate) const fn unit() -> Self {
358        Self {
359            repr: Repr::Inline(Inline::Unit),
360        }
361    }
362
363    /// Construct an empty value.
364    pub const fn empty() -> Self {
365        Self {
366            repr: Repr::Inline(Inline::Empty),
367        }
368    }
369
370    /// Format the value using the [`DISPLAY_FMT`] protocol.
371    ///
372    /// You must use [`Vm::with`] to specify which virtual machine this function
373    /// is called inside.
374    ///
375    /// [`Vm::with`]: crate::Vm::with
376    ///
377    /// # Errors
378    ///
379    /// This function errors if called outside of a virtual machine.
380    ///
381    /// [`DISPLAY_FMT`]: Protocol::DISPLAY_FMT
382    pub fn display_fmt(&self, f: &mut Formatter) -> Result<(), VmError> {
383        self.display_fmt_with(f, &mut EnvProtocolCaller)
384    }
385
386    /// Internal impl of display_fmt with a customizable caller.
387    #[cfg_attr(feature = "bench", inline(never))]
388    pub(crate) fn display_fmt_with(
389        &self,
390        f: &mut Formatter,
391        caller: &mut dyn ProtocolCaller,
392    ) -> Result<(), VmError> {
393        let _guard = env::enter_value()?;
394
395        'fallback: {
396            match self.as_ref() {
397                Repr::Inline(value) => match value {
398                    Inline::Char(c) => {
399                        f.try_write_char(*c)?;
400                    }
401                    Inline::Unsigned(byte) => {
402                        let mut buffer = itoa::Buffer::new();
403                        f.try_write_str(buffer.format(*byte))?;
404                    }
405                    Inline::Signed(integer) => {
406                        let mut buffer = itoa::Buffer::new();
407                        f.try_write_str(buffer.format(*integer))?;
408                    }
409                    Inline::Float(float) => {
410                        let mut buffer = ryu::Buffer::new();
411                        f.try_write_str(buffer.format(*float))?;
412                    }
413                    Inline::Bool(bool) => {
414                        write!(f, "{bool}")?;
415                    }
416                    _ => {
417                        break 'fallback;
418                    }
419                },
420                _ => {
421                    break 'fallback;
422                }
423            }
424
425            return Ok(());
426        };
427
428        let mut args = DynGuardedArgs::new((f,));
429
430        let result = caller.call_protocol_fn(&Protocol::DISPLAY_FMT, self.clone(), &mut args)?;
431
432        <()>::from_value(result)?;
433        Ok(())
434    }
435
436    /// Perform a shallow clone of the value using the [`CLONE`] protocol.
437    ///
438    /// You must use [`Vm::with`] to specify which virtual machine this function
439    /// is called inside.
440    ///
441    /// [`Vm::with`]: crate::Vm::with
442    ///
443    /// # Errors
444    ///
445    /// This function errors if called outside of a virtual machine.
446    ///
447    /// [`CLONE`]: Protocol::CLONE
448    pub fn clone_(&self) -> Result<Self, VmError> {
449        self.clone_with(&mut EnvProtocolCaller)
450    }
451
452    pub(crate) fn clone_with(&self, caller: &mut dyn ProtocolCaller) -> Result<Value, VmError> {
453        match self.as_ref() {
454            Repr::Inline(value) => {
455                return Ok(Self {
456                    repr: Repr::Inline(*value),
457                });
458            }
459            Repr::Dynamic(value) => {
460                // TODO: This type of cloning should be deep, not shallow.
461                return Ok(Self {
462                    repr: Repr::Dynamic(value.clone()),
463                });
464            }
465            Repr::Any(..) => {}
466        }
467
468        caller.call_protocol_fn(&Protocol::CLONE, self.clone(), &mut ())
469    }
470
471    /// Debug format the value using the [`DEBUG_FMT`] protocol.
472    ///
473    /// You must use [`Vm::with`] to specify which virtual machine this function
474    /// is called inside.
475    ///
476    /// [`Vm::with`]: crate::Vm::with
477    ///
478    /// # Errors
479    ///
480    /// This function errors if called outside of a virtual machine.
481    ///
482    /// [`DEBUG_FMT`]: Protocol::DEBUG_FMT
483    pub fn debug_fmt(&self, f: &mut Formatter) -> Result<(), VmError> {
484        self.debug_fmt_with(f, &mut EnvProtocolCaller)
485    }
486
487    /// Internal impl of debug_fmt with a customizable caller.
488    pub(crate) fn debug_fmt_with(
489        &self,
490        f: &mut Formatter,
491        caller: &mut dyn ProtocolCaller,
492    ) -> Result<(), VmError> {
493        let _guard = env::enter_value()?;
494
495        match &self.repr {
496            Repr::Inline(value) => {
497                write!(f, "{value:?}")?;
498            }
499            Repr::Dynamic(ref value) => {
500                value.debug_fmt_with(f, caller)?;
501            }
502            Repr::Any(..) => {
503                // reborrow f to avoid moving it
504                let mut args = DynGuardedArgs::new((&mut *f,));
505
506                match caller.try_call_protocol_fn(&Protocol::DEBUG_FMT, self.clone(), &mut args)? {
507                    CallResultOnly::Ok(value) => {
508                        <()>::from_value(value)?;
509                    }
510                    CallResultOnly::Unsupported(value) => match &value.repr {
511                        Repr::Inline(value) => {
512                            write!(f, "{value:?}")?;
513                        }
514                        Repr::Dynamic(value) => {
515                            let ty = value.type_info();
516                            write!(f, "<{ty} object at {value:p}>")?;
517                        }
518                        Repr::Any(value) => {
519                            let ty = value.type_info();
520                            write!(f, "<{ty} object at {value:p}>")?;
521                        }
522                    },
523                }
524            }
525        }
526
527        Ok(())
528    }
529
530    /// Convert value into an iterator using the [`Protocol::INTO_ITER`]
531    /// protocol.
532    ///
533    /// You must use [`Vm::with`] to specify which virtual machine this function
534    /// is called inside.
535    ///
536    /// [`Vm::with`]: crate::Vm::with
537    ///
538    /// # Errors
539    ///
540    /// This function will error if called outside of a virtual machine context.
541    pub fn into_iter(self) -> Result<Iterator, VmError> {
542        self.into_iter_with(&mut EnvProtocolCaller)
543    }
544
545    pub(crate) fn into_iter_with(
546        self,
547        caller: &mut dyn ProtocolCaller,
548    ) -> Result<Iterator, VmError> {
549        let value = caller.call_protocol_fn(&Protocol::INTO_ITER, self, &mut ())?;
550        Ok(Iterator::new(value))
551    }
552
553    /// Retrieves a human readable type name for the current value.
554    ///
555    /// You must use [`Vm::with`] to specify which virtual machine this function
556    /// is called inside.
557    ///
558    /// [`Vm::with`]: crate::Vm::with
559    ///
560    /// # Errors
561    ///
562    /// This function errors in case the provided type cannot be converted into
563    /// a name without the use of a [`Vm`] and one is not provided through the
564    /// environment.
565    ///
566    /// [`Vm`]: crate::Vm
567    pub fn into_type_name(self) -> Result<String, VmError> {
568        let hash = Hash::associated_function(self.type_hash(), &Protocol::INTO_TYPE_NAME);
569
570        crate::runtime::env::shared(|context, unit, _| {
571            if let Some(name) = context.constant(&hash) {
572                match name.kind() {
573                    ConstNodeKind::String(s) => return Ok(String::try_from(s.as_ref())?),
574                    _ => {
575                        return Err(VmError::new(VmErrorKind::expected::<String>(
576                            name.type_info(),
577                        )))
578                    }
579                }
580            }
581
582            if let Some(name) = unit.constant(&hash) {
583                match name.kind() {
584                    ConstNodeKind::String(s) => return Ok(String::try_from(s.as_ref())?),
585                    _ => {
586                        return Err(VmError::new(VmErrorKind::expected::<String>(
587                            name.type_info(),
588                        )))
589                    }
590                }
591            }
592
593            Ok(self.type_info().try_to_string()?)
594        })
595    }
596
597    /// Construct a vector.
598    pub fn vec(vec: alloc::Vec<Value>) -> alloc::Result<Self> {
599        let data = Vec::from(vec);
600        Value::try_from(data)
601    }
602
603    /// Construct a tuple.
604    pub fn tuple(vec: alloc::Vec<Value>) -> alloc::Result<Self> {
605        Value::try_from(OwnedTuple::try_from(vec)?)
606    }
607
608    /// Construct an empty.
609    pub fn empty_struct(rtti: Arc<Rtti>) -> alloc::Result<Self> {
610        Ok(Value::from(AnySequence::new(rtti, [])?))
611    }
612
613    /// Construct a typed tuple.
614    pub fn tuple_struct(
615        rtti: Arc<Rtti>,
616        data: impl IntoIterator<IntoIter: ExactSizeIterator, Item = Value>,
617    ) -> alloc::Result<Self> {
618        Ok(Value::from(AnySequence::new(rtti, data)?))
619    }
620
621    /// Drop the interior value.
622    ///
623    /// This consumes any live references of the value and accessing them in the
624    /// future will result in an error.
625    pub(crate) fn drop(self) -> Result<(), VmError> {
626        match self.take_repr() {
627            Repr::Dynamic(value) => {
628                value.drop()?;
629            }
630            Repr::Any(value) => {
631                value.drop()?;
632            }
633            _ => {}
634        }
635
636        Ok(())
637    }
638
639    /// Move the interior value.
640    pub(crate) fn move_(self) -> Result<Self, VmError> {
641        match self.take_repr() {
642            Repr::Dynamic(value) => Ok(Value {
643                repr: Repr::Dynamic(value.take()?),
644            }),
645            Repr::Any(value) => Ok(Value {
646                repr: Repr::Any(value.take()?),
647            }),
648            repr => Ok(Value { repr }),
649        }
650    }
651
652    /// Try to coerce value into a usize.
653    #[inline]
654    pub fn as_usize(&self) -> Result<usize, RuntimeError> {
655        self.as_integer()
656    }
657
658    /// Get the value as a string.
659    #[deprecated(
660        note = "For consistency with other methods, this has been renamed Value::borrow_string_ref"
661    )]
662    #[inline]
663    pub fn as_string(&self) -> Result<BorrowRef<'_, str>, RuntimeError> {
664        self.borrow_string_ref()
665    }
666
667    /// Borrow the interior value as a string reference.
668    pub fn borrow_string_ref(&self) -> Result<BorrowRef<'_, str>, RuntimeError> {
669        let string = self.borrow_ref::<String>()?;
670        Ok(BorrowRef::map(string, String::as_str))
671    }
672
673    /// Take the current value as a string.
674    #[inline]
675    pub fn into_string(self) -> Result<String, RuntimeError> {
676        match self.take_repr() {
677            Repr::Any(value) => Ok(value.downcast()?),
678            actual => Err(RuntimeError::expected::<String>(actual.type_info())),
679        }
680    }
681
682    /// Coerce into type value.
683    #[doc(hidden)]
684    #[inline]
685    pub fn as_type_value(&self) -> Result<TypeValue<'_>, RuntimeError> {
686        match self.as_ref() {
687            Repr::Inline(value) => match value {
688                Inline::Unit => Ok(TypeValue::Unit),
689                value => Ok(TypeValue::NotTypedInline(NotTypedInline(*value))),
690            },
691            Repr::Dynamic(value) => match value.rtti().kind {
692                RttiKind::Empty => Ok(TypeValue::EmptyStruct(EmptyStruct { rtti: value.rtti() })),
693                RttiKind::Tuple => Ok(TypeValue::TupleStruct(TupleStruct {
694                    rtti: value.rtti(),
695                    data: value.borrow_ref()?,
696                })),
697                RttiKind::Struct => Ok(TypeValue::Struct(Struct {
698                    rtti: value.rtti(),
699                    data: value.borrow_ref()?,
700                })),
701            },
702            Repr::Any(value) => match value.type_hash() {
703                OwnedTuple::HASH => Ok(TypeValue::Tuple(value.borrow_ref()?)),
704                Object::HASH => Ok(TypeValue::Object(value.borrow_ref()?)),
705                _ => Ok(TypeValue::NotTypedAnyObj(NotTypedAnyObj(value))),
706            },
707        }
708    }
709
710    /// Coerce into a unit.
711    #[inline]
712    pub fn into_unit(&self) -> Result<(), RuntimeError> {
713        match self.as_ref() {
714            Repr::Inline(Inline::Unit) => Ok(()),
715            value => Err(RuntimeError::expected::<()>(value.type_info())),
716        }
717    }
718
719    inline_into! {
720        /// Coerce into [`Ordering`].
721        Ordering(Ordering),
722        as_ordering,
723        as_ordering_mut,
724    }
725
726    inline_into! {
727        /// Coerce into [`Hash`][crate::Hash].
728        Hash(Hash),
729        as_hash,
730        as_hash_mut,
731    }
732
733    inline_into! {
734        /// Coerce into [`bool`].
735        Bool(bool),
736        as_bool,
737        as_bool_mut,
738    }
739
740    inline_into! {
741        /// Coerce into [`char`].
742        Char(char),
743        as_char,
744        as_char_mut,
745    }
746
747    inline_into! {
748        /// Coerce into [`i64`] integer.
749        Signed(i64),
750        as_signed,
751        as_signed_mut,
752    }
753
754    inline_into! {
755        /// Coerce into [`u64`] unsigned integer.
756        Unsigned(u64),
757        as_unsigned,
758        as_unsigned_mut,
759    }
760
761    inline_into! {
762        /// Coerce into [`f64`] float.
763        Float(f64),
764        as_float,
765        as_float_mut,
766    }
767
768    inline_into! {
769        /// Coerce into [`Type`].
770        Type(Type),
771        as_type,
772        as_type_mut,
773    }
774
775    /// Borrow as a tuple.
776    ///
777    /// This ensures that the value has read access to the underlying value
778    /// and does not consume it.
779    #[inline]
780    pub fn borrow_tuple_ref(&self) -> Result<BorrowRef<'_, Tuple>, RuntimeError> {
781        match self.as_ref() {
782            Repr::Inline(Inline::Unit) => Ok(BorrowRef::from_static(Tuple::new(&[]))),
783            Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
784            Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
785            Repr::Any(value) => {
786                let value = value.borrow_ref::<OwnedTuple>()?;
787                let value = BorrowRef::map(value, OwnedTuple::as_ref);
788                Ok(value)
789            }
790        }
791    }
792
793    /// Borrow as a tuple as mutable.
794    ///
795    /// This ensures that the value has write access to the underlying value and
796    /// does not consume it.
797    #[inline]
798    pub fn borrow_tuple_mut(&self) -> Result<BorrowMut<'_, Tuple>, RuntimeError> {
799        match self.as_ref() {
800            Repr::Inline(Inline::Unit) => Ok(BorrowMut::from_ref(Tuple::new_mut(&mut []))),
801            Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
802            Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
803            Repr::Any(value) => {
804                let value = value.borrow_mut::<OwnedTuple>()?;
805                let value = BorrowMut::map(value, OwnedTuple::as_mut);
806                Ok(value)
807            }
808        }
809    }
810
811    /// Borrow as an owned tuple reference.
812    ///
813    /// This ensures that the value has read access to the underlying value and
814    /// does not consume it.
815    #[inline]
816    pub fn into_tuple(&self) -> Result<Box<Tuple>, RuntimeError> {
817        match self.as_ref() {
818            Repr::Inline(Inline::Unit) => Ok(Tuple::from_boxed(Box::default())),
819            Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
820            Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
821            Repr::Any(value) => Ok(value.clone().downcast::<OwnedTuple>()?.into_boxed_tuple()),
822        }
823    }
824
825    /// Borrow as an owned tuple reference.
826    ///
827    /// This ensures that the value has read access to the underlying value and
828    /// does not consume it.
829    #[inline]
830    pub fn into_tuple_ref(&self) -> Result<Ref<Tuple>, RuntimeError> {
831        match self.as_ref() {
832            Repr::Inline(Inline::Unit) => Ok(Ref::from_static(Tuple::new(&[]))),
833            Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
834            Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
835            Repr::Any(value) => {
836                let value = value.clone().into_ref::<OwnedTuple>()?;
837                let value = Ref::map(value, OwnedTuple::as_ref);
838                Ok(value)
839            }
840        }
841    }
842
843    /// Borrow as an owned tuple mutable.
844    ///
845    /// This ensures that the value has write access to the underlying value and
846    /// does not consume it.
847    #[inline]
848    pub fn into_tuple_mut(&self) -> Result<Mut<Tuple>, RuntimeError> {
849        match self.as_ref() {
850            Repr::Inline(Inline::Unit) => Ok(Mut::from_static(Tuple::new_mut(&mut []))),
851            Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
852            Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
853            Repr::Any(value) => {
854                let value = value.clone().into_mut::<OwnedTuple>()?;
855                let value = Mut::map(value, OwnedTuple::as_mut);
856                Ok(value)
857            }
858        }
859    }
860
861    /// Coerce into an [`AnyObj`].
862    #[inline]
863    pub fn into_any_obj(self) -> Result<AnyObj, RuntimeError> {
864        match self.take_repr() {
865            Repr::Inline(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
866            Repr::Dynamic(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
867            Repr::Any(value) => Ok(value),
868        }
869    }
870
871    /// Coerce into a [`Shared<T>`].
872    ///
873    /// This type checks and coerces the value into a type which statically
874    /// guarantees that the underlying type is of the given type.
875    #[inline]
876    pub fn into_shared<T>(self) -> Result<Shared<T>, RuntimeError>
877    where
878        T: Any,
879    {
880        match self.take_repr() {
881            Repr::Inline(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
882            Repr::Dynamic(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
883            Repr::Any(value) => Ok(value.into_shared()?),
884        }
885    }
886
887    /// Coerce into a future, or convert into a future using the
888    /// [Protocol::INTO_FUTURE] protocol.
889    ///
890    /// You must use [`Vm::with`] to specify which virtual machine this function
891    /// is called inside.
892    ///
893    /// [`Vm::with`]: crate::Vm::with
894    ///
895    /// # Errors
896    ///
897    /// This function errors in case the provided type cannot be converted into
898    /// a future without the use of a [`Vm`] and one is not provided through the
899    /// environment.
900    ///
901    /// [`Vm`]: crate::Vm
902    #[inline]
903    pub fn into_future(self) -> Result<Future, RuntimeError> {
904        let target = match self.take_repr() {
905            Repr::Any(value) => match value.type_hash() {
906                Future::HASH => {
907                    return Ok(value.downcast::<Future>()?);
908                }
909                _ => Value::from(value),
910            },
911            repr => Value::from(repr),
912        };
913
914        let value = EnvProtocolCaller.call_protocol_fn(&Protocol::INTO_FUTURE, target, &mut ())?;
915
916        Future::from_value(value)
917    }
918
919    /// Try to coerce value into a typed reference.
920    ///
921    /// # Safety
922    ///
923    /// The returned pointer is only valid to dereference as long as the
924    /// returned guard is live.
925    #[inline]
926    pub fn into_any_ref_ptr<T>(self) -> Result<(NonNull<T>, RawValueGuard), RuntimeError>
927    where
928        T: Any,
929    {
930        match self.take_repr() {
931            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
932            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
933            Repr::Any(value) => {
934                let (ptr, guard) = value.borrow_ref_ptr::<T>()?;
935                let guard = RawValueGuard { guard };
936                Ok((ptr, guard))
937            }
938        }
939    }
940
941    /// Try to coerce value into a typed mutable reference.
942    ///
943    /// # Safety
944    ///
945    /// The returned pointer is only valid to dereference as long as the
946    /// returned guard is live.
947    #[inline]
948    #[doc(hidden)]
949    pub fn into_any_mut_ptr<T>(self) -> Result<(NonNull<T>, RawValueGuard), RuntimeError>
950    where
951        T: Any,
952    {
953        match self.take_repr() {
954            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
955            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
956            Repr::Any(value) => {
957                let (ptr, guard) = value.borrow_mut_ptr::<T>()?;
958                let guard = RawValueGuard { guard };
959                Ok((ptr, guard))
960            }
961        }
962    }
963
964    /// Downcast the value into a stored value that implements `Any`.
965    ///
966    /// This takes the interior value, making it inaccessible to other owned
967    /// references.
968    ///
969    /// You should usually prefer to use [`rune::from_value`] instead of this
970    /// directly.
971    ///
972    /// [`rune::from_value`]: crate::from_value
973    ///
974    /// # Examples
975    ///
976    /// ```
977    /// use rune::Value;
978    /// use rune::alloc::String;
979    ///
980    /// let a = Value::try_from("Hello World")?;
981    /// let b = a.clone();
982    ///
983    /// assert!(b.borrow_ref::<String>().is_ok());
984    ///
985    /// // NB: The interior representation of the stored string is from rune-alloc.
986    /// let a = a.downcast::<String>()?;
987    ///
988    /// assert!(b.borrow_ref::<String>().is_err());
989    ///
990    /// assert_eq!(a, "Hello World");
991    /// # Ok::<_, rune::support::Error>(())
992    /// ```
993    #[inline]
994    pub fn downcast<T>(self) -> Result<T, RuntimeError>
995    where
996        T: Any,
997    {
998        match self.take_repr() {
999            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1000            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1001            Repr::Any(value) => Ok(value.downcast::<T>()?),
1002        }
1003    }
1004
1005    /// Borrow the value as a typed reference of type `T`.
1006    ///
1007    /// # Examples
1008    ///
1009    /// ```
1010    /// use rune::Value;
1011    /// use rune::alloc::String;
1012    ///
1013    /// let a = Value::try_from("Hello World")?;
1014    /// let b = a.clone();
1015    ///
1016    /// assert!(b.borrow_ref::<String>().is_ok());
1017    ///
1018    /// // NB: The interior representation of the stored string is from rune-alloc.
1019    /// let a = a.downcast::<String>()?;
1020    ///
1021    /// assert!(b.borrow_ref::<String>().is_err());
1022    ///
1023    /// assert_eq!(a, "Hello World");
1024    /// # Ok::<_, rune::support::Error>(())
1025    /// ```
1026    #[inline]
1027    pub fn borrow_ref<T>(&self) -> Result<BorrowRef<'_, T>, RuntimeError>
1028    where
1029        T: Any,
1030    {
1031        match &self.repr {
1032            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1033            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1034            Repr::Any(value) => Ok(value.borrow_ref()?),
1035        }
1036    }
1037
1038    /// Try to coerce value into a typed reference of type `T`.
1039    ///
1040    /// You should usually prefer to use [`rune::from_value`] instead of this
1041    /// directly.
1042    ///
1043    /// [`rune::from_value`]: crate::from_value
1044    ///
1045    /// # Examples
1046    ///
1047    /// ```
1048    /// use rune::Value;
1049    /// use rune::alloc::String;
1050    ///
1051    /// let mut a = Value::try_from("Hello World")?;
1052    /// let b = a.clone();
1053    ///
1054    /// assert_eq!(a.into_ref::<String>()?.as_str(), "Hello World");
1055    /// assert_eq!(b.into_ref::<String>()?.as_str(), "Hello World");
1056    /// # Ok::<_, rune::support::Error>(())
1057    /// ```
1058    #[inline]
1059    pub fn into_ref<T>(self) -> Result<Ref<T>, RuntimeError>
1060    where
1061        T: Any,
1062    {
1063        match self.take_repr() {
1064            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1065            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1066            Repr::Any(value) => Ok(value.into_ref()?),
1067        }
1068    }
1069
1070    /// Try to borrow value into a typed mutable reference of type `T`.
1071    #[inline]
1072    pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, RuntimeError>
1073    where
1074        T: Any,
1075    {
1076        match &self.repr {
1077            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1078            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1079            Repr::Any(value) => Ok(value.borrow_mut()?),
1080        }
1081    }
1082
1083    /// Try to coerce value into a typed mutable reference of type `T`.
1084    ///
1085    /// You should usually prefer to use [`rune::from_value`] instead of this
1086    /// directly since it supports transparently coercing into types like
1087    /// [`Mut<str>`].
1088    ///
1089    /// [`rune::from_value`]: crate::from_value
1090    ///
1091    /// # Examples
1092    ///
1093    /// ```
1094    /// use rune::{Mut, Value};
1095    /// use rune::alloc::String;
1096    ///
1097    /// let mut a = Value::try_from("Hello World")?;
1098    /// let b = a.clone();
1099    ///
1100    /// fn modify_string(mut s: Mut<String>) {
1101    ///     assert_eq!(s.as_str(), "Hello World");
1102    ///     s.make_ascii_lowercase();
1103    ///     assert_eq!(s.as_str(), "hello world");
1104    /// }
1105    ///
1106    /// modify_string(a.into_mut::<String>()?);
1107    ///
1108    /// assert_eq!(b.borrow_mut::<String>()?.as_str(), "hello world");
1109    /// # Ok::<_, rune::support::Error>(())
1110    /// ```
1111    #[inline]
1112    pub fn into_mut<T>(self) -> Result<Mut<T>, RuntimeError>
1113    where
1114        T: Any,
1115    {
1116        match self.take_repr() {
1117            Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1118            Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1119            Repr::Any(value) => Ok(value.into_mut()?),
1120        }
1121    }
1122
1123    /// Get the type hash for the current value.
1124    ///
1125    /// One notable feature is that the type of a variant is its container
1126    /// *enum*, and not the type hash of the variant itself.
1127    #[inline(always)]
1128    pub fn type_hash(&self) -> Hash {
1129        match &self.repr {
1130            Repr::Inline(value) => value.type_hash(),
1131            Repr::Dynamic(value) => value.type_hash(),
1132            Repr::Any(value) => value.type_hash(),
1133        }
1134    }
1135
1136    /// Get the type information for the current value.
1137    #[inline(always)]
1138    pub fn type_info(&self) -> TypeInfo {
1139        match &self.repr {
1140            Repr::Inline(value) => value.type_info(),
1141            Repr::Dynamic(value) => value.type_info(),
1142            Repr::Any(value) => value.type_info(),
1143        }
1144    }
1145
1146    /// Perform a partial equality test between two values.
1147    ///
1148    /// This is the basis for the eq operation (`partial_eq` / '==').
1149    ///
1150    /// External types will use the [`Protocol::PARTIAL_EQ`] protocol when
1151    /// invoked through this function.
1152    ///
1153    /// # Errors
1154    ///
1155    /// This function will error if called outside of a virtual machine context.
1156    pub fn partial_eq(a: &Value, b: &Value) -> Result<bool, VmError> {
1157        Self::partial_eq_with(a, b, &mut EnvProtocolCaller)
1158    }
1159
1160    /// Perform a total equality test between two values.
1161    ///
1162    /// This is the basis for the eq operation (`partial_eq` / '==').
1163    #[cfg_attr(feature = "bench", inline(never))]
1164    pub(crate) fn partial_eq_with(
1165        &self,
1166        b: &Value,
1167        caller: &mut dyn ProtocolCaller,
1168    ) -> Result<bool, VmError> {
1169        let _guard = env::enter_value()?;
1170
1171        self.bin_op_with(
1172            b,
1173            caller,
1174            &Protocol::PARTIAL_EQ,
1175            Inline::partial_eq,
1176            |lhs, rhs, caller| {
1177                if lhs.0.variant_hash != rhs.0.variant_hash {
1178                    return Ok(false);
1179                }
1180
1181                Vec::eq_with(lhs.1, rhs.1, Value::partial_eq_with, caller)
1182            },
1183        )
1184    }
1185
1186    /// Perform a total equality test between two values.
1187    ///
1188    /// This is the basis for the eq operation (`==`).
1189    ///
1190    /// External types will use the [`Protocol::EQ`] protocol when invoked
1191    /// through this function.
1192    ///
1193    /// # Errors
1194    ///
1195    /// This function will error if called outside of a virtual machine context.
1196    pub fn eq(&self, b: &Value) -> Result<bool, VmError> {
1197        self.eq_with(b, &mut EnvProtocolCaller)
1198    }
1199
1200    /// Perform a total equality test between two values.
1201    ///
1202    /// This is the basis for the eq operation (`==`).
1203    #[cfg_attr(feature = "bench", inline(never))]
1204    pub(crate) fn eq_with(
1205        &self,
1206        b: &Value,
1207        caller: &mut dyn ProtocolCaller,
1208    ) -> Result<bool, VmError> {
1209        let _guard = env::enter_value()?;
1210
1211        self.bin_op_with(b, caller, &Protocol::EQ, Inline::eq, |lhs, rhs, caller| {
1212            if lhs.0.variant_hash != rhs.0.variant_hash {
1213                return Ok(false);
1214            }
1215
1216            Vec::eq_with(lhs.1, rhs.1, Value::eq_with, caller)
1217        })
1218    }
1219
1220    /// Perform a partial ordering comparison between two values.
1221    ///
1222    /// This is the basis for the comparison operation.
1223    ///
1224    /// External types will use the [`Protocol::PARTIAL_CMP`] protocol when
1225    /// invoked through this function.
1226    ///
1227    /// # Errors
1228    ///
1229    /// This function will error if called outside of a virtual machine context.
1230    pub fn partial_cmp(a: &Value, b: &Value) -> Result<Option<Ordering>, VmError> {
1231        Value::partial_cmp_with(a, b, &mut EnvProtocolCaller)
1232    }
1233
1234    /// Perform a partial ordering comparison between two values.
1235    ///
1236    /// This is the basis for the comparison operation.
1237    #[cfg_attr(feature = "bench", inline(never))]
1238    pub(crate) fn partial_cmp_with(
1239        &self,
1240        b: &Value,
1241        caller: &mut dyn ProtocolCaller,
1242    ) -> Result<Option<Ordering>, VmError> {
1243        let _guard = env::enter_value()?;
1244
1245        self.bin_op_with(
1246            b,
1247            caller,
1248            &Protocol::PARTIAL_CMP,
1249            Inline::partial_cmp,
1250            |lhs, rhs, caller| {
1251                let ord = lhs.0.variant_hash.cmp(&rhs.0.variant_hash);
1252
1253                if ord != Ordering::Equal {
1254                    return Ok(Some(ord));
1255                }
1256
1257                Vec::partial_cmp_with(lhs.1, rhs.1, caller)
1258            },
1259        )
1260    }
1261
1262    /// Perform a total ordering comparison between two values.
1263    ///
1264    /// This is the basis for the comparison operation (`cmp`).
1265    ///
1266    /// External types will use the [`Protocol::CMP`] protocol when invoked
1267    /// through this function.
1268    ///
1269    /// # Errors
1270    ///
1271    /// This function will error if called outside of a virtual machine context.
1272    pub fn cmp(a: &Value, b: &Value) -> Result<Ordering, VmError> {
1273        Value::cmp_with(a, b, &mut EnvProtocolCaller)
1274    }
1275
1276    /// Perform a total ordering comparison between two values.
1277    ///
1278    /// This is the basis for the comparison operation (`cmp`).
1279    #[cfg_attr(feature = "bench", inline(never))]
1280    pub(crate) fn cmp_with(
1281        &self,
1282        b: &Value,
1283        caller: &mut dyn ProtocolCaller,
1284    ) -> Result<Ordering, VmError> {
1285        let _guard = env::enter_value()?;
1286
1287        self.bin_op_with(
1288            b,
1289            caller,
1290            &Protocol::CMP,
1291            Inline::cmp,
1292            |lhs, rhs, caller| {
1293                let ord = lhs.0.variant_hash.cmp(&rhs.0.variant_hash);
1294
1295                if ord != Ordering::Equal {
1296                    return Ok(ord);
1297                }
1298
1299                Vec::cmp_with(lhs.1, rhs.1, caller)
1300            },
1301        )
1302    }
1303
1304    /// Hash the current value.
1305    pub fn hash(&self, hasher: &mut Hasher) -> Result<(), VmError> {
1306        self.hash_with(hasher, &mut EnvProtocolCaller)
1307    }
1308
1309    /// Hash the current value.
1310    #[cfg_attr(feature = "bench", inline(never))]
1311    pub(crate) fn hash_with(
1312        &self,
1313        hasher: &mut Hasher,
1314        caller: &mut dyn ProtocolCaller,
1315    ) -> Result<(), VmError> {
1316        let _guard = env::enter_value()?;
1317
1318        match self.as_ref() {
1319            Repr::Inline(value) => {
1320                value.hash(hasher)?;
1321                return Ok(());
1322            }
1323            Repr::Dynamic(value) => {
1324                // Equality on a value of a type declared in a script is
1325                // structural - the same type, the same variant, and fields
1326                // which are equal in turn - so hashing has to be, or a type
1327                // which can be compared cannot be a key.
1328                let rtti = value.rtti();
1329
1330                core::hash::Hash::hash(&rtti.hash, hasher);
1331                core::hash::Hash::hash(&rtti.variant_hash, hasher);
1332
1333                let values = value.borrow_ref()?;
1334
1335                for value in values.iter() {
1336                    value.hash_with(hasher, caller)?;
1337                }
1338
1339                return Ok(());
1340            }
1341            Repr::Any(value) => match value.type_hash() {
1342                Vec::HASH => {
1343                    let vec = value.borrow_ref::<Vec>()?;
1344                    return Vec::hash_with(&vec, hasher, caller);
1345                }
1346                OwnedTuple::HASH => {
1347                    let tuple = value.borrow_ref::<OwnedTuple>()?;
1348                    return Tuple::hash_with(&tuple, hasher, caller);
1349                }
1350                _ => {}
1351            },
1352        }
1353
1354        let mut args = DynGuardedArgs::new((hasher,));
1355
1356        if let CallResultOnly::Ok(value) =
1357            caller.try_call_protocol_fn(&Protocol::HASH, self.clone(), &mut args)?
1358        {
1359            <()>::from_value(value)?;
1360            return Ok(());
1361        }
1362
1363        Err(VmError::new(VmErrorKind::UnsupportedUnaryOperation {
1364            op: Protocol::HASH.name,
1365            operand: self.type_info(),
1366        }))
1367    }
1368
1369    fn bin_op_with<T>(
1370        &self,
1371        b: &Value,
1372        caller: &mut dyn ProtocolCaller,
1373        protocol: &'static Protocol,
1374        inline: fn(&Inline, &Inline) -> Result<T, RuntimeError>,
1375        dynamic: fn(
1376            (&Arc<Rtti>, &[Value]),
1377            (&Arc<Rtti>, &[Value]),
1378            &mut dyn ProtocolCaller,
1379        ) -> Result<T, VmError>,
1380    ) -> Result<T, VmError>
1381    where
1382        T: FromValue,
1383    {
1384        match (self.as_ref(), b.as_ref()) {
1385            (Repr::Inline(lhs), Repr::Inline(rhs)) => return Ok(inline(lhs, rhs)?),
1386            (Repr::Inline(lhs), rhs) => {
1387                return Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1388                    op: protocol.name,
1389                    lhs: lhs.type_info(),
1390                    rhs: rhs.type_info(),
1391                }));
1392            }
1393            (Repr::Dynamic(lhs), Repr::Dynamic(rhs)) => {
1394                let lhs_rtti = lhs.rtti();
1395                let rhs_rtti = rhs.rtti();
1396
1397                let lhs = lhs.borrow_ref()?;
1398                let rhs = rhs.borrow_ref()?;
1399
1400                if lhs_rtti.hash == rhs_rtti.hash {
1401                    return dynamic((lhs_rtti, &lhs), (rhs_rtti, &rhs), caller);
1402                }
1403
1404                return Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1405                    op: protocol.name,
1406                    lhs: Rtti::type_info(lhs_rtti.clone()),
1407                    rhs: Rtti::type_info(rhs_rtti.clone()),
1408                }));
1409            }
1410            _ => {}
1411        }
1412
1413        if let CallResultOnly::Ok(value) =
1414            caller.try_call_protocol_fn(protocol, self.clone(), &mut Some((b.clone(),)))?
1415        {
1416            return Ok(T::from_value(value)?);
1417        }
1418
1419        Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1420            op: protocol.name,
1421            lhs: self.type_info(),
1422            rhs: b.type_info(),
1423        }))
1424    }
1425
1426    /// Try to coerce the current value as the specified integer `T`.
1427    ///
1428    /// # Examples
1429    ///
1430    /// ```
1431    /// let value = rune::to_value(u32::MAX)?;
1432    ///
1433    /// assert_eq!(value.as_integer::<u64>()?, u32::MAX as u64);
1434    /// assert!(value.as_integer::<i32>().is_err());
1435    ///
1436    /// # Ok::<(), rune::support::Error>(())
1437    /// ```
1438    pub fn as_integer<T>(&self) -> Result<T, RuntimeError>
1439    where
1440        T: TryFrom<u64> + TryFrom<i64>,
1441    {
1442        match self.repr {
1443            Repr::Inline(value) => value.as_integer(),
1444            Repr::Dynamic(ref value) => Err(RuntimeError::new(VmErrorKind::ExpectedNumber {
1445                actual: value.type_info(),
1446            })),
1447            Repr::Any(ref value) => Err(RuntimeError::new(VmErrorKind::ExpectedNumber {
1448                actual: value.type_info(),
1449            })),
1450        }
1451    }
1452
1453    pub(crate) fn as_inline_unchecked(&self) -> Option<&Inline> {
1454        match &self.repr {
1455            Repr::Inline(value) => Some(value),
1456            _ => None,
1457        }
1458    }
1459
1460    /// Test if the value is inline.
1461    pub(crate) fn is_inline(&self) -> bool {
1462        matches!(self.repr, Repr::Inline(..))
1463    }
1464
1465    /// Coerce into a checked [`Inline`] object.
1466    ///
1467    /// Any empty value will cause an access error.
1468    #[inline]
1469    pub(crate) fn as_inline(&self) -> Option<&Inline> {
1470        match &self.repr {
1471            Repr::Inline(value) => Some(value),
1472            Repr::Dynamic(..) => None,
1473            Repr::Any(..) => None,
1474        }
1475    }
1476
1477    /// Coerce into a checked [`AnyObj`] object.
1478    ///
1479    /// Any empty value will cause an access error.
1480    #[inline]
1481    pub fn as_any(&self) -> Option<&AnyObj> {
1482        match &self.repr {
1483            Repr::Inline(..) => None,
1484            Repr::Dynamic(..) => None,
1485            Repr::Any(value) => Some(value),
1486        }
1487    }
1488
1489    #[inline(always)]
1490    pub(crate) fn take_repr(mut self) -> Repr {
1491        replace(&mut self.repr, Repr::Inline(Inline::Empty))
1492    }
1493
1494    #[inline(always)]
1495    pub(crate) fn as_ref(&self) -> &Repr {
1496        &self.repr
1497    }
1498
1499    #[inline(always)]
1500    pub(crate) fn as_mut(&mut self) -> &mut Repr {
1501        &mut self.repr
1502    }
1503
1504    #[inline]
1505    pub(crate) fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
1506    where
1507        T: Any,
1508    {
1509        match &self.repr {
1510            Repr::Inline(..) => Ok(None),
1511            Repr::Dynamic(..) => Ok(None),
1512            Repr::Any(value) => value.try_borrow_ref(),
1513        }
1514    }
1515
1516    #[inline]
1517    pub(crate) fn try_borrow_mut<T>(&self) -> Result<Option<BorrowMut<'_, T>>, AccessError>
1518    where
1519        T: Any,
1520    {
1521        match &self.repr {
1522            Repr::Inline(..) => Ok(None),
1523            Repr::Dynamic(..) => Ok(None),
1524            Repr::Any(value) => value.try_borrow_mut(),
1525        }
1526    }
1527
1528    // An adapter delegates to the iterator it wraps by walking into it, and a
1529    // script decides how many of them are wrapped around each other - `it =
1530    // it.skip(0)` in a loop - so each of these is a level of a walk over a
1531    // value and is bounded like every other one.
1532
1533    pub(crate) fn protocol_into_iter(&self) -> Result<Value, VmError> {
1534        let _guard = env::enter_value()?;
1535        EnvProtocolCaller.call_protocol_fn(&Protocol::INTO_ITER, self.clone(), &mut ())
1536    }
1537
1538    // Stepping an iterator from native code is a loop the machine cannot see -
1539    // it does not execute an instruction per element the way a script's own
1540    // loop does - so a permit is taken here rather than at each of the several
1541    // dozen native loops which step one. `Vm::op_iter_next` does not come
1542    // through here; a script's `for` pays for the instructions it runs.
1543
1544    pub(crate) fn protocol_next(&self) -> Result<Option<Value>, VmError> {
1545        budget::permit()?;
1546        let _guard = env::enter_value()?;
1547        let value = EnvProtocolCaller.call_protocol_fn(&Protocol::NEXT, self.clone(), &mut ())?;
1548
1549        Ok(FromValue::from_value(value)?)
1550    }
1551
1552    pub(crate) fn protocol_next_back(&self) -> Result<Option<Value>, VmError> {
1553        budget::permit()?;
1554        let _guard = env::enter_value()?;
1555
1556        let value =
1557            EnvProtocolCaller.call_protocol_fn(&Protocol::NEXT_BACK, self.clone(), &mut ())?;
1558
1559        Ok(FromValue::from_value(value)?)
1560    }
1561
1562    pub(crate) fn protocol_nth_back(&self, n: usize) -> Result<Option<Value>, VmError> {
1563        let _guard = env::enter_value()?;
1564
1565        let value = EnvProtocolCaller.call_protocol_fn(
1566            &Protocol::NTH_BACK,
1567            self.clone(),
1568            &mut Some((n,)),
1569        )?;
1570
1571        Ok(FromValue::from_value(value)?)
1572    }
1573
1574    pub(crate) fn protocol_len(&self) -> Result<usize, VmError> {
1575        let _guard = env::enter_value()?;
1576        let value = EnvProtocolCaller.call_protocol_fn(&Protocol::LEN, self.clone(), &mut ())?;
1577
1578        Ok(FromValue::from_value(value)?)
1579    }
1580
1581    pub(crate) fn protocol_size_hint(&self) -> Result<(usize, Option<usize>), VmError> {
1582        let _guard = env::enter_value()?;
1583
1584        let value =
1585            EnvProtocolCaller.call_protocol_fn(&Protocol::SIZE_HINT, self.clone(), &mut ())?;
1586
1587        Ok(FromValue::from_value(value)?)
1588    }
1589}
1590
1591impl fmt::Debug for Value {
1592    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1593        match &self.repr {
1594            Repr::Inline(value) => {
1595                write!(f, "{value:?}")?;
1596            }
1597            _ => {
1598                let mut s = String::new();
1599                let result = Formatter::format_with(&mut s, |f| self.debug_fmt(f));
1600
1601                if let Err(e) = result {
1602                    match &self.repr {
1603                        Repr::Inline(value) => {
1604                            write!(f, "<{value:?}: {e}>")?;
1605                        }
1606                        Repr::Dynamic(value) => {
1607                            let ty = value.type_info();
1608                            write!(f, "<{ty} object at {value:p}: {e}>")?;
1609                        }
1610                        Repr::Any(value) => {
1611                            let ty = value.type_info();
1612                            write!(f, "<{ty} object at {value:p}: {e}>")?;
1613                        }
1614                    }
1615
1616                    return Ok(());
1617                }
1618
1619                f.write_str(s.as_str())?;
1620            }
1621        }
1622
1623        Ok(())
1624    }
1625}
1626
1627impl From<Repr> for Value {
1628    #[inline]
1629    fn from(repr: Repr) -> Self {
1630        Self { repr }
1631    }
1632}
1633
1634impl From<()> for Value {
1635    #[inline]
1636    fn from((): ()) -> Self {
1637        Value::from(Inline::Unit)
1638    }
1639}
1640
1641impl From<Inline> for Value {
1642    #[inline]
1643    fn from(value: Inline) -> Self {
1644        Self {
1645            repr: Repr::Inline(value),
1646        }
1647    }
1648}
1649
1650/// Conversion from a [`AnyObj`] into a [`Value`].
1651///
1652/// # Examples
1653///
1654/// ```
1655/// use rune::Value;
1656/// use rune::runtime::AnyObj;
1657/// use rune::alloc::String;
1658///
1659/// let string = String::try_from("Hello World")?;
1660/// let string = AnyObj::new(string)?;
1661/// let string = Value::from(string);
1662///
1663/// let string = string.into_shared::<String>()?;
1664/// assert_eq!(string.borrow_ref()?.as_str(), "Hello World");
1665/// # Ok::<_, rune::support::Error>(())
1666/// ```
1667impl From<AnyObj> for Value {
1668    #[inline]
1669    fn from(value: AnyObj) -> Self {
1670        Self {
1671            repr: Repr::Any(value),
1672        }
1673    }
1674}
1675
1676/// Conversion from a [`Shared<T>`] into a [`Value`].
1677///
1678/// # Examples
1679///
1680/// ```
1681/// use rune::Value;
1682/// use rune::runtime::Shared;
1683/// use rune::alloc::String;
1684///
1685/// let string = String::try_from("Hello World")?;
1686/// let string = Shared::new(string)?;
1687/// let string = Value::from(string);
1688///
1689/// let string = string.into_any_obj()?;
1690/// assert_eq!(string.borrow_ref::<String>()?.as_str(), "Hello World");
1691/// # Ok::<_, rune::support::Error>(())
1692/// ```
1693impl<T> From<Shared<T>> for Value
1694where
1695    T: Any,
1696{
1697    #[inline]
1698    fn from(value: Shared<T>) -> Self {
1699        Self {
1700            repr: Repr::Any(value.into_any_obj()),
1701        }
1702    }
1703}
1704
1705impl From<AnySequence<Arc<Rtti>, Value>> for Value {
1706    #[inline]
1707    fn from(value: AnySequence<Arc<Rtti>, Value>) -> Self {
1708        Self {
1709            repr: Repr::Dynamic(value),
1710        }
1711    }
1712}
1713
1714impl TryFrom<&str> for Value {
1715    type Error = alloc::Error;
1716
1717    #[inline]
1718    fn try_from(value: &str) -> Result<Self, Self::Error> {
1719        Value::new(String::try_from(value)?)
1720    }
1721}
1722
1723inline_from! {
1724    Bool => bool,
1725    Char => char,
1726    Signed => i64,
1727    Unsigned => u64,
1728    Float => f64,
1729    Type => Type,
1730    Ordering => Ordering,
1731    Hash => Hash,
1732}
1733
1734any_from! {
1735    crate::alloc::String,
1736    super::Bytes,
1737    super::Format,
1738    super::ControlFlow,
1739    super::GeneratorState,
1740    super::Vec,
1741    super::OwnedTuple,
1742    super::Generator,
1743    super::Stream,
1744    super::Function,
1745    super::Future,
1746    super::Object,
1747    Option<Value>,
1748    Result<Value, Value>,
1749}
1750
1751signed_value_from!(i8, i16, i32);
1752signed_value_try_from!(i128, isize);
1753unsigned_value_from!(u8, u16, u32);
1754unsigned_value_try_from!(u128, usize);
1755signed_value_trait!(i8, i16, i32, i128, isize);
1756unsigned_value_trait!(u8, u16, u32, u128, usize);
1757float_value_trait!(f32);
1758
1759impl MaybeTypeOf for Value {
1760    #[inline]
1761    fn maybe_type_of() -> alloc::Result<meta::DocType> {
1762        Ok(meta::DocType::empty())
1763    }
1764}
1765
1766/// A graph of values is taken apart in place rather than by recursing into it,
1767/// since how deeply one nests is decided at runtime and dropping it by
1768/// recursing would exhaust the call stack.
1769///
1770/// A destructor has nobody to report a failure to and must not spend the memory
1771/// limit which is in effect, so it takes the graph apart without allocating.
1772/// The machine hands the values over to a worklist instead, which is faster and
1773/// reports running into the limit rather than working around it.
1774///
1775/// See the `dismantle` module for how the graph is walked.
1776impl Drop for Value {
1777    #[inline]
1778    fn drop(&mut self) {
1779        // Values which cannot contain other values are the common case and are
1780        // dropped in place.
1781        if matches!(self.repr, Repr::Inline(..)) {
1782            return;
1783        }
1784
1785        let repr = replace(&mut self.repr, Repr::Inline(Inline::Empty));
1786
1787        // Few enough values wait without allocating, so an ordinary value costs
1788        // a destructor nothing beyond the walk itself.
1789        self::dismantle::Worklist::new().dismantle_repr(repr);
1790    }
1791}
1792
1793impl Clone for Value {
1794    #[inline]
1795    fn clone(&self) -> Self {
1796        let repr = match &self.repr {
1797            Repr::Inline(inline) => Repr::Inline(*inline),
1798            Repr::Dynamic(mutable) => Repr::Dynamic(mutable.clone()),
1799            Repr::Any(any) => Repr::Any(any.clone()),
1800        };
1801
1802        Self { repr }
1803    }
1804
1805    #[inline]
1806    fn clone_from(&mut self, source: &Self) {
1807        match (&mut self.repr, &source.repr) {
1808            (Repr::Inline(lhs), Repr::Inline(rhs)) => {
1809                *lhs = *rhs;
1810            }
1811            (Repr::Dynamic(lhs), Repr::Dynamic(rhs)) => {
1812                lhs.clone_from(rhs);
1813            }
1814            (Repr::Any(lhs), Repr::Any(rhs)) => {
1815                lhs.clone_from(rhs);
1816            }
1817            (lhs, rhs) => {
1818                *lhs = rhs.clone();
1819            }
1820        }
1821    }
1822}
1823
1824impl TryClone for Value {
1825    fn try_clone(&self) -> alloc::Result<Self> {
1826        // NB: value cloning is a shallow clone of the underlying data.
1827        Ok(self.clone())
1828    }
1829}
1830
1831/// Wrapper for a value kind.
1832#[doc(hidden)]
1833pub struct NotTypedInline(Inline);
1834
1835/// Wrapper for an any ref value kind.
1836#[doc(hidden)]
1837pub struct NotTypedAnyObj<'a>(&'a AnyObj);
1838
1839/// The coersion of a value into a typed value.
1840#[non_exhaustive]
1841#[doc(hidden)]
1842pub enum TypeValue<'a> {
1843    /// The unit value.
1844    Unit,
1845    /// A tuple.
1846    Tuple(BorrowRef<'a, OwnedTuple>),
1847    /// An object.
1848    Object(BorrowRef<'a, Object>),
1849    /// An struct with a well-defined type.
1850    EmptyStruct(EmptyStruct<'a>),
1851    /// A tuple with a well-defined type.
1852    TupleStruct(TupleStruct<'a>),
1853    /// An struct with a well-defined type.
1854    Struct(Struct<'a>),
1855    /// Not a typed immutable value.
1856    #[doc(hidden)]
1857    NotTypedInline(NotTypedInline),
1858    /// Not a typed value.
1859    #[doc(hidden)]
1860    NotTypedAnyObj(NotTypedAnyObj<'a>),
1861}
1862
1863impl TypeValue<'_> {
1864    /// Get the type info of the current value.
1865    #[doc(hidden)]
1866    pub fn type_info(&self) -> TypeInfo {
1867        match self {
1868            TypeValue::Unit => TypeInfo::any::<OwnedTuple>(),
1869            TypeValue::Tuple(..) => TypeInfo::any::<OwnedTuple>(),
1870            TypeValue::Object(..) => TypeInfo::any::<Object>(),
1871            TypeValue::EmptyStruct(empty) => empty.type_info(),
1872            TypeValue::TupleStruct(tuple) => tuple.type_info(),
1873            TypeValue::Struct(object) => object.type_info(),
1874            TypeValue::NotTypedInline(value) => value.0.type_info(),
1875            TypeValue::NotTypedAnyObj(value) => value.0.type_info(),
1876        }
1877    }
1878}
1879
1880/// Ensures that `Value` and `Repr` is niche-filled when used in common
1881/// combinations.
1882#[test]
1883fn size_of_value() {
1884    use core::mem::size_of;
1885
1886    assert_eq!(size_of::<Repr>(), size_of::<Inline>());
1887    assert_eq!(size_of::<Repr>(), size_of::<Value>());
1888    assert_eq!(size_of::<Option<Value>>(), size_of::<Value>());
1889    assert_eq!(size_of::<Option<Repr>>(), size_of::<Repr>());
1890}