Skip to main content

datex_core/values/
value_container.rs

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