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#[cfg(test)]
603mod tests {
604
605    use super::*;
606
607    /*
608      Test a metric value can be transformed into a protobuf metric value
609    */
610    macro_rules! test_metric_value_to_proto_and_back {
611        ($metric_value:expr, $proto_type:ident) => {
612            let proto_val: metric::Value = $metric_value.clone().into();
613            //protobuf value variant is as expected
614            assert!(matches!(proto_val, metric::Value::$proto_type(_)));
615        };
616    }
617
618    /*
619      Test a value for a type can be transformed into a MetricValue into the protobuf metric value struct and back.
620    */
621    macro_rules! test_value_to_proto_value_and_back {
622        ($type:ty, $starting_value:expr, $proto_type:ident) => {
623            let val_metric_value: MetricValue = ($starting_value as $type).into();
624
625            test_metric_value_to_proto_and_back!(val_metric_value, $proto_type);
626
627            let out: $type = val_metric_value.try_into().unwrap();
628            assert_eq!($starting_value as $type, out);
629        };
630    }
631
632    macro_rules! test_numeric_mix_max_to_proto_value_and_back {
633        ($type:ty, $proto_type:ident) => {
634            test_value_to_proto_value_and_back!($type, <$type>::MIN, $proto_type);
635            test_value_to_proto_value_and_back!($type, <$type>::MAX, $proto_type);
636        };
637    }
638
639    mod types {
640        use super::*;
641        use traits::HasDataType;
642
643        #[test]
644        fn i8() {
645            test_numeric_mix_max_to_proto_value_and_back!(i8, IntValue);
646        }
647
648        #[test]
649        fn i16() {
650            test_numeric_mix_max_to_proto_value_and_back!(i16, IntValue);
651        }
652
653        #[test]
654        fn i32() {
655            test_numeric_mix_max_to_proto_value_and_back!(i32, IntValue);
656        }
657
658        #[test]
659        fn i64() {
660            test_numeric_mix_max_to_proto_value_and_back!(i64, LongValue);
661        }
662
663        #[test]
664        fn u8() {
665            test_numeric_mix_max_to_proto_value_and_back!(u8, IntValue);
666        }
667
668        #[test]
669        fn u16() {
670            test_numeric_mix_max_to_proto_value_and_back!(u16, IntValue);
671        }
672
673        #[test]
674        fn u32() {
675            test_numeric_mix_max_to_proto_value_and_back!(u32, IntValue);
676        }
677
678        #[test]
679        fn u64() {
680            test_numeric_mix_max_to_proto_value_and_back!(u64, LongValue);
681        }
682
683        #[test]
684        fn f32() {
685            test_numeric_mix_max_to_proto_value_and_back!(f32, FloatValue);
686        }
687
688        #[test]
689        fn f64() {
690            test_numeric_mix_max_to_proto_value_and_back!(f64, DoubleValue);
691        }
692
693        #[test]
694        fn bool() {
695            test_value_to_proto_value_and_back!(bool, false, BooleanValue);
696            test_value_to_proto_value_and_back!(bool, true, BooleanValue);
697        }
698
699        #[test]
700        fn string() {
701            test_value_to_proto_value_and_back!(String, "test".to_string(), StringValue);
702        }
703
704        #[test]
705        fn datetime() {
706            test_value_to_proto_value_and_back!(DateTime, DateTime::new(0), LongValue);
707        }
708
709        #[test]
710        fn bool_array() {
711            test_value_to_proto_value_and_back!(
712                Vec<bool>,
713                vec![false, false, true, true, false, true, false, false, true, true, false, true],
714                BytesValue
715            );
716        }
717
718        #[test]
719        fn datetime_array() {
720            test_value_to_proto_value_and_back!(
721                Vec<DateTime>,
722                vec![DateTime::new(1), DateTime::new(42)],
723                BytesValue
724            );
725        }
726
727        #[test]
728        fn metric_value_default_datatypes() {
729            assert_eq!(bool::default_datatype(), DataType::Boolean);
730            assert_eq!(i8::default_datatype(), DataType::Int8);
731            assert_eq!(i16::default_datatype(), DataType::Int16);
732            assert_eq!(i32::default_datatype(), DataType::Int32);
733            assert_eq!(i64::default_datatype(), DataType::Int64);
734            assert_eq!(u8::default_datatype(), DataType::UInt8);
735            assert_eq!(u16::default_datatype(), DataType::UInt16);
736            assert_eq!(u32::default_datatype(), DataType::UInt32);
737            assert_eq!(u64::default_datatype(), DataType::UInt64);
738            assert_eq!(f32::default_datatype(), DataType::Float);
739            assert_eq!(f64::default_datatype(), DataType::Double);
740            assert_eq!(String::default_datatype(), DataType::String);
741            assert_eq!(DateTime::default_datatype(), DataType::DateTime);
742            assert_eq!(Vec::<bool>::default_datatype(), DataType::BooleanArray);
743            assert_eq!(Vec::<i8>::default_datatype(), DataType::Int8Array);
744            assert_eq!(Vec::<i16>::default_datatype(), DataType::Int16Array);
745            assert_eq!(Vec::<i32>::default_datatype(), DataType::Int32Array);
746            assert_eq!(Vec::<i64>::default_datatype(), DataType::Int64Array);
747            assert_eq!(Vec::<u8>::default_datatype(), DataType::UInt8Array);
748            assert_eq!(Vec::<u16>::default_datatype(), DataType::UInt16Array);
749            assert_eq!(Vec::<u32>::default_datatype(), DataType::UInt32Array);
750            assert_eq!(Vec::<u64>::default_datatype(), DataType::UInt64Array);
751            assert_eq!(Vec::<f32>::default_datatype(), DataType::FloatArray);
752            assert_eq!(Vec::<f64>::default_datatype(), DataType::DoubleArray);
753            assert_eq!(Vec::<String>::default_datatype(), DataType::StringArray);
754        }
755    }
756
757    mod invalid_from_bytes_vec_conversion {
758        use crate::value::{proto_to_bool_vec, proto_to_string_vec};
759
760        fn test_bool_array_small_buffer(bool_count: u32, bool_byes_size: usize) {
761            let mut bytes = bool_count.to_le_bytes().to_vec();
762            bytes.resize(bool_byes_size, 0);
763            assert!(proto_to_bool_vec(bytes).is_err())
764        }
765
766        #[test]
767        fn bool() {
768            //invalid bytes prefix
769            let mut bytes = Vec::new();
770            bytes.extend(vec![0, 0, 0]);
771            assert!(proto_to_bool_vec(bytes).is_err());
772
773            //valid prefix but size does not match
774            test_bool_array_small_buffer(1, 0);
775            test_bool_array_small_buffer(4, 0);
776            test_bool_array_small_buffer(8, 0);
777            test_bool_array_small_buffer(9, 1);
778        }
779
780        #[test]
781        fn string() {
782            /*non terminated string */
783            assert!(proto_to_string_vec(vec![0x1]).is_err());
784            /* Invalid utf8 string */
785            assert!(proto_to_string_vec(b"Hello \xF0\x90\x80World\x00".to_vec()).is_err());
786        }
787    }
788
789    mod array_type_bytes_conversion {
790        use super::*;
791
792        fn create_bool_bytes_vec(bool_count: u32, bool_bytes: Vec<u8>) -> Vec<u8> {
793            let mut vec = bool_count.to_le_bytes().to_vec();
794            vec.extend(bool_bytes);
795            vec
796        }
797
798        #[test]
799        fn bool() {
800            let start = vec![true];
801            let bytes = bool_vec_to_proto(start.clone());
802            assert_eq!(bytes, create_bool_bytes_vec(1, vec![0b1000_0000]));
803            assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
804
805            let start = vec![true, false, true, false, true, true, true, false, true];
806            let bytes = bool_vec_to_proto(start.clone());
807            assert_eq!(
808                bytes,
809                create_bool_bytes_vec(9, vec![0b1010_1110, 0b1000_0000])
810            );
811            assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
812
813            let start = vec![
814                false, false, true, true, false, true, false, false, true, true, false, true,
815            ];
816            let bytes = bool_vec_to_proto(start.clone());
817            assert_eq!(
818                bytes,
819                create_bool_bytes_vec(12, vec![0b0011_0100, 0b1101_0000])
820            );
821            assert_eq!(proto_to_bool_vec(bytes).unwrap(), start);
822        }
823
824        #[test]
825        fn string() {
826            let start = vec!["test".to_string()];
827            let bytes = string_vec_to_proto(start.clone());
828            assert_eq!(bytes, b"test\x00".to_vec());
829            assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
830
831            let start = vec!["abc".to_string(), "123".to_string()];
832            let bytes = string_vec_to_proto(start.clone());
833            assert_eq!(bytes, b"abc\x00123\x00".to_vec());
834            assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
835
836            let start = vec!["abc".to_string(), "".to_string(), "cba".to_string()];
837            let bytes = string_vec_to_proto(start.clone());
838            assert_eq!(bytes, b"abc\x00\x00cba\x00".to_vec());
839            assert_eq!(proto_to_string_vec(bytes).unwrap(), start);
840        }
841
842        #[test]
843        fn test_vec_u8_conversion_invalid_data() {
844            /* invalid size data */
845            let data = vec![0x00_u8, 0x01, 0x02, 0x03, 0x04];
846            assert!(proto_to_u16_vec(data.clone()).is_err());
847            assert!(proto_to_u32_vec(data.clone()).is_err());
848            assert!(proto_to_u64_vec(data).is_err());
849        }
850
851        macro_rules! test_numeric_vec_u8_conversion{
852        ($($t:ty), *) => {
853          paste! {
854            $(
855              let vec = vec![0 as $t, <$t>::MIN, <$t>::MAX];
856              assert_eq!(vec, [<proto_to_$t:lower _vec>]([<$t:lower _vec_to_proto>](vec.clone())).unwrap());
857            )*
858          }
859        };
860    }
861
862        #[test]
863        fn test_standard_vec_u8_convertable_types() {
864            test_numeric_vec_u8_conversion!(u16, u32, u64, i8, i16, i32, i64, f32, f64);
865            let vec = vec![
866                DateTime::new(0),
867                DateTime::new(u64::MIN),
868                DateTime::new(u64::MAX),
869            ];
870            assert_eq!(
871                vec,
872                proto_to_datetime_vec(datetime_vec_to_proto(vec.clone())).unwrap()
873            );
874        }
875    }
876}