1use std::string::FromUtf8Error;
2
3use crate::payload::{
4 data_set::data_set_value, metric, property_value, template::parameter, DataType,
5};
6use crate::{payload, traits, TemplateValue};
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(pub $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 DataSet(payload::DataSet),
620 Bytes(Vec<u8>),
621 File(Vec<u8>),
622 Template(TemplateValue),
623 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 if let payload::metric::Value::DatasetValue(ds) = value.0 {
672 MetricValueKind::DataSet(ds)
673 } else {
674 return Err(FromMetricValueError::ValueDecodeError(
675 FromValueTypeError::InvalidVariantType,
676 ));
677 }
678 }
679 DataType::Bytes => MetricValueKind::Bytes(Vec::<u8>::try_from(value)?),
680 DataType::File => MetricValueKind::File(Vec::<u8>::try_from(value)?),
681 DataType::Template => MetricValueKind::Template(TemplateValue::try_from(value)?),
682 DataType::PropertySet => {
683 return Err(FromMetricValueError::UnsupportedDataType(
684 DataType::PropertySet,
685 ))
686 }
687 DataType::PropertySetList => {
688 return Err(FromMetricValueError::UnsupportedDataType(
689 DataType::PropertySetList,
690 ))
691 }
692 DataType::Int8Array => MetricValueKind::Int8Array(Vec::<i8>::try_from(value)?),
693 DataType::Int16Array => MetricValueKind::Int16Array(Vec::<i16>::try_from(value)?),
694 DataType::Int32Array => MetricValueKind::Int32Array(Vec::<i32>::try_from(value)?),
695 DataType::Int64Array => MetricValueKind::Int64Array(Vec::<i64>::try_from(value)?),
696 DataType::UInt8Array => MetricValueKind::UInt8Array(Vec::<u8>::try_from(value)?),
697 DataType::UInt16Array => MetricValueKind::UInt16Array(Vec::<u16>::try_from(value)?),
698 DataType::UInt32Array => MetricValueKind::UInt32Array(Vec::<u32>::try_from(value)?),
699 DataType::UInt64Array => MetricValueKind::UInt64Array(Vec::<u64>::try_from(value)?),
700 DataType::FloatArray => MetricValueKind::FloatArray(Vec::<f32>::try_from(value)?),
701 DataType::DoubleArray => MetricValueKind::DoubleArray(Vec::<f64>::try_from(value)?),
702 DataType::BooleanArray => MetricValueKind::BooleanArray(Vec::<bool>::try_from(value)?),
703 DataType::StringArray => MetricValueKind::StringArray(Vec::<String>::try_from(value)?),
704 DataType::DateTimeArray => {
705 MetricValueKind::DateTimeArray(Vec::<DateTime>::try_from(value)?)
706 }
707 };
708 Ok(out)
709 }
710}
711
712#[cfg(test)]
713mod tests {
714
715 use super::*;
716
717 macro_rules! test_metric_value_to_proto_and_back {
721 ($metric_value:expr, $proto_type:ident) => {
722 let proto_val: metric::Value = $metric_value.clone().into();
723 assert!(matches!(proto_val, metric::Value::$proto_type(_)));
725 };
726 }
727
728 macro_rules! test_value_to_proto_value_and_back {
732 ($type:ty, $starting_value:expr, $proto_type:ident) => {
733 let val_metric_value: MetricValue = ($starting_value as $type).into();
734
735 test_metric_value_to_proto_and_back!(val_metric_value, $proto_type);
736
737 let out: $type = val_metric_value.try_into().unwrap();
738 assert_eq!($starting_value as $type, out);
739 };
740 }
741
742 macro_rules! test_numeric_mix_max_to_proto_value_and_back {
743 ($type:ty, $proto_type:ident) => {
744 test_value_to_proto_value_and_back!($type, <$type>::MIN, $proto_type);
745 test_value_to_proto_value_and_back!($type, <$type>::MAX, $proto_type);
746 };
747 }
748
749 mod types {
750 use super::*;
751 use traits::HasDataType;
752
753 #[test]
754 fn i8() {
755 test_numeric_mix_max_to_proto_value_and_back!(i8, IntValue);
756 }
757
758 #[test]
759 fn i16() {
760 test_numeric_mix_max_to_proto_value_and_back!(i16, IntValue);
761 }
762
763 #[test]
764 fn i32() {
765 test_numeric_mix_max_to_proto_value_and_back!(i32, IntValue);
766 }
767
768 #[test]
769 fn i64() {
770 test_numeric_mix_max_to_proto_value_and_back!(i64, LongValue);
771 }
772
773 #[test]
774 fn u8() {
775 test_numeric_mix_max_to_proto_value_and_back!(u8, IntValue);
776 }
777
778 #[test]
779 fn u16() {
780 test_numeric_mix_max_to_proto_value_and_back!(u16, IntValue);
781 }
782
783 #[test]
784 fn u32() {
785 test_numeric_mix_max_to_proto_value_and_back!(u32, IntValue);
786 }
787
788 #[test]
789 fn u64() {
790 test_numeric_mix_max_to_proto_value_and_back!(u64, LongValue);
791 }
792
793 #[test]
794 fn f32() {
795 test_numeric_mix_max_to_proto_value_and_back!(f32, FloatValue);
796 }
797
798 #[test]
799 fn f64() {
800 test_numeric_mix_max_to_proto_value_and_back!(f64, DoubleValue);
801 }
802
803 #[test]
804 fn bool() {
805 test_value_to_proto_value_and_back!(bool, false, BooleanValue);
806 test_value_to_proto_value_and_back!(bool, true, BooleanValue);
807 }
808
809 #[test]
810 fn string() {
811 test_value_to_proto_value_and_back!(String, "test".to_string(), StringValue);
812 }
813
814 #[test]
815 fn datetime() {
816 test_value_to_proto_value_and_back!(DateTime, DateTime::new(0), LongValue);
817 }
818
819 #[test]
820 fn bool_array() {
821 test_value_to_proto_value_and_back!(
822 Vec<bool>,
823 vec![false, false, true, true, false, true, false, false, true, true, false, true],
824 BytesValue
825 );
826 }
827
828 #[test]
829 fn datetime_array() {
830 test_value_to_proto_value_and_back!(
831 Vec<DateTime>,
832 vec![DateTime::new(1), DateTime::new(42)],
833 BytesValue
834 );
835 }
836
837 #[test]
838 fn metric_value_default_datatypes() {
839 assert_eq!(bool::default_datatype(), DataType::Boolean);
840 assert_eq!(i8::default_datatype(), DataType::Int8);
841 assert_eq!(i16::default_datatype(), DataType::Int16);
842 assert_eq!(i32::default_datatype(), DataType::Int32);
843 assert_eq!(i64::default_datatype(), DataType::Int64);
844 assert_eq!(u8::default_datatype(), DataType::UInt8);
845 assert_eq!(u16::default_datatype(), DataType::UInt16);
846 assert_eq!(u32::default_datatype(), DataType::UInt32);
847 assert_eq!(u64::default_datatype(), DataType::UInt64);
848 assert_eq!(f32::default_datatype(), DataType::Float);
849 assert_eq!(f64::default_datatype(), DataType::Double);
850 assert_eq!(String::default_datatype(), DataType::String);
851 assert_eq!(DateTime::default_datatype(), DataType::DateTime);
852 assert_eq!(Vec::<bool>::default_datatype(), DataType::BooleanArray);
853 assert_eq!(Vec::<i8>::default_datatype(), DataType::Int8Array);
854 assert_eq!(Vec::<i16>::default_datatype(), DataType::Int16Array);
855 assert_eq!(Vec::<i32>::default_datatype(), DataType::Int32Array);
856 assert_eq!(Vec::<i64>::default_datatype(), DataType::Int64Array);
857 assert_eq!(Vec::<u8>::default_datatype(), DataType::UInt8Array);
858 assert_eq!(Vec::<u16>::default_datatype(), DataType::UInt16Array);
859 assert_eq!(Vec::<u32>::default_datatype(), DataType::UInt32Array);
860 assert_eq!(Vec::<u64>::default_datatype(), DataType::UInt64Array);
861 assert_eq!(Vec::<f32>::default_datatype(), DataType::FloatArray);
862 assert_eq!(Vec::<f64>::default_datatype(), DataType::DoubleArray);
863 assert_eq!(Vec::<String>::default_datatype(), DataType::StringArray);
864 }
865 }
866
867 mod invalid_from_bytes_vec_conversion {
868 use crate::value::{proto_to_bool_vec, proto_to_string_vec};
869
870 fn test_bool_array_small_buffer(bool_count: u32, bool_byes_size: usize) {
871 let mut bytes = bool_count.to_le_bytes().to_vec();
872 bytes.resize(bool_byes_size, 0);
873 assert!(proto_to_bool_vec(bytes).is_err())
874 }
875
876 #[test]
877 fn bool() {
878 let mut bytes = Vec::new();
880 bytes.extend(vec![0, 0, 0]);
881 assert!(proto_to_bool_vec(bytes).is_err());
882
883 test_bool_array_small_buffer(1, 0);
885 test_bool_array_small_buffer(4, 0);
886 test_bool_array_small_buffer(8, 0);
887 test_bool_array_small_buffer(9, 1);
888 }
889
890 #[test]
891 fn string() {
892 assert!(proto_to_string_vec(vec![0x1]).is_err());
894 assert!(proto_to_string_vec(b"Hello \xF0\x90\x80World\x00".to_vec()).is_err());
896 }
897 }
898
899 mod array_type_bytes_conversion {
900 use super::*;
901
902 fn create_bool_bytes_vec(bool_count: u32, bool_bytes: Vec<u8>) -> Vec<u8> {
903 let mut vec = bool_count.to_le_bytes().to_vec();
904 vec.extend(bool_bytes);
905 vec
906 }
907
908 #[test]
909 fn bool() {
910 let start = vec![true];
911 let bytes = bool_vec_to_proto(start.clone());
912 assert_eq!(bytes, create_bool_bytes_vec(1, vec![0b1000_0000]));
913 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
914
915 let start = vec![true, false, true, false, true, true, true, false, true];
916 let bytes = bool_vec_to_proto(start.clone());
917 assert_eq!(
918 bytes,
919 create_bool_bytes_vec(9, vec![0b1010_1110, 0b1000_0000])
920 );
921 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
922
923 let start = vec![
924 false, false, true, true, false, true, false, false, true, true, false, true,
925 ];
926 let bytes = bool_vec_to_proto(start.clone());
927 assert_eq!(
928 bytes,
929 create_bool_bytes_vec(12, vec![0b0011_0100, 0b1101_0000])
930 );
931 assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
932 }
933
934 #[test]
935 fn string() {
936 let start = vec!["test".to_string()];
937 let bytes = string_vec_to_proto(start.clone());
938 assert_eq!(bytes, b"test\x00".to_vec());
939 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
940
941 let start = vec!["abc".to_string(), "123".to_string()];
942 let bytes = string_vec_to_proto(start.clone());
943 assert_eq!(bytes, b"abc\x00123\x00".to_vec());
944 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
945
946 let start = vec!["abc".to_string(), "".to_string(), "cba".to_string()];
947 let bytes = string_vec_to_proto(start.clone());
948 assert_eq!(bytes, b"abc\x00\x00cba\x00".to_vec());
949 assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
950 }
951
952 #[test]
953 fn test_vec_u8_conversion_invalid_data() {
954 let data = vec![0x00_u8, 0x01, 0x02, 0x03, 0x04];
956 assert!(proto_to_u16_vec(data.clone()).is_err());
957 assert!(proto_to_u32_vec(data.clone()).is_err());
958 assert!(proto_to_u64_vec(data).is_err());
959 }
960
961 macro_rules! test_numeric_vec_u8_conversion{
962 ($($t:ty), *) => {
963 paste! {
964 $(
965 let vec = vec![0 as $t, <$t>::MIN, <$t>::MAX];
966 assert_eq!(vec, [<proto_to_$t:lower _vec>]([<$t:lower _vec_to_proto>](vec.clone())).unwrap());
967 )*
968 }
969 };
970 }
971
972 #[test]
973 fn test_standard_vec_u8_convertable_types() {
974 test_numeric_vec_u8_conversion!(u16, u32, u64, i8, i16, i32, i64, f32, f64);
975 let vec = vec![
976 DateTime::new(0),
977 DateTime::new(u64::MIN),
978 DateTime::new(u64::MAX),
979 ];
980 assert_eq!(
981 vec,
982 proto_to_datetime_vec(datetime_vec_to_proto(vec.clone())).unwrap()
983 );
984 }
985 }
986}