1#[macro_use]
2mod macros;
3
4#[cfg(test)]
5mod tests;
6
7mod inline;
8pub use self::inline::Inline;
9
10#[cfg(feature = "serde")]
11mod serde;
12
13mod rtti;
14pub(crate) use self::rtti::RttiKind;
15pub use self::rtti::{Accessor, Rtti};
16
17mod data;
18pub use self::data::{EmptyStruct, Struct, TupleStruct};
19
20mod any_sequence;
21pub use self::any_sequence::AnySequence;
22pub(crate) use self::any_sequence::AnySequenceTakeError;
23
24mod dismantle;
25pub(crate) use self::dismantle::Worklist;
26pub use self::dismantle::{Dismantle, Handover};
27
28use core::any;
29use core::cmp::Ordering;
30use core::fmt;
31use core::mem::replace;
32use core::ptr::NonNull;
33
34use crate::alloc::fmt::TryWrite;
35use crate::alloc::prelude::*;
36use crate::alloc::{self, String};
37use crate::compile::meta;
38use crate::runtime::{budget, env};
39use crate::sync::Arc;
40use crate::{Any, Hash, TypeHash};
41
42use super::{
43 AccessError, AnyObj, AnyObjDrop, BorrowMut, BorrowRef, CallResultOnly, ConstNodeKind,
44 ConstValueBuf, DynGuardedArgs, EnvProtocolCaller, Formatter, FromValue, Future, Hasher,
45 Iterator, MaybeTypeOf, Mut, Object, OwnedTuple, Protocol, ProtocolCaller, RawAnyObjGuard, Ref,
46 RuntimeError, Shared, Snapshot, Tuple, Type, TypeInfo, Vec, VmError, VmErrorKind,
47 VmIntegerRepr,
48};
49
50pub struct ValueRefGuard {
54 #[allow(unused)]
55 guard: AnyObjDrop,
56}
57
58pub struct ValueMutGuard {
62 #[allow(unused)]
63 guard: AnyObjDrop,
64}
65
66pub struct RawValueGuard {
68 #[allow(unused)]
69 guard: RawAnyObjGuard,
70}
71
72#[derive(Clone)]
73pub(crate) enum Repr {
74 Inline(Inline),
75 Dynamic(AnySequence<Arc<Rtti>, Value>),
76 Any(AnyObj),
77}
78
79impl Repr {
80 #[inline]
81 pub(crate) fn type_info(&self) -> TypeInfo {
82 match self {
83 Repr::Inline(value) => value.type_info(),
84 Repr::Dynamic(value) => value.type_info(),
85 Repr::Any(value) => value.type_info(),
86 }
87 }
88}
89
90pub struct Value {
92 repr: Repr,
93}
94
95impl Value {
96 #[inline]
98 pub fn take(value: &mut Self) -> Self {
99 replace(value, Self::empty())
100 }
101
102 pub fn new<T>(data: T) -> alloc::Result<Self>
105 where
106 T: Any,
107 {
108 Ok(Self {
109 repr: Repr::Any(AnyObj::new(data)?),
110 })
111 }
112
113 pub unsafe fn from_ref<T>(data: &T) -> alloc::Result<(Self, ValueRefGuard)>
158 where
159 T: Any,
160 {
161 let value = AnyObj::from_ref(data)?;
162 let (value, guard) = AnyObj::into_drop_guard(value);
163
164 let guard = ValueRefGuard { guard };
165
166 Ok((
167 Self {
168 repr: Repr::Any(value),
169 },
170 guard,
171 ))
172 }
173
174 pub unsafe fn from_mut<T>(data: &mut T) -> alloc::Result<(Self, ValueMutGuard)>
226 where
227 T: Any,
228 {
229 let value = AnyObj::from_mut(data)?;
230 let (value, guard) = AnyObj::into_drop_guard(value);
231
232 let guard = ValueMutGuard { guard };
233
234 Ok((
235 Self {
236 repr: Repr::Any(value),
237 },
238 guard,
239 ))
240 }
241
242 pub(crate) fn snapshot(&self) -> Option<Snapshot> {
244 match &self.repr {
245 Repr::Dynamic(value) => Some(value.snapshot()),
246 Repr::Any(value) => Some(value.snapshot()),
247 _ => None,
248 }
249 }
250
251 pub fn is_writable(&self) -> bool {
290 match self.repr {
291 Repr::Inline(Inline::Empty) => false,
292 Repr::Inline(..) => true,
293 Repr::Dynamic(ref value) => value.is_writable(),
294 Repr::Any(ref any) => any.is_writable(),
295 }
296 }
297
298 pub fn is_readable(&self) -> bool {
337 match &self.repr {
338 Repr::Inline(Inline::Empty) => false,
339 Repr::Inline(..) => true,
340 Repr::Dynamic(ref value) => value.is_readable(),
341 Repr::Any(ref any) => any.is_readable(),
342 }
343 }
344
345 #[inline]
352 pub(crate) fn is_empty(&self) -> bool {
353 matches!(self.repr, Repr::Inline(Inline::Empty))
354 }
355
356 pub(crate) const fn unit() -> Self {
358 Self {
359 repr: Repr::Inline(Inline::Unit),
360 }
361 }
362
363 pub const fn empty() -> Self {
365 Self {
366 repr: Repr::Inline(Inline::Empty),
367 }
368 }
369
370 pub fn display_fmt(&self, f: &mut Formatter) -> Result<(), VmError> {
383 self.display_fmt_with(f, &mut EnvProtocolCaller)
384 }
385
386 #[cfg_attr(feature = "bench", inline(never))]
388 pub(crate) fn display_fmt_with(
389 &self,
390 f: &mut Formatter,
391 caller: &mut dyn ProtocolCaller,
392 ) -> Result<(), VmError> {
393 let _guard = env::enter_value()?;
394
395 'fallback: {
396 match self.as_ref() {
397 Repr::Inline(value) => match value {
398 Inline::Char(c) => {
399 f.try_write_char(*c)?;
400 }
401 Inline::Unsigned(byte) => {
402 let mut buffer = itoa::Buffer::new();
403 f.try_write_str(buffer.format(*byte))?;
404 }
405 Inline::Signed(integer) => {
406 let mut buffer = itoa::Buffer::new();
407 f.try_write_str(buffer.format(*integer))?;
408 }
409 Inline::Float(float) => {
410 let mut buffer = ryu::Buffer::new();
411 f.try_write_str(buffer.format(*float))?;
412 }
413 Inline::Bool(bool) => {
414 write!(f, "{bool}")?;
415 }
416 _ => {
417 break 'fallback;
418 }
419 },
420 _ => {
421 break 'fallback;
422 }
423 }
424
425 return Ok(());
426 };
427
428 let mut args = DynGuardedArgs::new((f,));
429
430 let result = caller.call_protocol_fn(&Protocol::DISPLAY_FMT, self.clone(), &mut args)?;
431
432 <()>::from_value(result)?;
433 Ok(())
434 }
435
436 pub fn clone_(&self) -> Result<Self, VmError> {
449 self.clone_with(&mut EnvProtocolCaller)
450 }
451
452 pub(crate) fn clone_with(&self, caller: &mut dyn ProtocolCaller) -> Result<Value, VmError> {
453 match self.as_ref() {
454 Repr::Inline(value) => {
455 return Ok(Self {
456 repr: Repr::Inline(*value),
457 });
458 }
459 Repr::Dynamic(value) => {
460 return Ok(Self {
462 repr: Repr::Dynamic(value.clone()),
463 });
464 }
465 Repr::Any(..) => {}
466 }
467
468 caller.call_protocol_fn(&Protocol::CLONE, self.clone(), &mut ())
469 }
470
471 pub fn debug_fmt(&self, f: &mut Formatter) -> Result<(), VmError> {
484 self.debug_fmt_with(f, &mut EnvProtocolCaller)
485 }
486
487 pub(crate) fn debug_fmt_with(
489 &self,
490 f: &mut Formatter,
491 caller: &mut dyn ProtocolCaller,
492 ) -> Result<(), VmError> {
493 let _guard = env::enter_value()?;
494
495 match &self.repr {
496 Repr::Inline(value) => {
497 write!(f, "{value:?}")?;
498 }
499 Repr::Dynamic(ref value) => {
500 value.debug_fmt_with(f, caller)?;
501 }
502 Repr::Any(..) => {
503 let mut args = DynGuardedArgs::new((&mut *f,));
505
506 match caller.try_call_protocol_fn(&Protocol::DEBUG_FMT, self.clone(), &mut args)? {
507 CallResultOnly::Ok(value) => {
508 <()>::from_value(value)?;
509 }
510 CallResultOnly::Unsupported(value) => match &value.repr {
511 Repr::Inline(value) => {
512 write!(f, "{value:?}")?;
513 }
514 Repr::Dynamic(value) => {
515 let ty = value.type_info();
516 write!(f, "<{ty} object at {value:p}>")?;
517 }
518 Repr::Any(value) => {
519 let ty = value.type_info();
520 write!(f, "<{ty} object at {value:p}>")?;
521 }
522 },
523 }
524 }
525 }
526
527 Ok(())
528 }
529
530 pub fn into_iter(self) -> Result<Iterator, VmError> {
542 self.into_iter_with(&mut EnvProtocolCaller)
543 }
544
545 pub(crate) fn into_iter_with(
546 self,
547 caller: &mut dyn ProtocolCaller,
548 ) -> Result<Iterator, VmError> {
549 let value = caller.call_protocol_fn(&Protocol::INTO_ITER, self, &mut ())?;
550 Ok(Iterator::new(value))
551 }
552
553 pub fn into_type_name(self) -> Result<String, VmError> {
568 let hash = Hash::associated_function(self.type_hash(), &Protocol::INTO_TYPE_NAME);
569
570 crate::runtime::env::shared(|context, unit, _| {
571 if let Some(name) = context.constant(&hash) {
572 match name.kind() {
573 ConstNodeKind::String(s) => return Ok(String::try_from(s.as_ref())?),
574 _ => {
575 return Err(VmError::new(VmErrorKind::expected::<String>(
576 name.type_info(),
577 )))
578 }
579 }
580 }
581
582 if let Some(name) = unit.constant(&hash) {
583 match name.kind() {
584 ConstNodeKind::String(s) => return Ok(String::try_from(s.as_ref())?),
585 _ => {
586 return Err(VmError::new(VmErrorKind::expected::<String>(
587 name.type_info(),
588 )))
589 }
590 }
591 }
592
593 Ok(self.type_info().try_to_string()?)
594 })
595 }
596
597 pub fn vec(vec: alloc::Vec<Value>) -> alloc::Result<Self> {
599 let data = Vec::from(vec);
600 Value::try_from(data)
601 }
602
603 pub fn tuple(vec: alloc::Vec<Value>) -> alloc::Result<Self> {
605 Value::try_from(OwnedTuple::try_from(vec)?)
606 }
607
608 pub fn empty_struct(rtti: Arc<Rtti>) -> alloc::Result<Self> {
610 Ok(Value::from(AnySequence::new(rtti, [])?))
611 }
612
613 pub fn tuple_struct(
615 rtti: Arc<Rtti>,
616 data: impl IntoIterator<IntoIter: ExactSizeIterator, Item = Value>,
617 ) -> alloc::Result<Self> {
618 Ok(Value::from(AnySequence::new(rtti, data)?))
619 }
620
621 pub(crate) fn drop(self) -> Result<(), VmError> {
626 match self.take_repr() {
627 Repr::Dynamic(value) => {
628 value.drop()?;
629 }
630 Repr::Any(value) => {
631 value.drop()?;
632 }
633 _ => {}
634 }
635
636 Ok(())
637 }
638
639 pub(crate) fn move_(self) -> Result<Self, VmError> {
641 match self.take_repr() {
642 Repr::Dynamic(value) => Ok(Value {
643 repr: Repr::Dynamic(value.take()?),
644 }),
645 Repr::Any(value) => Ok(Value {
646 repr: Repr::Any(value.take()?),
647 }),
648 repr => Ok(Value { repr }),
649 }
650 }
651
652 #[inline]
654 pub fn as_usize(&self) -> Result<usize, RuntimeError> {
655 self.as_integer()
656 }
657
658 #[deprecated(
660 note = "For consistency with other methods, this has been renamed Value::borrow_string_ref"
661 )]
662 #[inline]
663 pub fn as_string(&self) -> Result<BorrowRef<'_, str>, RuntimeError> {
664 self.borrow_string_ref()
665 }
666
667 pub fn borrow_string_ref(&self) -> Result<BorrowRef<'_, str>, RuntimeError> {
669 let string = self.borrow_ref::<String>()?;
670 Ok(BorrowRef::map(string, String::as_str))
671 }
672
673 #[inline]
675 pub fn into_string(self) -> Result<String, RuntimeError> {
676 match self.take_repr() {
677 Repr::Any(value) => Ok(value.downcast()?),
678 actual => Err(RuntimeError::expected::<String>(actual.type_info())),
679 }
680 }
681
682 #[doc(hidden)]
684 #[inline]
685 pub fn as_type_value(&self) -> Result<TypeValue<'_>, RuntimeError> {
686 match self.as_ref() {
687 Repr::Inline(value) => match value {
688 Inline::Unit => Ok(TypeValue::Unit),
689 value => Ok(TypeValue::NotTypedInline(NotTypedInline(*value))),
690 },
691 Repr::Dynamic(value) => match value.rtti().kind {
692 RttiKind::Empty => Ok(TypeValue::EmptyStruct(EmptyStruct { rtti: value.rtti() })),
693 RttiKind::Tuple => Ok(TypeValue::TupleStruct(TupleStruct {
694 rtti: value.rtti(),
695 data: value.borrow_ref()?,
696 })),
697 RttiKind::Struct => Ok(TypeValue::Struct(Struct {
698 rtti: value.rtti(),
699 data: value.borrow_ref()?,
700 })),
701 },
702 Repr::Any(value) => match value.type_hash() {
703 OwnedTuple::HASH => Ok(TypeValue::Tuple(value.borrow_ref()?)),
704 Object::HASH => Ok(TypeValue::Object(value.borrow_ref()?)),
705 _ => Ok(TypeValue::NotTypedAnyObj(NotTypedAnyObj(value))),
706 },
707 }
708 }
709
710 #[inline]
712 pub fn into_unit(&self) -> Result<(), RuntimeError> {
713 match self.as_ref() {
714 Repr::Inline(Inline::Unit) => Ok(()),
715 value => Err(RuntimeError::expected::<()>(value.type_info())),
716 }
717 }
718
719 inline_into! {
720 Ordering(Ordering),
722 as_ordering,
723 as_ordering_mut,
724 }
725
726 inline_into! {
727 Hash(Hash),
729 as_hash,
730 as_hash_mut,
731 }
732
733 inline_into! {
734 Bool(bool),
736 as_bool,
737 as_bool_mut,
738 }
739
740 inline_into! {
741 Char(char),
743 as_char,
744 as_char_mut,
745 }
746
747 inline_into! {
748 Signed(i64),
750 as_signed,
751 as_signed_mut,
752 }
753
754 inline_into! {
755 Unsigned(u64),
757 as_unsigned,
758 as_unsigned_mut,
759 }
760
761 inline_into! {
762 Float(f64),
764 as_float,
765 as_float_mut,
766 }
767
768 inline_into! {
769 Type(Type),
771 as_type,
772 as_type_mut,
773 }
774
775 #[inline]
780 pub fn borrow_tuple_ref(&self) -> Result<BorrowRef<'_, Tuple>, RuntimeError> {
781 match self.as_ref() {
782 Repr::Inline(Inline::Unit) => Ok(BorrowRef::from_static(Tuple::new(&[]))),
783 Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
784 Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
785 Repr::Any(value) => {
786 let value = value.borrow_ref::<OwnedTuple>()?;
787 let value = BorrowRef::map(value, OwnedTuple::as_ref);
788 Ok(value)
789 }
790 }
791 }
792
793 #[inline]
798 pub fn borrow_tuple_mut(&self) -> Result<BorrowMut<'_, Tuple>, RuntimeError> {
799 match self.as_ref() {
800 Repr::Inline(Inline::Unit) => Ok(BorrowMut::from_ref(Tuple::new_mut(&mut []))),
801 Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
802 Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
803 Repr::Any(value) => {
804 let value = value.borrow_mut::<OwnedTuple>()?;
805 let value = BorrowMut::map(value, OwnedTuple::as_mut);
806 Ok(value)
807 }
808 }
809 }
810
811 #[inline]
816 pub fn into_tuple(&self) -> Result<Box<Tuple>, RuntimeError> {
817 match self.as_ref() {
818 Repr::Inline(Inline::Unit) => Ok(Tuple::from_boxed(Box::default())),
819 Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
820 Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
821 Repr::Any(value) => Ok(value.clone().downcast::<OwnedTuple>()?.into_boxed_tuple()),
822 }
823 }
824
825 #[inline]
830 pub fn into_tuple_ref(&self) -> Result<Ref<Tuple>, RuntimeError> {
831 match self.as_ref() {
832 Repr::Inline(Inline::Unit) => Ok(Ref::from_static(Tuple::new(&[]))),
833 Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
834 Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
835 Repr::Any(value) => {
836 let value = value.clone().into_ref::<OwnedTuple>()?;
837 let value = Ref::map(value, OwnedTuple::as_ref);
838 Ok(value)
839 }
840 }
841 }
842
843 #[inline]
848 pub fn into_tuple_mut(&self) -> Result<Mut<Tuple>, RuntimeError> {
849 match self.as_ref() {
850 Repr::Inline(Inline::Unit) => Ok(Mut::from_static(Tuple::new_mut(&mut []))),
851 Repr::Inline(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
852 Repr::Dynamic(value) => Err(RuntimeError::expected::<Tuple>(value.type_info())),
853 Repr::Any(value) => {
854 let value = value.clone().into_mut::<OwnedTuple>()?;
855 let value = Mut::map(value, OwnedTuple::as_mut);
856 Ok(value)
857 }
858 }
859 }
860
861 #[inline]
863 pub fn into_any_obj(self) -> Result<AnyObj, RuntimeError> {
864 match self.take_repr() {
865 Repr::Inline(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
866 Repr::Dynamic(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
867 Repr::Any(value) => Ok(value),
868 }
869 }
870
871 #[inline]
876 pub fn into_shared<T>(self) -> Result<Shared<T>, RuntimeError>
877 where
878 T: Any,
879 {
880 match self.take_repr() {
881 Repr::Inline(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
882 Repr::Dynamic(value) => Err(RuntimeError::expected_any_obj(value.type_info())),
883 Repr::Any(value) => Ok(value.into_shared()?),
884 }
885 }
886
887 #[inline]
903 pub fn into_future(self) -> Result<Future, RuntimeError> {
904 let target = match self.take_repr() {
905 Repr::Any(value) => match value.type_hash() {
906 Future::HASH => {
907 return Ok(value.downcast::<Future>()?);
908 }
909 _ => Value::from(value),
910 },
911 repr => Value::from(repr),
912 };
913
914 let value = EnvProtocolCaller.call_protocol_fn(&Protocol::INTO_FUTURE, target, &mut ())?;
915
916 Future::from_value(value)
917 }
918
919 #[inline]
926 pub fn into_any_ref_ptr<T>(self) -> Result<(NonNull<T>, RawValueGuard), RuntimeError>
927 where
928 T: Any,
929 {
930 match self.take_repr() {
931 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
932 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
933 Repr::Any(value) => {
934 let (ptr, guard) = value.borrow_ref_ptr::<T>()?;
935 let guard = RawValueGuard { guard };
936 Ok((ptr, guard))
937 }
938 }
939 }
940
941 #[inline]
948 #[doc(hidden)]
949 pub fn into_any_mut_ptr<T>(self) -> Result<(NonNull<T>, RawValueGuard), RuntimeError>
950 where
951 T: Any,
952 {
953 match self.take_repr() {
954 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
955 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
956 Repr::Any(value) => {
957 let (ptr, guard) = value.borrow_mut_ptr::<T>()?;
958 let guard = RawValueGuard { guard };
959 Ok((ptr, guard))
960 }
961 }
962 }
963
964 #[inline]
994 pub fn downcast<T>(self) -> Result<T, RuntimeError>
995 where
996 T: Any,
997 {
998 match self.take_repr() {
999 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1000 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1001 Repr::Any(value) => Ok(value.downcast::<T>()?),
1002 }
1003 }
1004
1005 #[inline]
1027 pub fn borrow_ref<T>(&self) -> Result<BorrowRef<'_, T>, RuntimeError>
1028 where
1029 T: Any,
1030 {
1031 match &self.repr {
1032 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1033 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1034 Repr::Any(value) => Ok(value.borrow_ref()?),
1035 }
1036 }
1037
1038 #[inline]
1059 pub fn into_ref<T>(self) -> Result<Ref<T>, RuntimeError>
1060 where
1061 T: Any,
1062 {
1063 match self.take_repr() {
1064 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1065 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1066 Repr::Any(value) => Ok(value.into_ref()?),
1067 }
1068 }
1069
1070 #[inline]
1072 pub fn borrow_mut<T>(&self) -> Result<BorrowMut<'_, T>, RuntimeError>
1073 where
1074 T: Any,
1075 {
1076 match &self.repr {
1077 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1078 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1079 Repr::Any(value) => Ok(value.borrow_mut()?),
1080 }
1081 }
1082
1083 #[inline]
1112 pub fn into_mut<T>(self) -> Result<Mut<T>, RuntimeError>
1113 where
1114 T: Any,
1115 {
1116 match self.take_repr() {
1117 Repr::Inline(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1118 Repr::Dynamic(value) => Err(RuntimeError::expected_any::<T>(value.type_info())),
1119 Repr::Any(value) => Ok(value.into_mut()?),
1120 }
1121 }
1122
1123 #[inline(always)]
1128 pub fn type_hash(&self) -> Hash {
1129 match &self.repr {
1130 Repr::Inline(value) => value.type_hash(),
1131 Repr::Dynamic(value) => value.type_hash(),
1132 Repr::Any(value) => value.type_hash(),
1133 }
1134 }
1135
1136 #[inline(always)]
1138 pub fn type_info(&self) -> TypeInfo {
1139 match &self.repr {
1140 Repr::Inline(value) => value.type_info(),
1141 Repr::Dynamic(value) => value.type_info(),
1142 Repr::Any(value) => value.type_info(),
1143 }
1144 }
1145
1146 pub fn partial_eq(a: &Value, b: &Value) -> Result<bool, VmError> {
1157 Self::partial_eq_with(a, b, &mut EnvProtocolCaller)
1158 }
1159
1160 #[cfg_attr(feature = "bench", inline(never))]
1164 pub(crate) fn partial_eq_with(
1165 &self,
1166 b: &Value,
1167 caller: &mut dyn ProtocolCaller,
1168 ) -> Result<bool, VmError> {
1169 let _guard = env::enter_value()?;
1170
1171 self.bin_op_with(
1172 b,
1173 caller,
1174 &Protocol::PARTIAL_EQ,
1175 Inline::partial_eq,
1176 |lhs, rhs, caller| {
1177 if lhs.0.variant_hash != rhs.0.variant_hash {
1178 return Ok(false);
1179 }
1180
1181 Vec::eq_with(lhs.1, rhs.1, Value::partial_eq_with, caller)
1182 },
1183 )
1184 }
1185
1186 pub fn eq(&self, b: &Value) -> Result<bool, VmError> {
1197 self.eq_with(b, &mut EnvProtocolCaller)
1198 }
1199
1200 #[cfg_attr(feature = "bench", inline(never))]
1204 pub(crate) fn eq_with(
1205 &self,
1206 b: &Value,
1207 caller: &mut dyn ProtocolCaller,
1208 ) -> Result<bool, VmError> {
1209 let _guard = env::enter_value()?;
1210
1211 self.bin_op_with(b, caller, &Protocol::EQ, Inline::eq, |lhs, rhs, caller| {
1212 if lhs.0.variant_hash != rhs.0.variant_hash {
1213 return Ok(false);
1214 }
1215
1216 Vec::eq_with(lhs.1, rhs.1, Value::eq_with, caller)
1217 })
1218 }
1219
1220 pub fn partial_cmp(a: &Value, b: &Value) -> Result<Option<Ordering>, VmError> {
1231 Value::partial_cmp_with(a, b, &mut EnvProtocolCaller)
1232 }
1233
1234 #[cfg_attr(feature = "bench", inline(never))]
1238 pub(crate) fn partial_cmp_with(
1239 &self,
1240 b: &Value,
1241 caller: &mut dyn ProtocolCaller,
1242 ) -> Result<Option<Ordering>, VmError> {
1243 let _guard = env::enter_value()?;
1244
1245 self.bin_op_with(
1246 b,
1247 caller,
1248 &Protocol::PARTIAL_CMP,
1249 Inline::partial_cmp,
1250 |lhs, rhs, caller| {
1251 let ord = lhs.0.variant_hash.cmp(&rhs.0.variant_hash);
1252
1253 if ord != Ordering::Equal {
1254 return Ok(Some(ord));
1255 }
1256
1257 Vec::partial_cmp_with(lhs.1, rhs.1, caller)
1258 },
1259 )
1260 }
1261
1262 pub fn cmp(a: &Value, b: &Value) -> Result<Ordering, VmError> {
1273 Value::cmp_with(a, b, &mut EnvProtocolCaller)
1274 }
1275
1276 #[cfg_attr(feature = "bench", inline(never))]
1280 pub(crate) fn cmp_with(
1281 &self,
1282 b: &Value,
1283 caller: &mut dyn ProtocolCaller,
1284 ) -> Result<Ordering, VmError> {
1285 let _guard = env::enter_value()?;
1286
1287 self.bin_op_with(
1288 b,
1289 caller,
1290 &Protocol::CMP,
1291 Inline::cmp,
1292 |lhs, rhs, caller| {
1293 let ord = lhs.0.variant_hash.cmp(&rhs.0.variant_hash);
1294
1295 if ord != Ordering::Equal {
1296 return Ok(ord);
1297 }
1298
1299 Vec::cmp_with(lhs.1, rhs.1, caller)
1300 },
1301 )
1302 }
1303
1304 pub fn hash(&self, hasher: &mut Hasher) -> Result<(), VmError> {
1306 self.hash_with(hasher, &mut EnvProtocolCaller)
1307 }
1308
1309 #[cfg_attr(feature = "bench", inline(never))]
1311 pub(crate) fn hash_with(
1312 &self,
1313 hasher: &mut Hasher,
1314 caller: &mut dyn ProtocolCaller,
1315 ) -> Result<(), VmError> {
1316 let _guard = env::enter_value()?;
1317
1318 match self.as_ref() {
1319 Repr::Inline(value) => {
1320 value.hash(hasher)?;
1321 return Ok(());
1322 }
1323 Repr::Dynamic(value) => {
1324 let rtti = value.rtti();
1329
1330 core::hash::Hash::hash(&rtti.hash, hasher);
1331 core::hash::Hash::hash(&rtti.variant_hash, hasher);
1332
1333 let values = value.borrow_ref()?;
1334
1335 for value in values.iter() {
1336 value.hash_with(hasher, caller)?;
1337 }
1338
1339 return Ok(());
1340 }
1341 Repr::Any(value) => match value.type_hash() {
1342 Vec::HASH => {
1343 let vec = value.borrow_ref::<Vec>()?;
1344 return Vec::hash_with(&vec, hasher, caller);
1345 }
1346 OwnedTuple::HASH => {
1347 let tuple = value.borrow_ref::<OwnedTuple>()?;
1348 return Tuple::hash_with(&tuple, hasher, caller);
1349 }
1350 _ => {}
1351 },
1352 }
1353
1354 let mut args = DynGuardedArgs::new((hasher,));
1355
1356 if let CallResultOnly::Ok(value) =
1357 caller.try_call_protocol_fn(&Protocol::HASH, self.clone(), &mut args)?
1358 {
1359 <()>::from_value(value)?;
1360 return Ok(());
1361 }
1362
1363 Err(VmError::new(VmErrorKind::UnsupportedUnaryOperation {
1364 op: Protocol::HASH.name,
1365 operand: self.type_info(),
1366 }))
1367 }
1368
1369 fn bin_op_with<T>(
1370 &self,
1371 b: &Value,
1372 caller: &mut dyn ProtocolCaller,
1373 protocol: &'static Protocol,
1374 inline: fn(&Inline, &Inline) -> Result<T, RuntimeError>,
1375 dynamic: fn(
1376 (&Arc<Rtti>, &[Value]),
1377 (&Arc<Rtti>, &[Value]),
1378 &mut dyn ProtocolCaller,
1379 ) -> Result<T, VmError>,
1380 ) -> Result<T, VmError>
1381 where
1382 T: FromValue,
1383 {
1384 match (self.as_ref(), b.as_ref()) {
1385 (Repr::Inline(lhs), Repr::Inline(rhs)) => return Ok(inline(lhs, rhs)?),
1386 (Repr::Inline(lhs), rhs) => {
1387 return Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1388 op: protocol.name,
1389 lhs: lhs.type_info(),
1390 rhs: rhs.type_info(),
1391 }));
1392 }
1393 (Repr::Dynamic(lhs), Repr::Dynamic(rhs)) => {
1394 let lhs_rtti = lhs.rtti();
1395 let rhs_rtti = rhs.rtti();
1396
1397 let lhs = lhs.borrow_ref()?;
1398 let rhs = rhs.borrow_ref()?;
1399
1400 if lhs_rtti.hash == rhs_rtti.hash {
1401 return dynamic((lhs_rtti, &lhs), (rhs_rtti, &rhs), caller);
1402 }
1403
1404 return Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1405 op: protocol.name,
1406 lhs: Rtti::type_info(lhs_rtti.clone()),
1407 rhs: Rtti::type_info(rhs_rtti.clone()),
1408 }));
1409 }
1410 _ => {}
1411 }
1412
1413 if let CallResultOnly::Ok(value) =
1414 caller.try_call_protocol_fn(protocol, self.clone(), &mut Some((b.clone(),)))?
1415 {
1416 return Ok(T::from_value(value)?);
1417 }
1418
1419 Err(VmError::new(VmErrorKind::UnsupportedBinaryOperation {
1420 op: protocol.name,
1421 lhs: self.type_info(),
1422 rhs: b.type_info(),
1423 }))
1424 }
1425
1426 pub fn as_integer<T>(&self) -> Result<T, RuntimeError>
1439 where
1440 T: TryFrom<u64> + TryFrom<i64>,
1441 {
1442 match self.repr {
1443 Repr::Inline(value) => value.as_integer(),
1444 Repr::Dynamic(ref value) => Err(RuntimeError::new(VmErrorKind::ExpectedNumber {
1445 actual: value.type_info(),
1446 })),
1447 Repr::Any(ref value) => Err(RuntimeError::new(VmErrorKind::ExpectedNumber {
1448 actual: value.type_info(),
1449 })),
1450 }
1451 }
1452
1453 pub(crate) fn as_inline_unchecked(&self) -> Option<&Inline> {
1454 match &self.repr {
1455 Repr::Inline(value) => Some(value),
1456 _ => None,
1457 }
1458 }
1459
1460 pub(crate) fn is_inline(&self) -> bool {
1462 matches!(self.repr, Repr::Inline(..))
1463 }
1464
1465 #[inline]
1469 pub(crate) fn as_inline(&self) -> Option<&Inline> {
1470 match &self.repr {
1471 Repr::Inline(value) => Some(value),
1472 Repr::Dynamic(..) => None,
1473 Repr::Any(..) => None,
1474 }
1475 }
1476
1477 #[inline]
1481 pub fn as_any(&self) -> Option<&AnyObj> {
1482 match &self.repr {
1483 Repr::Inline(..) => None,
1484 Repr::Dynamic(..) => None,
1485 Repr::Any(value) => Some(value),
1486 }
1487 }
1488
1489 #[inline(always)]
1490 pub(crate) fn take_repr(mut self) -> Repr {
1491 replace(&mut self.repr, Repr::Inline(Inline::Empty))
1492 }
1493
1494 #[inline(always)]
1495 pub(crate) fn as_ref(&self) -> &Repr {
1496 &self.repr
1497 }
1498
1499 #[inline(always)]
1500 pub(crate) fn as_mut(&mut self) -> &mut Repr {
1501 &mut self.repr
1502 }
1503
1504 #[inline]
1505 pub(crate) fn try_borrow_ref<T>(&self) -> Result<Option<BorrowRef<'_, T>>, AccessError>
1506 where
1507 T: Any,
1508 {
1509 match &self.repr {
1510 Repr::Inline(..) => Ok(None),
1511 Repr::Dynamic(..) => Ok(None),
1512 Repr::Any(value) => value.try_borrow_ref(),
1513 }
1514 }
1515
1516 #[inline]
1517 pub(crate) fn try_borrow_mut<T>(&self) -> Result<Option<BorrowMut<'_, T>>, AccessError>
1518 where
1519 T: Any,
1520 {
1521 match &self.repr {
1522 Repr::Inline(..) => Ok(None),
1523 Repr::Dynamic(..) => Ok(None),
1524 Repr::Any(value) => value.try_borrow_mut(),
1525 }
1526 }
1527
1528 pub(crate) fn protocol_into_iter(&self) -> Result<Value, VmError> {
1534 let _guard = env::enter_value()?;
1535 EnvProtocolCaller.call_protocol_fn(&Protocol::INTO_ITER, self.clone(), &mut ())
1536 }
1537
1538 pub(crate) fn protocol_next(&self) -> Result<Option<Value>, VmError> {
1545 budget::permit()?;
1546 let _guard = env::enter_value()?;
1547 let value = EnvProtocolCaller.call_protocol_fn(&Protocol::NEXT, self.clone(), &mut ())?;
1548
1549 Ok(FromValue::from_value(value)?)
1550 }
1551
1552 pub(crate) fn protocol_next_back(&self) -> Result<Option<Value>, VmError> {
1553 budget::permit()?;
1554 let _guard = env::enter_value()?;
1555
1556 let value =
1557 EnvProtocolCaller.call_protocol_fn(&Protocol::NEXT_BACK, self.clone(), &mut ())?;
1558
1559 Ok(FromValue::from_value(value)?)
1560 }
1561
1562 pub(crate) fn protocol_nth_back(&self, n: usize) -> Result<Option<Value>, VmError> {
1563 let _guard = env::enter_value()?;
1564
1565 let value = EnvProtocolCaller.call_protocol_fn(
1566 &Protocol::NTH_BACK,
1567 self.clone(),
1568 &mut Some((n,)),
1569 )?;
1570
1571 Ok(FromValue::from_value(value)?)
1572 }
1573
1574 pub(crate) fn protocol_len(&self) -> Result<usize, VmError> {
1575 let _guard = env::enter_value()?;
1576 let value = EnvProtocolCaller.call_protocol_fn(&Protocol::LEN, self.clone(), &mut ())?;
1577
1578 Ok(FromValue::from_value(value)?)
1579 }
1580
1581 pub(crate) fn protocol_size_hint(&self) -> Result<(usize, Option<usize>), VmError> {
1582 let _guard = env::enter_value()?;
1583
1584 let value =
1585 EnvProtocolCaller.call_protocol_fn(&Protocol::SIZE_HINT, self.clone(), &mut ())?;
1586
1587 Ok(FromValue::from_value(value)?)
1588 }
1589}
1590
1591impl fmt::Debug for Value {
1592 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1593 match &self.repr {
1594 Repr::Inline(value) => {
1595 write!(f, "{value:?}")?;
1596 }
1597 _ => {
1598 let mut s = String::new();
1599 let result = Formatter::format_with(&mut s, |f| self.debug_fmt(f));
1600
1601 if let Err(e) = result {
1602 match &self.repr {
1603 Repr::Inline(value) => {
1604 write!(f, "<{value:?}: {e}>")?;
1605 }
1606 Repr::Dynamic(value) => {
1607 let ty = value.type_info();
1608 write!(f, "<{ty} object at {value:p}: {e}>")?;
1609 }
1610 Repr::Any(value) => {
1611 let ty = value.type_info();
1612 write!(f, "<{ty} object at {value:p}: {e}>")?;
1613 }
1614 }
1615
1616 return Ok(());
1617 }
1618
1619 f.write_str(s.as_str())?;
1620 }
1621 }
1622
1623 Ok(())
1624 }
1625}
1626
1627impl From<Repr> for Value {
1628 #[inline]
1629 fn from(repr: Repr) -> Self {
1630 Self { repr }
1631 }
1632}
1633
1634impl From<()> for Value {
1635 #[inline]
1636 fn from((): ()) -> Self {
1637 Value::from(Inline::Unit)
1638 }
1639}
1640
1641impl From<Inline> for Value {
1642 #[inline]
1643 fn from(value: Inline) -> Self {
1644 Self {
1645 repr: Repr::Inline(value),
1646 }
1647 }
1648}
1649
1650impl From<AnyObj> for Value {
1668 #[inline]
1669 fn from(value: AnyObj) -> Self {
1670 Self {
1671 repr: Repr::Any(value),
1672 }
1673 }
1674}
1675
1676impl<T> From<Shared<T>> for Value
1694where
1695 T: Any,
1696{
1697 #[inline]
1698 fn from(value: Shared<T>) -> Self {
1699 Self {
1700 repr: Repr::Any(value.into_any_obj()),
1701 }
1702 }
1703}
1704
1705impl From<AnySequence<Arc<Rtti>, Value>> for Value {
1706 #[inline]
1707 fn from(value: AnySequence<Arc<Rtti>, Value>) -> Self {
1708 Self {
1709 repr: Repr::Dynamic(value),
1710 }
1711 }
1712}
1713
1714impl TryFrom<&str> for Value {
1715 type Error = alloc::Error;
1716
1717 #[inline]
1718 fn try_from(value: &str) -> Result<Self, Self::Error> {
1719 Value::new(String::try_from(value)?)
1720 }
1721}
1722
1723inline_from! {
1724 Bool => bool,
1725 Char => char,
1726 Signed => i64,
1727 Unsigned => u64,
1728 Float => f64,
1729 Type => Type,
1730 Ordering => Ordering,
1731 Hash => Hash,
1732}
1733
1734any_from! {
1735 crate::alloc::String,
1736 super::Bytes,
1737 super::Format,
1738 super::ControlFlow,
1739 super::GeneratorState,
1740 super::Vec,
1741 super::OwnedTuple,
1742 super::Generator,
1743 super::Stream,
1744 super::Function,
1745 super::Future,
1746 super::Object,
1747 Option<Value>,
1748 Result<Value, Value>,
1749}
1750
1751signed_value_from!(i8, i16, i32);
1752signed_value_try_from!(i128, isize);
1753unsigned_value_from!(u8, u16, u32);
1754unsigned_value_try_from!(u128, usize);
1755signed_value_trait!(i8, i16, i32, i128, isize);
1756unsigned_value_trait!(u8, u16, u32, u128, usize);
1757float_value_trait!(f32);
1758
1759impl MaybeTypeOf for Value {
1760 #[inline]
1761 fn maybe_type_of() -> alloc::Result<meta::DocType> {
1762 Ok(meta::DocType::empty())
1763 }
1764}
1765
1766impl Drop for Value {
1777 #[inline]
1778 fn drop(&mut self) {
1779 if matches!(self.repr, Repr::Inline(..)) {
1782 return;
1783 }
1784
1785 let repr = replace(&mut self.repr, Repr::Inline(Inline::Empty));
1786
1787 self::dismantle::Worklist::new().dismantle_repr(repr);
1790 }
1791}
1792
1793impl Clone for Value {
1794 #[inline]
1795 fn clone(&self) -> Self {
1796 let repr = match &self.repr {
1797 Repr::Inline(inline) => Repr::Inline(*inline),
1798 Repr::Dynamic(mutable) => Repr::Dynamic(mutable.clone()),
1799 Repr::Any(any) => Repr::Any(any.clone()),
1800 };
1801
1802 Self { repr }
1803 }
1804
1805 #[inline]
1806 fn clone_from(&mut self, source: &Self) {
1807 match (&mut self.repr, &source.repr) {
1808 (Repr::Inline(lhs), Repr::Inline(rhs)) => {
1809 *lhs = *rhs;
1810 }
1811 (Repr::Dynamic(lhs), Repr::Dynamic(rhs)) => {
1812 lhs.clone_from(rhs);
1813 }
1814 (Repr::Any(lhs), Repr::Any(rhs)) => {
1815 lhs.clone_from(rhs);
1816 }
1817 (lhs, rhs) => {
1818 *lhs = rhs.clone();
1819 }
1820 }
1821 }
1822}
1823
1824impl TryClone for Value {
1825 fn try_clone(&self) -> alloc::Result<Self> {
1826 Ok(self.clone())
1828 }
1829}
1830
1831#[doc(hidden)]
1833pub struct NotTypedInline(Inline);
1834
1835#[doc(hidden)]
1837pub struct NotTypedAnyObj<'a>(&'a AnyObj);
1838
1839#[non_exhaustive]
1841#[doc(hidden)]
1842pub enum TypeValue<'a> {
1843 Unit,
1845 Tuple(BorrowRef<'a, OwnedTuple>),
1847 Object(BorrowRef<'a, Object>),
1849 EmptyStruct(EmptyStruct<'a>),
1851 TupleStruct(TupleStruct<'a>),
1853 Struct(Struct<'a>),
1855 #[doc(hidden)]
1857 NotTypedInline(NotTypedInline),
1858 #[doc(hidden)]
1860 NotTypedAnyObj(NotTypedAnyObj<'a>),
1861}
1862
1863impl TypeValue<'_> {
1864 #[doc(hidden)]
1866 pub fn type_info(&self) -> TypeInfo {
1867 match self {
1868 TypeValue::Unit => TypeInfo::any::<OwnedTuple>(),
1869 TypeValue::Tuple(..) => TypeInfo::any::<OwnedTuple>(),
1870 TypeValue::Object(..) => TypeInfo::any::<Object>(),
1871 TypeValue::EmptyStruct(empty) => empty.type_info(),
1872 TypeValue::TupleStruct(tuple) => tuple.type_info(),
1873 TypeValue::Struct(object) => object.type_info(),
1874 TypeValue::NotTypedInline(value) => value.0.type_info(),
1875 TypeValue::NotTypedAnyObj(value) => value.0.type_info(),
1876 }
1877 }
1878}
1879
1880#[test]
1883fn size_of_value() {
1884 use core::mem::size_of;
1885
1886 assert_eq!(size_of::<Repr>(), size_of::<Inline>());
1887 assert_eq!(size_of::<Repr>(), size_of::<Value>());
1888 assert_eq!(size_of::<Option<Value>>(), size_of::<Value>());
1889 assert_eq!(size_of::<Option<Repr>>(), size_of::<Repr>());
1890}