1use crate::{
2 libs::core::CoreLibPointerId,
3 prelude::*,
4 runtime::execution::ExecutionError,
5 shared_values::shared_container::AccessError,
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::SharedReference(type_reference) =
147 self.actual_type.as_ref()
148 && let Ok(actual_type_core_ptr_id) = CoreLibPointerId::try_from(
149 &type_reference.borrow().pointer.address(),
150 )
151 {
152 let self_default_type_ptr_id = CoreLibPointerId::from(&self.inner);
154 self_default_type_ptr_id == actual_type_core_ptr_id
155 } else {
156 false
157 }
158 }
159
160 pub fn try_get_property<'a>(
162 &self,
163 key: impl Into<ValueKey<'a>>,
164 ) -> Result<ValueContainer, AccessError> {
165 match self.inner {
166 CoreValue::Map(ref map) => {
167 Ok(map.get(key)?.clone())
169 }
170 CoreValue::List(ref list) => {
171 if let Some(index) = key.into().try_as_index() {
172 Ok(list.get(index)?.clone())
173 } else {
174 Err(AccessError::InvalidIndexKey)
175 }
176 }
177 CoreValue::Text(ref text) => {
178 if let Some(index) = key.into().try_as_index() {
179 let char = text.char_at(index)?;
180 Ok(ValueContainer::from(char.to_string()))
181 } else {
182 Err(AccessError::InvalidIndexKey)
183 }
184 }
185 _ => {
186 Err(AccessError::InvalidOperation(
188 "Cannot get property".to_string(),
189 ))
190 }
191 }
192 }
193
194 pub fn try_set_property<'a>(
196 &mut self,
197 key: impl Into<ValueKey<'a>>,
198 val: ValueContainer,
199 ) -> Result<(), AccessError> {
200 let key = key.into();
201
202 match self.inner {
203 CoreValue::Map(ref mut map) => {
204 map.try_set(key, val)?;
206 }
207 CoreValue::List(ref mut list) => {
208 if let Some(index) = key.try_as_index() {
209 list.set(index, val)
210 .map_err(AccessError::IndexOutOfBounds)?;
211 } else {
212 return Err(AccessError::InvalidIndexKey);
213 }
214 }
215 CoreValue::Text(ref mut text) => {
216 if let Some(index) = key.try_as_index() {
217 if let ValueContainer::Local(v) = &val
218 && let CoreValue::Text(new_char) = &v.inner
219 && new_char.0.len() == 1
220 {
221 let char = new_char.0.chars().next().unwrap_or('\0');
222 text.set_char_at(index, char).map_err(|err| {
223 AccessError::IndexOutOfBounds(err)
224 })?;
225 } else {
226 return Err(AccessError::InvalidOperation(
227 "Can only set char character in text".to_string(),
228 ));
229 }
230 } else {
231 return Err(AccessError::InvalidIndexKey);
232 }
233 }
234 _ => {
235 return Err(AccessError::InvalidOperation(format!(
237 "Cannot set property '{}' on non-map value: {:?}",
238 key, self
239 )));
240 }
241 }
242
243 Ok(())
244 }
245}
246
247impl Add for Value {
248 type Output = Result<Value, ValueError>;
249 fn add(self, rhs: Value) -> Self::Output {
250 Ok((&self.inner + &rhs.inner)?.into())
251 }
252}
253
254impl Add for &Value {
255 type Output = Result<Value, ValueError>;
256 fn add(self, rhs: &Value) -> Self::Output {
257 Value::add(self.clone(), rhs.clone())
258 }
259}
260
261impl Sub for Value {
262 type Output = Result<Value, ValueError>;
263 fn sub(self, rhs: Value) -> Self::Output {
264 Ok((&self.inner - &rhs.inner)?.into())
265 }
266}
267
268impl Sub for &Value {
269 type Output = Result<Value, ValueError>;
270 fn sub(self, rhs: &Value) -> Self::Output {
271 Value::sub(self.clone(), rhs.clone())
272 }
273}
274
275impl Neg for Value {
276 type Output = Result<Value, ValueError>;
277
278 fn neg(self) -> Self::Output {
279 (-self.inner).map(Value::from)
280 }
281}
282
283impl Not for Value {
284 type Output = Option<Value>;
285
286 fn not(self) -> Self::Output {
287 (!self.inner).map(Value::from)
288 }
289}
290
291impl<T> AddAssign<T> for Value
293where
294 Value: From<T>,
295{
296 fn add_assign(&mut self, rhs: T) {
297 let rhs: Value = rhs.into();
298 let res = self.inner.clone() + rhs.inner;
299 if let Ok(res) = res {
300 self.inner = res;
301 } else {
302 error!("Failed to add value: {res:?}");
303 }
304 }
305}
306
307impl Display for Value {
308 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
309 core::write!(f, "{}", self.inner)
310 }
311}
312
313impl<T> From<Option<T>> for Value
314where
315 T: Into<Value>,
316{
317 fn from(opt: Option<T>) -> Self {
318 match opt {
319 Some(v) => v.into(),
320 None => Value::null(),
321 }
322 }
323}
324
325#[cfg(test)]
326mod tests {
330 use super::*;
331 use crate::{
332 assert_structural_eq, datex_list,
333 libs::core::{get_core_lib_type, get_core_lib_type_reference},
334 prelude::*,
335 values::core_values::{
336 endpoint::Endpoint,
337 integer::{Integer, typed_integer::TypedInteger},
338 list::List,
339 },
340 };
341 use core::str::FromStr;
342 use log::info;
343
344 #[test]
345 fn endpoint() {
346 let endpoint = Value::from(Endpoint::from_str("@test").unwrap());
347 assert_eq!(endpoint.to_string(), "@test");
348 }
349
350 #[test]
351 fn new_addition_assignments() {
352 let mut x = Value::from(42i8);
353 let y = Value::from(27i8);
354
355 x += y.clone();
356 assert_eq!(x, Value::from(69i8));
357 }
358
359 #[test]
360 fn new_additions() {
361 let x = Value::from(42i8);
362 let y = Value::from(27i8);
363
364 let z = (x.clone() + y.clone()).unwrap();
365 assert_eq!(z, Value::from(69i8));
366 }
367
368 #[test]
369 fn list() {
370 let mut a = List::from(vec![
371 Value::from("42"),
372 Value::from(42),
373 Value::from(true),
374 ]);
375
376 a.push(Value::from(42));
377 a.push(4);
378
379 assert_eq!(a.len(), 5);
380
381 let b = List::from(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
382 assert_eq!(b.len(), 11);
383
384 let c = datex_list![1, "test", 3, true, false];
385 assert_eq!(c.len(), 5);
386 assert_eq!(c[0], 1.into());
387 assert_eq!(c[1], "test".into());
388 assert_eq!(c[2], 3.into());
389 }
390
391 #[test]
392 fn boolean() {
393 let a = Value::from(true);
394 let b = Value::from(false);
395 let c = Value::from(false);
396 assert_ne!(a, b);
397 assert_eq!(b, c);
398
399 let d = (!b.clone()).unwrap();
400 assert_eq!(a, d);
401
402 let a_plus_b = a.clone() + b.clone();
404 assert!(a_plus_b.is_err());
405 }
406
407 #[test]
408 fn equality_same_type() {
409 let a = Value::from(42i8);
410 let b = Value::from(42i8);
411 let c = Value::from(27i8);
412
413 assert_eq!(a, b);
414 assert_ne!(a, c);
415 assert_ne!(b, c);
416
417 info!("{} === {}", a.clone(), b.clone());
418 info!("{} !== {}", a.clone(), c.clone());
419 }
420
421 #[test]
422 fn decimal() {
423 let a = Value::from(42.1f32);
424 let b = Value::from(27f32);
425
426 let a_plus_b = (a.clone() + b.clone()).unwrap();
427 assert_eq!(a_plus_b, Value::from(69.1f32));
428 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
429 }
430
431 #[test]
432 fn null() {
433 let null_value = Value::null();
434 assert_eq!(null_value.to_string(), "null");
435
436 let maybe_value: Option<i8> = None;
437 let null_value = Value::from(maybe_value);
438 assert_eq!(null_value.to_string(), "null");
439 assert!(null_value.is_null());
440 }
441
442 #[test]
443 fn addition() {
444 let a = Value::from(42i8);
445 let b = Value::from(27i8);
446
447 let a_plus_b = (a.clone() + b.clone()).unwrap();
448 assert_eq!(a_plus_b, Value::from(69i8));
449 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
450 }
451
452 #[test]
453 fn string_concatenation() {
454 let a = Value::from("Hello ");
455 let b = Value::from(42i8);
456
457 assert!(a.is_text());
458 assert!(b.is_integer_i8());
459
460 let a_plus_b = (a.clone() + b.clone()).unwrap();
461 let b_plus_a = (b.clone() + a.clone()).unwrap();
462
463 assert!(a_plus_b.is_text());
464 assert!(b_plus_a.is_text());
465
466 assert_eq!(a_plus_b, Value::from("Hello 42"));
467 assert_eq!(b_plus_a, Value::from("42Hello "));
468
469 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
470 info!("{} + {} = {}", b.clone(), a.clone(), b_plus_a);
471 }
472
473 #[test]
474 fn structural_equality() {
475 let a = Value::from(42_i8);
476 let b = Value::from(42_i32);
477 assert!(a.is_integer_i8());
478
479 assert_structural_eq!(a, b);
480
481 assert_structural_eq!(
482 Value::from(TypedInteger::I8(42)),
483 Value::from(TypedInteger::U32(42)),
484 );
485
486 assert_structural_eq!(
487 Value::from(42_i8),
488 Value::from(Integer::from(42_i8))
489 );
490 }
491
492 #[test]
493 fn default_types() {
494 let val = Value::from(Integer::from(42));
495 assert!(val.has_default_type());
496
497 let val = Value::from(42i8);
498 assert!(val.has_default_type());
499
500 let val = Value {
501 inner: CoreValue::Integer(Integer::from(42)),
502 actual_type: Box::new(TypeDefinition::ImplType(
503 Box::new(get_core_lib_type(CoreLibPointerId::Integer(None))),
504 vec![],
505 )),
506 };
507
508 assert!(!val.has_default_type());
509 }
510}