1use crate::{
2 shared_values::shared_type_container::{
3 NominalTypeDeclaration, SharedTypeContainer,
4 },
5 values::core_value::CoreValue,
6};
7use core::result::Result;
8
9use crate::{
10 prelude::*,
11 runtime::execution::ExecutionError,
12 shared_values::{
13 pointer::{Pointer, PointerReferenceMutability},
14 pointer_address::PointerAddress,
15 shared_value_container::SharedValueContainer,
16 },
17 traits::{
18 apply::Apply, identity::Identity, structural_eq::StructuralEq,
19 value_eq::ValueEq,
20 },
21 types::definition::TypeDefinition,
22 values::{
23 core_values::{map::MapAccessError, r#type::Type},
24 value::Value,
25 value_container::{ValueContainer, ValueKey},
26 },
27};
28use core::{
29 cell::{Ref, RefCell},
30 fmt::Display,
31 hash::{Hash, Hasher},
32 ops::FnOnce,
33 option::Option,
34 unreachable, write,
35};
36use num_enum::TryFromPrimitive;
37use serde::{Deserialize, Serialize};
38
39#[derive(Debug)]
40pub struct IndexOutOfBoundsError {
41 pub index: u32,
42}
43
44impl Display for IndexOutOfBoundsError {
45 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46 write!(f, "Index out of bounds: {}", self.index)
47 }
48}
49
50#[derive(Debug, Clone, PartialEq)]
51pub struct KeyNotFoundError {
52 pub key: ValueContainer,
53}
54
55impl Display for KeyNotFoundError {
56 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57 write!(f, "Property not found: {}", self.key)
58 }
59}
60
61#[derive(Debug)]
62pub enum AccessError {
63 ImmutableReference,
64 InvalidOperation(String),
65 KeyNotFound(KeyNotFoundError),
66 IndexOutOfBounds(IndexOutOfBoundsError),
67 MapAccessError(MapAccessError),
68 InvalidIndexKey,
69}
70
71impl From<IndexOutOfBoundsError> for AccessError {
72 fn from(err: IndexOutOfBoundsError) -> Self {
73 AccessError::IndexOutOfBounds(err)
74 }
75}
76
77impl From<MapAccessError> for AccessError {
78 fn from(err: MapAccessError) -> Self {
79 AccessError::MapAccessError(err)
80 }
81}
82
83impl From<KeyNotFoundError> for AccessError {
84 fn from(err: KeyNotFoundError) -> Self {
85 AccessError::KeyNotFound(err)
86 }
87}
88
89impl Display for AccessError {
90 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 match self {
92 AccessError::MapAccessError(err) => {
93 write!(f, "Map access error: {}", err)
94 }
95 AccessError::ImmutableReference => {
96 write!(f, "Cannot modify an immutable reference")
97 }
98 AccessError::InvalidOperation(op) => {
99 write!(f, "Invalid operation: {}", op)
100 }
101 AccessError::KeyNotFound(key) => {
102 write!(f, "{}", key)
103 }
104 AccessError::IndexOutOfBounds(error) => {
105 write!(f, "{}", error)
106 }
107 AccessError::InvalidIndexKey => {
108 write!(f, "Invalid index key")
109 }
110 }
111 }
112}
113
114#[derive(Debug)]
115pub enum TypeError {
116 TypeMismatch { expected: Type, found: Type },
117}
118impl Display for TypeError {
119 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
120 match self {
121 TypeError::TypeMismatch { expected, found } => write!(
122 f,
123 "Type mismatch: expected {}, found {}",
124 expected, found
125 ),
126 }
127 }
128}
129
130#[derive(Debug)]
131pub enum AssignmentError {
132 ImmutableReference,
133 TypeError(Box<TypeError>),
134}
135
136impl Display for AssignmentError {
137 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
138 match self {
139 AssignmentError::ImmutableReference => {
140 write!(f, "Cannot assign to an immutable reference")
141 }
142 AssignmentError::TypeError(e) => {
143 write!(f, "Type error: {}", e)
144 }
145 }
146 }
147}
148
149#[derive(
150 Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, TryFromPrimitive,
151)]
152#[repr(u8)]
153pub enum SharedContainerMutability {
154 Mutable = 0,
155 Immutable = 1,
156}
157
158pub mod mutability_as_int {
159 use super::SharedContainerMutability;
160 use crate::prelude::*;
161 use serde::{Deserialize, Deserializer, Serializer, de::Error};
162
163 pub fn serialize<S>(
164 value: &SharedContainerMutability,
165 serializer: S,
166 ) -> Result<S::Ok, S::Error>
167 where
168 S: Serializer,
169 {
170 match value {
171 SharedContainerMutability::Mutable => serializer.serialize_u8(0),
172 SharedContainerMutability::Immutable => serializer.serialize_u8(1),
173 }
174 }
175
176 pub fn deserialize<'de, D>(
177 deserializer: D,
178 ) -> Result<SharedContainerMutability, D::Error>
179 where
180 D: Deserializer<'de>,
181 {
182 let opt = u8::deserialize(deserializer)?;
183 Ok(match opt {
184 0 => SharedContainerMutability::Mutable,
185 1 => SharedContainerMutability::Immutable,
186 x => {
187 return Err(D::Error::custom(format!(
188 "invalid mutability code: {}",
189 x
190 )));
191 }
192 })
193 }
194}
195pub mod mutability_option_as_int {
196 use super::SharedContainerMutability;
197
198 use crate::prelude::*;
199 use serde::{Deserialize, Deserializer, Serializer, de::Error};
200
201 pub fn serialize<S>(
202 value: &Option<SharedContainerMutability>,
203 serializer: S,
204 ) -> Result<S::Ok, S::Error>
205 where
206 S: Serializer,
207 {
208 match value {
209 Some(SharedContainerMutability::Mutable) => {
210 serializer.serialize_u8(0)
211 }
212 Some(SharedContainerMutability::Immutable) => {
213 serializer.serialize_u8(1)
214 }
215 None => serializer.serialize_none(),
216 }
217 }
218
219 pub fn deserialize<'de, D>(
220 deserializer: D,
221 ) -> Result<Option<SharedContainerMutability>, D::Error>
222 where
223 D: Deserializer<'de>,
224 {
225 let opt = Option::<u8>::deserialize(deserializer)?;
226 Ok(match opt {
227 Some(0) => Some(SharedContainerMutability::Mutable),
228 Some(1) => Some(SharedContainerMutability::Immutable),
229 Some(x) => {
230 return Err(D::Error::custom(format!(
231 "invalid mutability code: {}",
232 x
233 )));
234 }
235 None => None,
236 })
237 }
238}
239
240impl Display for SharedContainerMutability {
241 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
242 match self {
243 SharedContainerMutability::Mutable => write!(f, "mut"),
244 SharedContainerMutability::Immutable => write!(f, ""),
245 }
246 }
247}
248
249#[derive(Debug, Clone)]
250pub enum SharedContainer {
251 Value(Rc<RefCell<SharedValueContainer>>),
252 Type(Rc<RefCell<SharedTypeContainer>>),
253}
254
255impl Display for SharedContainer {
256 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
257 match self {
258 SharedContainer::Value(vr) => {
259 let vr = vr.borrow();
260 write!(f, "{} {}", vr.mutability, vr.value_container)
261 }
262 SharedContainer::Type(tr) => {
263 let tr = tr.borrow();
264 write!(f, "{}", tr)
265 }
266 }
267 }
268}
269
270impl From<SharedValueContainer> for SharedContainer {
271 fn from(reference: SharedValueContainer) -> Self {
272 SharedContainer::Value(Rc::new(RefCell::new(reference)))
273 }
274}
275impl From<SharedTypeContainer> for SharedContainer {
276 fn from(reference: SharedTypeContainer) -> Self {
277 SharedContainer::Type(Rc::new(RefCell::new(reference)))
278 }
279}
280
281impl Identity for SharedContainer {
283 fn identical(&self, other: &Self) -> bool {
284 match (self, other) {
285 (SharedContainer::Value(a), SharedContainer::Value(b)) => {
286 Rc::ptr_eq(a, b)
287 }
288 (SharedContainer::Type(a), SharedContainer::Type(b)) => {
289 Rc::ptr_eq(a, b)
290 }
291 _ => false,
292 }
293 }
294}
295
296impl Eq for SharedContainer {}
297
298impl PartialEq for SharedContainer {
300 fn eq(&self, other: &Self) -> bool {
301 self.identical(other)
302 }
303}
304
305impl StructuralEq for SharedContainer {
306 fn structural_eq(&self, other: &Self) -> bool {
307 match (self, other) {
308 (SharedContainer::Type(a), SharedContainer::Type(b)) => {
309 a.borrow().type_value.structural_eq(&b.borrow().type_value)
310 }
311 (SharedContainer::Value(a), SharedContainer::Value(b)) => a
312 .borrow()
313 .value_container
314 .structural_eq(&b.borrow().value_container),
315 _ => false,
316 }
317 }
318}
319
320impl ValueEq for SharedContainer {
321 fn value_eq(&self, other: &Self) -> bool {
322 match (self, other) {
323 (SharedContainer::Type(a), SharedContainer::Type(b)) => {
324 a.borrow().type_value.structural_eq(&b.borrow().type_value)
326 }
327 (SharedContainer::Value(a), SharedContainer::Value(b)) => a
328 .borrow()
329 .value_container
330 .value_eq(&b.borrow().value_container),
331 _ => false,
332 }
333 }
334}
335
336impl Hash for SharedContainer {
342 fn hash<H: Hasher>(&self, state: &mut H) {
343 match self {
344 SharedContainer::Type(tr) => {
345 let ptr = Rc::as_ptr(tr);
346 ptr.hash(state); }
348 SharedContainer::Value(vr) => {
349 let ptr = Rc::as_ptr(vr);
350 ptr.hash(state); }
352 }
353 }
354}
355
356#[derive(Debug, Clone, PartialEq, Eq, Hash)]
357pub enum SharedValueCreationError {
358 InvalidType,
359 MutabilityMismatch,
360}
361
362impl Display for SharedValueCreationError {
363 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
364 match self {
365 SharedValueCreationError::InvalidType => {
366 write!(
367 f,
368 "Cannot create shared value from value container: invalid type"
369 )
370 }
371 SharedValueCreationError::MutabilityMismatch => {
372 write!(
373 f,
374 "Cannot create mutable shared value for immutable value"
375 )
376 }
377 }
378 }
379}
380
381impl SharedContainer {
382 pub(crate) fn with_value<R, F: FnOnce(&mut Value) -> R>(
384 &self,
385 f: F,
386 ) -> Option<R> {
387 let reference = self.collapse_reference_chain();
388 match reference {
389 SharedContainer::Value(vr) => {
390 match &mut vr.borrow_mut().value_container {
391 ValueContainer::Local(value) => Some(f(value)),
392 ValueContainer::Shared(_) => {
393 unreachable!(
394 "Expected a ValueContainer::Value, but found a Reference"
395 )
396 }
397 }
398 }
399 SharedContainer::Type(_) => None,
400 }
401 }
402
403 pub(crate) fn with_value_unchecked<R, F: FnOnce(&mut Value) -> R>(
406 &self,
407 f: F,
408 ) -> R {
409 unsafe { self.with_value(f).unwrap_unchecked() }
410 }
411}
412
413impl SharedContainer {
414 pub fn pointer_address(&self) -> PointerAddress {
415 match self {
416 SharedContainer::Value(vr) => vr.borrow().pointer.address(),
417 SharedContainer::Type(tr) => tr.borrow().pointer.address(),
418 }
419 }
420
421 pub fn pointer(&self) -> Ref<'_, Pointer> {
422 match self {
423 SharedContainer::Value(vr) => {
424 Ref::map(vr.borrow(), |vr| &vr.pointer)
425 }
426 SharedContainer::Type(tr) => {
427 Ref::map(tr.borrow(), |tr| &tr.pointer)
428 }
429 }
430 }
431
432 pub(crate) fn mutability(&self) -> SharedContainerMutability {
435 match self {
436 SharedContainer::Value(vr) => vr.borrow().mutability.clone(),
437 SharedContainer::Type(_) => SharedContainerMutability::Immutable,
438 }
439 }
440
441 pub(crate) fn can_mutate(&self) -> bool {
443 match self.pointer().reference_mutability() {
444 Some(PointerReferenceMutability::Mutable) => true,
446 None => self.mutability() == SharedContainerMutability::Mutable,
448 _ => false,
449 }
450 }
451
452 pub fn is_mutable(&self) -> bool {
458 match self {
459 SharedContainer::Type(_) => false, SharedContainer::Value(vr) => {
461 let vr_borrow = vr.borrow();
462 if vr_borrow.mutability != SharedContainerMutability::Mutable {
464 return false;
465 }
466
467 match &vr_borrow.value_container {
469 ValueContainer::Shared(inner) => inner.is_mutable(),
470 ValueContainer::Local(_) => true,
471 }
472 }
473 }
474 }
475
476 pub fn try_boxed(
478 value_container: ValueContainer,
479 allowed_type: Option<TypeDefinition>,
480 pointer: Pointer,
481 mutability: SharedContainerMutability,
482 ) -> Result<Self, SharedValueCreationError> {
483 if let ValueContainer::Shared(ref shared) = value_container
485 && mutability == SharedContainerMutability::Mutable
486 && shared.mutability() != SharedContainerMutability::Mutable
487 {
488 return Err(SharedValueCreationError::MutabilityMismatch);
489 }
490 let allowed_type =
491 allowed_type.unwrap_or_else(|| value_container.allowed_type());
492
493 Ok(SharedContainer::Value(Rc::new(RefCell::new(
495 SharedValueContainer::new(
496 value_container,
497 pointer,
498 allowed_type,
499 mutability,
500 ),
501 ))))
502 }
503
504 pub fn new_from_type(
505 type_value: Type,
506 pointer: Pointer,
507 maybe_nominal_type_declaration: Option<NominalTypeDeclaration>,
508 ) -> Self {
509 let type_reference = SharedTypeContainer {
510 pointer,
511 nominal_type_declaration: maybe_nominal_type_declaration,
512 type_value,
513 };
514 SharedContainer::Type(Rc::new(RefCell::new(type_reference)))
515 }
516
517 pub fn boxed_mut(
518 value_container: ValueContainer,
519 pointer: Pointer,
520 ) -> Result<Self, SharedValueCreationError> {
521 SharedContainer::try_boxed(
522 value_container,
523 None,
524 pointer,
525 SharedContainerMutability::Mutable,
526 )
527 }
528
529 pub fn boxed(
530 value_container: impl Into<ValueContainer>,
531 pointer: Pointer,
532 ) -> Self {
533 SharedContainer::try_boxed(
534 value_container.into(),
535 None,
536 pointer,
537 SharedContainerMutability::Immutable,
538 )
539 .unwrap()
540 }
541
542 pub fn collapse_reference_chain(&self) -> SharedContainer {
544 match self {
545 SharedContainer::Type(tr) => SharedContainer::Type(Rc::new(
547 RefCell::new(tr.borrow().collapse_reference_chain()),
548 )),
549 SharedContainer::Value(vr) => {
550 match &vr.borrow().value_container {
551 ValueContainer::Shared(reference) => {
552 reference.collapse_reference_chain()
554 }
555 ValueContainer::Local(_) => {
556 self.clone()
558 }
559 }
560 }
561 }
562 }
563
564 pub fn collapse_to_value(&self) -> Rc<RefCell<Value>> {
566 let reference = self.collapse_reference_chain();
567 match reference {
568 SharedContainer::Value(vr) => match &vr.borrow().value_container {
569 ValueContainer::Local(_) => {
570 vr.borrow().value_container.to_value()
571 }
572 ValueContainer::Shared(_) => unreachable!(
573 "Expected a ValueContainer::Value, but found a Reference"
574 ),
575 },
576 SharedContainer::Type(tr) => Rc::new(RefCell::new(Value::from(
578 CoreValue::Type(tr.borrow().type_value.clone()),
579 ))),
580 }
581 }
582
583 pub fn value_container(&self) -> ValueContainer {
585 match self {
586 SharedContainer::Value(vr) => vr.borrow().value_container.clone(),
587 SharedContainer::Type(tr) => ValueContainer::Local(Value::from(
588 CoreValue::Type(tr.borrow().type_value.clone()),
589 )),
590 }
591 }
592
593 pub fn allowed_type(&self) -> TypeDefinition {
594 match self {
595 SharedContainer::Value(vr) => vr.borrow().allowed_type.clone(),
596 SharedContainer::Type(_) => core::todo!("#293 type Type"),
597 }
598 }
599
600 pub fn actual_type(&self) -> TypeDefinition {
601 match self {
602 SharedContainer::Value(vr) => vr
603 .borrow()
604 .value_container
605 .to_value()
606 .borrow()
607 .actual_type()
608 .clone(),
609 SharedContainer::Type(_tr) => core::todo!("#294 type Type"),
610 }
611 }
612
613 pub fn is_type(&self) -> bool {
614 match self {
615 SharedContainer::Type(_) => true,
616 SharedContainer::Value(vr) => {
617 vr.borrow().resolve_current_value().borrow().is_type()
618 }
619 }
620 }
621
622 pub fn mutable_reference(
624 &self,
625 ) -> Option<Rc<RefCell<SharedValueContainer>>> {
626 match self {
627 SharedContainer::Type(_) => None,
628 SharedContainer::Value(vr) => {
629 if vr.borrow().is_mutable() {
630 Some(vr.clone())
631 } else {
632 None
633 }
634 }
635 }
636 }
637
638 pub fn set_value_container(
641 &self,
642 new_value_container: ValueContainer,
643 ) -> Result<(), AssignmentError> {
644 match &self {
645 SharedContainer::Type(_) => {
646 Err(AssignmentError::ImmutableReference)
647 }
648 SharedContainer::Value(vr) => {
649 if self.is_mutable() {
650 vr.borrow_mut().value_container = new_value_container;
652 Ok(())
653 } else {
654 Err(AssignmentError::ImmutableReference)
655 }
656 }
657 }
658 }
659}
660impl SharedContainer {
662 pub fn try_get_property<'a>(
670 &self,
671 key: impl Into<ValueKey<'a>>,
672 ) -> Result<ValueContainer, AccessError> {
673 self.with_value(|value| value.try_get_property(key))
674 .unwrap_or(Err(AccessError::InvalidOperation(
675 "Cannot get property on invalid reference".to_string(),
676 )))
677 }
678}
679
680impl Apply for SharedContainer {
681 fn apply(
682 &self,
683 args: &[ValueContainer],
684 ) -> Result<Option<ValueContainer>, ExecutionError> {
685 match self {
686 SharedContainer::Type(tr) => tr.borrow().apply(args),
687 SharedContainer::Value(vr) => {
688 vr.borrow().resolve_current_value().borrow().apply(args)
689 }
690 }
691 }
692
693 fn apply_single(
694 &self,
695 arg: &ValueContainer,
696 ) -> Result<Option<ValueContainer>, ExecutionError> {
697 match self {
698 SharedContainer::Type(tr) => tr.borrow().apply_single(arg),
699 SharedContainer::Value(vr) => vr
700 .borrow()
701 .resolve_current_value()
702 .borrow()
703 .apply_single(arg),
704 }
705 }
706}
707
708#[cfg(test)]
709mod tests {
710 use super::*;
711 use crate::{
712 assert_identical, assert_structural_eq, assert_value_eq, prelude::*,
713 runtime::memory::Memory, traits::value_eq::ValueEq,
714 values::core_values::map::Map,
715 };
716 use core::assert_matches;
717
718 #[test]
719 fn try_mut_from() {
720 let value = ValueContainer::from(42);
722 let reference =
723 SharedContainer::boxed_mut(value, Pointer::NULL).unwrap();
724 assert_eq!(reference.mutability(), SharedContainerMutability::Mutable);
725
726 let type_value = ValueContainer::Shared(SharedContainer::Type(
728 SharedTypeContainer::anonymous(Type::UNIT, Pointer::NULL)
729 .as_ref_cell(),
730 ));
731 assert_matches!(
732 SharedContainer::boxed_mut(type_value, Pointer::NULL),
733 Err(SharedValueCreationError::MutabilityMismatch)
734 );
735 }
736
737 #[test]
738 fn property() {
739 let mut map = Map::default();
740 map.set("name", ValueContainer::from("Jonas"));
741 map.set("age", ValueContainer::from(30));
742 let reference =
743 SharedContainer::boxed(ValueContainer::from(map), Pointer::NULL);
744 assert_eq!(
745 reference.try_get_property("name").unwrap(),
746 ValueContainer::from("Jonas")
747 );
748 assert_eq!(
749 reference.try_get_property("age").unwrap(),
750 ValueContainer::from(30)
751 );
752 assert!(reference.try_get_property("nonexistent").is_err());
753 assert_matches!(
754 reference.try_get_property("nonexistent"),
755 Err(AccessError::KeyNotFound(_))
756 );
757 }
758
759 #[test]
760 fn text_property() {
761 let struct_val = Map::from(vec![
762 ("name".to_string(), ValueContainer::from("Jonas")),
763 ("age".to_string(), ValueContainer::from(30)),
764 ]);
765 let reference = SharedContainer::boxed(
766 ValueContainer::from(struct_val),
767 Pointer::NULL,
768 );
769 assert_eq!(
770 reference.try_get_property("name").unwrap(),
771 ValueContainer::from("Jonas")
772 );
773 assert_eq!(
774 reference.try_get_property("age").unwrap(),
775 ValueContainer::from(30)
776 );
777 assert!(reference.try_get_property("nonexistent").is_err());
778 assert_matches!(
779 reference.try_get_property("nonexistent"),
780 Err(AccessError::KeyNotFound(_))
781 );
782 }
783
784 #[test]
785 fn numeric_property() {
786 let list = vec![
787 ValueContainer::from(1),
788 ValueContainer::from(2),
789 ValueContainer::from(3),
790 ];
791 let reference =
792 SharedContainer::boxed(ValueContainer::from(list), Pointer::NULL);
793
794 assert_eq!(
795 reference.try_get_property(0).unwrap(),
796 ValueContainer::from(1)
797 );
798 assert_eq!(
799 reference.try_get_property(1).unwrap(),
800 ValueContainer::from(2)
801 );
802 assert_eq!(
803 reference.try_get_property(2).unwrap(),
804 ValueContainer::from(3)
805 );
806 assert!(reference.try_get_property(3).is_err());
807
808 assert_matches!(
809 reference.try_get_property(100),
810 Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError {
811 index: 100
812 }))
813 );
814
815 let text_ref = SharedContainer::boxed(
816 ValueContainer::from("hello"),
817 Pointer::NULL,
818 );
819 assert_eq!(
820 text_ref.try_get_property(1).unwrap(),
821 ValueContainer::from("e".to_string())
822 );
823 assert!(text_ref.try_get_property(5).is_err());
824 assert_matches!(
825 text_ref.try_get_property(100),
826 Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError {
827 index: 100
828 }))
829 );
830 }
831
832 #[test]
833 fn reference_identity() {
834 let value = 42;
835 let reference1 = SharedContainer::boxed(value, Pointer::NULL);
836 let reference2 = reference1.clone();
837
838 assert_eq!(reference1, reference2);
840 assert_eq!(
842 ValueContainer::Shared(reference1.clone()),
843 ValueContainer::Shared(reference2.clone())
844 );
845 assert_identical!(reference1.clone(), reference2);
847 assert_ne!(reference1, SharedContainer::boxed(value, Pointer::NULL));
849 }
850
851 #[test]
852 fn reference_value_equality() {
853 let value = 42;
854 let reference1 = ValueContainer::Shared(SharedContainer::boxed(
855 value,
856 Pointer::NULL,
857 ));
858 let reference2 = ValueContainer::Shared(SharedContainer::boxed(
859 value,
860 Pointer::NULL,
861 ));
862
863 assert_ne!(reference1, reference2);
865 assert_value_eq!(reference1, ValueContainer::from(value));
867 }
868
869 #[test]
870 fn reference_structural_equality() {
871 let reference1 = SharedContainer::boxed(42.0, Pointer::NULL);
872 let reference2 = SharedContainer::boxed(42, Pointer::NULL);
873
874 assert_ne!(reference1, reference2);
876 assert!(!reference1.structural_eq(&reference2));
878 }
879
880 #[test]
881 fn nested_references() {
882 let memory = &RefCell::new(Memory::default());
883
884 let mut map_a = Map::default();
885 map_a.set("number", ValueContainer::from(42));
886 map_a.set(
887 "obj",
888 ValueContainer::Shared(SharedContainer::boxed(
889 Map::default(),
890 Pointer::NULL,
891 )),
892 );
893
894 let map_a_original_ref = ValueContainer::Shared(
896 SharedContainer::boxed(map_a, Pointer::NULL),
897 );
898
899 let map_b_ref = SharedContainer::try_boxed(
901 Map::default().into(),
902 None,
903 Pointer::NULL,
904 SharedContainerMutability::Mutable,
905 )
906 .unwrap();
907
908 map_b_ref
911 .try_set_property(0, None, "a", map_a_original_ref.clone())
912 .unwrap();
913
914 let map_a_ref = map_b_ref.try_get_property("a").unwrap();
916 assert_structural_eq!(map_a_ref, map_a_original_ref);
917 assert_eq!(map_a_ref, map_a_original_ref);
918 assert_identical!(map_a_ref, map_a_original_ref);
919 assert_matches!(map_a_ref, ValueContainer::Shared(_));
921 map_a_ref.with_maybe_shared(|a_ref| {
922 assert_matches!(
924 a_ref.try_get_property("number"),
925 Ok(ValueContainer::Local(_))
926 );
927 assert_matches!(
929 a_ref.try_get_property("obj"),
930 Ok(ValueContainer::Shared(_))
931 );
932 });
933 }
934}