rune/runtime/
value.rs

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