datex_core/values/
reference.rs1use super::datex_type::CoreValueType;
2use crate::values::pointer::Pointer;
3use crate::values::traits::identity::Identity;
4use crate::values::traits::structural_eq::StructuralEq;
5use crate::values::traits::value_eq::ValueEq;
6use crate::values::value::Value;
7use crate::values::value_container::ValueContainer;
8use std::cell::RefCell;
9use std::hash::{Hash, Hasher};
10use std::ops::Deref;
11use std::rc::Rc;
12
13#[derive(Clone, Debug, Eq)]
14pub struct Reference(pub Rc<RefCell<ReferenceData>>);
15
16impl Identity for Reference {
18 fn identical(&self, other: &Self) -> bool {
19 Rc::ptr_eq(&self.0, &other.0)
20 }
21}
22
23impl PartialEq for Reference {
25 fn eq(&self, other: &Self) -> bool {
26 self.identical(other)
27 }
28}
29
30impl StructuralEq for Reference {
31 fn structural_eq(&self, other: &Self) -> bool {
32 self.borrow()
34 .current_resolved_value()
35 .borrow()
36 .structural_eq(&other.borrow().current_resolved_value().borrow())
37 }
38}
39
40impl ValueEq for Reference {
41 fn value_eq(&self, other: &Self) -> bool {
42 self.borrow()
44 .current_resolved_value()
45 .borrow()
46 .value_eq(&other.borrow().current_resolved_value().borrow())
47 }
48}
49
50impl Hash for Reference {
51 fn hash<H: Hasher>(&self, state: &mut H) {
52 let ptr = Rc::as_ptr(&self.0); ptr.hash(state); }
55}
56
57impl<T: Into<ValueContainer>> From<T> for Reference {
58 fn from(value_container: T) -> Self {
59 let value_container = value_container.into();
60 let allowed_type =
61 value_container.to_value().borrow().actual_type.clone();
62 Reference(Rc::new(RefCell::new(ReferenceData {
63 value_container,
64 pointer: None,
65 allowed_type,
66 })))
67 }
68}
69
70impl Deref for Reference {
72 type Target = RefCell<ReferenceData>;
73
74 fn deref(&self) -> &Self::Target {
75 &self.0
76 }
77}
78
79#[derive(Debug, PartialEq, Eq, Hash)]
80pub struct ReferenceData {
81 pub value_container: ValueContainer,
83 pointer: Option<Pointer>,
86 pub allowed_type: CoreValueType,
88}
89
90impl ReferenceData {
91 pub fn pointer_id(&self) -> Option<u64> {
92 self.pointer.as_ref().map(|p| p.pointer_id())
93 }
94
95 pub fn current_value_container(&self) -> &ValueContainer {
96 &self.value_container
97 }
98
99 pub fn current_resolved_value(&self) -> Rc<RefCell<Value>> {
100 self.value_container.to_value()
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107 use crate::values::traits::value_eq::ValueEq;
108 use crate::{assert_identical, assert_value_eq};
109
110 #[test]
111 fn test_reference_identity() {
112 let value = 42;
113 let reference1 = Reference::from(value);
114 let reference2 = reference1.clone();
115
116 assert_eq!(reference1, reference2);
118 assert_eq!(
120 ValueContainer::Reference(reference1.clone()),
121 ValueContainer::Reference(reference2.clone())
122 );
123 assert_identical!(reference1.clone(), reference2);
125 assert_ne!(reference1, Reference::from(value));
127 }
128
129 #[test]
130 fn test_reference_value_equality() {
131 let value = 42;
132 let reference1 = ValueContainer::Reference(Reference::from(value));
133 let reference2 = ValueContainer::Reference(Reference::from(value));
134
135 assert_ne!(reference1, reference2);
137 assert_value_eq!(reference1, ValueContainer::from(value));
139 }
140
141 #[test]
142 fn test_reference_structural_equality() {
143 let reference1 = Reference::from(42.0);
144 let reference2 = Reference::from(42);
145
146 assert_ne!(reference1, reference2);
148 assert!(!reference1.structural_eq(&reference2));
150 }
151}