1use super::datex_type::CoreValueType;
2use crate::values::core_value::CoreValue;
3use crate::values::traits::structural_eq::StructuralEq;
4use crate::values::traits::value_eq::ValueEq;
5use crate::values::value_container::ValueError;
6use log::error;
7use std::fmt::{Display, Formatter};
8use std::ops::{Add, AddAssign, Deref, Not, Sub};
9
10#[derive(Clone, Debug, Eq, PartialEq, Hash)]
11pub struct Value {
12 pub inner: CoreValue,
13 pub actual_type: CoreValueType, }
15
16impl StructuralEq for Value {
19 fn structural_eq(&self, other: &Self) -> bool {
20 self.inner.structural_eq(&other.inner)
21 }
22}
23
24impl ValueEq for Value {
27 fn value_eq(&self, other: &Self) -> bool {
28 self == other
29 }
30}
31
32impl Deref for Value {
33 type Target = CoreValue;
34
35 fn deref(&self) -> &Self::Target {
36 &self.inner
37 }
38}
39
40impl<T: Into<CoreValue>> From<T> for Value {
41 fn from(inner: T) -> Self {
42 let inner = inner.into();
43 let actual_type = inner.get_default_type();
44 Value { inner, actual_type }
45 }
46}
47
48impl Value {
49 pub fn is_of_type(&self, target: CoreValueType) -> bool {
50 self.get_type() == target
51 }
52 pub fn is_null(&self) -> bool {
53 self.is_of_type(CoreValueType::Null)
54 }
55 pub fn is_text(&self) -> bool {
56 self.is_of_type(CoreValueType::Text)
57 }
58 pub fn is_i8(&self) -> bool {
59 self.is_of_type(CoreValueType::I8)
60 }
61 pub fn is_bool(&self) -> bool {
62 self.is_of_type(CoreValueType::Bool)
63 }
64
65 pub fn try_cast_to(&self, target_type: CoreValueType) -> Option<Value> {
83 self.inner.cast_to(target_type.clone()).map(|inner| Value {
84 inner,
85 actual_type: target_type,
86 })
87 }
88
89 pub fn cast_to(&self, target_type: CoreValueType) -> Value {
108 self.try_cast_to(target_type.clone()).unwrap_or_else(|| {
109 panic!("Failed to cast value to target type: {target_type:?}")
110 })
111 }
112
113 pub fn cast_or_null(&self, target_type: CoreValueType) -> Value {
130 self.try_cast_to(target_type).unwrap_or(Value::null())
131 }
132
133 pub fn get_type(&self) -> CoreValueType {
134 self.actual_type.clone()
135 }
136
137 pub fn null() -> Self {
138 CoreValue::Null.into()
139 }
140}
141
142impl Add for Value {
143 type Output = Result<Value, ValueError>;
144 fn add(self, rhs: Value) -> Self::Output {
145 Ok((&self.inner + &rhs.inner)?.into())
146 }
147}
148
149impl Add for &Value {
150 type Output = Result<Value, ValueError>;
151 fn add(self, rhs: &Value) -> Self::Output {
152 Value::add(self.clone(), rhs.clone())
153 }
154}
155
156impl Sub for Value {
157 type Output = Result<Value, ValueError>;
158 fn sub(self, rhs: Value) -> Self::Output {
159 Ok((&self.inner - &rhs.inner)?.into())
160 }
161}
162
163impl Sub for &Value {
164 type Output = Result<Value, ValueError>;
165 fn sub(self, rhs: &Value) -> Self::Output {
166 Value::sub(self.clone(), rhs.clone())
167 }
168}
169
170impl Not for Value {
171 type Output = Option<Value>;
172
173 fn not(self) -> Self::Output {
174 (!self.inner).map(Value::from)
175 }
176}
177
178impl<T> AddAssign<T> for Value
180where
181 Value: From<T>,
182{
183 fn add_assign(&mut self, rhs: T) {
184 let rhs: Value = rhs.into();
185 let res = self.inner.clone() + rhs.inner;
186 if let Ok(res) = res {
187 self.inner = res;
188 } else {
189 error!("Failed to add value: {res:?}");
190 }
191 }
192}
193
194impl Display for Value {
195 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
196 write!(f, "{}", self.inner)
197 }
198}
199
200impl<T> From<Option<T>> for Value
201where
202 T: Into<Value>,
203{
204 fn from(opt: Option<T>) -> Self {
205 match opt {
206 Some(v) => v.into(),
207 None => Value::null(),
208 }
209 }
210}
211
212#[cfg(test)]
213mod tests {
217 use super::*;
218 use crate::{
219 assert_structural_eq, datex_array,
220 logger::init_logger_debug,
221 values::core_values::{
222 array::Array,
223 endpoint::Endpoint,
224 integer::{integer::Integer, typed_integer::TypedInteger},
225 },
226 };
227 use log::{debug, info};
228 use std::str::FromStr;
229
230 #[test]
231 fn test_endpoint() {
232 init_logger_debug();
233 let endpoint = Value::from(Endpoint::from_str("@test").unwrap());
234 assert_eq!(endpoint.get_type(), CoreValueType::Endpoint);
235 assert_eq!(endpoint.to_string(), "@test");
236
237 let endpoint = Value::from("@test").cast_to(CoreValueType::Endpoint);
238 assert_eq!(endpoint.get_type(), CoreValueType::Endpoint);
239 assert_eq!(endpoint.to_string(), "@test");
240 }
241
242 #[test]
243 fn new_addition_assignments() {
244 let mut x = Value::from(42i8);
245 let y = Value::from(27i8);
246
247 x += y.clone();
248 assert_eq!(x.get_type(), CoreValueType::I8);
249 assert_eq!(x, Value::from(69i8));
250 }
251
252 #[test]
253 fn new_additions() {
254 let x = Value::from(42i8);
255 let y = Value::from(27i8);
256
257 let z = (x.clone() + y.clone()).unwrap();
258 assert_eq!(z.get_type(), CoreValueType::I8);
259 assert_eq!(z, Value::from(69i8));
260 }
261
262 #[test]
263 fn array() {
264 init_logger_debug();
265 let mut a: Array = CoreValue::from(vec![
266 Value::from("42"),
267 Value::from(42),
268 Value::from(true),
269 ])
270 .try_into()
271 .unwrap();
272
273 a.push(Value::from(42));
274 a.push(4);
275
276 assert_eq!(a.len(), 5);
277
278 let b = Array::from(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
279 assert_eq!(b.len(), 11);
280
281 let c = datex_array![1, "test", 3, true, false];
282 assert_eq!(c.len(), 5);
283 assert_eq!(c[0], 1.into());
284 assert_eq!(c[1], "test".into());
285 assert_eq!(c[2], 3.into());
286 debug!("Array: {c}");
287 }
288
289 #[test]
290 fn boolean() {
291 init_logger_debug();
292 let a = Value::from(true);
293 let b = Value::from(false);
294 let c = Value::from(false);
295 assert_eq!(a.get_type(), CoreValueType::Bool);
296 assert_eq!(b.get_type(), CoreValueType::Bool);
297 assert_ne!(a, b);
298 assert_eq!(b, c);
299
300 let d = (!b.clone()).unwrap();
301 assert_eq!(a, d);
302
303 let a_plus_b = a.clone() + b.clone();
305 assert!(a_plus_b.is_err());
306 }
307
308 #[test]
309 fn equality_same_type() {
310 init_logger_debug();
311 let a = Value::from(42i8);
312 let b = Value::from(42i8);
313 let c = Value::from(27i8);
314
315 assert_eq!(a.get_type(), CoreValueType::I8);
316 assert_eq!(b.get_type(), CoreValueType::I8);
317 assert_eq!(c.get_type(), CoreValueType::I8);
318
319 assert_eq!(a, b);
320 assert_ne!(a, c);
321 assert_ne!(b, c);
322
323 info!("{} === {}", a.clone(), b.clone());
324 info!("{} !== {}", a.clone(), c.clone());
325 }
326
327 #[test]
328 fn decimal() {
329 init_logger_debug();
330 let a = Value::from(42.1f32);
331 let b = Value::from(27f32);
332
333 assert_eq!(a.get_type(), CoreValueType::F32);
334 assert_eq!(b.get_type(), CoreValueType::F32);
335
336 let a_plus_b = (a.clone() + b.clone()).unwrap();
337 assert_eq!(a_plus_b.get_type(), CoreValueType::F32);
338 assert_eq!(a_plus_b, Value::from(69.1f32));
339 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
340 }
341
342 #[test]
343 fn test_cast_type() {
344 init_logger_debug();
345 let a = Value::from(42);
346 let b = a.try_cast_to(CoreValueType::Text).unwrap();
347 assert_eq!(b.get_type(), CoreValueType::Text);
348 }
349
350 #[test]
351 fn test_null() {
352 init_logger_debug();
353
354 let null_value = Value::null();
355 assert_eq!(null_value.get_type(), CoreValueType::Null);
356 assert_eq!(null_value.to_string(), "null");
357
358 let maybe_value: Option<i8> = None;
359 let null_value = Value::from(maybe_value);
360 assert_eq!(null_value.get_type(), CoreValueType::Null);
361 assert_eq!(null_value.to_string(), "null");
362 }
363
364 #[test]
365 fn test_addition() {
366 init_logger_debug();
367 let a = Value::from(42i8);
368 let b = Value::from(27i8);
369
370 assert_eq!(a.get_type(), CoreValueType::I8);
371 assert_eq!(b.get_type(), CoreValueType::I8);
372
373 let a_plus_b = (a.clone() + b.clone()).unwrap();
374
375 assert_eq!(a_plus_b.get_type(), CoreValueType::I8);
376
377 assert_eq!(a_plus_b, Value::from(69i8));
378 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
379 }
380
381 #[test]
382 fn test_string_concatenation() {
383 init_logger_debug();
384 let a = Value::from("Hello ");
385 let b = Value::from(42i8);
386
387 assert_eq!(a.get_type(), CoreValueType::Text);
388 assert_eq!(b.get_type(), CoreValueType::I8);
389
390 let a_plus_b = (a.clone() + b.clone()).unwrap();
391 let b_plus_a = (b.clone() + a.clone()).unwrap();
392
393 assert_eq!(a_plus_b.get_type(), CoreValueType::Text);
394 assert_eq!(b_plus_a.get_type(), CoreValueType::Text);
395
396 assert_eq!(a_plus_b, Value::from("Hello 42"));
397 assert_eq!(b_plus_a, Value::from("42Hello "));
398
399 info!("{} + {} = {}", a.clone(), b.clone(), a_plus_b);
400 info!("{} + {} = {}", b.clone(), a.clone(), b_plus_a);
401 }
402
403 #[test]
404 fn test_structural_equality() {
405 let a = Value::from(42_i8);
406 let b = Value::from(42_i32);
407
408 assert_eq!(a.get_type(), CoreValueType::I8);
409 assert_eq!(b.get_type(), CoreValueType::I32);
410
411 assert_structural_eq!(a, b);
412
413 assert_eq!(
414 Value::from(Integer(TypedInteger::I8(42))),
415 Value::from(Integer(TypedInteger::U32(42))),
416 );
417
418 assert_structural_eq!(
419 Value::from(Integer(TypedInteger::I8(42))),
420 Value::from(Integer(TypedInteger::U32(42))),
421 );
422
423 assert_structural_eq!(
424 Value::from(42_i8),
425 Value::from(Integer::from(42_i8))
426 );
427 }
428}