Skip to main content

cdr_encoding/
cdr_deserializer.rs

1use std::marker::PhantomData;
2
3#[cfg(test)]
4use byteorder::{BigEndian, LittleEndian};
5use byteorder::{ByteOrder, ReadBytesExt};
6#[allow(unused_imports)]
7use log::{debug, error, info, trace, warn};
8use pastey::paste;
9#[cfg(test)]
10use serde::de::DeserializeOwned;
11use serde::de::{
12  self, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess, VariantAccess, Visitor,
13};
14
15pub use super::error::{Error, Result};
16
17/// Deserializer type for converting CDR data stream to Rust objects.
18///
19/// `CdrDeserializer` is about three machine words of data, so fairly cheap to
20/// create.
21pub struct CdrDeserializer<'i, BO> {
22  phantom: PhantomData<BO>, // This field exists only to provide use for BO. See PhantomData docs.
23  input: &'i [u8],          /* We borrow the input data, therefore we carry lifetime 'i all
24                             * around. */
25  serialized_data_count: usize, // This is to keep track of CDR data alignment requirements.
26}
27
28impl<'de, BO> CdrDeserializer<'de, BO>
29where
30  BO: ByteOrder,
31{
32  pub fn new(input: &'de [u8]) -> CdrDeserializer<'de, BO> {
33    CdrDeserializer::<BO> {
34      phantom: PhantomData,
35      input,
36      serialized_data_count: 0,
37    }
38  }
39
40  /// How many bytes of input stream have been consumed
41  pub fn bytes_consumed(&self) -> usize {
42    self.serialized_data_count
43  }
44
45  /// Read the first bytes in the input.
46  fn next_bytes(&mut self, count: usize) -> Result<&'de [u8]> {
47    if count <= self.input.len() {
48      let (head, tail) = self.input.split_at(count);
49      self.input = tail;
50      self.serialized_data_count += count;
51      Ok(head)
52    } else {
53      Err(Error::Eof)
54    }
55  }
56
57  /// consume and discard bytes
58  fn remove_bytes_from_input(&mut self, count: usize) -> Result<()> {
59    let _pad = self.next_bytes(count)?;
60    Ok(())
61  }
62
63  fn calculate_padding_count_from_written_bytes_and_remove(
64    &mut self,
65    type_octet_alignment: usize,
66  ) -> Result<()> {
67    let modulo = self.serialized_data_count % type_octet_alignment;
68    if modulo == 0 {
69      Ok(())
70    } else {
71      let padding = type_octet_alignment - modulo;
72      self.remove_bytes_from_input(padding)
73    }
74  }
75}
76
77/// Deserialize an object from `&[u8]` based on a [`serde::Deserialize`]
78/// implementation.
79///
80/// return deserialized object + count of bytes consumed
81pub fn from_bytes<'de, T, BO>(input_bytes: &'de [u8]) -> Result<(T, usize)>
82where
83  T: serde::Deserialize<'de>,
84  BO: ByteOrder,
85{
86  from_bytes_with::<PhantomData<T>, BO>(input_bytes, PhantomData)
87}
88
89/// Deserialize type based on a [`serde::Deserialize`] implementation.
90///
91/// return deserialized object + count of bytes consumed
92pub fn from_bytes_with<'de, S, BO>(input_bytes: &'de [u8], decoder: S) -> Result<(S::Value, usize)>
93where
94  S: DeserializeSeed<'de>,
95  BO: ByteOrder,
96{
97  let mut deserializer = CdrDeserializer::<BO>::new(input_bytes);
98  let t = decoder.deserialize(&mut deserializer)?;
99  Ok((t, deserializer.serialized_data_count))
100}
101
102#[cfg(test)]
103pub fn deserialize_from_little_endian<T>(s: &[u8]) -> Result<T>
104where
105  T: DeserializeOwned,
106{
107  let mut deserializer = CdrDeserializer::<LittleEndian>::new(s);
108  T::deserialize(&mut deserializer)
109}
110
111#[cfg(test)]
112pub fn deserialize_from_big_endian<T>(s: &[u8]) -> Result<T>
113where
114  T: DeserializeOwned,
115{
116  let mut deserializer = CdrDeserializer::<BigEndian>::new(s);
117  T::deserialize(&mut deserializer)
118}
119
120/// macro for writing primitive number deserializers. Rust does not allow
121/// declaring a macro inside impl block, so it is here.
122macro_rules! deserialize_multibyte_number {
123  ($num_type:ident) => {
124    paste! {
125      fn [<deserialize_ $num_type>]<V>(self, visitor: V) -> Result<V::Value>
126      where
127        V: Visitor<'de>,
128      {
129        const SIZE :usize = std::mem::size_of::<$num_type>();
130        static_assertions::const_assert!(SIZE > 1); // "multibyte means size must be > 1"
131        self.calculate_padding_count_from_written_bytes_and_remove(SIZE)?;
132        visitor.[<visit_ $num_type>](
133          self.next_bytes(SIZE)?.[<read_ $num_type>]::<BO>().unwrap() )
134      }
135    }
136  };
137}
138
139impl<'de, 'a, 'c, BO> de::Deserializer<'de> for &'a mut CdrDeserializer<'c, BO>
140where
141  'c: 'de,
142  BO: ByteOrder,
143{
144  type Error = Error;
145
146  /// CDR serialization is not a self-describing data format, so we cannot
147  /// implement this. Serialized CDR data has no clue to what each bit means,
148  /// so we have to know the structure beforehand.
149  fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
150  where
151    V: Visitor<'de>,
152  {
153    Err(Error::NotSelfDescribingFormat(
154      "CDR cannot deserialize \"any\" type. ".to_string(),
155    ))
156  }
157
158  // 15.3.1.5 Boolean
159  //  Boolean values are encoded as single octets, where TRUE is the value 1, and
160  // FALSE as 0.
161  fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value>
162  where
163    V: Visitor<'de>,
164  {
165    match self.next_bytes(1)?.first().unwrap() {
166      0 => visitor.visit_bool(false),
167      1 => visitor.visit_bool(true),
168      x => Err(Error::BadBoolean(*x)),
169    }
170  }
171
172  deserialize_multibyte_number!(i16);
173  deserialize_multibyte_number!(i32);
174  deserialize_multibyte_number!(i64);
175
176  deserialize_multibyte_number!(u16);
177  deserialize_multibyte_number!(u32);
178  deserialize_multibyte_number!(u64);
179
180  deserialize_multibyte_number!(f32);
181  deserialize_multibyte_number!(f64);
182
183  // Single-byte numbers have a bit simpler logic: No alignment, no endianness.
184  fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value>
185  where
186    V: Visitor<'de>,
187  {
188    visitor.visit_i8(self.next_bytes(1)?.read_i8().unwrap())
189  }
190
191  fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value>
192  where
193    V: Visitor<'de>,
194  {
195    visitor.visit_u8(self.next_bytes(1)?.read_u8().unwrap())
196  }
197
198  /// Since this is Rust, a char is 32-bit Unicode codepoint.
199  fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
200  where
201    V: Visitor<'de>,
202  {
203    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
204    let codepoint = self.next_bytes(4)?.read_u32::<BO>().unwrap();
205    match char::from_u32(codepoint) {
206      Some(c) => visitor.visit_char(c),
207      None => Err(Error::BadChar(codepoint)),
208    }
209  }
210
211  fn deserialize_str<V>(self, visitor: V) -> Result<V::Value>
212  where
213    V: Visitor<'de>,
214  {
215    // read string length
216    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
217    let bytes_len = self.next_bytes(4)?.read_u32::<BO>().unwrap() as usize;
218
219    let bytes = self.next_bytes(bytes_len)?; // length includes null terminator
220
221    // Remove the null terminating character
222    let bytes_without_null = match bytes.split_last() {
223      None => {
224        //  This is a hacky "Fix" for IntercomDDS version 01.05 protocol version 2.1.
225        // Where IntercomDDS sends an empty string with no NULL terminator.
226        info!("deserialize_str: Received string with not even a null terminator.");
227        bytes
228      }
229      Some((null_char, contents)) => {
230        if *null_char != 0 {
231          warn!(
232            "deserialize_str: Expected string null terminator, got {:#x} instead.",
233            null_char
234          );
235        }
236        contents
237      }
238    };
239
240    // convert contents without NUL to String and apply visitor
241    std::str::from_utf8(bytes_without_null)
242      .map_err(Error::BadUTF8)
243      .and_then(|s| visitor.visit_str(s))
244
245    // match  {
246    //   Ok(s) => visitor.visit_str(s),
247    //   Err(utf8_err) => Err(Error::BadUTF8(utf8_err)),
248    // }
249  }
250
251  fn deserialize_string<V>(self, visitor: V) -> Result<V::Value>
252  where
253    V: Visitor<'de>,
254  {
255    self.deserialize_str(visitor)
256  }
257
258  // Byte strings
259
260  fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value>
261  where
262    V: Visitor<'de>,
263  {
264    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
265    let len = self.next_bytes(4)?.read_u32::<BO>().unwrap() as usize;
266    let bytes = self.next_bytes(len)?;
267    visitor.visit_borrowed_bytes(bytes)
268  }
269
270  fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value>
271  where
272    V: Visitor<'de>,
273  {
274    // Align to 4 bytes
275    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
276    // Length prefix
277    let len = self.next_bytes(4)?.read_u32::<BO>().unwrap() as usize;
278    // Read the entire buffer at once
279    let buf = self.next_bytes(len)?.to_vec();
280
281    visitor.visit_byte_buf(buf)
282
283  }
284
285  fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
286  where
287    V: Visitor<'de>,
288  {
289    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
290    let enum_tag = self.next_bytes(4)?.read_u32::<BO>().unwrap();
291    match enum_tag {
292      0 => visitor.visit_none(),
293      1 => visitor.visit_some(self),
294      wtf => Err(Error::BadOption(wtf)),
295    }
296  }
297
298  fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value>
299  where
300    V: Visitor<'de>,
301  {
302    // Unit data is not put on wire, to match behavior with cdr_serializer
303    visitor.visit_unit()
304  }
305
306  fn deserialize_unit_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
307  where
308    V: Visitor<'de>,
309  {
310    self.deserialize_unit(visitor) // This means a named type, which has no
311                                   // data.
312  }
313
314  fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::Value>
315  where
316    V: Visitor<'de>,
317  {
318    visitor.visit_newtype_struct(self)
319  }
320
321  /// Sequences are encoded as an unsigned long value, followed by the elements
322  /// of the
323  // sequence. The initial unsigned long contains the number of elements in the
324  // sequence. The elements of the sequence are encoded as specified for their
325  // type.
326  fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value>
327  where
328    V: Visitor<'de>,
329  {
330    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
331    let element_count = self.next_bytes(4)?.read_u32::<BO>().unwrap() as usize;
332    visitor.visit_seq(SequenceHelper::new(self, element_count))
333  }
334
335  // if sequence is fixed length array then number of elements is not included
336  fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value>
337  where
338    V: Visitor<'de>,
339  {
340    visitor.visit_seq(SequenceHelper::new(self, len))
341  }
342
343  fn deserialize_tuple_struct<V>(
344    self,
345    _name: &'static str,
346    len: usize,
347    visitor: V,
348  ) -> Result<V::Value>
349  where
350    V: Visitor<'de>,
351  {
352    visitor.visit_seq(SequenceHelper::new(self, len))
353  }
354
355  fn deserialize_map<V>(self, visitor: V) -> Result<V::Value>
356  where
357    V: Visitor<'de>,
358  {
359    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
360    let element_count = self.next_bytes(4)?.read_u32::<BO>().unwrap() as usize;
361    visitor.visit_map(SequenceHelper::new(self, element_count))
362  }
363
364  fn deserialize_struct<V>(
365    self,
366    _name: &'static str,
367    fields: &'static [&'static str],
368    visitor: V,
369  ) -> Result<V::Value>
370  where
371    V: Visitor<'de>,
372  {
373    visitor.visit_seq(SequenceHelper::new(self, fields.len()))
374  }
375
376  /// Enum values are encoded as unsigned longs. (u32)
377  /// The numeric values associated with enum identifiers are determined by the
378  /// order in which the identifiers appear in the enum declaration. The first
379  /// enum identifier has the numeric value zero (0). Successive enum
380  /// identifiers take ascending numeric values, in order of declaration from
381  /// left to right.
382  fn deserialize_enum<V>(
383    self,
384    _name: &'static str,
385    _variants: &'static [&'static str],
386    visitor: V,
387  ) -> Result<V::Value>
388  where
389    V: Visitor<'de>,
390  {
391    self.calculate_padding_count_from_written_bytes_and_remove(4)?;
392    visitor.visit_enum(EnumerationHelper::<BO>::new(self))
393  }
394
395  /// An identifier in Serde is the type that identifies a field of a struct or
396  /// the variant of an enum. In JSON, struct fields and enum variants are
397  /// represented as strings. In other formats they may be represented as
398  /// numeric indices.
399  fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value>
400  where
401    V: Visitor<'de>,
402  {
403    self.deserialize_u32(visitor)
404  }
405
406  fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value>
407  where
408    V: Visitor<'de>,
409  {
410    self.deserialize_any(visitor)
411  }
412
413  fn is_human_readable(&self) -> bool {
414    false
415  }
416}
417
418// ----------------------------------------------------------
419
420struct EnumerationHelper<'a, 'i: 'a, BO> {
421  de: &'a mut CdrDeserializer<'i, BO>,
422}
423
424impl<'a, 'i, BO> EnumerationHelper<'a, 'i, BO>
425where
426  BO: ByteOrder,
427{
428  fn new(de: &'a mut CdrDeserializer<'i, BO>) -> Self {
429    EnumerationHelper::<BO> { de }
430  }
431}
432
433impl<'de, 'a, 'i, BO> EnumAccess<'de> for EnumerationHelper<'a, 'i, BO>
434where
435  'i: 'de,
436  BO: ByteOrder,
437{
438  type Error = Error;
439  type Variant = Self;
440
441  fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant)>
442  where
443    V: DeserializeSeed<'de>,
444  {
445    // preceding deserialize_enum aligned to 4
446    let enum_tag = self.de.next_bytes(4)?.read_u32::<BO>().unwrap();
447    let val: Result<_> = seed.deserialize(enum_tag.into_deserializer());
448    Ok((val?, self))
449  }
450}
451
452// ----------------------------------------------------------
453
454impl<'de, 'a, 'i, BO> VariantAccess<'de> for EnumerationHelper<'a, 'i, BO>
455where
456  'i: 'de,
457  BO: ByteOrder,
458{
459  type Error = Error;
460
461  fn unit_variant(self) -> Result<()> {
462    Ok(())
463  }
464
465  fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value>
466  where
467    T: DeserializeSeed<'de>,
468  {
469    seed.deserialize(self.de)
470  }
471
472  fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value>
473  where
474    V: Visitor<'de>,
475  {
476    de::Deserializer::deserialize_tuple(self.de, len, visitor)
477  }
478
479  fn struct_variant<V>(self, fields: &'static [&'static str], visitor: V) -> Result<V::Value>
480  where
481    V: Visitor<'de>,
482  {
483    de::Deserializer::deserialize_tuple(self.de, fields.len(), visitor)
484  }
485}
486
487// ----------------------------------------------------------
488
489struct SequenceHelper<'a, 'i: 'a, BO> {
490  de: &'a mut CdrDeserializer<'i, BO>,
491  element_counter: usize,
492  expected_count: usize,
493}
494
495impl<'a, 'i, BO> SequenceHelper<'a, 'i, BO> {
496  fn new(de: &'a mut CdrDeserializer<'i, BO>, expected_count: usize) -> Self {
497    SequenceHelper {
498      de,
499      element_counter: 0,
500      expected_count,
501    }
502  }
503}
504
505// `SeqAccess` is provided to the `Visitor` to give it the ability to iterate
506// through elements of the sequence.
507impl<'a, 'de, 'i, BO> SeqAccess<'de> for SequenceHelper<'a, 'i, BO>
508where
509  'i: 'de,
510  BO: ByteOrder,
511{
512  type Error = Error;
513
514  fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
515  where
516    T: DeserializeSeed<'de>,
517  {
518    if self.element_counter == self.expected_count {
519      Ok(None)
520    } else {
521      self.element_counter += 1;
522      seed.deserialize(&mut *self.de).map(Some)
523    }
524  }
525}
526
527// `MapAccess` is provided to the `Visitor` to give it the ability to iterate
528// through entries of the map.
529impl<'de, 'a, 'i, BO> MapAccess<'de> for SequenceHelper<'a, 'i, BO>
530where
531  'i: 'de,
532  BO: ByteOrder,
533{
534  type Error = Error;
535
536  fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
537  where
538    K: DeserializeSeed<'de>,
539  {
540    if self.element_counter == self.expected_count {
541      Ok(None)
542    } else {
543      self.element_counter += 1;
544      seed.deserialize(&mut *self.de).map(Some)
545    }
546  }
547
548  fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
549  where
550    V: DeserializeSeed<'de>,
551  {
552    // Deserialize a map value.
553    seed.deserialize(&mut *self.de)
554  }
555}
556
557#[cfg(test)]
558#[allow(clippy::needless_pass_by_value)]
559mod tests {
560  use byteorder::{BigEndian, LittleEndian};
561  use log::info;
562  use serde::{Deserialize, Serialize};
563  use serde_repr::{Deserialize_repr, Serialize_repr};
564  use test_case::test_case;
565
566  use crate::{
567    cdr_deserializer::{deserialize_from_big_endian, deserialize_from_little_endian},
568    cdr_serializer::to_vec,
569    from_bytes,
570  };
571
572  #[test]
573  fn cdr_deserialization_struct() {
574    //IDL
575    /*
576    struct MyType
577    {
578     octet first;
579    octet second;
580    long third;
581    unsigned long long fourth;
582    boolean fifth;
583    float sixth;
584    boolean seventh;
585    sequence<long> eighth;
586    sequence<octet> ninth;
587    sequence<short> tenth;
588    sequence<long long> eleventh;
589    unsigned short twelve [3];
590    string thirteen;
591    };
592    */
593
594    /*
595
596      ser_var.first(1);
597    ser_var.second(-3);
598    ser_var.third(-5000);
599    ser_var.fourth(1234);
600    ser_var.fifth(true);
601    ser_var.sixth(-6.6);
602    ser_var.seventh(true);
603    ser_var.eighth({1,2});
604    ser_var.ninth({1});
605    ser_var.tenth({5,-4,3,-2,1});
606    ser_var.eleventh({});
607    ser_var.twelve({3,2,1});
608    ser_var.thirteen("abc");
609
610      */
611    #[derive(Serialize, Deserialize, Debug, PartialEq)]
612    struct MyType {
613      first_value: u8,
614      second_value: i8,
615      third_value: i32,
616      fourth_value: u64,
617      fifth: bool,
618      sixth: f32,
619      seventh: bool,
620      eighth: Vec<i32>,
621      ninth: Vec<u8>,
622      tenth: Vec<i16>,
623      eleventh: Vec<i64>,
624      twelve: [u16; 3],
625      thirteen: String,
626    }
627
628    let micky_mouse = MyType {
629      first_value: 1,
630      second_value: -3,
631      third_value: -5000,
632      fourth_value: 1234u64,
633      fifth: true,
634      sixth: -6.6f32,
635      seventh: true,
636      eighth: vec![1, 2],
637      ninth: vec![1],
638      tenth: vec![5, -4, 3, -2, 1],
639      eleventh: vec![],
640      twelve: [3, 2, 1],
641      thirteen: "abc".to_string(),
642    };
643
644    let expected_serialized_result: Vec<u8> = vec![
645      0x01, 0xfd, 0x00, 0x00, 0x78, 0xec, 0xff, 0xff, 0xd2, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
646      0x00, 0x01, 0x00, 0x00, 0x00, 0x33, 0x33, 0xd3, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00,
647      0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
648      0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xfc, 0xff, 0x03, 0x00, 0xfe, 0xff,
649      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00,
650      0x00, 0x04, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x00,
651    ];
652
653    let serialized = to_vec::<MyType, LittleEndian>(&micky_mouse).unwrap();
654
655    for x in 0..expected_serialized_result.len() {
656      if expected_serialized_result[x] != serialized[x] {
657        info!("index: {}", x);
658      }
659    }
660    assert_eq!(serialized, expected_serialized_result);
661    info!("serialization successful!");
662
663    let built: MyType = deserialize_from_little_endian(&expected_serialized_result).unwrap();
664    assert_eq!(built, micky_mouse);
665    info!("deserialized: {:?}", built);
666  }
667
668  #[test]
669
670  fn cdr_deserialization_user_defined_data() {
671    // look this example https://www.omg.org/spec/DDSI-RTPS/2.3/PDF
672    // 10.7 Example for User-defined Topic Data
673    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
674    struct ShapeType {
675      color: String,
676      x: i32,
677      y: i32,
678      size: i32,
679    }
680
681    let message = ShapeType {
682      color: "BLUE".to_string(),
683      x: 34,
684      y: 100,
685      size: 24,
686    };
687
688    let expected_serialized_result: Vec<u8> = vec![
689      0x05, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x55, 0x45, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00,
690      0x00, 0x64, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
691    ];
692
693    let serialized = to_vec::<ShapeType, LittleEndian>(&message).unwrap();
694    assert_eq!(serialized, expected_serialized_result);
695    let deserialized_message: ShapeType = deserialize_from_little_endian(&serialized).unwrap();
696    assert_eq!(deserialized_message, message);
697  }
698
699  #[test]
700
701  fn cdr_deserialization_serialization_topic_name() {
702    // look this example https://www.omg.org/spec/DDSI-RTPS/2.3/PDF
703    // 10.6 Example for Built-in Endpoint Data
704    // this is just CRD topic name strings
705
706    // TODO what about padding??
707    let received_cdr_string: Vec<u8> = vec![
708      0x07, 0x00, 0x00, 0x00, 0x053, 0x71, 0x75, 0x61, 0x72, 0x65, 0x00, // 0x00,
709    ];
710
711    let deserialized_message: String =
712      deserialize_from_little_endian(&received_cdr_string).unwrap();
713    info!("{:?}", deserialized_message);
714    assert_eq!("Square", deserialized_message);
715
716    let received_cdr_string2: Vec<u8> = vec![
717      0x0A, 0x00, 0x00, 0x00, 0x53, 0x68, 0x61, 0x70, 0x65, 0x54, 0x79, 0x70, 0x65,
718      0x00, // 0x00, 0x00,
719    ];
720
721    let deserialized_message2: String =
722      deserialize_from_little_endian(&received_cdr_string2).unwrap();
723    info!("{:?}", deserialized_message2);
724    assert_eq!("ShapeType", deserialized_message2);
725  }
726
727  #[test]
728  fn cdr_deserialization_example_struct() {
729    // look this example https://www.omg.org/spec/DDSI-RTPS/2.2/PDF
730    // 10.2.2 Example
731
732    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
733    struct Example {
734      a: u32,
735      b: [u8; 4],
736    }
737
738    let o = Example {
739      a: 1,
740      b: [b'a', b'b', b'c', b'd'],
741    };
742
743    let serialized_le: Vec<u8> = vec![0x01, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64];
744
745    let serialized_be: Vec<u8> = vec![0x00, 0x00, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64];
746
747    let deserialized_le: Example = deserialize_from_little_endian(&serialized_le).unwrap();
748    let deserialized_be: Example = deserialize_from_big_endian(&serialized_be).unwrap();
749    let serialized_o_le = to_vec::<Example, LittleEndian>(&o).unwrap();
750    let serialized_o_be = to_vec::<Example, BigEndian>(&o).unwrap();
751
752    assert_eq!(
753      serialized_o_le,
754      vec![0x01, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64,]
755    );
756
757    assert_eq!(
758      serialized_o_be,
759      vec![0x00, 0x00, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64,]
760    );
761
762    info!("serialization success");
763
764    assert_eq!(deserialized_le, o);
765    assert_eq!(deserialized_be, o);
766    info!("deserialization success");
767  }
768
769  #[test]
770
771  fn cdr_deserialization_serialization_payload_shapes() {
772    // This test uses wireshark captured shapes demo part of serialized message as
773    // received_message.
774    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
775    struct ShapeType {
776      color: String,
777      x: i32,
778      y: i32,
779      size: i32,
780    }
781    // this message is DataMessages serialized data without encapsulation kind and
782    // encapsulation options
783    let received_message: Vec<u8> = vec![
784      0x04, 0x00, 0x00, 0x00, 0x52, 0x45, 0x44, 0x00, 0x61, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
785      0x00, 0x1e, 0x00, 0x00, 0x00,
786    ];
787    let received_message2: Vec<u8> = vec![
788      0x04, 0x00, 0x00, 0x00, 0x52, 0x45, 0x44, 0x00, 0x61, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
789      0x00, 0x1e, 0x00, 0x00, 0x00,
790    ];
791
792    let deserialized_message: ShapeType =
793      deserialize_from_little_endian(&received_message).unwrap();
794    info!("{:?}", deserialized_message);
795
796    let serialized_message = to_vec::<ShapeType, LittleEndian>(&deserialized_message).unwrap();
797
798    assert_eq!(serialized_message, received_message2);
799    // assert_eq!(deserialized_message,received_message)
800  }
801
802  #[test]
803
804  fn cdr_deserialization_custom_data_message_from_ros_and_wireshark() {
805    // IDL of message
806    // float64 x
807    // float64 y
808    // float64 heading
809    // float64 v_x
810    // float64 v_y
811    // float64 kappa
812    // string test
813
814    #[derive(Serialize, Deserialize, Debug, PartialEq)]
815    struct MessageType {
816      x: f64,
817      y: f64,
818      heading: f64,
819      v_x: f64,
820      v_y: f64,
821      kappa: f64,
822      test: String,
823    }
824
825    // The serialized form of the message "Toimiiko?" (?) (Finnish for "Working?")
826    let received_message_le: Vec<u8> = vec![
827      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829      0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x85, 0xeb, 0x51, 0xb8,
830      0x1e, 0xd5, 0x3f, 0x0a, 0x00, 0x00, 0x00, 0x54, 0x6f, 0x69, 0x6d, 0x69, 0x69, 0x6b, 0x6f,
831      0x3f, 0x00, // 0x00, 0x00,
832    ];
833
834    let value: MessageType = deserialize_from_little_endian(&received_message_le).unwrap();
835    info!("{:?}", value);
836    assert_eq!(value.test, "Toimiiko?");
837  }
838
839  #[derive(Serialize, Deserialize, Debug, PartialEq)]
840  struct InterestingMessage {
841    unbounded_string: String,
842    x: i32,
843    y: i32,
844    shape_size: i32,
845    slide: f32,
846    double_slide: f64,
847    three_short: [u16; 3],
848    four_short: [i16; 4],
849    booleans: Vec<bool>,
850    three_bytes: Vec<u8>,
851  }
852
853  #[derive(Serialize, Deserialize, Debug, PartialEq)]
854  enum BigEnum {
855    Interesting(InterestingMessage),
856    Boring,
857    Something { x: f32, y: f32 },
858  }
859
860  #[test]
861  fn cdr_deserialization_custom_type() {
862    // IDL Definition of message:
863    /*struct InterestingMessage
864    {
865    string unbounded_string;
866      long x;
867      long y;
868      long shape_size;
869      float slide;
870      double double_slide;
871      unsigned short three_short [3];
872      short four_short [4];
873      sequence<boolean> booleans;
874      sequence<octet,3> three_bytes;
875    };
876    */
877
878    // values put to serialization message with eprosima fastbuffers
879    /*
880      ser_var.unbounded_string("Here is a fairly long text");
881      ser_var.x(1);
882      ser_var.x(2);
883      ser_var.y(-3);
884      ser_var.shape_size(-4);
885      ser_var.slide(5.5);
886      ser_var.double_slide(-6.6);
887      std::array<uint16_t, 3> foo  = {1,2,3};
888      ser_var.three_short(foo);
889      std::array<int16_t, 4>  faa = {1,-2,-3,4};
890      ser_var.four_short(faa);
891      ser_var.booleans({true,false,true});
892      ser_var.three_bytes({23,0,2});
893    */
894
895    let value = InterestingMessage {
896      unbounded_string: "Tassa on aika pitka teksti".to_string(), /* Finnish for "Here us a
897                                                                   * fairly long text" */
898      x: 2,
899      y: -3,
900      shape_size: -4,
901      slide: 5.5,
902      double_slide: -6.6,
903      three_short: [1, 2, 3],
904      four_short: [1, -2, -3, 4],
905      booleans: vec![true, false, true],
906      three_bytes: [23, 0, 2].to_vec(),
907    };
908
909    const DATA: &[u8] = &[
910      0x1b, 0x00, 0x00, 0x00, 0x54, 0x61, 0x73, 0x73, 0x61, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x69,
911      0x6b, 0x61, 0x20, 0x70, 0x69, 0x74, 0x6b, 0x61, 0x20, 0x74, 0x65, 0x6b, 0x73, 0x74, 0x69,
912      0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00,
913      0x00, 0xb0, 0x40, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x1a, 0xc0, 0x01, 0x00, 0x02, 0x00,
914      0x03, 0x00, 0x01, 0x00, 0xfe, 0xff, 0xfd, 0xff, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
915      0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00, 0x17, 0x00, 0x02,
916    ];
917
918    let serialization_result_le = to_vec::<InterestingMessage, LittleEndian>(&value).unwrap();
919
920    assert_eq!(serialization_result_le, DATA);
921    info!("serialization success!");
922    let deserialization_result: InterestingMessage = deserialize_from_little_endian(DATA).unwrap();
923
924    info!("{:?}", deserialization_result);
925  }
926
927  #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
928  enum SomeTupleEnum {
929    A(i32),
930    B(i32),
931    C(i32),
932  }
933
934  #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
935  enum MixedEnum {
936    A(i32),
937    B { value: i32 },
938    C(i32, i32),
939  }
940
941  #[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
942  #[repr(i8)]
943  pub enum GoalStatusEnum {
944    Unknown = 0, // Let's use this also for "New"
945    Accepted = 1,
946    Executing = 2,
947    Canceling = 3,
948    Succeeded = 4,
949    Canceled = 5,
950    Aborted = 6,
951  }
952
953  #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
954  struct AlignMe {
955    some_bytes: [u8; 4],
956    status: i8,
957  }
958
959  #[test_case(35_u8 ; "u8")]
960  #[test_case(35_u16 ; "u16")]
961  #[test_case(352323_u32 ; "u32")]
962  #[test_case(352323232_u64 ; "u64")]
963  #[test_case(-3_i8 ; "i8")]
964  #[test_case(-3_i16 ; "i16")]
965  #[test_case(-323232_i32 ; "i32")]
966  #[test_case(-3232323434_i64 ; "i64")]
967  #[test_case(true)]
968  #[test_case(false)]
969  #[test_case(2.35_f32 ; "f32")]
970  #[test_case(278.35_f64 ; "f64")]
971  #[test_case('a' ; "char")]
972  #[test_case("BLUE".to_string() ; "string")]
973  #[test_case(vec![1_i32, -2_i32, 3_i32] ; "Vec<i32>")]
974  #[test_case(InterestingMessage {
975      unbounded_string: "Here is a fairly long text".to_string(),
976      x: 2,
977      y: -3,
978      shape_size: -4,
979      slide: 5.5,
980      double_slide: -6.6,
981      three_short: [1, 2, 3],
982      four_short: [1, -2, -3, 4],
983      booleans: vec![true, false, true],
984      three_bytes: [23, 0, 2].to_vec(),
985    } ; "InterestingMessage")]
986  #[test_case( BigEnum::Boring ; "BigEnum::Boring")]
987  #[test_case( BigEnum::Interesting(InterestingMessage {
988      unbounded_string: "Here is a fairly long text".to_string(),
989      x: 2,
990      y: -3,
991      shape_size: -4,
992      slide: 5.5,
993      double_slide: -6.6,
994      three_short: [1, 2, 3],
995      four_short: [1, -2, -3, 4],
996      booleans: vec![true, false, true],
997      three_bytes: [23, 0, 2].to_vec(),
998    }) ; "BigEnum::Interesting")]
999  #[test_case( BigEnum::Something{ x:123.0, y:-0.1 } ; "BigEnum::Something")]
1000  #[test_case( SomeTupleEnum::A(123) ; "SomeTupleEnum::A")]
1001  #[test_case( SomeTupleEnum::B(1234) ; "SomeTupleEnum::B")]
1002  #[test_case( SomeTupleEnum::C(-1) ; "SomeTupleEnum::C")]
1003  #[test_case( MixedEnum::A(123) ; "MixedEnum::A")]
1004  #[test_case( MixedEnum::B{ value:1234 } ; "MixedEnum::B")]
1005  #[test_case( MixedEnum::C(42,43) ; "MixedEnum::C")]
1006  #[test_case( GoalStatusEnum::Accepted ; "GoalStatusEnum::Accepted")]
1007  #[test_case( [AlignMe{some_bytes: [1,2,3,4], status:10 } ,
1008                AlignMe{some_bytes: [5,6,7,8], status:11 } ]  ; "AlignMeArray")]
1009  fn cdr_serde_round_trip<T>(input: T)
1010  where
1011    T: PartialEq + std::fmt::Debug + Serialize + for<'a> Deserialize<'a>,
1012  {
1013    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1014    println!("Serialized data: {:x?}", &serialized);
1015    let (deserialized, bytes_consumed): (T, usize) =
1016      from_bytes::<T, LittleEndian>(&serialized).unwrap();
1017    // let deserialized = deserialize_from_little_endian(&serialized).unwrap();
1018    assert_eq!(input, deserialized);
1019    assert_eq!(serialized.len(), bytes_consumed);
1020  }
1021
1022  #[test]
1023  fn cdr_serde_round_trip_bytes() {
1024    let input: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(vec![1u8, 2, 3, 4, 5]);
1025    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1026    // Wire format: 4-byte LE length prefix (5) + 5 raw bytes
1027    assert_eq!(
1028      serialized,
1029      vec![0x05, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05]
1030    );
1031    let (deserialized, bytes_consumed): (serde_bytes::ByteBuf, usize) =
1032      from_bytes::<serde_bytes::ByteBuf, LittleEndian>(&serialized).unwrap();
1033    assert_eq!(input, deserialized);
1034    assert_eq!(serialized.len(), bytes_consumed);
1035  }
1036
1037  #[test]
1038  fn cdr_serde_round_trip_bytes_empty() {
1039    let input: serde_bytes::ByteBuf = serde_bytes::ByteBuf::from(vec![]);
1040    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1041    // Wire format: just 4-byte LE length prefix (0)
1042    assert_eq!(serialized, vec![0x00, 0x00, 0x00, 0x00]);
1043    let (deserialized, bytes_consumed): (serde_bytes::ByteBuf, usize) =
1044      from_bytes::<serde_bytes::ByteBuf, LittleEndian>(&serialized).unwrap();
1045    assert_eq!(input, deserialized);
1046    assert_eq!(serialized.len(), bytes_consumed);
1047  }
1048
1049  #[test]
1050  fn cdr_serde_round_trip_borrowed_bytes() {
1051    // Wire format: u32 LE length (3) followed by 3 payload bytes
1052    let raw = vec![0x03, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC];
1053    let (deserialized, bytes_consumed): (&serde_bytes::Bytes, usize) =
1054      from_bytes::<&serde_bytes::Bytes, LittleEndian>(&raw).unwrap();
1055    assert_eq!(deserialized.as_ref(), &[0xAA, 0xBB, 0xCC]);
1056    assert_eq!(bytes_consumed, 7);
1057  }
1058
1059  #[test]
1060  fn cdr_serde_round_trip_bytes_in_struct() {
1061    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
1062    struct WithBytes {
1063      id: u32,
1064      #[serde(with = "serde_bytes")]
1065      payload: Vec<u8>,
1066      tag: u8,
1067    }
1068
1069    let input = WithBytes {
1070      id: 42,
1071      payload: vec![0xDE, 0xAD, 0xBE, 0xEF],
1072      tag: 7,
1073    };
1074    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1075    let (deserialized, bytes_consumed): (WithBytes, usize) =
1076      from_bytes::<WithBytes, LittleEndian>(&serialized).unwrap();
1077    assert_eq!(input, deserialized);
1078    assert_eq!(serialized.len(), bytes_consumed);
1079  }
1080
1081  #[test]
1082  fn cdr_serde_vec_u8_still_works_via_seq() {
1083    // Plain Vec<u8> (without serde_bytes) goes through serialize_seq/deserialize_seq,
1084    // not serialize_bytes/deserialize_bytes. Confirm this path still works.
1085    let input: Vec<u8> = vec![10, 20, 30];
1086    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1087    let (deserialized, bytes_consumed): (Vec<u8>, usize) =
1088      from_bytes::<Vec<u8>, LittleEndian>(&serialized).unwrap();
1089    assert_eq!(input, deserialized);
1090    assert_eq!(serialized.len(), bytes_consumed);
1091  }
1092
1093  #[test]
1094  fn cdr_serde_seq_serialized_bytes_deserializable_via_bytes_path() {
1095    // Data serialized as Vec<u8> (seq path) must be deserializable via serde_bytes (bytes path).
1096    let input: Vec<u8> = vec![0xDE, 0xAD, 0xBE, 0xEF];
1097    let serialized = to_vec::<_, LittleEndian>(&input).unwrap();
1098    let (deserialized, bytes_consumed): (serde_bytes::ByteBuf, usize) =
1099      from_bytes::<serde_bytes::ByteBuf, LittleEndian>(&serialized).unwrap();
1100    assert_eq!(input, deserialized.as_ref());
1101    assert_eq!(serialized.len(), bytes_consumed);
1102  }
1103}