Skip to main content

cdr_encoding/
cdr_serializer.rs

1//! OMG Common Data Representation (CDR) serialization with [Serde](https://serde.rs/)
2//!
3//!
4//!
5//! Note: In CDR encoding, alignment padding bytes are inserted *before* a
6//! multibyte primitive, but not after.
7//!
8//!  e.g. `struct Example {
9//!   a: u8,
10//!   b: i32,
11//!   c: u16,
12//! }`
13//!
14//! Would be serialized as
15//! `
16//! |aa|PP|PP|PP|
17//! |bb|bb|bb|bb|
18//! |cc|cc|
19//! `
20//! which is 10 bytes. `PP` means a byte of padding data.
21//!
22//! Tuple type  `(Example,Example)` would be serialized as
23//! `
24//! |aa|PP|PP|PP|
25//! |bb|bb|bb|bb|
26//! |cc|cc|aa|PP|
27//! |bb|bb|bb|bb|
28//! |cc|cc|
29//! `
30//! Note that this is only 18 bytes, not 20, and the layout of the second
31//! struct is different due to different padding.
32
33use std::{io, io::Write, marker::PhantomData};
34
35#[cfg(test)]
36use byteorder::{BigEndian, LittleEndian};
37use byteorder::{ByteOrder, WriteBytesExt};
38use serde::{ser, Serialize};
39
40pub use super::error::{Error, Result};
41
42// CountingWrite is a wrapper for a Write object. The wrapper keeps count of
43// bytes written. CDR needs to count bytes, because multibyte primitive types '
44// (such as integers and floats) must be aligned to their size, i.e. 2, 4, or 8
45// bytes.
46struct CountingWrite<W: io::Write> {
47  writer: W,
48  bytes_written: usize,
49}
50
51impl<W> CountingWrite<W>
52where
53  W: io::Write,
54{
55  pub fn new(w: W) -> Self {
56    Self {
57      writer: w,
58      bytes_written: 0,
59    }
60  }
61  pub fn count(&self) -> usize {
62    self.bytes_written
63  }
64}
65
66impl<W> io::Write for CountingWrite<W>
67where
68  W: io::Write,
69{
70  fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
71    match self.writer.write(buf) {
72      Ok(c) => {
73        self.bytes_written += c;
74        Ok(c)
75      }
76      e => e,
77    }
78  }
79  fn flush(&mut self) -> io::Result<()> {
80    self.writer.flush()
81  }
82}
83
84// ---------------------------------------------------------------------------------
85// ---------------------------------------------------------------------------------
86
87// ---------------------------------------------------------------------------------
88// ---------------------------------------------------------------------------------
89
90/// a CDR serializer implementation
91///
92/// Parameter W is an [`io::Write`] that would receive the serialization.
93///
94/// Parameter BO is byte order: [`LittleEndian`](byteorder::LittleEndian) or
95/// [`BigEndian`](byteorder::BigEndian)
96pub struct CdrSerializer<W, BO>
97where
98  W: io::Write,
99{
100  writer: CountingWrite<W>, // serialization destination
101  phantom: PhantomData<BO>, // This field exists only to provide use for BO. See PhantomData docs.
102}
103
104impl<W, BO> CdrSerializer<W, BO>
105where
106  BO: ByteOrder,
107  W: io::Write,
108{
109  pub fn new(w: W) -> Self {
110    Self {
111      writer: CountingWrite::new(w),
112      phantom: PhantomData,
113    }
114  }
115
116  fn calculate_padding_need_and_write_padding(&mut self, alignment: usize) -> Result<()> {
117    let modulo = self.writer.count() % alignment;
118    if modulo != 0 {
119      let padding_need: usize = alignment - modulo;
120      for _x in 0..padding_need {
121        self.writer.write_u8(0)?;
122      }
123    }
124    Ok(())
125  }
126} // impl
127
128/// General CDR serialization for type `T:Serialize`
129///
130/// Takes ownership of the `writer`, but that can be a reference.
131///
132/// You need to specifiy the byte order (endianness) to use. In CDR, endianess
133/// cannot be detected from serialized stream, but has to be agreed out-of-band.
134pub fn to_writer<T, BO, W>(writer: W, value: &T) -> Result<()>
135where
136  T: Serialize,
137  BO: ByteOrder,
138  W: io::Write,
139{
140  value.serialize(&mut CdrSerializer::<W, BO>::new(writer))
141}
142
143/// Serialize to `Vec<u8>`
144/// Size hint indicates how many bytes to initially allocate for serialized
145/// data.
146pub fn to_vec_with_size_hint<T, BO>(value: &T, capacity_hint: usize) -> Result<Vec<u8>>
147where
148  T: Serialize,
149  BO: ByteOrder,
150{
151  let mut buffer: Vec<u8> = Vec::with_capacity(capacity_hint);
152  to_writer::<T, BO, &mut Vec<u8>>(&mut buffer, value)?;
153  Ok(buffer)
154}
155
156/// Serialize to `Vec<u8>`
157pub fn to_vec<T, BO>(value: &T) -> Result<Vec<u8>>
158where
159  T: Serialize,
160  BO: ByteOrder,
161{
162  to_vec_with_size_hint::<T, BO>(value, std::mem::size_of_val(value) * 2)
163}
164
165// just testing
166#[cfg(test)]
167pub(crate) fn to_little_endian_binary<T>(value: &T) -> Result<Vec<u8>>
168where
169  T: Serialize,
170{
171  to_vec::<T, LittleEndian>(value)
172}
173
174#[cfg(test)]
175fn to_big_endian_binary<T>(value: &T) -> Result<Vec<u8>>
176where
177  T: Serialize,
178{
179  to_vec::<T, BigEndian>(value)
180}
181
182// ----------------------------------------------------------
183// ----------------------------------------------------------
184// ----------------------------------------------------------
185// ----------------------------------------------------------
186// ----------------------------------------------------------
187
188impl<'a, W, BO> ser::Serializer for &'a mut CdrSerializer<W, BO>
189where
190  BO: ByteOrder,
191  W: io::Write,
192{
193  type Ok = ();
194  // The error type when some error occurs during serialization.
195  type Error = Error;
196
197  // Associated types for keeping track of additional state while serializing
198  // compound data structures like sequences and maps. In this case no
199  // additional state is required beyond what is already stored in the
200  // Serializer struct.
201  type SerializeSeq = Self;
202  type SerializeTuple = Self;
203  type SerializeTupleStruct = Self;
204  type SerializeTupleVariant = Self;
205  type SerializeMap = Self;
206  type SerializeStruct = Self;
207  type SerializeStructVariant = Self;
208
209  // Little-Endian encoding least significant bit is first.
210
211  // 15.3.1.5 Boolean
212  //  Boolean values are encoded as single octets, where TRUE is the value 1, and
213  // FALSE as 0.
214  fn serialize_bool(self, v: bool) -> Result<()> {
215    if v {
216      self.writer.write_u8(1u8)?;
217    } else {
218      self.writer.write_u8(0u8)?;
219    }
220    Ok(())
221  }
222
223  // Figure 15-1 on page 15-7 illustrates the representations for OMG IDL integer
224  // data types, including the following data types:
225  // short
226  // unsigned short
227  // long
228  // unsigned long
229  // long long
230  // unsigned long long
231
232  fn serialize_u8(self, v: u8) -> Result<()> {
233    self.writer.write_u8(v)?;
234    Ok(())
235  }
236
237  fn serialize_u16(self, v: u16) -> Result<()> {
238    self.calculate_padding_need_and_write_padding(2)?;
239    self.writer.write_u16::<BO>(v)?;
240    Ok(())
241  }
242
243  fn serialize_u32(self, v: u32) -> Result<()> {
244    self.calculate_padding_need_and_write_padding(4)?;
245    self.writer.write_u32::<BO>(v)?;
246    Ok(())
247  }
248
249  fn serialize_u64(self, v: u64) -> Result<()> {
250    self.calculate_padding_need_and_write_padding(8)?;
251    self.writer.write_u64::<BO>(v)?;
252    Ok(())
253  }
254
255  fn serialize_u128(self, v: u128) -> Result<()> {
256    self.calculate_padding_need_and_write_padding(16)?;
257    self.writer.write_u128::<BO>(v)?;
258    Ok(())
259  }
260
261  fn serialize_i8(self, v: i8) -> Result<()> {
262    self.writer.write_i8(v)?;
263    Ok(())
264  }
265
266  fn serialize_i16(self, v: i16) -> Result<()> {
267    self.calculate_padding_need_and_write_padding(2)?;
268    self.writer.write_i16::<BO>(v)?;
269    Ok(())
270  }
271
272  fn serialize_i32(self, v: i32) -> Result<()> {
273    self.calculate_padding_need_and_write_padding(4)?;
274    self.writer.write_i32::<BO>(v)?;
275    Ok(())
276  }
277
278  fn serialize_i64(self, v: i64) -> Result<()> {
279    self.calculate_padding_need_and_write_padding(8)?;
280    self.writer.write_i64::<BO>(v)?;
281    Ok(())
282  }
283
284  fn serialize_f32(self, v: f32) -> Result<()> {
285    self.calculate_padding_need_and_write_padding(4)?;
286    self.writer.write_f32::<BO>(v)?;
287    Ok(())
288  }
289  fn serialize_f64(self, v: f64) -> Result<()> {
290    self.calculate_padding_need_and_write_padding(8)?;
291    self.writer.write_f64::<BO>(v)?;
292    Ok(())
293  }
294
295  // An IDL character is represented as a single octet; the code set used for
296  // transmission of character data (e.g., TCS-C) between a particular client
297  // and server ORBs is determined via the process described in Section 13.10,
298  // “Code Set Conversion,”
299  fn serialize_char(self, v: char) -> Result<()> {
300    // Rust "char" means a 32-bit Unicode code point.
301    // IDL & CDR "char" means an octet.
302    // We are here actually serializing the 32-bit quantity.
303    // If we want to serialize CDR "char", then the corresponding Rust type is "u8".
304    self.serialize_u32(v as u32)?;
305    Ok(())
306  }
307
308  // A string is encoded as an unsigned long indicating the length of the string
309  // in octets, followed by the string value in single- or multi-byte form
310  // represented as a sequence of octets. The string contents include a single
311  // terminating null character. The string length includes the null character,
312  // so an empty string has a length of 1.
313  fn serialize_str(self, v: &str) -> Result<()> {
314    let byte_count: u32 = v.as_bytes().len() as u32 + 1;
315    self.serialize_u32(byte_count)?; // +1 for terminator
316    self.writer.write_all(v.as_bytes())?;
317    self.writer.write_u8(0)?; // CDR spec requires a null terminator
318    Ok(())
319    // The end result is not UTF-8-encoded string, but how could we do better in
320    // CDR?
321  }
322
323  fn serialize_bytes(self, v: &[u8]) -> Result<()> {
324    // Write length prefix
325    self.serialize_u32(v.len() as u32)?;
326    // Write raw bytes
327    self.writer.write_all(v)?;
328    Ok(())
329  }
330
331  fn serialize_none(self) -> Result<()> {
332    self.serialize_u32(0) // None is the first variant
333  }
334
335  fn serialize_some<T>(self, t: &T) -> Result<()>
336  where
337    T: ?Sized + Serialize,
338  {
339    self.serialize_u32(1)?; // Some is the second variant
340    t.serialize(self)?;
341    Ok(())
342  }
343
344  // Unit contains no data, but the CDR spec has no concept of types that carry no
345  // data. We decide to serialize this as nothing.
346  fn serialize_unit(self) -> Result<()> {
347    // nothing
348    Ok(())
349  }
350
351  fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
352    self.serialize_unit()
353  }
354
355  // CDR 15.3.2.6:
356  // Enum values are encoded as unsigned longs. The numeric values associated with
357  // enum identifiers are determined by the order in which the identifiers
358  // appear in the enum declaration. The first enum identifier has the numeric
359  // value zero (0). Successive enum identifiers take ascending numeric values,
360  // in order of declaration from left to right.
361  fn serialize_unit_variant(
362    self,
363    _name: &'static str,
364    variant_index: u32,
365    _variant: &'static str,
366  ) -> Result<()> {
367    self.serialize_u32(variant_index)
368  }
369
370  // In CDR, this would be a special case of struct.
371  fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
372  where
373    T: ?Sized + Serialize,
374  {
375    value.serialize(self)
376  }
377
378  fn serialize_newtype_variant<T>(
379    self,
380    _name: &'static str,
381    variant_index: u32,
382    _variant: &'static str,
383    value: &T,
384  ) -> Result<()>
385  where
386    T: ?Sized + Serialize,
387  {
388    self.serialize_u32(variant_index)?;
389    value.serialize(self)
390  }
391
392  // Sequences are encoded as an unsigned long value, followed by the elements of
393  // the sequence. The initial unsigned long contains the number of elements in
394  // the sequence. The elements of the sequence are encoded as specified for
395  // their type.
396  //
397  // Serde calls this to start sequence. Then it calls serialize_element() for
398  // each element, and finally calls end().
399  fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> {
400    match len {
401      None => Err(Error::SequenceLengthUnknown),
402      Some(elem_count) => {
403        self.serialize_u32(elem_count as u32)?;
404        Ok(self)
405      }
406    } // match
407  } // fn
408
409  // if CDR contains fixed length array then number of elements is not written.
410  fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple> {
411    // nothing to be done here
412    Ok(self)
413  }
414
415  fn serialize_tuple_struct(
416    self,
417    _name: &'static str,
418    _len: usize,
419  ) -> Result<Self::SerializeTupleStruct> {
420    // (tuple) struct length is not written. Nothing to be done.
421    Ok(self)
422  }
423
424  // This is technically enum/union, so write the variant index.
425  fn serialize_tuple_variant(
426    self,
427    _name: &'static str,
428    variant_index: u32,
429    _variant: &'static str,
430    _len: usize,
431  ) -> Result<Self::SerializeTupleVariant> {
432    self.serialize_u32(variant_index)?;
433    Ok(self)
434  }
435
436  // CDR spec from year 2002 does not yet know about maps.
437  // We make an educated guess that the design is similar to sequences:
438  // First the number of key-value pairs, then each entry as a (key,value)-pair.
439  fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> {
440    match len {
441      None => Err(Error::SequenceLengthUnknown),
442      Some(elem_count) => {
443        self.serialize_u32(elem_count as u32)?;
444        Ok(self)
445      }
446    } // match
447  }
448
449  // Similar to tuple. No need to mark the beginning.
450  fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
451    // self.calculate_padding_need_and_write_padding(4)?;
452    // No! There is no "align to 4 before struct"-rule in CDR!
453
454    // nothing to be done.
455    Ok(self)
456  }
457
458  // Same as tuple variant: Serialize variant index. Serde will then serialize
459  // fields.
460  fn serialize_struct_variant(
461    self,
462    _name: &'static str,
463    variant_index: u32,
464    _variant: &'static str,
465    _len: usize,
466  ) -> Result<Self::SerializeStructVariant> {
467    self.serialize_u32(variant_index)?;
468    Ok(self)
469  }
470
471  fn is_human_readable(&self) -> bool {
472    false
473  }
474}
475
476impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeSeq for &'a mut CdrSerializer<W, BO> {
477  type Ok = ();
478  type Error = Error;
479
480  fn serialize_element<T>(&mut self, value: &T) -> Result<()>
481  where
482    T: ?Sized + Serialize,
483  {
484    value.serialize(&mut **self)
485  }
486
487  fn end(self) -> Result<()> {
488    Ok(())
489  }
490}
491
492impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeTuple for &'a mut CdrSerializer<W, BO> {
493  type Ok = ();
494  type Error = Error;
495
496  fn serialize_element<T>(&mut self, value: &T) -> Result<()>
497  where
498    T: ?Sized + Serialize,
499  {
500    value.serialize(&mut **self)
501  }
502
503  fn end(self) -> Result<()> {
504    Ok(())
505  }
506}
507
508impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeTupleStruct for &'a mut CdrSerializer<W, BO> {
509  type Ok = ();
510  type Error = Error;
511
512  fn serialize_field<T>(&mut self, value: &T) -> Result<()>
513  where
514    T: ?Sized + Serialize,
515  {
516    value.serialize(&mut **self)
517  }
518
519  fn end(self) -> Result<()> {
520    Ok(())
521  }
522}
523
524impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeTupleVariant for &'a mut CdrSerializer<W, BO> {
525  type Ok = ();
526  type Error = Error;
527
528  fn serialize_field<T>(&mut self, value: &T) -> Result<()>
529  where
530    T: ?Sized + Serialize,
531  {
532    value.serialize(&mut **self)
533  }
534  fn end(self) -> Result<()> {
535    Ok(())
536  }
537}
538
539impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeMap for &'a mut CdrSerializer<W, BO> {
540  type Ok = ();
541  type Error = Error;
542  fn serialize_key<T>(&mut self, key: &T) -> Result<()>
543  where
544    T: ?Sized + Serialize,
545  {
546    key.serialize(&mut **self)
547  }
548
549  fn serialize_value<T>(&mut self, value: &T) -> Result<()>
550  where
551    T: ?Sized + Serialize,
552  {
553    value.serialize(&mut **self)
554  }
555
556  fn end(self) -> Result<()> {
557    Ok(())
558  }
559}
560
561impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeStruct for &'a mut CdrSerializer<W, BO> {
562  type Ok = ();
563  type Error = Error;
564
565  fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<()>
566  where
567    T: ?Sized + Serialize,
568  {
569    value.serialize(&mut **self)?;
570    Ok(())
571  }
572
573  fn end(self) -> Result<()> {
574    Ok(())
575  }
576}
577
578impl<'a, W: io::Write, BO: ByteOrder> ser::SerializeStructVariant for &'a mut CdrSerializer<W, BO> {
579  type Ok = ();
580  type Error = Error;
581
582  fn serialize_field<T>(&mut self, _key: &'static str, value: &T) -> Result<()>
583  where
584    T: ?Sized + Serialize,
585  {
586    value.serialize(&mut **self)?;
587    Ok(())
588  }
589
590  fn end(self) -> Result<()> {
591    Ok(())
592  }
593}
594
595#[cfg(test)]
596mod tests {
597  use log::info;
598  use serde::{Deserialize, Serialize};
599  use serde_repr::{Deserialize_repr, Serialize_repr};
600
601  use crate::{
602    cdr_deserializer::deserialize_from_little_endian,
603    cdr_serializer::{to_big_endian_binary, to_little_endian_binary},
604  };
605
606  #[test]
607
608  fn cdr_serialize_and_deserialize_sequence_of_structs() {
609    // this length is not dividable by 4 so paddings are necessary???
610    #[derive(Debug, Eq, PartialEq, Serialize, Deserialize)]
611    pub struct MyType {
612      first_value: i16,
613      second: u8,
614    }
615    impl MyType {
616      pub fn new(first_value: i16, second: u8) -> Self {
617        Self {
618          first_value,
619          second,
620        }
621      }
622    }
623
624    let sequence_of_structs: Vec<MyType> =
625      vec![MyType::new(1, 23), MyType::new(2, 34), MyType::new(-3, 45)];
626    let serialized = to_little_endian_binary(&sequence_of_structs).unwrap();
627    let deserialized: Vec<MyType> = deserialize_from_little_endian(&serialized).unwrap();
628    info!("deserialized    {:?}", deserialized);
629    info!("serialized    {:?}", serialized);
630    assert_eq!(deserialized, sequence_of_structs);
631  }
632
633  #[test]
634  fn cdr_serialize_enum() {
635    // Enum values are encoded as unsigned longs. The numeric values associated with
636    // enum identifiers are determined by the order in which the identifiers
637    // appear in the enum declaration. The first enum identifier has the numeric
638    // value zero (0). Successive enum identifiers are take ascending numeric
639    // values, in order of declaration from left to right. -> Only C type
640    // "classic enumerations" are possible to be serialized. use Serialize_repr
641    // and Deserialize_repr when enum member has value that is not same as unit
642    // variant index (when specified explicitly in code with assign)
643    #[derive(Debug, Eq, PartialEq, Serialize_repr, Deserialize_repr)]
644    #[repr(u32)]
645    pub enum MyEnumeration {
646      First,
647      Second,
648      Third,
649      // fourth(u8,u8,u8,u8),
650      // fifth(u8,u8,u16),
651      // sixth(i16,i16),
652      SevenHundredth = 700,
653      /*eighth(u32),
654       *this_should_not_be_valid(u64,u8,u8,u16,String),
655       *similar_to_fourth(u8,u8,u8,u8), */
656    }
657
658    let enum_object_1 = MyEnumeration::First;
659    let enum_object_2 = MyEnumeration::Second;
660    let enum_object_3 = MyEnumeration::Third;
661    // let enum_object_4 = MyEnumeration::fourth(1,2,3,4);
662    // let enum_object_5 = MyEnumeration::fifth(5,6,7);
663    // let enum_object_6 = MyEnumeration::sixth(-8,9);
664    let enum_object_7 = MyEnumeration::SevenHundredth;
665    // let enum_object_8 = MyEnumeration::eighth(1000);
666    // let enum_object_9 =
667    // MyEnumeration::this_should_not_be_valid(1000,1,2,3,String::from("Hey all!"));
668    // let enum_object_10 =MyEnumeration::similar_to_fourth(5,6,7,8);
669
670    let serialized_1 = to_little_endian_binary(&enum_object_1).unwrap();
671    info!("{:?}", serialized_1);
672    let u32_value_1: u32 = deserialize_from_little_endian(&serialized_1).unwrap();
673    let deserialized_1: MyEnumeration = deserialize_from_little_endian(&serialized_1).unwrap();
674    info!("Decoded 1: {:?}", deserialized_1);
675    assert_eq!(deserialized_1, enum_object_1);
676    assert_eq!(u32_value_1, 0);
677
678    let serialized_2 = to_little_endian_binary(&enum_object_2).unwrap();
679    info!("{:?}", serialized_2);
680    let u32_value_2: u32 = deserialize_from_little_endian(&serialized_2).unwrap();
681    let deserialized_2: MyEnumeration = deserialize_from_little_endian(&serialized_2).unwrap();
682    info!("Decoded 2: {:?}", deserialized_2);
683    assert_eq!(deserialized_2, enum_object_2);
684    assert_eq!(u32_value_2, 1);
685
686    let serialized_3 = to_little_endian_binary(&enum_object_3).unwrap();
687    info!("{:?}", serialized_3);
688    let deserialized_3: MyEnumeration = deserialize_from_little_endian(&serialized_3).unwrap();
689    let u32_value_3: u32 = deserialize_from_little_endian(&serialized_3).unwrap();
690    info!("Decoded 3: {:?}", deserialized_3);
691    assert_eq!(deserialized_3, enum_object_3);
692    assert_eq!(u32_value_3, 2);
693
694    // let serialized_4 = to_little_endian_binary(&enum_object_4).unwrap();
695    // let deserialized_4 : MyEnumeration =
696    // deserialize_from_little_endian(serialized_4).unwrap();
697
698    let serialized_7 = to_little_endian_binary(&enum_object_7).unwrap();
699    info!("{:?}", serialized_7);
700    let deserialized_7: MyEnumeration = deserialize_from_little_endian(&serialized_7).unwrap();
701    let u32_value_7: u32 = deserialize_from_little_endian(&serialized_7).unwrap();
702    info!("Decoded 7: {:?}", deserialized_7);
703    assert_eq!(deserialized_7, enum_object_7);
704    assert_eq!(u32_value_7, 700);
705
706    /*
707    let serialized_5 = to_little_endian_binary(&enum_object_5).unwrap();
708    let serialized_6 = to_little_endian_binary(&enum_object_6).unwrap();
709    let serialized_8 = to_little_endian_binary(&enum_object_8).unwrap();
710    let serialized_9 = to_little_endian_binary(&enum_object_9).unwrap();
711    let serialized_10 = to_little_endian_binary(&enum_object_10).unwrap();
712    */
713  }
714
715  #[test]
716  fn cdr_serialization_example() {
717    // look this example https://www.omg.org/spec/DDSI-RTPS/2.2/PDF
718    // 10.2.2 Example
719
720    #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
721    struct Example {
722      a: u32,
723      b: [u8; 4],
724    }
725
726    let o = Example {
727      a: 1,
728      b: [b'a', b'b', b'c', b'd'],
729    };
730
731    let expected_serialization_le: Vec<u8> = vec![0x01, 0x00, 0x00, 0x00, 0x61, 0x62, 0x63, 0x64];
732
733    let expected_serialization_be: Vec<u8> = vec![0x00, 0x00, 0x00, 0x01, 0x61, 0x62, 0x63, 0x64];
734
735    let serialized_le = to_little_endian_binary(&o).unwrap();
736    let serialized_be = to_big_endian_binary(&o).unwrap();
737    assert_eq!(serialized_le, expected_serialization_le);
738    assert_eq!(serialized_be, expected_serialization_be);
739  }
740
741  #[test]
742  fn cdr_serialization_test() {
743    #[derive(Serialize)]
744    struct MyType {
745      first_value: u8,
746      second_value: i8,
747      third_value: i32,
748      fourth_value: u64,
749      fifth: bool,
750    }
751
752    let micky_mouse = MyType {
753      first_value: 1,
754      second_value: -1,
755      third_value: 23,
756      fourth_value: 3434343,
757      fifth: true,
758    };
759
760    let serialized = to_little_endian_binary(&micky_mouse).unwrap();
761    let expected: Vec<u8> = vec![
762      0x01, 0xff, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x67, 0x67, 0x34, 0x00, 0x00, 0x00, 0x00,
763      0x00, 0x01,
764    ];
765    assert_eq!(expected, serialized);
766  }
767
768  #[test]
769  fn cdr_serialization_char() {
770    #[derive(Serialize)]
771    struct MyType {
772      first_value: u8,
773      second: u8,
774      third: u8,
775    }
776    let micky_mouse = MyType {
777      first_value: b'a',
778      second: b'b',
779      third: b'\xE4', // 'ä'
780    };
781
782    let serialized = to_little_endian_binary(&micky_mouse).unwrap();
783    let expected: Vec<u8> = vec![0x61, 0x62, 0xe4];
784    assert_eq!(expected, serialized);
785  }
786
787  #[test]
788  fn cdr_serialization_string() {
789    #[derive(Serialize)]
790    struct MyType<'a> {
791      first_value: &'a str,
792    }
793    let micky_mouse = MyType {
794      first_value: "BLUE",
795    };
796    let serialized = to_little_endian_binary(&micky_mouse).unwrap();
797    let expected: Vec<u8> = vec![0x05, 0x00, 0x00, 0x00, 0x42, 0x4c, 0x55, 0x45, 0x00];
798    assert_eq!(expected, serialized);
799  }
800
801  #[test]
802  fn cdr_serialization_little() {
803    let number: u16 = 60000;
804    let le = to_little_endian_binary(&number).unwrap();
805    let be = to_big_endian_binary(&number).unwrap();
806
807    assert_ne!(le, be);
808  }
809
810  #[test]
811  fn cdr_serialize_seq() {
812    #[derive(Serialize)]
813    struct MyType {
814      first_value: Vec<i32>,
815    }
816    let micky_mouse = MyType {
817      first_value: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 123123],
818    };
819    let serialized = to_little_endian_binary(&micky_mouse).unwrap();
820    let expected: Vec<u8> = vec![
821      0x0b, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
822      0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00,
823      0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xf3,
824      0xe0, 0x01, 0x00,
825    ];
826    assert_eq!(expected, serialized);
827  }
828}