datex_core/values/
value_container.rs

1use crate::traits::identity::Identity;
2use crate::traits::structural_eq::StructuralEq;
3use core::cell::RefCell;
4use core::prelude::rust_2024::*;
5use core::result::Result;
6
7use super::value::Value;
8use crate::references::mutations::DIFUpdateDataOrMemory;
9use crate::references::observers::TransceiverId;
10use crate::references::reference::{AccessError, Reference};
11use crate::runtime::execution::ExecutionError;
12use crate::serde::deserializer::DatexDeserializer;
13use crate::stdlib::borrow::Cow;
14use crate::stdlib::boxed::Box;
15use crate::stdlib::rc::Rc;
16use crate::stdlib::string::String;
17use crate::traits::apply::Apply;
18use crate::traits::value_eq::ValueEq;
19use crate::types::definition::TypeDefinition;
20use crate::values::core_value::CoreValue;
21use crate::values::core_values::r#type::Type;
22use core::fmt::Display;
23use core::hash::{Hash, Hasher};
24use core::ops::FnOnce;
25use core::ops::{Add, Neg, Sub};
26use serde::Deserialize;
27
28#[derive(Debug, Clone, PartialEq)]
29pub enum ValueError {
30    IsVoid,
31    InvalidOperation,
32    IntegerOverflow,
33    TypeConversionError,
34}
35
36impl Display for ValueError {
37    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38        match self {
39            ValueError::IsVoid => core::write!(f, "Value is void"),
40            ValueError::InvalidOperation => {
41                core::write!(f, "Invalid operation on value")
42            }
43            ValueError::TypeConversionError => {
44                core::write!(f, "Type conversion error")
45            }
46            ValueError::IntegerOverflow => {
47                core::write!(f, "Integer overflow occurred")
48            }
49        }
50    }
51}
52
53#[derive(Clone, Debug, PartialEq, Eq, Hash)]
54pub enum ValueKey<'a> {
55    Text(Cow<'a, str>),
56    Index(i64),
57    Value(Cow<'a, ValueContainer>),
58}
59
60impl<'a> ValueKey<'a> {
61    pub fn with_value_container<R>(
62        &self,
63        callback: impl FnOnce(&ValueContainer) -> R,
64    ) -> R {
65        match self {
66            ValueKey::Value(value_container) => callback(value_container),
67            ValueKey::Text(text) => {
68                let value_container = ValueContainer::new_value(text.as_ref());
69                callback(&value_container)
70            }
71            ValueKey::Index(index) => {
72                let value_container = ValueContainer::new_value(*index);
73                callback(&value_container)
74            }
75        }
76    }
77}
78
79impl<'a> Display for ValueKey<'a> {
80    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
81        match self {
82            ValueKey::Text(text) => core::write!(f, "{}", text),
83            ValueKey::Index(index) => core::write!(f, "{}", index),
84            ValueKey::Value(value_container) => {
85                core::write!(f, "{}", value_container)
86            }
87        }
88    }
89}
90
91impl<'a> From<&'a String> for ValueKey<'a> {
92    fn from(text: &'a String) -> Self {
93        ValueKey::Text(Cow::from(text))
94    }
95}
96
97impl<'a> From<&'a str> for ValueKey<'a> {
98    fn from(text: &'a str) -> Self {
99        ValueKey::Text(Cow::from(text))
100    }
101}
102
103impl<'a> From<i64> for ValueKey<'a> {
104    fn from(index: i64) -> Self {
105        ValueKey::Index(index)
106    }
107}
108
109impl<'a> From<u32> for ValueKey<'a> {
110    fn from(index: u32) -> Self {
111        ValueKey::Index(index as i64)
112    }
113}
114
115impl<'a> From<i32> for ValueKey<'a> {
116    fn from(index: i32) -> Self {
117        ValueKey::Index(index as i64)
118    }
119}
120
121impl<'a> From<&'a ValueContainer> for ValueKey<'a> {
122    fn from(value_container: &'a ValueContainer) -> Self {
123        ValueKey::Value(Cow::Borrowed(value_container))
124    }
125}
126
127impl<'a> ValueKey<'a> {
128    pub fn try_as_text(&self) -> Option<&str> {
129        if let ValueKey::Text(text) = self {
130            Some(text)
131        } else if let ValueKey::Value(val) = self
132            && let ValueContainer::Value(Value {
133                inner: CoreValue::Text(text),
134                ..
135            }) = val.as_ref()
136        {
137            Some(&text.0)
138        } else {
139            None
140        }
141    }
142
143    pub fn try_as_index(&self) -> Option<i64> {
144        if let ValueKey::Index(index) = self {
145            Some(*index)
146        } else if let ValueKey::Value(value) = self
147            && let ValueContainer::Value(Value {
148                inner: CoreValue::Integer(index),
149                ..
150            }) = value.as_ref()
151        {
152            index.as_i64()
153        } else if let ValueKey::Value(value) = self
154            && let ValueContainer::Value(Value {
155                inner: CoreValue::TypedInteger(index),
156                ..
157            }) = value.as_ref()
158        {
159            index.as_i64()
160        } else {
161            None
162        }
163    }
164}
165
166impl<'a> From<ValueKey<'a>> for ValueContainer {
167    fn from(value_key: ValueKey) -> Self {
168        match value_key {
169            ValueKey::Text(text) => {
170                ValueContainer::new_value(text.into_owned())
171            }
172            ValueKey::Index(index) => ValueContainer::new_value(index),
173            ValueKey::Value(value_container) => value_container.into_owned(),
174        }
175    }
176}
177
178#[derive(Debug)]
179pub enum OwnedValueKey {
180    Text(String),
181    Index(i64),
182    Value(ValueContainer),
183}
184
185impl<'a> From<OwnedValueKey> for ValueKey<'a> {
186    fn from(owned: OwnedValueKey) -> Self {
187        match owned {
188            OwnedValueKey::Text(text) => ValueKey::Text(Cow::Owned(text)),
189            OwnedValueKey::Index(index) => ValueKey::Index(index),
190            OwnedValueKey::Value(value_container) => {
191                ValueKey::Value(Cow::Owned(value_container))
192            }
193        }
194    }
195}
196
197#[derive(Clone, Debug, Eq)]
198pub enum ValueContainer {
199    Value(Value),
200    Reference(Reference),
201}
202
203impl<'a> Deserialize<'a> for ValueContainer {
204    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
205    where
206        D: serde::Deserializer<'a>,
207    {
208        let deserializer: &DatexDeserializer = unsafe {
209            &*(&deserializer as *const D as *const DatexDeserializer)
210        };
211
212        Ok(deserializer.value.clone())
213    }
214}
215
216impl Hash for ValueContainer {
217    fn hash<H: Hasher>(&self, state: &mut H) {
218        match self {
219            ValueContainer::Value(value) => value.hash(state),
220            ValueContainer::Reference(pointer) => pointer.hash(state),
221        }
222    }
223}
224
225/// Partial equality for ValueContainer is identical to Hash behavior:
226/// Identical references are partially equal, value-equal values are also partially equal.
227/// A pointer and a value are never partially equal.
228impl PartialEq for ValueContainer {
229    fn eq(&self, other: &Self) -> bool {
230        match (self, other) {
231            (ValueContainer::Value(a), ValueContainer::Value(b)) => a == b,
232            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
233                a == b
234            }
235            _ => false,
236        }
237    }
238}
239
240/// Structural equality checks the structural equality of the underlying values, collapsing
241/// references to their current resolved values.
242impl StructuralEq for ValueContainer {
243    fn structural_eq(&self, other: &Self) -> bool {
244        match (self, other) {
245            (ValueContainer::Value(a), ValueContainer::Value(b)) => {
246                a.structural_eq(b)
247            }
248            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
249                a.structural_eq(b)
250            }
251            (ValueContainer::Value(a), ValueContainer::Reference(b))
252            | (ValueContainer::Reference(b), ValueContainer::Value(a)) => {
253                a.structural_eq(&b.collapse_to_value().borrow())
254            }
255        }
256    }
257}
258
259/// Value equality checks the value equality of the underlying values, collapsing
260/// references to their current resolved values.
261impl ValueEq for ValueContainer {
262    fn value_eq(&self, other: &Self) -> bool {
263        match (self, other) {
264            (ValueContainer::Value(a), ValueContainer::Value(b)) => {
265                a.value_eq(b)
266            }
267            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
268                a.value_eq(b)
269            }
270            (ValueContainer::Value(a), ValueContainer::Reference(b))
271            | (ValueContainer::Reference(b), ValueContainer::Value(a)) => {
272                a.value_eq(&b.collapse_to_value().borrow())
273            }
274        }
275    }
276}
277
278/// Identity checks only returns true if two references are identical.
279/// Values are never identical to references or other values.
280impl Identity for ValueContainer {
281    fn identical(&self, other: &Self) -> bool {
282        match (self, other) {
283            (ValueContainer::Value(_), ValueContainer::Value(_)) => false,
284            (ValueContainer::Reference(a), ValueContainer::Reference(b)) => {
285                a.identical(b)
286            }
287            _ => false,
288        }
289    }
290}
291
292impl Display for ValueContainer {
293    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
294        match self {
295            ValueContainer::Value(value) => core::write!(f, "{value}"),
296            // TODO #118: only simple temporary way to distinguish between Value and Pointer
297            ValueContainer::Reference(reference) => {
298                core::write!(f, "&({})", reference.collapse_to_value().borrow())
299            }
300        }
301    }
302}
303
304impl ValueContainer {
305    pub fn to_value(&self) -> Rc<RefCell<Value>> {
306        match self {
307            ValueContainer::Value(value) => {
308                Rc::new(RefCell::new(value.clone()))
309            }
310            ValueContainer::Reference(pointer) => pointer.collapse_to_value(),
311        }
312    }
313
314    pub fn is_type(&self) -> bool {
315        match self {
316            ValueContainer::Value(value) => value.is_type(),
317            ValueContainer::Reference(reference) => reference.is_type(),
318        }
319    }
320
321    /// Returns the actual type of the contained value, resolving references if necessary.
322    pub fn actual_value_type(&self) -> TypeDefinition {
323        match self {
324            ValueContainer::Value(value) => value.actual_type().clone(),
325            ValueContainer::Reference(reference) => {
326                reference.actual_type().clone()
327            }
328        }
329    }
330
331    /// Returns the actual type that describes the value container (e.g. integer or &&mut integer).
332    pub fn actual_container_type(&self) -> Type {
333        match self {
334            ValueContainer::Value(value) => {
335                Type::new(*value.actual_type.clone(), None)
336            }
337            ValueContainer::Reference(reference) => {
338                let inner_type =
339                    reference.value_container().actual_container_type();
340                Type::new(
341                    // when nesting references, we need to keep the reference information
342                    if inner_type.is_reference_type() {
343                        TypeDefinition::Type(Box::new(inner_type))
344                    }
345                    // for simple non-ref type, we can collapse the definition
346                    else {
347                        inner_type.type_definition
348                    },
349                    Some(reference.mutability()),
350                )
351            }
352        }
353    }
354
355    pub fn new_value<T: Into<Value>>(value: T) -> ValueContainer {
356        ValueContainer::Value(value.into())
357    }
358
359    pub fn new_reference<T: Into<Reference>>(value: T) -> ValueContainer {
360        ValueContainer::Reference(value.into())
361    }
362
363    /// Returns the contained Reference if it is a Reference, otherwise returns None.
364    pub fn maybe_reference(&self) -> Option<&Reference> {
365        if let ValueContainer::Reference(reference) = self {
366            Some(reference)
367        } else {
368            None
369        }
370    }
371
372    /// Runs a closure with the contained Reference if it is a Reference, otherwise returns None.
373    pub fn with_maybe_reference<F, R>(&self, f: F) -> Option<R>
374    where
375        F: FnOnce(&Reference) -> R,
376    {
377        if let ValueContainer::Reference(reference) = self {
378            Some(f(reference))
379        } else {
380            None
381        }
382    }
383
384    /// Returns a reference to the contained Reference, panics if it is not a Reference.
385    pub fn reference_unchecked(&self) -> &Reference {
386        match self {
387            ValueContainer::Reference(reference) => reference,
388            _ => core::panic!("Cannot convert ValueContainer to Reference"),
389        }
390    }
391
392    /// Tries to get a property from the contained Value or Reference.
393    pub fn try_get_property<'a>(
394        &self,
395        key: impl Into<ValueKey<'a>>,
396    ) -> Result<ValueContainer, AccessError> {
397        match self {
398            ValueContainer::Value(value) => value.try_get_property(key),
399            ValueContainer::Reference(reference) => {
400                reference.try_get_property(key)
401            }
402        }
403    }
404
405    pub fn try_set_property<'a>(
406        &mut self,
407        source_id: TransceiverId,
408        dif_update_data_or_memory: impl Into<DIFUpdateDataOrMemory<'a>>,
409        key: impl Into<ValueKey<'a>>,
410        val: ValueContainer,
411    ) -> Result<(), AccessError> {
412        match self {
413            ValueContainer::Value(v) => v.try_set_property(key, val),
414            ValueContainer::Reference(r) => r.try_set_property(
415                source_id,
416                dif_update_data_or_memory,
417                key,
418                val,
419            ),
420        }
421    }
422}
423
424impl Apply for ValueContainer {
425    fn apply(
426        &self,
427        args: &[ValueContainer],
428    ) -> Result<Option<ValueContainer>, ExecutionError> {
429        match self {
430            ValueContainer::Value(value) => value.apply(args),
431            ValueContainer::Reference(reference) => reference.apply(args),
432        }
433    }
434
435    fn apply_single(
436        &self,
437        arg: &ValueContainer,
438    ) -> Result<Option<ValueContainer>, ExecutionError> {
439        match self {
440            ValueContainer::Value(value) => value.apply_single(arg),
441            ValueContainer::Reference(reference) => reference.apply_single(arg),
442        }
443    }
444}
445
446impl<T: Into<Value>> From<T> for ValueContainer {
447    fn from(value: T) -> Self {
448        ValueContainer::Value(value.into())
449    }
450}
451
452impl Add<ValueContainer> for ValueContainer {
453    type Output = Result<ValueContainer, ValueError>;
454
455    fn add(self, rhs: ValueContainer) -> Self::Output {
456        match (self, rhs) {
457            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
458                (lhs + rhs).map(ValueContainer::Value)
459            }
460            (
461                ValueContainer::Reference(lhs),
462                ValueContainer::Reference(rhs),
463            ) => {
464                let lhs_value = lhs.collapse_to_value().borrow().clone();
465                let rhs_value = rhs.collapse_to_value().borrow().clone();
466                (lhs_value + rhs_value).map(ValueContainer::Value)
467            }
468            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
469                let rhs_value = rhs.collapse_to_value().borrow().clone();
470                (lhs + rhs_value).map(ValueContainer::Value)
471            }
472            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
473                let lhs_value = lhs.collapse_to_value().borrow().clone();
474                (lhs_value + rhs).map(ValueContainer::Value)
475            }
476        }
477    }
478}
479
480impl Add<&ValueContainer> for &ValueContainer {
481    type Output = Result<ValueContainer, ValueError>;
482
483    fn add(self, rhs: &ValueContainer) -> Self::Output {
484        match (self, rhs) {
485            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
486                (lhs + rhs).map(ValueContainer::Value)
487            }
488            (
489                ValueContainer::Reference(lhs),
490                ValueContainer::Reference(rhs),
491            ) => {
492                let lhs_value = lhs.collapse_to_value().borrow().clone();
493                let rhs_value = rhs.collapse_to_value().borrow().clone();
494                (lhs_value + rhs_value).map(ValueContainer::Value)
495            }
496            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
497                let rhs_value = rhs.collapse_to_value().borrow().clone();
498                (lhs + &rhs_value).map(ValueContainer::Value)
499            }
500            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
501                let lhs_value = lhs.collapse_to_value().borrow().clone();
502                (&lhs_value + rhs).map(ValueContainer::Value)
503            }
504        }
505    }
506}
507
508impl Sub<ValueContainer> for ValueContainer {
509    type Output = Result<ValueContainer, ValueError>;
510
511    fn sub(self, rhs: ValueContainer) -> Self::Output {
512        match (self, rhs) {
513            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
514                (lhs - rhs).map(ValueContainer::Value)
515            }
516            (
517                ValueContainer::Reference(lhs),
518                ValueContainer::Reference(rhs),
519            ) => {
520                let lhs_value = lhs.collapse_to_value().borrow().clone();
521                let rhs_value = rhs.collapse_to_value().borrow().clone();
522                (lhs_value - rhs_value).map(ValueContainer::Value)
523            }
524            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
525                let rhs_value = rhs.collapse_to_value().borrow().clone();
526                (lhs - rhs_value).map(ValueContainer::Value)
527            }
528            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
529                let lhs_value = lhs.collapse_to_value().borrow().clone();
530                (lhs_value - rhs).map(ValueContainer::Value)
531            }
532        }
533    }
534}
535
536impl Sub<&ValueContainer> for &ValueContainer {
537    type Output = Result<ValueContainer, ValueError>;
538
539    fn sub(self, rhs: &ValueContainer) -> Self::Output {
540        match (self, rhs) {
541            (ValueContainer::Value(lhs), ValueContainer::Value(rhs)) => {
542                (lhs - rhs).map(ValueContainer::Value)
543            }
544            (
545                ValueContainer::Reference(lhs),
546                ValueContainer::Reference(rhs),
547            ) => {
548                let lhs_value = lhs.collapse_to_value().borrow().clone();
549                let rhs_value = rhs.collapse_to_value().borrow().clone();
550                (lhs_value - rhs_value).map(ValueContainer::Value)
551            }
552            (ValueContainer::Value(lhs), ValueContainer::Reference(rhs)) => {
553                let rhs_value = rhs.collapse_to_value().borrow().clone();
554                (lhs - &rhs_value).map(ValueContainer::Value)
555            }
556            (ValueContainer::Reference(lhs), ValueContainer::Value(rhs)) => {
557                let lhs_value = lhs.collapse_to_value().borrow().clone();
558                (&lhs_value - rhs).map(ValueContainer::Value)
559            }
560        }
561    }
562}
563
564impl Neg for ValueContainer {
565    type Output = Result<ValueContainer, ValueError>;
566
567    fn neg(self) -> Self::Output {
568        match self {
569            ValueContainer::Value(value) => (-value).map(ValueContainer::Value),
570            ValueContainer::Reference(reference) => {
571                let value = reference.collapse_to_value().borrow().clone(); // FIXME #311: Avoid clone
572                (-value).map(ValueContainer::Value)
573            }
574        }
575    }
576}