1use crate::{
2 libs::core::CoreLibPointerId,
3 prelude::*,
4 references::{reference::AccessError, type_reference::TypeReference},
5 runtime::execution::ExecutionError,
6 traits::{apply::Apply, structural_eq::StructuralEq, value_eq::ValueEq},
7 types::definition::TypeDefinition,
8 values::{
9 core_value::CoreValue,
10 core_values::{
11 callable::{Callable, CallableBody, CallableSignature},
12 integer::typed_integer::TypedInteger,
13 },
14 value_container::{ValueContainer, ValueError, ValueKey},
15 },
16};
17
18use core::{
19 fmt::{Display, Formatter},
20 ops::{Add, AddAssign, Deref, Neg, Not, Sub},
21 result::Result,
22};
23use log::error;
24
25#[derive(Clone, Debug, Eq, PartialEq, Hash)]
26pub struct Value {
27 pub inner: CoreValue,
28 pub actual_type: Box<TypeDefinition>,
29}
30
31impl StructuralEq for Value {
34 fn structural_eq(&self, other: &Self) -> bool {
35 self.inner.structural_eq(&other.inner)
36 }
37}
38
39impl ValueEq for Value {
42 fn value_eq(&self, other: &Self) -> bool {
43 self == other
44 }
45}
46
47impl Deref for Value {
48 type Target = CoreValue;
49
50 fn deref(&self) -> &Self::Target {
51 &self.inner
52 }
53}
54
55impl Apply for Value {
56 fn apply(
57 &self,
58 args: &[ValueContainer],
59 ) -> Result<Option<ValueContainer>, ExecutionError> {
60 match self.inner {
61 CoreValue::Callable(ref callable) => callable.apply(args),
62 _ => Err(ExecutionError::InvalidApply),
63 }
64 }
65 fn apply_single(
66 &self,
67 arg: &ValueContainer,
68 ) -> Result<Option<ValueContainer>, ExecutionError> {
69 match self.inner {
70 CoreValue::Callable(ref callable) => callable.apply_single(arg),
71 _ => Err(ExecutionError::InvalidApply),
72 }
73 }
74}
75
76impl<T: Into<CoreValue>> From<T> for Value {
77 fn from(inner: T) -> Self {
78 let inner = inner.into();
79 let new_type = inner.default_type_definition();
80 Value {
81 inner,
82 actual_type: Box::new(new_type),
83 }
84 }
85}
86impl Value {
87 pub fn null() -> Self {
88 CoreValue::Null.into()
89 }
90}
91
92impl Value {
93 pub fn callable(
94 name: Option<String>,
95 signature: CallableSignature,
96 body: CallableBody,
97 ) -> Self {
98 Value {
99 inner: CoreValue::Callable(Callable {
100 name,
101 signature: signature.clone(),
102 body,
103 }),
104 actual_type: Box::new(TypeDefinition::callable(signature)),
105 }
106 }
107
108 pub fn is_type(&self) -> bool {
109 core::matches!(self.inner, CoreValue::Type(_))
110 }
111 pub fn is_null(&self) -> bool {
112 core::matches!(self.inner, CoreValue::Null)
113 }
114 pub fn is_text(&self) -> bool {
115 core::matches!(self.inner, CoreValue::Text(_))
116 }
117 pub fn is_integer_i8(&self) -> bool {
118 core::matches!(
119 &self.inner,
120 CoreValue::TypedInteger(TypedInteger::I8(_))
121 )
122 }
123 pub fn is_bool(&self) -> bool {
124 core::matches!(self.inner, CoreValue::Boolean(_))
125 }
126 pub fn is_map(&self) -> bool {
127 core::matches!(self.inner, CoreValue::Map(_))
128 }
129 pub fn is_list(&self) -> bool {
130 core::matches!(self.inner, CoreValue::List(_))
131 }
132 pub fn actual_type(&self) -> &TypeDefinition {
133 self.actual_type.as_ref()
134 }
135
136 pub fn has_default_type(&self) -> bool {
146 if let TypeDefinition::Reference(type_reference) =
147 self.actual_type.as_ref()
148 && let TypeReference {
149 pointer_address: Some(pointer_address),
150 ..
151 } = &*type_reference.borrow()
152 && let Ok(actual_type_core_ptr_id) =
153 CoreLibPointerId::try_from(pointer_address)
154 {
155 let self_default_type_ptr_id = CoreLibPointerId::from(&self.inner);
157 self_default_type_ptr_id == actual_type_core_ptr_id
158 } else {
159 false
160 }
161 }
162
163 pub fn try_get_property<'a>(
165 &self,
166 key: impl Into<ValueKey<'a>>,
167 ) -> Result<ValueContainer, AccessError> {
168 match self.inner {
169 CoreValue::Map(ref map) => {
170 Ok(map.get(key)?.clone())
172 }
173 CoreValue::List(ref list) => {
174 if let Some(index) = key.into().try_as_index() {
175 Ok(list.get(index)?.clone())
176 } else {
177 Err(AccessError::InvalidIndexKey)
178 }
179 }
180 CoreValue::Text(ref text) => {
181 if let Some(index) = key.into().try_as_index() {
182 let char = text.char_at(index)?;
183 Ok(ValueContainer::from(char.to_string()))
184 } else {
185 Err(AccessError::InvalidIndexKey)
186 }
187 }
188 _ => {
189 Err(AccessError::InvalidOperation(
191 "Cannot get property".to_string(),
192 ))
193 }
194 }
195 }
196
197 pub fn try_set_property<'a>(
199 &mut self,
200 key: impl Into<ValueKey<'a>>,
201 val: ValueContainer,
202 ) -> Result<(), AccessError> {
203 let key = key.into();
204
205 match self.inner {
206 CoreValue::Map(ref mut map) => {
207 map.try_set(key, val)?;
209 }
210 CoreValue::List(ref mut list) => {
211 if let Some(index) = key.try_as_index() {
212 list.set(index, val)
213 .map_err(AccessError::IndexOutOfBounds)?;
214 } else {
215 return Err(AccessError::InvalidIndexKey);
216 }
217 }
218 CoreValue::Text(ref mut text) => {
219 if let Some(index) = key.try_as_index() {
220 if let ValueContainer::Value(v) = &val
221 && let CoreValue::Text(new_char) = &v.inner
222 && new_char.0.len() == 1
223 {
224 let char = new_char.0.chars().next().unwrap_or('\0');
225 text.set_char_at(index, char).map_err(|err| {
226 AccessError::IndexOutOfBounds(err)
227 })?;
228 } else {
229 return Err(AccessError::InvalidOperation(
230 "Can only set char character in text".to_string(),
231 ));
232 }
233 } else {
234 return Err(AccessError::InvalidIndexKey);
235 }
236 }
237 _ => {
238 return Err(AccessError::InvalidOperation(format!(
240 "Cannot set property '{}' on non-map value: {:?}",
241 key, self
242 )));
243 }
244 }
245
246 Ok(())
247 }
248}
249
250impl Add for Value {
251 type Output = Result<Value, ValueError>;
252 fn add(self, rhs: Value) -> Self::Output {
253 Ok((&self.inner + &rhs.inner)?.into())
254 }
255}
256
257impl Add for &Value {
258 type Output = Result<Value, ValueError>;
259 fn add(self, rhs: &Value) -> Self::Output {
260 Value::add(self.clone(), rhs.clone())
261 }
262}
263
264impl Sub for Value {
265 type Output = Result<Value, ValueError>;
266 fn sub(self, rhs: Value) -> Self::Output {
267 Ok((&self.inner - &rhs.inner)?.into())
268 }
269}
270
271impl Sub for &Value {
272 type Output = Result<Value, ValueError>;
273 fn sub(self, rhs: &Value) -> Self::Output {
274 Value::sub(self.clone(), rhs.clone())
275 }
276}
277
278impl Neg for Value {
279 type Output = Result<Value, ValueError>;
280
281 fn neg(self) -> Self::Output {
282 (-self.inner).map(Value::from)
283 }
284}
285
286impl Not for Value {
287 type Output = Option<Value>;
288
289 fn not(self) -> Self::Output {
290 (!self.inner).map(Value::from)
291 }
292}
293
294impl<T> AddAssign<T> for Value
296where
297 Value: From<T>,
298{
299 fn add_assign(&mut self, rhs: T) {
300 let rhs: Value = rhs.into();
301 let res = self.inner.clone() + rhs.inner;
302 if let Ok(res) = res {
303 self.inner = res;
304 } else {
305 error!("Failed to add value: {res:?}");
306 }
307 }
308}
309
310impl Display for Value {
311 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
312 core::write!(f, "{}", self.inner)
313 }
314}
315
316impl<T> From<Option<T>> for Value
317where
318 T: Into<Value>,
319{
320 fn from(opt: Option<T>) -> Self {
321 match opt {
322 Some(v) => v.into(),
323 None => Value::null(),
324 }
325 }
326}
327
328#[cfg(test)]
329mod tests {
333 use super::*;
334 use crate::{
335 assert_structural_eq, datex_list,
336 libs::core::{get_core_lib_type, get_core_lib_type_reference},
337 prelude::*,
338 values::core_values::{
339 endpoint::Endpoint,
340 integer::{Integer, typed_integer::TypedInteger},
341 list::List,
342 },
343 };
344 use core::str::FromStr;
345 use log::info;
346
347 #[test]
348 fn endpoint() {
349 let endpoint = Value::from(Endpoint::from_str("@test").unwrap());
350 assert_eq!(endpoint.to_string(), "@test");
351 }
352
353 #[test]
354 fn new_addition_assignments() {
355 let mut x = Value::from(42i8);
356 let y = Value::from(27i8);
357
358 x += y.clone();
359 assert_eq!(x, Value::from(69i8));
360 }
361
362 #[test]
363 fn new_additions() {
364 let x = Value::from(42i8);
365 let y = Value::from(27i8);
366
367 let z = (x.clone() + y.clone()).unwrap();
368 assert_eq!(z, Value::from(69i8));
369 }
370
371 #[test]
372 fn list() {
373 let mut a = List::from(vec![
374 Value::from("42"),
375 Value::from(42),
376 Value::from(true),
377 ]);
378
379 a.push(Value::from(42));
380 a.push(4);
381
382 assert_eq!(a.len(), 5);
383
384 let b = List::from(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
385 assert_eq!(b.len(), 11);
386
387 let c = datex_list![1, "test", 3, true, false];
388 assert_eq!(c.len(), 5);
389 assert_eq!(c[0], 1.into());
390 assert_eq!(c[1], "test".into());
391 assert_eq!(c[2], 3.into());
392 }
393
394 #[test]
395 fn boolean() {
396 let a = Value::from(true);
397 let b = Value::from(false);
398 let c = Value::from(false);
399 assert_ne!(a, b);
400 assert_eq!(b, c);
401
402 let d = (!b.clone()).unwrap();
403 assert_eq!(a, d);
404
405 let a_plus_b = a.clone() + b.clone();
407 assert!(a_plus_b.is_err());
408 }
409
410 #[test]
411 fn equality_same_type() {
412 let a = Value::from(42i8);
413 let b = Value::from(42i8);
414 let c = Value::from(27i8);
415
416 assert_eq!(a, b);
417 assert_ne!(a, c);
418 assert_ne!(b, c);
419
420 info!("{} === {}", a.clone(), b.clone());
421 info!("{} !== {}", a.clone(), c.clone());
422 }
423
424 #[test]
425 fn decimal() {
426 let a = Value::from(42.1f32);
427 let b = Value::from(27f32);
428
429 let a_plus_b = (a.clone() + b.clone()).unwrap();
430 assert_eq!(a_plus_b, Value::from(69.1f32));
431 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
432 }
433
434 #[test]
435 fn null() {
436 let null_value = Value::null();
437 assert_eq!(null_value.to_string(), "null");
438
439 let maybe_value: Option<i8> = None;
440 let null_value = Value::from(maybe_value);
441 assert_eq!(null_value.to_string(), "null");
442 assert!(null_value.is_null());
443 }
444
445 #[test]
446 fn addition() {
447 let a = Value::from(42i8);
448 let b = Value::from(27i8);
449
450 let a_plus_b = (a.clone() + b.clone()).unwrap();
451 assert_eq!(a_plus_b, Value::from(69i8));
452 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
453 }
454
455 #[test]
456 fn string_concatenation() {
457 let a = Value::from("Hello ");
458 let b = Value::from(42i8);
459
460 assert!(a.is_text());
461 assert!(b.is_integer_i8());
462
463 let a_plus_b = (a.clone() + b.clone()).unwrap();
464 let b_plus_a = (b.clone() + a.clone()).unwrap();
465
466 assert!(a_plus_b.is_text());
467 assert!(b_plus_a.is_text());
468
469 assert_eq!(a_plus_b, Value::from("Hello 42"));
470 assert_eq!(b_plus_a, Value::from("42Hello "));
471
472 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
473 info!("{} + {} = {}", b.clone(), a.clone(), b_plus_a);
474 }
475
476 #[test]
477 fn structural_equality() {
478 let a = Value::from(42_i8);
479 let b = Value::from(42_i32);
480 assert!(a.is_integer_i8());
481
482 assert_structural_eq!(a, b);
483
484 assert_structural_eq!(
485 Value::from(TypedInteger::I8(42)),
486 Value::from(TypedInteger::U32(42)),
487 );
488
489 assert_structural_eq!(
490 Value::from(42_i8),
491 Value::from(Integer::from(42_i8))
492 );
493 }
494
495 #[test]
496 fn default_types() {
497 let val = Value::from(Integer::from(42));
498 assert!(val.has_default_type());
499
500 let val = Value::from(42i8);
501 assert!(val.has_default_type());
502
503 let val = Value {
504 inner: CoreValue::Integer(Integer::from(42)),
505 actual_type: Box::new(TypeDefinition::ImplType(
506 Box::new(get_core_lib_type(CoreLibPointerId::Integer(None))),
507 vec![],
508 )),
509 };
510
511 assert!(!val.has_default_type());
512 }
513}