datex_core/values/
value_container.rs

1use crate::values::traits::identity::Identity;
2use crate::values::traits::structural_eq::StructuralEq;
3use std::cell::RefCell;
4
5use super::{reference::Reference, value::Value};
6use crate::values::traits::value_eq::ValueEq;
7use std::fmt::Display;
8use std::hash::Hash;
9use std::ops::{Add, Sub};
10use std::rc::Rc;
11use serde::{Deserialize, Serialize};
12use crate::compiler::compile_value;
13use crate::values::serde::deserializer::DatexDeserializer;
14
15#[derive(Debug, Clone, PartialEq)]
16pub enum ValueError {
17    IsVoid,
18    InvalidOperation,
19    IntegerOverflow,
20    TypeConversionError,
21}
22
23impl Display for ValueError {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        match self {
26            ValueError::IsVoid => write!(f, "Value is void"),
27            ValueError::InvalidOperation => {
28                write!(f, "Invalid operation on value")
29            }
30            ValueError::TypeConversionError => {
31                write!(f, "Type conversion error")
32            }
33            ValueError::IntegerOverflow => {
34                write!(f, "Integer overflow occurred")
35            }
36        }
37    }
38}
39
40#[derive(Clone, Debug, Eq)]
41pub enum ValueContainer {
42    Value(Value),
43    Reference(Reference),
44}
45
46impl Serialize for ValueContainer {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: serde::Serializer,
50    {
51        serializer.serialize_newtype_struct("value", &compile_value(self).unwrap())
52    }
53}
54
55impl<'a> Deserialize<'a> for ValueContainer {
56    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57    where
58        D: serde::Deserializer<'a>,
59    {
60        let deserializer: &DatexDeserializer = unsafe {
61            &*(&deserializer as *const D as *const DatexDeserializer)
62        };
63        
64        Ok(deserializer.value.clone())
65    }
66}
67
68
69impl Hash for ValueContainer {
70    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
71        match self {
72            ValueContainer::Value(value) => value.hash(state),
73            ValueContainer::Reference(pointer) => pointer.hash(state),
74        }
75    }
76}
77
78/// Partial equality for ValueContainer is identical to Hash behavior:
79/// Identical references are partially equal, value-equal values are also partially equal.
80/// A pointer and a value are never partially equal.
81impl PartialEq for ValueContainer {
82    fn eq(&self, other: &Self) -> bool {
83        match (self, other) {
84            (ValueContainer::Value(a), ValueContainer::Value(b)) => a == b,
85            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
86                a == b
87            }
88            _ => false,
89        }
90    }
91}
92
93/// Structural equality checks the structural equality of the underlying values, collapsing
94/// references to their current resolved values.
95impl StructuralEq for ValueContainer {
96    fn structural_eq(&self, other: &Self) -> bool {
97        match (self, other) {
98            (ValueContainer::Value(a), ValueContainer::Value(b)) => {
99                a.structural_eq(b)
100            }
101            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
102                a.structural_eq(b)
103            }
104            (ValueContainer::Value(a), ValueContainer::Reference(b))
105            | (ValueContainer::Reference(b), ValueContainer::Value(a)) => {
106                a.structural_eq(&b.borrow().current_resolved_value().borrow())
107            }
108        }
109    }
110}
111
112/// Value equality checks the value equality of the underlying values, collapsing
113/// references to their current resolved values.
114impl ValueEq for ValueContainer {
115    fn value_eq(&self, other: &Self) -> bool {
116        match (self, other) {
117            (ValueContainer::Value(a), ValueContainer::Value(b)) => {
118                a.value_eq(b)
119            }
120            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
121                a.value_eq(b)
122            }
123            (ValueContainer::Value(a), ValueContainer::Reference(b))
124            | (ValueContainer::Reference(b), ValueContainer::Value(a)) => {
125                a.value_eq(&b.borrow().current_resolved_value().borrow())
126            }
127        }
128    }
129}
130
131/// Identity checks only returns true if two references are identical.
132/// Values are never identical to references or other values.
133impl Identity for ValueContainer {
134    fn identical(&self, other: &Self) -> bool {
135        match (self, other) {
136            (ValueContainer::Value(_), ValueContainer::Value(_)) => false,
137            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
138                a.identical(b)
139            }
140            _ => false,
141        }
142    }
143}
144
145impl Display for ValueContainer {
146    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147        match self {
148            ValueContainer::Value(value) => write!(f, "{value}"),
149            // TODO #118: only simple temporary way to distinguish between Value and Pointer
150            ValueContainer::Reference(pointer) => {
151                write!(
152                    f,
153                    "$({})",
154                    pointer.borrow().current_resolved_value().borrow()
155                )
156            }
157        }
158    }
159}
160
161impl ValueContainer {
162    pub fn to_value(&self) -> Rc<RefCell<Value>> {
163        match self {
164            ValueContainer::Value(value) => {
165                Rc::new(RefCell::new(value.clone()))
166            }
167            ValueContainer::Reference(pointer) => {
168                let reference = pointer.0.clone();
169
170                reference.borrow().value_container.to_value()
171            }
172        }
173    }
174}
175
176impl<T: Into<Value>> From<T> for ValueContainer {
177    fn from(value: T) -> Self {
178        ValueContainer::Value(value.into())
179    }
180}
181
182impl Add<ValueContainer> for ValueContainer {
183    type Output = Result<ValueContainer, ValueError>;
184
185    fn add(self, rhs: ValueContainer) -> Self::Output {
186        match (self, rhs) {
187            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
188                (lhs + rhs).map(ValueContainer::Value)
189            }
190            (
191                ValueContainer::Reference(lhs),
192                ValueContainer::Reference(rhs),
193            ) => {
194                let lhs_value =
195                    lhs.borrow().current_resolved_value().borrow().clone();
196                let rhs_value =
197                    rhs.borrow().current_resolved_value().borrow().clone();
198                (lhs_value + rhs_value).map(ValueContainer::Value)
199            }
200            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
201                let rhs_value =
202                    rhs.borrow().current_resolved_value().borrow().clone();
203                (lhs + rhs_value).map(ValueContainer::Value)
204            }
205            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
206                let lhs_value =
207                    lhs.borrow().current_resolved_value().borrow().clone();
208                (lhs_value + rhs).map(ValueContainer::Value)
209            }
210        }
211    }
212}
213
214impl Add<&ValueContainer> for &ValueContainer {
215    type Output = Result<ValueContainer, ValueError>;
216
217    fn add(self, rhs: &ValueContainer) -> Self::Output {
218        match (self, rhs) {
219            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
220                (lhs + rhs).map(ValueContainer::Value)
221            }
222            (
223                ValueContainer::Reference(lhs),
224                ValueContainer::Reference(rhs),
225            ) => {
226                let lhs_value =
227                    lhs.borrow().current_resolved_value().borrow().clone();
228                let rhs_value =
229                    rhs.borrow().current_resolved_value().borrow().clone();
230                (lhs_value + rhs_value).map(ValueContainer::Value)
231            }
232            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
233                let rhs_value =
234                    rhs.borrow().current_resolved_value().borrow().clone();
235                (lhs + &rhs_value).map(ValueContainer::Value)
236            }
237            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
238                let lhs_value =
239                    lhs.borrow().current_resolved_value().borrow().clone();
240                (&lhs_value + rhs).map(ValueContainer::Value)
241            }
242        }
243    }
244}
245
246impl Sub<ValueContainer> for ValueContainer {
247    type Output = Result<ValueContainer, ValueError>;
248
249    fn sub(self, rhs: ValueContainer) -> Self::Output {
250        match (self, rhs) {
251            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
252                (lhs - rhs).map(ValueContainer::Value)
253            }
254            (
255                ValueContainer::Reference(lhs),
256                ValueContainer::Reference(rhs),
257            ) => {
258                let lhs_value =
259                    lhs.borrow().current_resolved_value().borrow().clone();
260                let rhs_value =
261                    rhs.borrow().current_resolved_value().borrow().clone();
262                (lhs_value - rhs_value).map(ValueContainer::Value)
263            }
264            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
265                let rhs_value =
266                    rhs.borrow().current_resolved_value().borrow().clone();
267                (lhs - rhs_value).map(ValueContainer::Value)
268            }
269            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
270                let lhs_value =
271                    lhs.borrow().current_resolved_value().borrow().clone();
272                (lhs_value - rhs).map(ValueContainer::Value)
273            }
274        }
275    }
276}
277
278impl Sub<&ValueContainer> for &ValueContainer {
279    type Output = Result<ValueContainer, ValueError>;
280
281    fn sub(self, rhs: &ValueContainer) -> Self::Output {
282        match (self, rhs) {
283            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
284                (lhs - rhs).map(ValueContainer::Value)
285            }
286            (
287                ValueContainer::Reference(lhs),
288                ValueContainer::Reference(rhs),
289            ) => {
290                let lhs_value =
291                    lhs.borrow().current_resolved_value().borrow().clone();
292                let rhs_value =
293                    rhs.borrow().current_resolved_value().borrow().clone();
294                (lhs_value - rhs_value).map(ValueContainer::Value)
295            }
296            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
297                let rhs_value =
298                    rhs.borrow().current_resolved_value().borrow().clone();
299                (lhs - &rhs_value).map(ValueContainer::Value)
300            }
301            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
302                let lhs_value =
303                    lhs.borrow().current_resolved_value().borrow().clone();
304                (&lhs_value - rhs).map(ValueContainer::Value)
305            }
306        }
307    }
308}