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