1pub use crate::proto::kuksa::val::v1 as v1_proto;
17pub use crate::proto::kuksa::val::v2 as v2_proto;
18pub use crate::proto::sdv::databroker::v1 as sdv_proto;
19
20pub mod kuksa {
21 pub mod common;
22 pub mod val {
23 pub mod v1;
24
25 pub mod v2;
26 }
27}
28
29pub mod sdv {
30 pub mod databroker {
31 pub mod v1;
32 }
33}
34
35pub mod proto {
36 pub mod kuksa {
37 pub mod val {
38 #[allow(clippy::doc_lazy_continuation)]
40 pub mod v1 {
41 pub const FILE_DESCRIPTOR_SET: &[u8] =
42 tonic::include_file_descriptor_set!("kuksa.val.v1_descriptor");
43 tonic::include_proto!("kuksa.val.v1");
44
45 use datapoint::Value;
46 use std::{any::Any, fmt::Display, str::FromStr};
47
48 #[derive(Debug)]
49 pub struct ParsingError {
50 message: String,
51 }
52
53 impl ParsingError {
54 pub fn new<T: Into<String>>(message: T) -> Self {
55 ParsingError {
56 message: message.into(),
57 }
58 }
59 }
60
61 impl Display for ParsingError {
62 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63 self.message.fmt(f)
64 }
65 }
66
67 impl std::error::Error for ParsingError {}
68
69 impl FromStr for DataType {
70 type Err = ParsingError;
71 fn from_str(s: &str) -> Result<Self, Self::Err> {
72 match s.to_lowercase().as_str() {
73 "string" => Ok(DataType::String),
74 "string[]" => Ok(DataType::StringArray),
75 "bool" => Ok(DataType::Boolean),
76 "bool[]" => Ok(DataType::BooleanArray),
77 "int8" => Ok(DataType::Int8),
78 "int8[]" => Ok(DataType::Int8Array),
79 "int16" => Ok(DataType::Int16),
80 "int16[]" => Ok(DataType::Int16Array),
81 "int32" => Ok(DataType::Int32),
82 "int32[]" => Ok(DataType::Int32Array),
83 "int64" => Ok(DataType::Int64),
84 "int64[]" => Ok(DataType::Int64Array),
85 "uint8" => Ok(DataType::Uint8),
86 "uint8[]" => Ok(DataType::Uint8Array),
87 "uint16" => Ok(DataType::Uint16),
88 "uint16[]" => Ok(DataType::Uint16Array),
89 "uint32" => Ok(DataType::Uint32),
90 "uint32[]" => Ok(DataType::Uint32Array),
91 "uint64" => Ok(DataType::Uint64),
92 "uint64[]" => Ok(DataType::Uint64Array),
93 "float" => Ok(DataType::Float),
94 "float[]" => Ok(DataType::FloatArray),
95 "double" => Ok(DataType::Double),
96 "double[]" => Ok(DataType::DoubleArray),
97 _ => Err(ParsingError::new(format!("unsupported data type '{s}'"))),
98 }
99 }
100 }
101
102 impl Value {
103 pub fn new<T: Into<DataType>>(
104 vss_type: T,
105 value: &str,
106 ) -> Result<Self, ParsingError> {
107 let dt: DataType = vss_type.into();
108 match dt {
109 DataType::String => Ok(Value::String(value.to_string())),
110 DataType::Boolean => value
111 .parse::<bool>()
112 .map(Value::Bool)
113 .map_err(|e| ParsingError::new(e.to_string())),
114 DataType::Int8 => value
115 .parse::<i8>()
116 .map(|v| Value::Int32(v as i32))
117 .map_err(|e| ParsingError::new(e.to_string())),
118 DataType::Int16 => value
119 .parse::<i16>()
120 .map(|v| Value::Int32(v as i32))
121 .map_err(|e| ParsingError::new(e.to_string())),
122 DataType::Int32 => value
123 .parse::<i32>()
124 .map(Value::Int32)
125 .map_err(|e| ParsingError::new(e.to_string())),
126 DataType::Int64 => value
127 .parse::<i64>()
128 .map(Value::Int64)
129 .map_err(|e| ParsingError::new(e.to_string())),
130 DataType::Uint8 => value
131 .parse::<u8>()
132 .map(|v| Value::Uint32(v as u32))
133 .map_err(|e| ParsingError::new(e.to_string())),
134 DataType::Uint16 => value
135 .parse::<u16>()
136 .map(|v| Value::Uint32(v as u32))
137 .map_err(|e| ParsingError::new(e.to_string())),
138 DataType::Uint32 => value
139 .parse::<u32>()
140 .map(Value::Uint32)
141 .map_err(|e| ParsingError::new(e.to_string())),
142 DataType::Uint64 => value
143 .parse::<u64>()
144 .map(Value::Uint64)
145 .map_err(|e| ParsingError::new(e.to_string())),
146 DataType::Float => value
147 .parse::<f32>()
148 .map(Value::Float)
149 .map_err(|e| ParsingError::new(e.to_string())),
150 DataType::Double => value
151 .parse::<f64>()
152 .map(Value::Double)
153 .map_err(|e| ParsingError::new(e.to_string())),
154 _ => Err(ParsingError::new(format!(
155 "data type '{:?}' not supported for parsing string into typed value",
156 dt.type_id()
157 ))),
158 }
159 }
160 }
161 }
162 #[allow(clippy::doc_lazy_continuation)]
164 pub mod v2 {
165 use value::TypedValue;
166
167 tonic::include_proto!("kuksa.val.v2");
168
169 pub const FILE_DESCRIPTOR_SET: &[u8] =
170 tonic::include_file_descriptor_set!("kuksa.val.v2_descriptor");
171
172 #[derive(Debug)]
175 pub struct IncompatibleValueTypeError {}
176
177 impl TryFrom<TypedValue> for u32 {
178 type Error = IncompatibleValueTypeError;
179 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
180 Self::try_from(&value)
181 }
182 }
183
184 impl TryFrom<&TypedValue> for u32 {
185 type Error = IncompatibleValueTypeError;
186 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
187 match value {
188 TypedValue::Uint32(v) => Ok(*v),
189 _ => Err(IncompatibleValueTypeError {}),
190 }
191 }
192 }
193
194 impl TryFrom<TypedValue> for Vec<u32> {
195 type Error = IncompatibleValueTypeError;
196 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
197 Self::try_from(&value)
198 }
199 }
200
201 impl TryFrom<&TypedValue> for Vec<u32> {
202 type Error = IncompatibleValueTypeError;
203 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
204 match value {
205 TypedValue::Uint32Array(v) => Ok(v.values.clone()),
206 _ => Err(IncompatibleValueTypeError {}),
207 }
208 }
209 }
210
211 impl TryFrom<TypedValue> for u64 {
212 type Error = IncompatibleValueTypeError;
213 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
214 Self::try_from(&value)
215 }
216 }
217
218 impl TryFrom<&TypedValue> for u64 {
219 type Error = IncompatibleValueTypeError;
220 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
221 match value {
222 TypedValue::Uint32(v) => Ok(*v as u64),
223 TypedValue::Uint64(v) => Ok(*v),
224 _ => Err(IncompatibleValueTypeError {}),
225 }
226 }
227 }
228
229 impl TryFrom<TypedValue> for Vec<u64> {
230 type Error = IncompatibleValueTypeError;
231 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
232 Self::try_from(&value)
233 }
234 }
235
236 impl TryFrom<&TypedValue> for Vec<u64> {
237 type Error = IncompatibleValueTypeError;
238 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
239 match value {
240 TypedValue::Uint32Array(v) => {
241 Ok(v.values.iter().map(|v| *v as u64).collect())
242 }
243 TypedValue::Uint64Array(v) => Ok(v.values.clone()),
244 _ => Err(IncompatibleValueTypeError {}),
245 }
246 }
247 }
248
249 impl TryFrom<TypedValue> for i32 {
250 type Error = IncompatibleValueTypeError;
251 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
252 Self::try_from(&value)
253 }
254 }
255
256 impl TryFrom<&TypedValue> for i32 {
257 type Error = IncompatibleValueTypeError;
258 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
259 match value {
260 TypedValue::Uint32(v) => {
261 i32::try_from(*v).map_err(|_e| IncompatibleValueTypeError {})
262 }
263 TypedValue::Int32(v) => Ok(*v),
264 _ => Err(IncompatibleValueTypeError {}),
265 }
266 }
267 }
268
269 impl TryFrom<TypedValue> for Vec<i32> {
270 type Error = IncompatibleValueTypeError;
271 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
272 Self::try_from(&value)
273 }
274 }
275
276 impl TryFrom<&TypedValue> for Vec<i32> {
277 type Error = IncompatibleValueTypeError;
278 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
279 match value {
280 TypedValue::Uint32Array(v) => {
281 let mut result = vec![];
282 for u in &v.values {
283 result.push(
284 i32::try_from(*u)
285 .map_err(|_e| IncompatibleValueTypeError {})?,
286 );
287 }
288 Ok(result)
289 }
290 TypedValue::Int32Array(v) => Ok(v.values.clone()),
291 _ => Err(IncompatibleValueTypeError {}),
292 }
293 }
294 }
295
296 impl TryFrom<TypedValue> for i64 {
297 type Error = IncompatibleValueTypeError;
298 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
299 Self::try_from(&value)
300 }
301 }
302
303 impl TryFrom<&TypedValue> for i64 {
304 type Error = IncompatibleValueTypeError;
305 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
306 match value {
307 TypedValue::Uint32(v) => Ok(*v as i64),
308 TypedValue::Uint64(v) => {
309 i64::try_from(*v).map_err(|_e| IncompatibleValueTypeError {})
310 }
311 TypedValue::Int32(v) => Ok(*v as i64),
312 TypedValue::Int64(v) => Ok(*v),
313 _ => Err(IncompatibleValueTypeError {}),
314 }
315 }
316 }
317
318 impl TryFrom<TypedValue> for Vec<i64> {
319 type Error = IncompatibleValueTypeError;
320 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
321 Self::try_from(&value)
322 }
323 }
324
325 impl TryFrom<&TypedValue> for Vec<i64> {
326 type Error = IncompatibleValueTypeError;
327 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
328 match value {
329 TypedValue::Uint32Array(v) => {
330 Ok(v.values.iter().map(|v| *v as i64).collect())
331 }
332 TypedValue::Uint64Array(v) => {
333 let mut result = vec![];
334 for u in &v.values {
335 result.push(
336 i64::try_from(*u)
337 .map_err(|_e| IncompatibleValueTypeError {})?,
338 );
339 }
340 Ok(result)
341 }
342 TypedValue::Int32Array(v) => {
343 Ok(v.values.iter().map(|v| *v as i64).collect())
344 }
345 TypedValue::Int64Array(v) => Ok(v.values.clone()),
346 _ => Err(IncompatibleValueTypeError {}),
347 }
348 }
349 }
350
351 impl TryFrom<TypedValue> for f32 {
352 type Error = IncompatibleValueTypeError;
353 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
354 Self::try_from(&value)
355 }
356 }
357
358 impl TryFrom<&TypedValue> for f32 {
359 type Error = IncompatibleValueTypeError;
360 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
361 match value {
362 TypedValue::Uint32(v) => Ok(*v as f32),
363 TypedValue::Int32(v) => Ok(*v as f32),
364 TypedValue::Float(v) => Ok(*v),
365 _ => Err(IncompatibleValueTypeError {}),
366 }
367 }
368 }
369
370 impl TryFrom<TypedValue> for Vec<f32> {
371 type Error = IncompatibleValueTypeError;
372 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
373 Self::try_from(&value)
374 }
375 }
376
377 impl TryFrom<&TypedValue> for Vec<f32> {
378 type Error = IncompatibleValueTypeError;
379 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
380 match value {
381 TypedValue::Uint32Array(v) => {
382 Ok(v.values.iter().map(|v| *v as f32).collect())
383 }
384 TypedValue::Int32Array(v) => {
385 Ok(v.values.iter().map(|v| *v as f32).collect())
386 }
387 TypedValue::FloatArray(v) => Ok(v.values.clone()),
388 _ => Err(IncompatibleValueTypeError {}),
389 }
390 }
391 }
392
393 impl TryFrom<TypedValue> for f64 {
394 type Error = IncompatibleValueTypeError;
395 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
396 Self::try_from(&value)
397 }
398 }
399
400 impl TryFrom<&TypedValue> for f64 {
401 type Error = IncompatibleValueTypeError;
402 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
403 match value {
404 TypedValue::Uint32(v) => Ok(*v as f64),
405 TypedValue::Uint64(v) => Ok(*v as f64),
406 TypedValue::Int32(v) => Ok(*v as f64),
407 TypedValue::Int64(v) => Ok(*v as f64),
408 TypedValue::Float(v) => Ok(*v as f64),
409 TypedValue::Double(v) => Ok(*v),
410 _ => Err(IncompatibleValueTypeError {}),
411 }
412 }
413 }
414
415 impl TryFrom<TypedValue> for Vec<f64> {
416 type Error = IncompatibleValueTypeError;
417 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
418 Self::try_from(&value)
419 }
420 }
421
422 impl TryFrom<&TypedValue> for Vec<f64> {
423 type Error = IncompatibleValueTypeError;
424 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
425 match value {
426 TypedValue::Uint32Array(v) => {
427 Ok(v.values.iter().map(|v| *v as f64).collect())
428 }
429 TypedValue::Uint64Array(v) => {
430 Ok(v.values.iter().map(|v| *v as f64).collect())
431 }
432 TypedValue::Int32Array(v) => {
433 Ok(v.values.iter().map(|v| *v as f64).collect())
434 }
435 TypedValue::Int64Array(v) => {
436 Ok(v.values.iter().map(|v| *v as f64).collect())
437 }
438 TypedValue::FloatArray(v) => {
439 Ok(v.values.iter().map(|v| *v as f64).collect())
440 }
441 TypedValue::DoubleArray(v) => Ok(v.values.clone()),
442 _ => Err(IncompatibleValueTypeError {}),
443 }
444 }
445 }
446
447 impl TryFrom<TypedValue> for String {
448 type Error = IncompatibleValueTypeError;
449 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
450 Self::try_from(&value)
451 }
452 }
453
454 impl TryFrom<&TypedValue> for String {
455 type Error = IncompatibleValueTypeError;
456 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
457 match value {
458 TypedValue::String(v) => Ok(v.to_string()),
459 _ => Err(IncompatibleValueTypeError {}),
460 }
461 }
462 }
463
464 impl TryFrom<TypedValue> for Vec<String> {
465 type Error = IncompatibleValueTypeError;
466 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
467 Self::try_from(&value)
468 }
469 }
470
471 impl TryFrom<&TypedValue> for Vec<String> {
472 type Error = IncompatibleValueTypeError;
473 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
474 match value {
475 TypedValue::StringArray(v) => Ok(v.values.clone()),
476 _ => Err(IncompatibleValueTypeError {}),
477 }
478 }
479 }
480
481 impl TryFrom<TypedValue> for bool {
482 type Error = IncompatibleValueTypeError;
483 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
484 Self::try_from(&value)
485 }
486 }
487
488 impl TryFrom<&TypedValue> for bool {
489 type Error = IncompatibleValueTypeError;
490 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
491 match value {
492 TypedValue::Bool(v) => Ok(*v),
493 _ => Err(IncompatibleValueTypeError {}),
494 }
495 }
496 }
497
498 impl TryFrom<TypedValue> for Vec<bool> {
499 type Error = IncompatibleValueTypeError;
500 fn try_from(value: TypedValue) -> Result<Self, Self::Error> {
501 Self::try_from(&value)
502 }
503 }
504
505 impl TryFrom<&TypedValue> for Vec<bool> {
506 type Error = IncompatibleValueTypeError;
507 fn try_from(value: &TypedValue) -> Result<Self, Self::Error> {
508 match value {
509 TypedValue::BoolArray(v) => Ok(v.values.clone()),
510 _ => Err(IncompatibleValueTypeError {}),
511 }
512 }
513 }
514 }
515 }
516 }
517 pub mod sdv {
518 pub mod databroker {
519 #[allow(clippy::doc_lazy_continuation)]
521 pub mod v1 {
522 pub const FILE_DESCRIPTOR_SET: &[u8] =
523 tonic::include_file_descriptor_set!("sdv.databroker.v1_descriptor");
524 tonic::include_proto!("sdv.databroker.v1");
525 }
526 }
527 }
528}
529
530#[cfg(test)]
531mod tests {
532 use super::*;
533 use crate::v2_proto::value::TypedValue;
534 use test_case::test_case;
535
536 #[test_case(
537 TypedValue::String("one".to_string()),
538 "one".to_string();
539 "for String")]
540 #[test_case(
541 TypedValue::StringArray(proto::kuksa::val::v2::StringArray { values: vec!["one".to_string(), "two".to_string()] }),
542 vec!["one".to_string(), "two".to_string()];
543 "for StringArray")]
544 #[test_case(
545 TypedValue::Bool(true),
546 true;
547 "for Bool")]
548 #[test_case(
549 TypedValue::BoolArray(proto::kuksa::val::v2::BoolArray { values: vec![true, false] }),
550 vec![true, false];
551 "for BoolArray")]
552 #[test_case(
553 TypedValue::Uint32(0x01234567_u32),
554 0x01234567_u32;
555 "for UInt32")]
556 #[test_case(
557 TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array { values: vec![0x01234567_u32, 0x89abcdef_u32] }),
558 vec![0x01234567_u32, 0x89abcdef_u32];
559 "for UInt32Array")]
560 #[test_case(
561 TypedValue::Int32(0x01234567_i32),
562 0x01234567_i32;
563 "for Int32")]
564 #[test_case(
565 TypedValue::Int32Array(proto::kuksa::val::v2::Int32Array { values: vec![0x01234567_i32, 0x89abcdef_u32 as i32] }),
566 vec![0x01234567_i32, 0x89abcdef_u32 as i32];
567 "for Int32Array")]
568 #[test_case(
569 TypedValue::Uint32(0x01234567_u32),
570 0x01234567_u32 as i32;
571 "for UInt32 as Int32")]
572 #[test_case(
573 TypedValue::Uint64(0x0123456789abcdef_u64),
574 0x0123456789abcdef_u64;
575 "for UInt64")]
576 #[test_case(
577 TypedValue::Uint64Array(proto::kuksa::val::v2::Uint64Array { values: vec![0x0123456789abcdef_u64, 0x0123456789abcdef_u64] }),
578 vec![0x0123456789abcdef_u64, 0x0123456789abcdef_u64];
579 "for UInt64Array")]
580 #[test_case(
581 TypedValue::Uint32(0x01234567_u32),
582 0x01234567_u32 as u64;
583 "for UInt32 as UInt64")]
584 #[test_case(
585 TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array { values: vec![0x01234567_u32, 0x89abcdef_u32] }),
586 vec![0x01234567_u32 as u64, 0x89abcdef_u32 as u64];
587 "for UInt32Array as UInt64Array")]
588 #[test_case(
589 TypedValue::Int64(0x0123456789abcdef_i64),
590 0x0123456789abcdef_i64;
591 "for Int64")]
592 #[test_case(
593 TypedValue::Int64Array(proto::kuksa::val::v2::Int64Array { values: vec![0x0123456789abcdef_i64, 0xfedcba9876543210_u64 as i64] }),
594 vec![0x0123456789abcdef_i64, 0xfedcba9876543210_u64 as i64];
595 "for Int64Array")]
596 #[test_case(
597 TypedValue::Uint32(0x01234567_u32),
598 0x01234567_u32 as i64;
599 "for UInt32 as Int64")]
600 #[test_case(
601 TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array { values: vec![0x01234567_u32, 0x89abcdef_u32] }),
602 vec![0x01234567_u32 as i64, 0x89abcdef_u32 as i64];
603 "for UInt32Array as Int64Array")]
604 #[test_case(
605 TypedValue::Int32(0x01234567_i32),
606 0x01234567_i32 as i64;
607 "for Int32 as Int64")]
608 #[test_case(
609 TypedValue::Int32Array(proto::kuksa::val::v2::Int32Array { values: vec![0x01234567_i32, 0x89abcdef_u32 as i32] }),
610 vec![0x01234567_i32 as i64, (0x89abcdef_u32 as i32) as i64];
611 "for Int32Array as Int64Array")]
612 #[test_case(
613 TypedValue::Float(34.345),
614 34.345_f32;
615 "for Float")]
616 #[test_case(
617 TypedValue::FloatArray(proto::kuksa::val::v2::FloatArray { values: vec![34.345, -34.345] }),
618 vec![34.345_f32, -34.345_f32];
619 "for FloatArray")]
620 #[test_case(
621 TypedValue::Uint32(0x01234567_u32),
622 0x01234567_u32 as f32;
623 "for UInt32 as Float")]
624 #[test_case(
625 TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array { values: vec![0x01234567_u32, 0x89abcdef_u32] }),
626 vec![0x01234567_u32 as f32, 0x89abcdef_u32 as f32];
627 "for UInt32Array as Float32Array")]
628 #[test_case(
629 TypedValue::Int32(0x01234567_i32),
630 0x01234567_i32 as f32;
631 "for Int32 as Float")]
632 #[test_case(
633 TypedValue::Int32Array(proto::kuksa::val::v2::Int32Array { values: vec![0x01234567_i32, 0x89abcdef_u32 as i32] }),
634 vec![0x01234567_i32 as f32, (0x89abcdef_u32 as i32) as f32];
635 "for Int32Array as FloatArray")]
636 #[test_case(
637 TypedValue::Double(34.345),
638 34.345_f64;
639 "for Double")]
640 #[test_case(
641 TypedValue::DoubleArray(proto::kuksa::val::v2::DoubleArray { values: vec![34.345, -34.345] }),
642 vec![34.345_f64, -34.345_f64];
643 "for DoubleArray")]
644 #[test_case(
645 TypedValue::Float(34.345),
646 34.345_f32 as f64;
647 "for Float as Double")]
648 #[test_case(
649 TypedValue::FloatArray(proto::kuksa::val::v2::FloatArray { values: vec![34.345, -34.345] }),
650 vec![34.345_f32 as f64, -34.345_f32 as f64];
651 "for FloatArray as DoubleArray")]
652 #[test_case(
653 TypedValue::Uint32(0x89abcdef_u32),
654 0x89abcdef_u32 as f64;
655 "for UInt32 as Double")]
656 #[test_case(
657 TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array { values: vec![0x01234567_u32, 0x89abcdef_u32] }),
658 vec![0x01234567_u32 as f64, 0x89abcdef_u32 as f64];
659 "for UInt32Array as DoubleArray")]
660 #[test_case(
661 TypedValue::Uint64(0xfedcba9876543210_u64),
662 0xfedcba9876543210_u64 as f64;
663 "for UInt64 as Double")]
664 #[test_case(
665 TypedValue::Uint64Array(proto::kuksa::val::v2::Uint64Array { values: vec![0x0123456789abcdef_u64, 0xfedcba9876543210_u64] }),
666 vec![0x0123456789abcdef_u64 as f64, 0xfedcba9876543210_u64 as f64];
667 "for UInt64Array as DoubleArray")]
668 #[test_case(
669 TypedValue::Int32(0x01234567_i32),
670 0x01234567_i32 as f64;
671 "for Int32 as Double")]
672 #[test_case(
673 TypedValue::Int32Array(proto::kuksa::val::v2::Int32Array { values: vec![0x01234567_i32, 0x89abcdef_u32 as i32] }),
674 vec![0x01234567_i32 as f64, (0x89abcdef_u32 as i32) as f64];
675 "for Int32Array as DoubleArray")]
676 #[test_case(
677 TypedValue::Int64(0x0123456789abcdef_i64),
678 0x0123456789abcdef_i64 as f64;
679 "for Int64 as Double")]
680 #[test_case(
681 TypedValue::Int64Array(proto::kuksa::val::v2::Int64Array { values: vec![0x0123456789abcdef_i64, 0xfedcba9876543210_u64 as i64] }),
682 vec![0x0123456789abcdef_i64, 0xfedcba9876543210_u64 as i64];
683 "for Int64Array as DoubleArray")]
684 fn test_try_from_typedvalue<T>(data: TypedValue, expected_value: T)
685 where
686 T: Sized
687 + std::convert::TryFrom<proto::kuksa::val::v2::value::TypedValue>
688 + std::cmp::PartialEq,
689 {
690 assert!(T::try_from(data).is_ok_and(|v| v.eq(&expected_value)));
691 }
692
693 #[test]
694 fn test_try_from_uint32_fails() {
695 assert!(i32::try_from(TypedValue::Uint32(0x90000000_u32)).is_err());
696 }
697
698 #[test]
699 fn test_try_from_uint32array_fails() {
700 let v = TypedValue::Uint32Array(proto::kuksa::val::v2::Uint32Array {
701 values: vec![0x90000000_u32],
702 });
703 assert!(Vec::<i32>::try_from(v).is_err());
704 }
705
706 #[test]
707 fn test_try_from_uint64_fails() {
708 assert!(i64::try_from(TypedValue::Uint64(0x9000000000000000_u64)).is_err());
709 }
710
711 #[test]
712 fn test_try_from_uint64array_fails() {
713 let v = TypedValue::Uint64Array(proto::kuksa::val::v2::Uint64Array {
714 values: vec![0x9000000000000000_u64],
715 });
716 assert!(Vec::<i64>::try_from(v).is_err());
717 }
718}