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