1use std::string::FromUtf8Error;
2
3use crate::payload::{
4 data_set::data_set_value, metric, property_value, template::parameter, DataType,
5};
6use crate::traits;
7
8use paste::paste;
9use thiserror::Error;
10
11macro_rules! impl_wrapper_type_for_proto_value_type {
12 ($new_type:ident, $wrapped_type:ty) => {
13 #[derive(Debug, Clone)]
14 pub struct $new_type($wrapped_type);
15
16 impl $new_type {
17 pub fn new(inner: $wrapped_type) -> Self {
18 Self(inner)
19 }
20 }
21
22 impl From<$new_type> for $wrapped_type {
23 fn from(value: $new_type) -> Self {
24 value.0
25 }
26 }
27
28 impl From<$wrapped_type> for $new_type {
29 fn from(value: $wrapped_type) -> Self {
30 $new_type(value)
31 }
32 }
33 };
34}
35
36impl_wrapper_type_for_proto_value_type!(MetricValue, metric::Value);
37impl_wrapper_type_for_proto_value_type!(PropertyValue, property_value::Value);
38impl_wrapper_type_for_proto_value_type!(DataSetValue, data_set_value::Value);
39impl_wrapper_type_for_proto_value_type!(ParameterValue, parameter::Value);
40
41#[derive(Debug, PartialEq, Clone)]
42pub struct DateTime {
43 pub date_time: u64,
45}
46
47impl DateTime {
48 pub fn new(date_time: u64) -> Self {
49 Self { date_time }
50 }
51
52 #[allow(clippy::wrong_self_convention)]
53 fn to_le_bytes(self) -> [u8; 8] {
54 self.date_time.to_le_bytes()
55 }
56
57 fn from_le_bytes(bytes: [u8; 8]) -> Self {
58 Self::new(u64::from_le_bytes(bytes))
59 }
60}
61
62fn bool_to_proto(val: bool) -> bool {
63 val
64}
65fn u8_to_proto(val: u8) -> u32 {
66 val as u32
67}
68fn u16_to_proto(val: u16) -> u32 {
69 let b = val.to_le_bytes();
70 u32::from_le_bytes([b[0], b[1], 0, 0])
71}
72fn u32_to_proto(val: u32) -> u32 {
73 val
74}
75fn u64_to_proto(val: u64) -> u64 {
76 val
77}
78fn i8_to_proto(val: i8) -> u32 {
79 let b = val.to_le_bytes();
80 u32::from_le_bytes([b[0], 0, 0, 0])
81}
82fn i16_to_proto(val: i16) -> u32 {
83 let b = val.to_le_bytes();
84 u32::from_le_bytes([b[0], b[1], 0, 0])
85}
86fn i32_to_proto(val: i32) -> u32 {
87 u32::from_le_bytes(val.to_le_bytes())
88}
89fn i64_to_proto(val: i64) -> u64 {
90 u64::from_le_bytes(val.to_le_bytes())
91}
92fn f32_to_proto(val: f32) -> f32 {
93 val
94}
95fn f64_to_proto(val: f64) -> f64 {
96 val
97}
98fn string_to_proto(val: String) -> String {
99 val
100}
101fn datetime_to_proto(val: DateTime) -> u64 {
102 val.date_time
103}
104
105fn proto_to_bool(val: bool) -> bool {
106 val
107}
108fn proto_to_u8(val: u32) -> u8 {
109 val as u8
110}
111fn proto_to_u16(val: u32) -> u16 {
112 val as u16
113}
114fn proto_to_u32(val: u32) -> u32 {
115 val
116}
117fn proto_to_u64(val: u64) -> u64 {
118 val
119}
120fn proto_to_i8(val: u32) -> i8 {
121 let bytes = val.to_le_bytes();
122 i8::from_le_bytes([bytes[0]])
123}
124fn proto_to_i16(val: u32) -> i16 {
125 let bytes = val.to_le_bytes();
126 i16::from_le_bytes([bytes[0], bytes[1]])
127}
128fn proto_to_i32(val: u32) -> i32 {
129 i32::from_le_bytes(val.to_le_bytes())
130}
131fn proto_to_i64(val: u64) -> i64 {
132 i64::from_le_bytes(val.to_le_bytes())
133}
134fn proto_to_f32(val: f32) -> f32 {
135 val
136}
137fn proto_to_f64(val: f64) -> f64 {
138 val
139}
140fn proto_to_string(val: String) -> String {
141 val
142}
143fn proto_to_datetime(val: u64) -> DateTime {
144 DateTime { date_time: val }
145}
146
147#[derive(Debug, Error)]
150pub enum FromBytesError {
151 #[error("Invalid format")]
152 InvalidFormat,
153 #[error("Invalid bytes size")]
154 InvalidSize,
155 #[error("StringArray string decoding error {0}")]
156 BadStringElement(#[from] FromUtf8Error),
157}
158
159fn u8_vec_to_proto(vec: Vec<u8>) -> Vec<u8> {
160 vec
161}
162fn proto_to_u8_vec(vec: Vec<u8>) -> Result<Vec<u8>, FromBytesError> {
163 Ok(vec)
164}
165
166macro_rules! define_array_proto_conversions {
167 ($ty:ty) => {
168 paste! {
169 fn [<$ty:lower _vec_to_proto>](vec: Vec<$ty>) -> Vec<u8> {
170 let mut out = Vec::with_capacity(vec.len() * size_of::<$ty>());
171 vec.into_iter().for_each(|x| out.extend(x.to_le_bytes()));
172 out
173 }
174
175 fn [<proto_to_$ty:lower _vec>](vec: Vec<u8>) -> Result<Vec<$ty>,FromBytesError> {
176 let div = std::mem::size_of::<$ty>();
177 let len = vec.len();
178 if len % div != 0 { return Err(FromBytesError::InvalidFormat) }
179 let mut out = Vec::with_capacity(len/div);
180 vec.chunks_exact(div).for_each(|x| { out.push(<$ty>::from_le_bytes(x.try_into().unwrap()));});
181 Ok(out)
182 }
183 }
184 };
185}
186
187define_array_proto_conversions!(i8);
188define_array_proto_conversions!(i16);
189define_array_proto_conversions!(i32);
190define_array_proto_conversions!(i64);
191define_array_proto_conversions!(u16);
192define_array_proto_conversions!(u32);
193define_array_proto_conversions!(u64);
194define_array_proto_conversions!(f32);
195define_array_proto_conversions!(f64);
196define_array_proto_conversions!(DateTime);
197
198fn pack_byte_with_bool(bools: &[bool]) -> u8 {
199 bools
200 .iter()
201 .enumerate()
202 .fold(0u8, |acc, (i, b)| acc | ((*b as u8) << (7 - i)))
203}
204
205fn bool_vec_to_proto(vec: Vec<bool>) -> Vec<u8> {
206 let count = vec.len() as u32;
208 let bool_bytes_len = count.div_ceil(8) as usize;
209 let mut out = Vec::<u8>::with_capacity(std::mem::size_of::<u32>() + bool_bytes_len);
210 for x in count.to_le_bytes() {
212 out.push(x);
213 }
214 let chunks = vec.chunks_exact(8);
216 let remainder = chunks.remainder();
217 chunks
218 .into_iter()
219 .for_each(|chunk| out.push(pack_byte_with_bool(chunk)));
220 if !remainder.is_empty() {
221 out.push(pack_byte_with_bool(remainder))
222 }
223 out
224}
225
226fn proto_to_bool_vec(bytes: Vec<u8>) -> Result<Vec<bool>, FromBytesError> {
227 let len = bytes.len();
228 if len < 4 {
229 return Err(FromBytesError::InvalidSize);
230 }
231 let bool_bytes = len - 4;
232 let bool_count = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
233 if bool_count == 0 {
234 return Ok(Vec::new());
235 }
236
237 let needed_bytes = bool_count.div_ceil(8) as usize;
238 if len < 4 + needed_bytes {
239 return Err(FromBytesError::InvalidFormat);
240 }
241
242 let bools_data = &bytes.as_slice()[4..];
243 let mut bools_out = Vec::with_capacity(bool_count as usize);
244
245 for b in bools_data.iter().take(bool_bytes - 1) {
246 for j in (0..8).rev() {
247 bools_out.push(((b >> j) & 1) == 1);
248 }
249 }
250
251 for i in 0..(bool_count % 8) {
252 bools_out.push(((bools_data[bool_bytes - 1] >> (7 - i)) & 1) == 1);
253 }
254 Ok(bools_out)
255}
256
257fn string_vec_to_proto(vec: Vec<String>) -> Vec<u8> {
258 let buffer_len = vec.iter().fold(0usize, |len, string| len + string.len()) + vec.len();
260 let mut out = Vec::with_capacity(buffer_len);
261 vec.into_iter().for_each(|string| {
262 out.extend(string.into_bytes());
263 out.push(0x0);
264 });
265 out
266}
267
268fn proto_to_string_vec(vec: Vec<u8>) -> Result<Vec<String>, FromBytesError> {
269 if let Some(last) = vec.last() {
270 if *last != 0 {
271 return Err(FromBytesError::InvalidFormat);
272 }
273 } else {
274 return Ok(Vec::new());
275 }
276
277 let mut res = Vec::new();
278
279 let mut split = vec.split(|x| *x == 0).peekable();
280 while let Some(string_data) = split.next() {
281 if split.peek().is_none() {
282 break;
283 }
284 res.push(String::from_utf8(string_data.into())?)
285 }
286 Ok(res)
287}
288
289#[derive(Debug, Error)]
290pub enum FromValueTypeError {
291 #[error("Bytes decoding error: {0}")]
292 ArrayDecodeError(#[from] FromBytesError),
293 #[error("Value variant type was invalid")]
294 InvalidVariantType,
295 #[error("Value contained an invalid value: {0}")]
296 InvalidValue(String),
297}
298
299macro_rules! impl_to_from_proto_value_type_for_type {
302 (
303 $type:ty,
304 $wrapping_type:ty,
305 $proto_variant:path,
306 $to_proto_fn:ident,
307 $from_proto_fn:ident
308 ) => {
309 impl From<$type> for $wrapping_type {
310 fn from(value: $type) -> Self {
311 $proto_variant($to_proto_fn(value)).into()
312 }
313 }
314
315 impl TryFrom<$wrapping_type> for $type {
316 type Error = FromValueTypeError;
317 fn try_from(value: $wrapping_type) -> Result<Self, Self::Error> {
318 if let $proto_variant(v) = value.0 {
319 Ok($from_proto_fn(v))
320 } else {
321 Err(FromValueTypeError::InvalidVariantType)
322 }
323 }
324 }
325 };
326}
327
328macro_rules! array_length {
329 ([$($element:expr),* $(,)?]) => {
330 {
331 0 $(+ {let _ = $element; 1})*
332 }
333 };
334}
335
336macro_rules! impl_has_datatype {
337 ($type:ty, [$($datatypes:expr),* $(,)?]) => {
338 impl traits::HasDataType for $type {
339 fn supported_datatypes() -> &'static[DataType] {
340 static SUPPORTED_TYPES: [DataType; array_length!([$($datatypes),*])] = [$($datatypes),*];
341 &SUPPORTED_TYPES
342 }
343 }
344 };
345}
346
347macro_rules! impl_basic_type {
348 ($type:ty, [$($datatypes:expr),* $(,)?], $variant_metric:path, $variant_property:path, $variant_dataset:path, $variant_parameter:path, $to_proto_fn:ident, $from_proto_fn:ident) => {
349
350 impl_has_datatype!($type, [$($datatypes),*]);
351
352 impl traits::MetricValue for $type {}
353 impl traits::PropertyValue for $type {}
354 impl traits::DataSetValue for $type {}
355 impl traits::ParameterValue for $type {}
356
357 impl_to_from_proto_value_type_for_type!($type, MetricValue, $variant_metric, $to_proto_fn, $from_proto_fn) ;
358 impl_to_from_proto_value_type_for_type!($type, PropertyValue, $variant_property, $to_proto_fn, $from_proto_fn);
359 impl_to_from_proto_value_type_for_type!($type, DataSetValue, $variant_dataset, $to_proto_fn, $from_proto_fn);
360 impl_to_from_proto_value_type_for_type!($type, ParameterValue, $variant_parameter, $to_proto_fn, $from_proto_fn);
361 };
362}
363
364impl_basic_type!(
365 bool,
366 [DataType::Boolean],
367 metric::Value::BooleanValue,
368 property_value::Value::BooleanValue,
369 data_set_value::Value::BooleanValue,
370 parameter::Value::BooleanValue,
371 bool_to_proto,
372 proto_to_bool
373);
374impl_basic_type!(
375 u8,
376 [DataType::UInt8],
377 metric::Value::IntValue,
378 property_value::Value::IntValue,
379 data_set_value::Value::IntValue,
380 parameter::Value::IntValue,
381 u8_to_proto,
382 proto_to_u8
383);
384impl_basic_type!(
385 u16,
386 [DataType::UInt16],
387 metric::Value::IntValue,
388 property_value::Value::IntValue,
389 data_set_value::Value::IntValue,
390 parameter::Value::IntValue,
391 u16_to_proto,
392 proto_to_u16
393);
394impl_basic_type!(
395 u32,
396 [DataType::UInt32],
397 metric::Value::IntValue,
398 property_value::Value::IntValue,
399 data_set_value::Value::IntValue,
400 parameter::Value::IntValue,
401 u32_to_proto,
402 proto_to_u32
403);
404impl_basic_type!(
405 u64,
406 [DataType::UInt64],
407 metric::Value::LongValue,
408 property_value::Value::LongValue,
409 data_set_value::Value::LongValue,
410 parameter::Value::LongValue,
411 u64_to_proto,
412 proto_to_u64
413);
414impl_basic_type!(
415 i8,
416 [DataType::Int8],
417 metric::Value::IntValue,
418 property_value::Value::IntValue,
419 data_set_value::Value::IntValue,
420 parameter::Value::IntValue,
421 i8_to_proto,
422 proto_to_i8
423);
424impl_basic_type!(
425 i16,
426 [DataType::Int16],
427 metric::Value::IntValue,
428 property_value::Value::IntValue,
429 data_set_value::Value::IntValue,
430 parameter::Value::IntValue,
431 i16_to_proto,
432 proto_to_i16
433);
434impl_basic_type!(
435 i32,
436 [DataType::Int32],
437 metric::Value::IntValue,
438 property_value::Value::IntValue,
439 data_set_value::Value::IntValue,
440 parameter::Value::IntValue,
441 i32_to_proto,
442 proto_to_i32
443);
444impl_basic_type!(
445 i64,
446 [DataType::Int64],
447 metric::Value::LongValue,
448 property_value::Value::LongValue,
449 data_set_value::Value::LongValue,
450 parameter::Value::LongValue,
451 i64_to_proto,
452 proto_to_i64
453);
454impl_basic_type!(
455 f32,
456 [DataType::Float],
457 metric::Value::FloatValue,
458 property_value::Value::FloatValue,
459 data_set_value::Value::FloatValue,
460 parameter::Value::FloatValue,
461 f32_to_proto,
462 proto_to_f32
463);
464impl_basic_type!(
465 f64,
466 [DataType::Double],
467 metric::Value::DoubleValue,
468 property_value::Value::DoubleValue,
469 data_set_value::Value::DoubleValue,
470 parameter::Value::DoubleValue,
471 f64_to_proto,
472 proto_to_f64
473);
474impl_basic_type!(
475 String,
476 [DataType::String, DataType::Text],
477 metric::Value::StringValue,
478 property_value::Value::StringValue,
479 data_set_value::Value::StringValue,
480 parameter::Value::StringValue,
481 string_to_proto,
482 proto_to_string
483);
484impl_basic_type!(
485 DateTime,
486 [DataType::DateTime],
487 metric::Value::LongValue,
488 property_value::Value::LongValue,
489 data_set_value::Value::LongValue,
490 parameter::Value::LongValue,
491 datetime_to_proto,
492 proto_to_datetime
493);
494
495macro_rules! impl_vec_type_metric_value_conversions {
496 ($type:ty, [$($datatypes:expr),* $(,)?], $to_proto_fn:ident, $from_proto_fn:ident) => {
497
498 impl_has_datatype!(Vec::<$type>, [$($datatypes),*]);
499
500 impl traits::MetricValue for Vec<$type> {}
501
502 impl From<Vec<$type>> for MetricValue {
503 fn from(value: Vec<$type>) -> Self {
504 metric::Value::BytesValue($to_proto_fn(value)).into()
505 }
506 }
507
508 impl TryFrom<MetricValue> for Vec<$type> {
509 type Error = FromValueTypeError;
510 fn try_from(value: MetricValue) -> Result<Self, Self::Error> {
511 if let metric::Value::BytesValue(v) = value.0 {
512 Ok( $from_proto_fn(v)?)
513 }
514 else {
515 Err(FromValueTypeError::InvalidVariantType)
516 }
517 }
518 }
519
520 };
521}
522
523impl_vec_type_metric_value_conversions!(
524 bool,
525 [DataType::BooleanArray],
526 bool_vec_to_proto,
527 proto_to_bool_vec
528);
529impl_vec_type_metric_value_conversions!(
530 u8,
531 [DataType::UInt8Array, DataType::Bytes],
532 u8_vec_to_proto,
533 proto_to_u8_vec
534);
535impl_vec_type_metric_value_conversions!(
536 u16,
537 [DataType::UInt16Array],
538 u16_vec_to_proto,
539 proto_to_u16_vec
540);
541impl_vec_type_metric_value_conversions!(
542 u32,
543 [DataType::UInt32Array],
544 u32_vec_to_proto,
545 proto_to_u32_vec
546);
547impl_vec_type_metric_value_conversions!(
548 u64,
549 [DataType::UInt64Array],
550 u64_vec_to_proto,
551 proto_to_u64_vec
552);
553impl_vec_type_metric_value_conversions!(
554 i8,
555 [DataType::Int8Array],
556 i8_vec_to_proto,
557 proto_to_i8_vec
558);
559impl_vec_type_metric_value_conversions!(
560 i16,
561 [DataType::Int16Array],
562 i16_vec_to_proto,
563 proto_to_i16_vec
564);
565impl_vec_type_metric_value_conversions!(
566 i32,
567 [DataType::Int32Array],
568 i32_vec_to_proto,
569 proto_to_i32_vec
570);
571impl_vec_type_metric_value_conversions!(
572 i64,
573 [DataType::Int64Array],
574 i64_vec_to_proto,
575 proto_to_i64_vec
576);
577impl_vec_type_metric_value_conversions!(
578 f32,
579 [DataType::FloatArray],
580 f32_vec_to_proto,
581 proto_to_f32_vec
582);
583impl_vec_type_metric_value_conversions!(
584 f64,
585 [DataType::DoubleArray],
586 f64_vec_to_proto,
587 proto_to_f64_vec
588);
589impl_vec_type_metric_value_conversions!(
590 DateTime,
591 [DataType::DateTimeArray],
592 datetime_vec_to_proto,
593 proto_to_datetime_vec
594);
595impl_vec_type_metric_value_conversions!(
596 String,
597 [DataType::StringArray],
598 string_vec_to_proto,
599 proto_to_string_vec
600);
601
602#[derive(Debug)]
603pub enum MetricValueKind {
604 Int8(i8),
605 Int16(i16),
606 Int32(i32),
607 Int64(i64),
608 UInt8(u8),
609 UInt16(u16),
610 UInt32(u32),
611 UInt64(u64),
612 Float(f32),
613 Double(f64),
614 Boolean(bool),
615 String(String),
616 DateTime(DateTime),
617 Text(String),
618 Uuid(String),
619 Bytes(Vec<u8>),
621 File(Vec<u8>),
622 Int8Array(Vec<i8>),
624 Int16Array(Vec<i16>),
625 Int32Array(Vec<i32>),
626 Int64Array(Vec<i64>),
627 UInt8Array(Vec<u8>),
628 UInt16Array(Vec<u16>),
629 UInt32Array(Vec<u32>),
630 UInt64Array(Vec<u64>),
631 FloatArray(Vec<f32>),
632 DoubleArray(Vec<f64>),
633 BooleanArray(Vec<bool>),
634 StringArray(Vec<String>),
635 DateTimeArray(Vec<DateTime>),
636}
637
638#[derive(Debug, Error)]
639pub enum FromMetricValueError {
640 #[error("Bytes decoding error: {0}")]
641 ValueDecodeError(#[from] FromValueTypeError),
642 #[error("Unsupported datatype")]
643 UnsupportedDataType(DataType),
644 #[error("Invalid datatype provided")]
645 InvalidDataType,
646}
647
648impl MetricValueKind {
649 pub fn try_from_metric_value(
650 datatype: DataType,
651 value: MetricValue,
652 ) -> Result<Self, FromMetricValueError> {
653 let out = match datatype {
654 DataType::Unknown => return Err(FromMetricValueError::InvalidDataType),
655 DataType::Int8 => MetricValueKind::Int8(i8::try_from(value)?),
656 DataType::Int16 => MetricValueKind::Int16(i16::try_from(value)?),
657 DataType::Int32 => MetricValueKind::Int32(i32::try_from(value)?),
658 DataType::Int64 => MetricValueKind::Int64(i64::try_from(value)?),
659 DataType::UInt8 => MetricValueKind::UInt8(u8::try_from(value)?),
660 DataType::UInt16 => MetricValueKind::UInt16(u16::try_from(value)?),
661 DataType::UInt32 => MetricValueKind::UInt32(u32::try_from(value)?),
662 DataType::UInt64 => MetricValueKind::UInt64(u64::try_from(value)?),
663 DataType::Float => MetricValueKind::Float(f32::try_from(value)?),
664 DataType::Double => MetricValueKind::Double(f64::try_from(value)?),
665 DataType::Boolean => MetricValueKind::Boolean(bool::try_from(value)?),
666 DataType::String => MetricValueKind::String(String::try_from(value)?),
667 DataType::DateTime => MetricValueKind::DateTime(DateTime::try_from(value)?),
668 DataType::Text => MetricValueKind::String(String::try_from(value)?),
669 DataType::Uuid => MetricValueKind::Uuid(String::try_from(value)?),
670 DataType::DataSet => {
671 return Err(FromMetricValueError::UnsupportedDataType(DataType::DataSet))
672 }
673 DataType::Bytes => MetricValueKind::Bytes(Vec::<u8>::try_from(value)?),
674 DataType::File => MetricValueKind::File(Vec::<u8>::try_from(value)?),
675 DataType::Template => {
676 return Err(FromMetricValueError::UnsupportedDataType(DataType::DataSet))
677 }
678 DataType::PropertySet => {
679 return Err(FromMetricValueError::UnsupportedDataType(
680 DataType::PropertySet,
681 ))
682 }
683 DataType::PropertySetList => {
684 return Err(FromMetricValueError::UnsupportedDataType(
685 DataType::PropertySetList,
686 ))
687 }
688 DataType::Int8Array => MetricValueKind::Int8Array(Vec::<i8>::try_from(value)?),
689 DataType::Int16Array => MetricValueKind::Int16Array(Vec::<i16>::try_from(value)?),
690 DataType::Int32Array => MetricValueKind::Int32Array(Vec::<i32>::try_from(value)?),
691 DataType::Int64Array => MetricValueKind::Int64Array(Vec::<i64>::try_from(value)?),
692 DataType::UInt8Array => MetricValueKind::UInt8Array(Vec::<u8>::try_from(value)?),
693 DataType::UInt16Array => MetricValueKind::UInt16Array(Vec::<u16>::try_from(value)?),
694 DataType::UInt32Array => MetricValueKind::UInt32Array(Vec::<u32>::try_from(value)?),
695 DataType::UInt64Array => MetricValueKind::UInt64Array(Vec::<u64>::try_from(value)?),
696 DataType::FloatArray => MetricValueKind::FloatArray(Vec::<f32>::try_from(value)?),
697 DataType::DoubleArray => MetricValueKind::DoubleArray(Vec::<f64>::try_from(value)?),
698 DataType::BooleanArray => MetricValueKind::BooleanArray(Vec::<bool>::try_from(value)?),
699 DataType::StringArray => MetricValueKind::StringArray(Vec::<String>::try_from(value)?),
700 DataType::DateTimeArray => {
701 MetricValueKind::DateTimeArray(Vec::<DateTime>::try_from(value)?)
702 }
703 };
704 Ok(out)
705 }
706}
707
708#[cfg(test)]
709mod tests {
710
711 use super::*;
712
713 macro_rules! test_metric_value_to_proto_and_back {
717 ($metric_value:expr, $proto_type:ident) => {
718 let proto_val: metric::Value = $metric_value.clone().into();
719 assert!(matches!(proto_val, metric::Value::$proto_type(_)));
721 };
722 }
723
724 macro_rules! test_value_to_proto_value_and_back {
728 ($type:ty, $starting_value:expr, $proto_type:ident) => {
729 let val_metric_value: MetricValue = ($starting_value as $type).into();
730
731 test_metric_value_to_proto_and_back!(val_metric_value, $proto_type);
732
733 let out: $type = val_metric_value.try_into().unwrap();
734 assert_eq!($starting_value as $type, out);
735 };
736 }
737
738 macro_rules! test_numeric_mix_max_to_proto_value_and_back {
739 ($type:ty, $proto_type:ident) => {
740 test_value_to_proto_value_and_back!($type, <$type>::MIN, $proto_type);
741 test_value_to_proto_value_and_back!($type, <$type>::MAX, $proto_type);
742 };
743 }
744
745 mod types {
746 use super::*;
747 use traits::HasDataType;
748
749 #[test]
750 fn i8() {
751 test_numeric_mix_max_to_proto_value_and_back!(i8, IntValue);
752 }
753
754 #[test]
755 fn i16() {
756 test_numeric_mix_max_to_proto_value_and_back!(i16, IntValue);
757 }
758
759 #[test]
760 fn i32() {
761 test_numeric_mix_max_to_proto_value_and_back!(i32, IntValue);
762 }
763
764 #[test]
765 fn i64() {
766 test_numeric_mix_max_to_proto_value_and_back!(i64, LongValue);
767 }
768
769 #[test]
770 fn u8() {
771 test_numeric_mix_max_to_proto_value_and_back!(u8, IntValue);
772 }
773
774 #[test]
775 fn u16() {
776 test_numeric_mix_max_to_proto_value_and_back!(u16, IntValue);
777 }
778
779 #[test]
780 fn u32() {
781 test_numeric_mix_max_to_proto_value_and_back!(u32, IntValue);
782 }
783
784 #[test]
785 fn u64() {
786 test_numeric_mix_max_to_proto_value_and_back!(u64, LongValue);
787 }
788
789 #[test]
790 fn f32() {
791 test_numeric_mix_max_to_proto_value_and_back!(f32, FloatValue);
792 }
793
794 #[test]
795 fn f64() {
796 test_numeric_mix_max_to_proto_value_and_back!(f64, DoubleValue);
797 }
798
799 #[test]
800 fn bool() {
801 test_value_to_proto_value_and_back!(bool, false, BooleanValue);
802 test_value_to_proto_value_and_back!(bool, true, BooleanValue);
803 }
804
805 #[test]
806 fn string() {
807 test_value_to_proto_value_and_back!(String, "test".to_string(), StringValue);
808 }
809
810 #[test]
811 fn datetime() {
812 test_value_to_proto_value_and_back!(DateTime, DateTime::new(0), LongValue);
813 }
814
815 #[test]
816 fn bool_array() {
817 test_value_to_proto_value_and_back!(
818 Vec<bool>,
819 vec![false, false, true, true, false, true, false, false, true, true, false, true],
820 BytesValue
821 );
822 }
823
824 #[test]
825 fn datetime_array() {
826 test_value_to_proto_value_and_back!(
827 Vec<DateTime>,
828 vec![DateTime::new(1), DateTime::new(42)],
829 BytesValue
830 );
831 }
832
833 #[test]
834 fn metric_value_default_datatypes() {
835 assert_eq!(bool::default_datatype(), DataType::Boolean);
836 assert_eq!(i8::default_datatype(), DataType::Int8);
837 assert_eq!(i16::default_datatype(), DataType::Int16);
838 assert_eq!(i32::default_datatype(), DataType::Int32);
839 assert_eq!(i64::default_datatype(), DataType::Int64);
840 assert_eq!(u8::default_datatype(), DataType::UInt8);
841 assert_eq!(u16::default_datatype(), DataType::UInt16);
842 assert_eq!(u32::default_datatype(), DataType::UInt32);
843 assert_eq!(u64::default_datatype(), DataType::UInt64);
844 assert_eq!(f32::default_datatype(), DataType::Float);
845 assert_eq!(f64::default_datatype(), DataType::Double);
846 assert_eq!(String::default_datatype(), DataType::String);
847 assert_eq!(DateTime::default_datatype(), DataType::DateTime);
848 assert_eq!(Vec::<bool>::default_datatype(), DataType::BooleanArray);
849 assert_eq!(Vec::<i8>::default_datatype(), DataType::Int8Array);
850 assert_eq!(Vec::<i16>::default_datatype(), DataType::Int16Array);
851 assert_eq!(Vec::<i32>::default_datatype(), DataType::Int32Array);
852 assert_eq!(Vec::<i64>::default_datatype(), DataType::Int64Array);
853 assert_eq!(Vec::<u8>::default_datatype(), DataType::UInt8Array);
854 assert_eq!(Vec::<u16>::default_datatype(), DataType::UInt16Array);
855 assert_eq!(Vec::<u32>::default_datatype(), DataType::UInt32Array);
856 assert_eq!(Vec::<u64>::default_datatype(), DataType::UInt64Array);
857 assert_eq!(Vec::<f32>::default_datatype(), DataType::FloatArray);
858 assert_eq!(Vec::<f64>::default_datatype(), DataType::DoubleArray);
859 assert_eq!(Vec::<String>::default_datatype(), DataType::StringArray);
860 }
861 }
862
863 mod invalid_from_bytes_vec_conversion {
864 use crate::value::{proto_to_bool_vec, proto_to_string_vec};
865
866 fn test_bool_array_small_buffer(bool_count: u32, bool_byes_size: usize) {
867 let mut bytes = bool_count.to_le_bytes().to_vec();
868 bytes.resize(bool_byes_size, 0);
869 assert!(proto_to_bool_vec(bytes).is_err())
870 }
871
872 #[test]
873 fn bool() {
874 let mut bytes = Vec::new();
876 bytes.extend(vec![0, 0, 0]);
877 assert!(proto_to_bool_vec(bytes).is_err());
878
879 test_bool_array_small_buffer(1, 0);
881 test_bool_array_small_buffer(4, 0);
882 test_bool_array_small_buffer(8, 0);
883 test_bool_array_small_buffer(9, 1);
884 }
885
886 #[test]
887 fn string() {
888 assert!(proto_to_string_vec(vec![0x1]).is_err());
890 assert!(proto_to_string_vec(b"Hello \xF0\x90\x80World\x00".to_vec()).is_err());
892 }
893 }
894
895 mod array_type_bytes_conversion {
896 use super::*;
897
898 fn create_bool_bytes_vec(bool_count: u32, bool_bytes: Vec<u8>) -> Vec<u8> {
899 let mut vec = bool_count.to_le_bytes().to_vec();
900 vec.extend(bool_bytes);
901 vec
902 }
903
904 #[test]
905 fn bool() {
906 let start = vec![true];
907 let bytes = bool_vec_to_proto(start.clone());
908 assert_eq!(bytes, create_bool_bytes_vec(1, vec![0b1000_0000]));
909 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
910
911 let start = vec![true, false, true, false, true, true, true, false, true];
912 let bytes = bool_vec_to_proto(start.clone());
913 assert_eq!(
914 bytes,
915 create_bool_bytes_vec(9, vec![0b1010_1110, 0b1000_0000])
916 );
917 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
918
919 let start = vec![
920 false, false, true, true, false, true, false, false, true, true, false, true,
921 ];
922 let bytes = bool_vec_to_proto(start.clone());
923 assert_eq!(
924 bytes,
925 create_bool_bytes_vec(12, vec![0b0011_0100, 0b1101_0000])
926 );
927 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
928 }
929
930 #[test]
931 fn string() {
932 let start = vec!["test".to_string()];
933 let bytes = string_vec_to_proto(start.clone());
934 assert_eq!(bytes, b"test\x00".to_vec());
935 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
936
937 let start = vec!["abc".to_string(), "123".to_string()];
938 let bytes = string_vec_to_proto(start.clone());
939 assert_eq!(bytes, b"abc\x00123\x00".to_vec());
940 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
941
942 let start = vec!["abc".to_string(), "".to_string(), "cba".to_string()];
943 let bytes = string_vec_to_proto(start.clone());
944 assert_eq!(bytes, b"abc\x00\x00cba\x00".to_vec());
945 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
946 }
947
948 #[test]
949 fn test_vec_u8_conversion_invalid_data() {
950 let data = vec![0x00_u8, 0x01, 0x02, 0x03, 0x04];
952 assert!(proto_to_u16_vec(data.clone()).is_err());
953 assert!(proto_to_u32_vec(data.clone()).is_err());
954 assert!(proto_to_u64_vec(data).is_err());
955 }
956
957 macro_rules! test_numeric_vec_u8_conversion{
958 ($($t:ty), *) => {
959 paste! {
960 $(
961 let vec = vec![0 as $t, <$t>::MIN, <$t>::MAX];
962 assert_eq!(vec, [<proto_to_$t:lower _vec>]([<$t:lower _vec_to_proto>](vec.clone())).unwrap());
963 )*
964 }
965 };
966 }
967
968 #[test]
969 fn test_standard_vec_u8_convertable_types() {
970 test_numeric_vec_u8_conversion!(u16, u32, u64, i8, i16, i32, i64, f32, f64);
971 let vec = vec![
972 DateTime::new(0),
973 DateTime::new(u64::MIN),
974 DateTime::new(u64::MAX),
975 ];
976 assert_eq!(
977 vec,
978 proto_to_datetime_vec(datetime_vec_to_proto(vec.clone())).unwrap()
979 );
980 }
981 }
982}