srad_types/
value.rs

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    /* milliseconds since epoch (Jan 1, 1970) */
44    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/* Array type conversions */
148
149#[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    /* BooleanArray as an array of bit-packed bytes preceded by a 4-byte integer that represents the total number of boolean values */
207    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    /* Set first bytes as count */
211    for x in count.to_le_bytes() {
212        out.push(x);
213    }
214    /* Pack bools into bytes */
215    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    /* StringArray as an array of null terminated strings */
259    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
299/* Trait implementations */
300
301macro_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    /*
718      Test a metric value can be transformed into a protobuf metric value
719    */
720    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            //protobuf value variant is as expected
724            assert!(matches!(proto_val, metric::Value::$proto_type(_)));
725        };
726    }
727
728    /*
729      Test a value for a type can be transformed into a MetricValue into the protobuf metric value struct and back.
730    */
731    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            //invalid bytes prefix
879            let mut bytes = Vec::new();
880            bytes.extend(vec![0, 0, 0]);
881            assert!(proto_to_bool_vec(bytes).is_err());
882
883            //valid prefix but size does not match
884            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            /*non terminated string */
893            assert!(proto_to_string_vec(vec![0x1]).is_err());
894            /* Invalid utf8 string */
895            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            /* invalid size data */
955            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}