1use crate::references::type_reference::{
2 NominalTypeDeclaration, TypeReference,
3};
4use crate::values::core_value::CoreValue;
5use core::prelude::rust_2024::*;
6use core::result::Result;
7
8use crate::references::value_reference::ValueReference;
9use crate::runtime::execution::ExecutionError;
10use crate::stdlib::boxed::Box;
11use crate::stdlib::rc::Rc;
12use crate::stdlib::string::String;
13use crate::stdlib::string::ToString;
14use crate::traits::apply::Apply;
15use crate::traits::identity::Identity;
16use crate::traits::structural_eq::StructuralEq;
17use crate::traits::value_eq::ValueEq;
18use crate::types::definition::TypeDefinition;
19use crate::values::core_values::map::MapAccessError;
20use crate::values::core_values::r#type::Type;
21use crate::values::pointer::PointerAddress;
22use crate::values::value::Value;
23use crate::values::value_container::{ValueContainer, ValueKey};
24use core::cell::RefCell;
25use core::fmt::Display;
26use core::hash::{Hash, Hasher};
27use core::ops::FnOnce;
28use core::option::Option;
29use core::unreachable;
30use core::write;
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::stdlib::format;
156 use core::prelude::rust_2024::*;
157 use serde::de::Error;
158 use serde::{Deserialize, Deserializer, Serializer};
159
160 pub fn serialize<S>(
161 value: &ReferenceMutability,
162 serializer: S,
163 ) -> Result<S::Ok, S::Error>
164 where
165 S: Serializer,
166 {
167 match value {
168 (ReferenceMutability::Mutable) => serializer.serialize_u8(0),
169 (ReferenceMutability::Immutable) => serializer.serialize_u8(1),
170 }
171 }
172
173 pub fn deserialize<'de, D>(
174 deserializer: D,
175 ) -> Result<ReferenceMutability, D::Error>
176 where
177 D: Deserializer<'de>,
178 {
179 let opt = u8::deserialize(deserializer)?;
180 Ok(match opt {
181 (0) => (ReferenceMutability::Mutable),
182 (1) => (ReferenceMutability::Immutable),
183 (x) => {
184 return Err(D::Error::custom(format!(
185 "invalid mutability code: {}",
186 x
187 )));
188 }
189 })
190 }
191}
192pub mod mutability_option_as_int {
193 use super::ReferenceMutability;
194 use crate::stdlib::format;
195 use core::prelude::rust_2024::*;
196 use serde::de::Error;
197 use serde::{Deserialize, Deserializer, Serializer};
198
199 pub fn serialize<S>(
200 value: &Option<ReferenceMutability>,
201 serializer: S,
202 ) -> Result<S::Ok, S::Error>
203 where
204 S: Serializer,
205 {
206 match value {
207 Some(ReferenceMutability::Mutable) => serializer.serialize_u8(0),
208 Some(ReferenceMutability::Immutable) => serializer.serialize_u8(1),
209 None => serializer.serialize_none(),
210 }
211 }
212
213 pub fn deserialize<'de, D>(
214 deserializer: D,
215 ) -> Result<Option<ReferenceMutability>, D::Error>
216 where
217 D: Deserializer<'de>,
218 {
219 let opt = Option::<u8>::deserialize(deserializer)?;
220 Ok(match opt {
221 Some(0) => Some(ReferenceMutability::Mutable),
222 Some(1) => Some(ReferenceMutability::Immutable),
223 Some(x) => {
224 return Err(D::Error::custom(format!(
225 "invalid mutability code: {}",
226 x
227 )));
228 }
229 None => None,
230 })
231 }
232}
233
234impl Display for ReferenceMutability {
235 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
236 match self {
237 ReferenceMutability::Mutable => write!(f, "&mut"),
238 ReferenceMutability::Immutable => write!(f, "&"),
239 }
240 }
241}
242
243#[derive(Debug, Clone)]
244pub enum Reference {
245 ValueReference(Rc<RefCell<ValueReference>>),
246 TypeReference(Rc<RefCell<TypeReference>>),
247}
248
249impl Display for Reference {
250 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
251 match self {
252 Reference::ValueReference(vr) => {
253 let vr = vr.borrow();
254 write!(f, "{} {}", vr.mutability, vr.value_container)
255 }
256 Reference::TypeReference(tr) => {
257 let tr = tr.borrow();
258 write!(f, "{}", tr)
259 }
260 }
261 }
262}
263
264impl From<ValueReference> for Reference {
265 fn from(reference: ValueReference) -> Self {
266 Reference::ValueReference(Rc::new(RefCell::new(reference)))
267 }
268}
269impl From<TypeReference> for Reference {
270 fn from(reference: TypeReference) -> Self {
271 Reference::TypeReference(Rc::new(RefCell::new(reference)))
272 }
273}
274
275impl Identity for Reference {
277 fn identical(&self, other: &Self) -> bool {
278 match (self, other) {
279 (Reference::ValueReference(a), Reference::ValueReference(b)) => {
280 Rc::ptr_eq(a, b)
281 }
282 (Reference::TypeReference(a), Reference::TypeReference(b)) => {
283 Rc::ptr_eq(a, b)
284 }
285 _ => false,
286 }
287 }
288}
289
290impl Eq for Reference {}
291
292impl PartialEq for Reference {
294 fn eq(&self, other: &Self) -> bool {
295 self.identical(other)
296 }
297}
298
299impl StructuralEq for Reference {
300 fn structural_eq(&self, other: &Self) -> bool {
301 match (self, other) {
302 (Reference::TypeReference(a), Reference::TypeReference(b)) => {
303 a.borrow().type_value.structural_eq(&b.borrow().type_value)
304 }
305 (Reference::ValueReference(a), Reference::ValueReference(b)) => a
306 .borrow()
307 .value_container
308 .structural_eq(&b.borrow().value_container),
309 _ => false,
310 }
311 }
312}
313
314impl ValueEq for Reference {
315 fn value_eq(&self, other: &Self) -> bool {
316 match (self, other) {
317 (Reference::TypeReference(a), Reference::TypeReference(b)) => {
318 a.borrow().type_value.structural_eq(&b.borrow().type_value)
320 }
321 (Reference::ValueReference(a), Reference::ValueReference(b)) => a
322 .borrow()
323 .value_container
324 .value_eq(&b.borrow().value_container),
325 _ => false,
326 }
327 }
328}
329
330impl Hash for Reference {
331 fn hash<H: Hasher>(&self, state: &mut H) {
332 match self {
333 Reference::TypeReference(tr) => {
334 let ptr = Rc::as_ptr(tr);
335 ptr.hash(state); }
337 Reference::ValueReference(vr) => {
338 let ptr = Rc::as_ptr(vr);
339 ptr.hash(state); }
341 }
342 }
343}
344
345impl<T: Into<ValueContainer>> From<T> for Reference {
346 fn from(value_container: T) -> Self {
348 let value_container = value_container.into();
349 Reference::try_new_from_value_container(
350 value_container,
351 None,
352 None,
353 ReferenceMutability::Immutable,
354 )
355 .unwrap()
356 }
357}
358
359#[derive(Debug, Clone, PartialEq, Eq, Hash)]
360pub enum ReferenceCreationError {
361 InvalidType,
362 MutableTypeReference,
363}
364
365impl Display for ReferenceCreationError {
366 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
367 match self {
368 ReferenceCreationError::InvalidType => {
369 write!(
370 f,
371 "Cannot create reference from value container: invalid type"
372 )
373 }
374 ReferenceCreationError::MutableTypeReference => {
375 write!(f, "Cannot create mutable reference for type")
376 }
377 }
378 }
379}
380
381impl Reference {
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 Reference::ValueReference(vr) => {
390 match &mut vr.borrow_mut().value_container {
391 ValueContainer::Value(value) => Some(f(value)),
392 ValueContainer::Reference(_) => {
393 unreachable!(
394 "Expected a ValueContainer::Value, but found a Reference"
395 )
396 }
397 }
398 }
399 Reference::TypeReference(_) => 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 Reference {
414 pub fn pointer_address(&self) -> Option<PointerAddress> {
415 match self {
416 Reference::ValueReference(vr) => {
417 vr.borrow().pointer_address().clone()
418 }
419 Reference::TypeReference(tr) => tr.borrow().pointer_address.clone(),
420 }
421 }
422
423 pub fn set_pointer_address(&self, pointer_address: PointerAddress) {
426 if self.pointer_address().is_some() {
427 core::panic!(
428 "Cannot set pointer address on reference that already has one"
429 );
430 }
431 match self {
432 Reference::ValueReference(vr) => {
433 vr.borrow_mut().pointer_address = Some(pointer_address)
434 }
435 Reference::TypeReference(tr) => {
436 tr.borrow_mut().pointer_address = Some(pointer_address)
437 }
438 }
439 }
440
441 pub(crate) fn mutability(&self) -> ReferenceMutability {
444 match self {
445 Reference::ValueReference(vr) => vr.borrow().mutability.clone(),
446 Reference::TypeReference(_) => ReferenceMutability::Immutable,
447 }
448 }
449
450 pub fn is_mutable(&self) -> bool {
456 match self {
457 Reference::TypeReference(_) => false, Reference::ValueReference(vr) => {
459 let vr_borrow = vr.borrow();
460 if vr_borrow.mutability != ReferenceMutability::Mutable {
462 return false;
463 }
464
465 match &vr_borrow.value_container {
467 ValueContainer::Reference(inner) => inner.is_mutable(),
468 ValueContainer::Value(_) => true,
469 }
470 }
471 }
472 }
473
474 pub fn try_new_from_value_container(
476 value_container: ValueContainer,
477 allowed_type: Option<TypeDefinition>,
478 maybe_pointer_id: Option<PointerAddress>,
479 mutability: ReferenceMutability,
480 ) -> Result<Self, ReferenceCreationError> {
481 Ok(match value_container {
483 ValueContainer::Reference(ref reference) => {
484 match reference {
485 Reference::ValueReference(vr) => {
486 let allowed_type = allowed_type.unwrap_or_else(|| {
487 vr.borrow().allowed_type.clone()
488 });
489 Reference::ValueReference(Rc::new(RefCell::new(
491 ValueReference::new(
492 value_container,
493 maybe_pointer_id,
494 allowed_type,
495 mutability,
496 ),
497 )))
498 }
499 Reference::TypeReference(tr) => {
500 if mutability == ReferenceMutability::Mutable {
501 return Err(
502 ReferenceCreationError::MutableTypeReference,
503 );
504 }
505 Reference::TypeReference(
506 TypeReference::anonymous(
507 Type::reference(tr.clone(), mutability),
508 maybe_pointer_id,
509 )
510 .as_ref_cell(),
511 )
512 }
513 }
514 }
515 ValueContainer::Value(value) => {
516 match value.inner {
517 CoreValue::Type(type_value) => {
519 if allowed_type.is_some() {
521 return Err(ReferenceCreationError::InvalidType);
522 }
523 if mutability == ReferenceMutability::Mutable {
524 return Err(
525 ReferenceCreationError::MutableTypeReference,
526 );
527 }
528 Reference::new_from_type(
529 type_value,
530 maybe_pointer_id,
531 None,
532 )
533 }
534 _ => {
536 let allowed_type = allowed_type.unwrap_or_else(|| {
537 value.actual_type.as_ref().clone()
538 });
539 Reference::ValueReference(Rc::new(RefCell::new(
540 ValueReference::new(
541 ValueContainer::Value(value),
542 maybe_pointer_id,
543 allowed_type,
544 mutability,
545 ),
546 )))
547 }
548 }
549 }
550 })
551 }
552
553 pub fn new_from_type(
554 type_value: Type,
555 maybe_pointer_address: Option<PointerAddress>,
556 maybe_nominal_type_declaration: Option<NominalTypeDeclaration>,
557 ) -> Self {
558 let type_reference = TypeReference {
559 pointer_address: maybe_pointer_address,
560 nominal_type_declaration: maybe_nominal_type_declaration,
561 type_value,
562 };
563 Reference::TypeReference(Rc::new(RefCell::new(type_reference)))
564 }
565
566 pub fn try_mut_from(
567 value_container: ValueContainer,
568 ) -> Result<Self, ReferenceCreationError> {
569 Reference::try_new_from_value_container(
570 value_container,
571 None,
572 None,
573 ReferenceMutability::Mutable,
574 )
575 }
576
577 pub fn collapse_reference_chain(&self) -> Reference {
579 match self {
580 Reference::TypeReference(tr) => Reference::TypeReference(Rc::new(
582 RefCell::new(tr.borrow().collapse_reference_chain()),
583 )),
584 Reference::ValueReference(vr) => {
585 match &vr.borrow().value_container {
586 ValueContainer::Reference(reference) => {
587 reference.collapse_reference_chain()
589 }
590 ValueContainer::Value(_) => {
591 self.clone()
593 }
594 }
595 }
596 }
597 }
598
599 pub fn collapse_to_value(&self) -> Rc<RefCell<Value>> {
601 let reference = self.collapse_reference_chain();
602 match reference {
603 Reference::ValueReference(vr) => match &vr.borrow().value_container
604 {
605 ValueContainer::Value(_) => {
606 vr.borrow().value_container.to_value()
607 }
608 ValueContainer::Reference(_) => unreachable!(
609 "Expected a ValueContainer::Value, but found a Reference"
610 ),
611 },
612 Reference::TypeReference(tr) => Rc::new(RefCell::new(Value::from(
614 CoreValue::Type(tr.borrow().type_value.clone()),
615 ))),
616 }
617 }
618
619 pub fn value_container(&self) -> ValueContainer {
621 match self {
622 Reference::ValueReference(vr) => {
623 vr.borrow().value_container.clone()
624 }
625 Reference::TypeReference(tr) => ValueContainer::Value(Value::from(
626 CoreValue::Type(tr.borrow().type_value.clone()),
627 )),
628 }
629 }
630
631 pub fn allowed_type(&self) -> TypeDefinition {
632 match self {
633 Reference::ValueReference(vr) => vr.borrow().allowed_type.clone(),
634 Reference::TypeReference(_) => core::todo!("#293 type Type"),
635 }
636 }
637
638 pub fn actual_type(&self) -> TypeDefinition {
639 match self {
640 Reference::ValueReference(vr) => vr
641 .borrow()
642 .value_container
643 .to_value()
644 .borrow()
645 .actual_type()
646 .clone(),
647 Reference::TypeReference(tr) => core::todo!("#294 type Type"),
648 }
649 }
650
651 pub fn is_type(&self) -> bool {
652 match self {
653 Reference::TypeReference(_) => true,
654 Reference::ValueReference(vr) => {
655 vr.borrow().resolve_current_value().borrow().is_type()
656 }
657 }
658 }
659
660 pub fn mutable_reference(&self) -> Option<Rc<RefCell<ValueReference>>> {
662 match self {
663 Reference::TypeReference(_) => None,
664 Reference::ValueReference(vr) => {
665 if vr.borrow().is_mutable() {
666 Some(vr.clone())
667 } else {
668 None
669 }
670 }
671 }
672 }
673
674 pub fn set_value_container(
677 &self,
678 new_value_container: ValueContainer,
679 ) -> Result<(), AssignmentError> {
680 match &self {
681 Reference::TypeReference(_) => {
682 Err(AssignmentError::ImmutableReference)
683 }
684 Reference::ValueReference(vr) => {
685 if self.is_mutable() {
686 vr.borrow_mut().value_container = new_value_container;
688 Ok(())
689 } else {
690 Err(AssignmentError::ImmutableReference)
691 }
692 }
693 }
694 }
695}
696impl Reference {
698 pub fn try_get_property<'a>(
706 &self,
707 key: impl Into<ValueKey<'a>>,
708 ) -> Result<ValueContainer, AccessError> {
709 self.with_value(|value| value.try_get_property(key))
710 .unwrap_or(Err(AccessError::InvalidOperation(
711 "Cannot get property on invalid reference".to_string(),
712 )))
713 }
714}
715
716impl Apply for Reference {
717 fn apply(
718 &self,
719 args: &[ValueContainer],
720 ) -> Result<Option<ValueContainer>, ExecutionError> {
721 match self {
722 Reference::TypeReference(tr) => tr.borrow().apply(args),
723 Reference::ValueReference(vr) => {
724 vr.borrow().resolve_current_value().borrow().apply(args)
725 }
726 }
727 }
728
729 fn apply_single(
730 &self,
731 arg: &ValueContainer,
732 ) -> Result<Option<ValueContainer>, ExecutionError> {
733 match self {
734 Reference::TypeReference(tr) => tr.borrow().apply_single(arg),
735 Reference::ValueReference(vr) => vr
736 .borrow()
737 .resolve_current_value()
738 .borrow()
739 .apply_single(arg),
740 }
741 }
742}
743
744#[cfg(test)]
745mod tests {
746 use super::*;
747 use crate::runtime::global_context::{GlobalContext, set_global_context};
748 use crate::runtime::memory::Memory;
749 use crate::stdlib::assert_matches::assert_matches;
750 use crate::traits::value_eq::ValueEq;
751 use crate::{assert_identical, assert_structural_eq, assert_value_eq};
752 use datex_core::values::core_values::map::Map;
753
754 #[test]
755 fn try_mut_from() {
756 let value = ValueContainer::from(42);
758 let reference = Reference::try_mut_from(value).unwrap();
759 assert_eq!(reference.mutability(), ReferenceMutability::Mutable);
760
761 let type_value = ValueContainer::Reference(Reference::TypeReference(
763 TypeReference::anonymous(Type::UNIT, None).as_ref_cell(),
764 ));
765 assert_matches!(
766 Reference::try_mut_from(type_value),
767 Err(ReferenceCreationError::MutableTypeReference)
768 );
769 }
770
771 #[test]
772 fn property() {
773 let mut map = Map::default();
774 map.set("name", ValueContainer::from("Jonas"));
775 map.set("age", ValueContainer::from(30));
776 let reference = Reference::from(ValueContainer::from(map));
777 assert_eq!(
778 reference.try_get_property("name").unwrap(),
779 ValueContainer::from("Jonas")
780 );
781 assert_eq!(
782 reference.try_get_property("age").unwrap(),
783 ValueContainer::from(30)
784 );
785 assert!(reference.try_get_property("nonexistent").is_err());
786 assert_matches!(
787 reference.try_get_property("nonexistent"),
788 Err(AccessError::KeyNotFound(_))
789 );
790 }
791
792 #[test]
793 fn text_property() {
794 let struct_val = Map::from(vec![
795 ("name".to_string(), ValueContainer::from("Jonas")),
796 ("age".to_string(), ValueContainer::from(30)),
797 ]);
798 let reference = Reference::from(ValueContainer::from(struct_val));
799 assert_eq!(
800 reference.try_get_property("name").unwrap(),
801 ValueContainer::from("Jonas")
802 );
803 assert_eq!(
804 reference.try_get_property("age").unwrap(),
805 ValueContainer::from(30)
806 );
807 assert!(reference.try_get_property("nonexistent").is_err());
808 assert_matches!(
809 reference.try_get_property("nonexistent"),
810 Err(AccessError::KeyNotFound(_))
811 );
812 }
813
814 #[test]
815 fn numeric_property() {
816 let list = vec![
817 ValueContainer::from(1),
818 ValueContainer::from(2),
819 ValueContainer::from(3),
820 ];
821 let reference = Reference::from(ValueContainer::from(list));
822
823 assert_eq!(
824 reference.try_get_property(0).unwrap(),
825 ValueContainer::from(1)
826 );
827 assert_eq!(
828 reference.try_get_property(1).unwrap(),
829 ValueContainer::from(2)
830 );
831 assert_eq!(
832 reference.try_get_property(2).unwrap(),
833 ValueContainer::from(3)
834 );
835 assert!(reference.try_get_property(3).is_err());
836
837 assert_matches!(
838 reference.try_get_property(100),
839 Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError {
840 index: 100
841 }))
842 );
843
844 let text_ref = Reference::from(ValueContainer::from("hello"));
845 assert_eq!(
846 text_ref.try_get_property(1).unwrap(),
847 ValueContainer::from("e".to_string())
848 );
849 assert!(text_ref.try_get_property(5).is_err());
850 assert_matches!(
851 text_ref.try_get_property(100),
852 Err(AccessError::IndexOutOfBounds(IndexOutOfBoundsError {
853 index: 100
854 }))
855 );
856 }
857
858 #[test]
859 fn reference_identity() {
860 let value = 42;
861 let reference1 = Reference::from(value);
862 let reference2 = reference1.clone();
863
864 assert_eq!(reference1, reference2);
866 assert_eq!(
868 ValueContainer::Reference(reference1.clone()),
869 ValueContainer::Reference(reference2.clone())
870 );
871 assert_identical!(reference1.clone(), reference2);
873 assert_ne!(reference1, Reference::from(value));
875 }
876
877 #[test]
878 fn reference_value_equality() {
879 let value = 42;
880 let reference1 = ValueContainer::Reference(Reference::from(value));
881 let reference2 = ValueContainer::Reference(Reference::from(value));
882
883 assert_ne!(reference1, reference2);
885 assert_value_eq!(reference1, ValueContainer::from(value));
887 }
888
889 #[test]
890 fn reference_structural_equality() {
891 let reference1 = Reference::from(42.0);
892 let reference2 = Reference::from(42);
893
894 assert_ne!(reference1, reference2);
896 assert!(!reference1.structural_eq(&reference2));
898 }
899
900 #[test]
901 fn nested_references() {
902 set_global_context(GlobalContext::native());
903 let memory = &RefCell::new(Memory::default());
904
905 let mut map_a = Map::default();
906 map_a.set("number", ValueContainer::from(42));
907 map_a.set("obj", ValueContainer::new_reference(Map::default()));
908
909 let map_a_original_ref = ValueContainer::new_reference(map_a);
911
912 let map_b_ref = Reference::try_new_from_value_container(
914 Map::default().into(),
915 None,
916 None,
917 ReferenceMutability::Mutable,
918 )
919 .unwrap();
920
921 map_b_ref
924 .try_set_property(0, memory, "a", map_a_original_ref.clone())
925 .unwrap();
926
927 let map_a_ref = map_b_ref.try_get_property("a").unwrap();
929 assert_structural_eq!(map_a_ref, map_a_original_ref);
930 assert_eq!(map_a_ref, map_a_original_ref);
931 assert_identical!(map_a_ref, map_a_original_ref);
932 assert_matches!(map_a_ref, ValueContainer::Reference(_));
934 map_a_ref.with_maybe_reference(|a_ref| {
935 assert_matches!(
937 a_ref.try_get_property("number"),
938 Ok(ValueContainer::Value(_))
939 );
940 assert_matches!(
942 a_ref.try_get_property("obj"),
943 Ok(ValueContainer::Reference(_))
944 );
945 });
946 }
947}