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::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    /* 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,
620    Bytes(Vec<u8>),
621    File(Vec<u8>),
622    //Template
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                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    /*
714      Test a metric value can be transformed into a protobuf metric value
715    */
716    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            //protobuf value variant is as expected
720            assert!(matches!(proto_val, metric::Value::$proto_type(_)));
721        };
722    }
723
724    /*
725      Test a value for a type can be transformed into a MetricValue into the protobuf metric value struct and back.
726    */
727    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            //invalid bytes prefix
875            let mut bytes = Vec::new();
876            bytes.extend(vec![0, 0, 0]);
877            assert!(proto_to_bool_vec(bytes).is_err());
878
879            //valid prefix but size does not match
880            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            /*non terminated string */
889            assert!(proto_to_string_vec(vec![0x1]).is_err());
890            /* Invalid utf8 string */
891            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            /* invalid size data */
951            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}