1use std::string::FromUtf8Error;
2
3use crate::payload::{
4 data_set::data_set_value, metric, property_value, template::parameter, DataType,
5};
6use crate::traits;
7
8use paste::paste;
9use thiserror::Error;
10
11macro_rules! impl_wrapper_type_for_proto_value_type {
12 ($new_type:ident, $wrapped_type:ty) => {
13 #[derive(Debug, Clone)]
14 pub struct $new_type($wrapped_type);
15
16 impl $new_type {
17 pub fn new(inner: $wrapped_type) -> Self {
18 Self(inner)
19 }
20 }
21
22 impl From<$new_type> for $wrapped_type {
23 fn from(value: $new_type) -> Self {
24 value.0
25 }
26 }
27
28 impl From<$wrapped_type> for $new_type {
29 fn from(value: $wrapped_type) -> Self {
30 $new_type(value)
31 }
32 }
33 };
34}
35
36impl_wrapper_type_for_proto_value_type!(MetricValue, metric::Value);
37impl_wrapper_type_for_proto_value_type!(PropertyValue, property_value::Value);
38impl_wrapper_type_for_proto_value_type!(DataSetValue, data_set_value::Value);
39impl_wrapper_type_for_proto_value_type!(ParameterValue, parameter::Value);
40
41#[derive(Debug, PartialEq, Clone)]
42pub struct DateTime {
43 pub date_time: u64,
45}
46
47impl DateTime {
48 pub fn new(date_time: u64) -> Self {
49 Self { date_time }
50 }
51
52 #[allow(clippy::wrong_self_convention)]
53 fn to_le_bytes(self) -> [u8; 8] {
54 self.date_time.to_le_bytes()
55 }
56
57 fn from_le_bytes(bytes: [u8; 8]) -> Self {
58 Self::new(u64::from_le_bytes(bytes))
59 }
60}
61
62fn bool_to_proto(val: bool) -> bool {
63 val
64}
65fn u8_to_proto(val: u8) -> u32 {
66 val as u32
67}
68fn u16_to_proto(val: u16) -> u32 {
69 let b = val.to_le_bytes();
70 u32::from_le_bytes([b[0], b[1], 0, 0])
71}
72fn u32_to_proto(val: u32) -> u32 {
73 val
74}
75fn u64_to_proto(val: u64) -> u64 {
76 val
77}
78fn i8_to_proto(val: i8) -> u32 {
79 let b = val.to_le_bytes();
80 u32::from_le_bytes([b[0], 0, 0, 0])
81}
82fn i16_to_proto(val: i16) -> u32 {
83 let b = val.to_le_bytes();
84 u32::from_le_bytes([b[0], b[1], 0, 0])
85}
86fn i32_to_proto(val: i32) -> u32 {
87 u32::from_le_bytes(val.to_le_bytes())
88}
89fn i64_to_proto(val: i64) -> u64 {
90 u64::from_le_bytes(val.to_le_bytes())
91}
92fn f32_to_proto(val: f32) -> f32 {
93 val
94}
95fn f64_to_proto(val: f64) -> f64 {
96 val
97}
98fn string_to_proto(val: String) -> String {
99 val
100}
101fn datetime_to_proto(val: DateTime) -> u64 {
102 val.date_time
103}
104
105fn proto_to_bool(val: bool) -> bool {
106 val
107}
108fn proto_to_u8(val: u32) -> u8 {
109 val as u8
110}
111fn proto_to_u16(val: u32) -> u16 {
112 val as u16
113}
114fn proto_to_u32(val: u32) -> u32 {
115 val
116}
117fn proto_to_u64(val: u64) -> u64 {
118 val
119}
120fn proto_to_i8(val: u32) -> i8 {
121 let bytes = val.to_le_bytes();
122 i8::from_le_bytes([bytes[0]])
123}
124fn proto_to_i16(val: u32) -> i16 {
125 let bytes = val.to_le_bytes();
126 i16::from_le_bytes([bytes[0], bytes[1]])
127}
128fn proto_to_i32(val: u32) -> i32 {
129 i32::from_le_bytes(val.to_le_bytes())
130}
131fn proto_to_i64(val: u64) -> i64 {
132 i64::from_le_bytes(val.to_le_bytes())
133}
134fn proto_to_f32(val: f32) -> f32 {
135 val
136}
137fn proto_to_f64(val: f64) -> f64 {
138 val
139}
140fn proto_to_string(val: String) -> String {
141 val
142}
143fn proto_to_datetime(val: u64) -> DateTime {
144 DateTime { date_time: val }
145}
146
147#[derive(Debug, Error)]
150pub enum FromBytesError {
151 #[error("Invalid format")]
152 InvalidFormat,
153 #[error("Invalid bytes size")]
154 InvalidSize,
155 #[error("StringArray string decoding error {0}")]
156 BadStringElement(#[from] FromUtf8Error),
157}
158
159fn u8_vec_to_proto(vec: Vec<u8>) -> Vec<u8> {
160 vec
161}
162fn proto_to_u8_vec(vec: Vec<u8>) -> Result<Vec<u8>, FromBytesError> {
163 Ok(vec)
164}
165
166macro_rules! define_array_proto_conversions {
167 ($ty:ty) => {
168 paste! {
169 fn [<$ty:lower _vec_to_proto>](vec: Vec<$ty>) -> Vec<u8> {
170 let mut out = Vec::with_capacity(vec.len() * size_of::<$ty>());
171 vec.into_iter().for_each(|x| out.extend(x.to_le_bytes()));
172 out
173 }
174
175 fn [<proto_to_$ty:lower _vec>](vec: Vec<u8>) -> Result<Vec<$ty>,FromBytesError> {
176 let div = std::mem::size_of::<$ty>();
177 let len = vec.len();
178 if len % div != 0 { return Err(FromBytesError::InvalidFormat) }
179 let mut out = Vec::with_capacity(len/div);
180 vec.chunks_exact(div).for_each(|x| { out.push(<$ty>::from_le_bytes(x.try_into().unwrap()));});
181 Ok(out)
182 }
183 }
184 };
185}
186
187define_array_proto_conversions!(i8);
188define_array_proto_conversions!(i16);
189define_array_proto_conversions!(i32);
190define_array_proto_conversions!(i64);
191define_array_proto_conversions!(u16);
192define_array_proto_conversions!(u32);
193define_array_proto_conversions!(u64);
194define_array_proto_conversions!(f32);
195define_array_proto_conversions!(f64);
196define_array_proto_conversions!(DateTime);
197
198fn pack_byte_with_bool(bools: &[bool]) -> u8 {
199 bools
200 .iter()
201 .enumerate()
202 .fold(0u8, |acc, (i, b)| acc | ((*b as u8) << (7 - i)))
203}
204
205fn bool_vec_to_proto(vec: Vec<bool>) -> Vec<u8> {
206 let count = vec.len() as u32;
208 let bool_bytes_len = count.div_ceil(8) as usize;
209 let mut out = Vec::<u8>::with_capacity(std::mem::size_of::<u32>() + bool_bytes_len);
210 for x in count.to_le_bytes() {
212 out.push(x);
213 }
214 let chunks = vec.chunks_exact(8);
216 let remainder = chunks.remainder();
217 chunks
218 .into_iter()
219 .for_each(|chunk| out.push(pack_byte_with_bool(chunk)));
220 if !remainder.is_empty() {
221 out.push(pack_byte_with_bool(remainder))
222 }
223 out
224}
225
226fn proto_to_bool_vec(bytes: Vec<u8>) -> Result<Vec<bool>, FromBytesError> {
227 let len = bytes.len();
228 if len < 4 {
229 return Err(FromBytesError::InvalidSize);
230 }
231 let bool_bytes = len - 4;
232 let bool_count = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
233 if bool_count == 0 {
234 return Ok(Vec::new());
235 }
236
237 let needed_bytes = bool_count.div_ceil(8) as usize;
238 if len < 4 + needed_bytes {
239 return Err(FromBytesError::InvalidFormat);
240 }
241
242 let bools_data = &bytes.as_slice()[4..];
243 let mut bools_out = Vec::with_capacity(bool_count as usize);
244
245 for b in bools_data.iter().take(bool_bytes - 1) {
246 for j in (0..8).rev() {
247 bools_out.push(((b >> j) & 1) == 1);
248 }
249 }
250
251 for i in 0..(bool_count % 8) {
252 bools_out.push(((bools_data[bool_bytes - 1] >> (7 - i)) & 1) == 1);
253 }
254 Ok(bools_out)
255}
256
257fn string_vec_to_proto(vec: Vec<String>) -> Vec<u8> {
258 let buffer_len = vec.iter().fold(0usize, |len, string| len + string.len()) + vec.len();
260 let mut out = Vec::with_capacity(buffer_len);
261 vec.into_iter().for_each(|string| {
262 out.extend(string.into_bytes());
263 out.push(0x0);
264 });
265 out
266}
267
268fn proto_to_string_vec(vec: Vec<u8>) -> Result<Vec<String>, FromBytesError> {
269 if let Some(last) = vec.last() {
270 if *last != 0 {
271 return Err(FromBytesError::InvalidFormat);
272 }
273 } else {
274 return Ok(Vec::new());
275 }
276
277 let mut res = Vec::new();
278
279 let mut split = vec.split(|x| *x == 0).peekable();
280 while let Some(string_data) = split.next() {
281 if split.peek().is_none() {
282 break;
283 }
284 res.push(String::from_utf8(string_data.into())?)
285 }
286 Ok(res)
287}
288
289#[derive(Debug, Error)]
290pub enum FromValueTypeError {
291 #[error("Bytes decoding error: {0}")]
292 ArrayDecodeError(#[from] FromBytesError),
293 #[error("Value variant type was invalid")]
294 InvalidVariantType,
295 #[error("Value contained an invalid value: {0}")]
296 InvalidValue(String),
297}
298
299macro_rules! impl_to_from_proto_value_type_for_type {
302 (
303 $type:ty,
304 $wrapping_type:ty,
305 $proto_variant:path,
306 $to_proto_fn:ident,
307 $from_proto_fn:ident
308 ) => {
309 impl From<$type> for $wrapping_type {
310 fn from(value: $type) -> Self {
311 $proto_variant($to_proto_fn(value)).into()
312 }
313 }
314
315 impl TryFrom<$wrapping_type> for $type {
316 type Error = FromValueTypeError;
317 fn try_from(value: $wrapping_type) -> Result<Self, Self::Error> {
318 if let $proto_variant(v) = value.0 {
319 Ok($from_proto_fn(v))
320 } else {
321 Err(FromValueTypeError::InvalidVariantType)
322 }
323 }
324 }
325 };
326}
327
328macro_rules! array_length {
329 ([$($element:expr),* $(,)?]) => {
330 {
331 0 $(+ {let _ = $element; 1})*
332 }
333 };
334}
335
336macro_rules! impl_has_datatype {
337 ($type:ty, [$($datatypes:expr),* $(,)?]) => {
338 impl traits::HasDataType for $type {
339 fn supported_datatypes() -> &'static[DataType] {
340 static SUPPORTED_TYPES: [DataType; array_length!([$($datatypes),*])] = [$($datatypes),*];
341 &SUPPORTED_TYPES
342 }
343 }
344 };
345}
346
347macro_rules! impl_basic_type {
348 ($type:ty, [$($datatypes:expr),* $(,)?], $variant_metric:path, $variant_property:path, $variant_dataset:path, $variant_parameter:path, $to_proto_fn:ident, $from_proto_fn:ident) => {
349
350 impl_has_datatype!($type, [$($datatypes),*]);
351
352 impl traits::MetricValue for $type {}
353 impl traits::PropertyValue for $type {}
354 impl traits::DataSetValue for $type {}
355 impl traits::ParameterValue for $type {}
356
357 impl_to_from_proto_value_type_for_type!($type, MetricValue, $variant_metric, $to_proto_fn, $from_proto_fn) ;
358 impl_to_from_proto_value_type_for_type!($type, PropertyValue, $variant_property, $to_proto_fn, $from_proto_fn);
359 impl_to_from_proto_value_type_for_type!($type, DataSetValue, $variant_dataset, $to_proto_fn, $from_proto_fn);
360 impl_to_from_proto_value_type_for_type!($type, ParameterValue, $variant_parameter, $to_proto_fn, $from_proto_fn);
361 };
362}
363
364impl_basic_type!(
365 bool,
366 [DataType::Boolean],
367 metric::Value::BooleanValue,
368 property_value::Value::BooleanValue,
369 data_set_value::Value::BooleanValue,
370 parameter::Value::BooleanValue,
371 bool_to_proto,
372 proto_to_bool
373);
374impl_basic_type!(
375 u8,
376 [DataType::UInt8],
377 metric::Value::IntValue,
378 property_value::Value::IntValue,
379 data_set_value::Value::IntValue,
380 parameter::Value::IntValue,
381 u8_to_proto,
382 proto_to_u8
383);
384impl_basic_type!(
385 u16,
386 [DataType::UInt16],
387 metric::Value::IntValue,
388 property_value::Value::IntValue,
389 data_set_value::Value::IntValue,
390 parameter::Value::IntValue,
391 u16_to_proto,
392 proto_to_u16
393);
394impl_basic_type!(
395 u32,
396 [DataType::UInt32],
397 metric::Value::IntValue,
398 property_value::Value::IntValue,
399 data_set_value::Value::IntValue,
400 parameter::Value::IntValue,
401 u32_to_proto,
402 proto_to_u32
403);
404impl_basic_type!(
405 u64,
406 [DataType::UInt64],
407 metric::Value::LongValue,
408 property_value::Value::LongValue,
409 data_set_value::Value::LongValue,
410 parameter::Value::LongValue,
411 u64_to_proto,
412 proto_to_u64
413);
414impl_basic_type!(
415 i8,
416 [DataType::Int8],
417 metric::Value::IntValue,
418 property_value::Value::IntValue,
419 data_set_value::Value::IntValue,
420 parameter::Value::IntValue,
421 i8_to_proto,
422 proto_to_i8
423);
424impl_basic_type!(
425 i16,
426 [DataType::Int16],
427 metric::Value::IntValue,
428 property_value::Value::IntValue,
429 data_set_value::Value::IntValue,
430 parameter::Value::IntValue,
431 i16_to_proto,
432 proto_to_i16
433);
434impl_basic_type!(
435 i32,
436 [DataType::Int32],
437 metric::Value::IntValue,
438 property_value::Value::IntValue,
439 data_set_value::Value::IntValue,
440 parameter::Value::IntValue,
441 i32_to_proto,
442 proto_to_i32
443);
444impl_basic_type!(
445 i64,
446 [DataType::Int64],
447 metric::Value::LongValue,
448 property_value::Value::LongValue,
449 data_set_value::Value::LongValue,
450 parameter::Value::LongValue,
451 i64_to_proto,
452 proto_to_i64
453);
454impl_basic_type!(
455 f32,
456 [DataType::Float],
457 metric::Value::FloatValue,
458 property_value::Value::FloatValue,
459 data_set_value::Value::FloatValue,
460 parameter::Value::FloatValue,
461 f32_to_proto,
462 proto_to_f32
463);
464impl_basic_type!(
465 f64,
466 [DataType::Double],
467 metric::Value::DoubleValue,
468 property_value::Value::DoubleValue,
469 data_set_value::Value::DoubleValue,
470 parameter::Value::DoubleValue,
471 f64_to_proto,
472 proto_to_f64
473);
474impl_basic_type!(
475 String,
476 [DataType::String, DataType::Text],
477 metric::Value::StringValue,
478 property_value::Value::StringValue,
479 data_set_value::Value::StringValue,
480 parameter::Value::StringValue,
481 string_to_proto,
482 proto_to_string
483);
484impl_basic_type!(
485 DateTime,
486 [DataType::DateTime],
487 metric::Value::LongValue,
488 property_value::Value::LongValue,
489 data_set_value::Value::LongValue,
490 parameter::Value::LongValue,
491 datetime_to_proto,
492 proto_to_datetime
493);
494
495macro_rules! impl_vec_type_metric_value_conversions {
496 ($type:ty, [$($datatypes:expr),* $(,)?], $to_proto_fn:ident, $from_proto_fn:ident) => {
497
498 impl_has_datatype!(Vec::<$type>, [$($datatypes),*]);
499
500 impl traits::MetricValue for Vec<$type> {}
501
502 impl From<Vec<$type>> for MetricValue {
503 fn from(value: Vec<$type>) -> Self {
504 metric::Value::BytesValue($to_proto_fn(value)).into()
505 }
506 }
507
508 impl TryFrom<MetricValue> for Vec<$type> {
509 type Error = FromValueTypeError;
510 fn try_from(value: MetricValue) -> Result<Self, Self::Error> {
511 if let metric::Value::BytesValue(v) = value.0 {
512 Ok( $from_proto_fn(v)?)
513 }
514 else {
515 Err(FromValueTypeError::InvalidVariantType)
516 }
517 }
518 }
519
520 };
521}
522
523impl_vec_type_metric_value_conversions!(
524 bool,
525 [DataType::BooleanArray],
526 bool_vec_to_proto,
527 proto_to_bool_vec
528);
529impl_vec_type_metric_value_conversions!(
530 u8,
531 [DataType::UInt8Array, DataType::Bytes],
532 u8_vec_to_proto,
533 proto_to_u8_vec
534);
535impl_vec_type_metric_value_conversions!(
536 u16,
537 [DataType::UInt16Array],
538 u16_vec_to_proto,
539 proto_to_u16_vec
540);
541impl_vec_type_metric_value_conversions!(
542 u32,
543 [DataType::UInt32Array],
544 u32_vec_to_proto,
545 proto_to_u32_vec
546);
547impl_vec_type_metric_value_conversions!(
548 u64,
549 [DataType::UInt64Array],
550 u64_vec_to_proto,
551 proto_to_u64_vec
552);
553impl_vec_type_metric_value_conversions!(
554 i8,
555 [DataType::Int8Array],
556 i8_vec_to_proto,
557 proto_to_i8_vec
558);
559impl_vec_type_metric_value_conversions!(
560 i16,
561 [DataType::Int16Array],
562 i16_vec_to_proto,
563 proto_to_i16_vec
564);
565impl_vec_type_metric_value_conversions!(
566 i32,
567 [DataType::Int32Array],
568 i32_vec_to_proto,
569 proto_to_i32_vec
570);
571impl_vec_type_metric_value_conversions!(
572 i64,
573 [DataType::Int64Array],
574 i64_vec_to_proto,
575 proto_to_i64_vec
576);
577impl_vec_type_metric_value_conversions!(
578 f32,
579 [DataType::FloatArray],
580 f32_vec_to_proto,
581 proto_to_f32_vec
582);
583impl_vec_type_metric_value_conversions!(
584 f64,
585 [DataType::DoubleArray],
586 f64_vec_to_proto,
587 proto_to_f64_vec
588);
589impl_vec_type_metric_value_conversions!(
590 DateTime,
591 [DataType::DateTimeArray],
592 datetime_vec_to_proto,
593 proto_to_datetime_vec
594);
595impl_vec_type_metric_value_conversions!(
596 String,
597 [DataType::StringArray],
598 string_vec_to_proto,
599 proto_to_string_vec
600);
601
602#[cfg(test)]
603mod tests {
604
605 use super::*;
606
607 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 assert!(matches!(proto_val, metric::Value::$proto_type(_)));
615 };
616 }
617
618 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 let mut bytes = Vec::new();
770 bytes.extend(vec![0, 0, 0]);
771 assert!(proto_to_bool_vec(bytes).is_err());
772
773 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 assert!(proto_to_string_vec(vec![0x1]).is_err());
784 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 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}