Skip to main content

nros_serdes/
lib.rs

1//! CDR serialization/deserialization for nros.
2//!
3//! Implements OMG Common Data Representation (CDR) encoding compatible with
4//! ROS 2. All types use little-endian byte order with natural alignment.
5//!
6//! # Examples
7//!
8//! ```
9//! use nros_serdes::{CdrReader, CdrWriter, DeserError, Deserialize, SerError, Serialize};
10//!
11//! // Serialize a u32 into a CDR buffer
12//! let mut buf = [0u8; 64];
13//! let mut writer = CdrWriter::new_with_header(&mut buf).unwrap();
14//! 42u32.serialize(&mut writer).unwrap();
15//! let len = writer.position();
16//!
17//! // Deserialize it back
18//! let mut reader = CdrReader::new_with_header(&buf[..len]).unwrap();
19//! let value = u32::deserialize(&mut reader).unwrap();
20//! assert_eq!(value, 42);
21//! ```
22//!
23//! # Features
24//!
25//! - `std` — Enable standard library support
26//! - `alloc` — Enable heap allocation (`String`, `Vec<T>`)
27
28#![no_std]
29
30#[cfg(feature = "std")]
31extern crate std;
32
33#[cfg(feature = "alloc")]
34extern crate alloc;
35
36pub mod cdr;
37pub mod error;
38pub mod primitives;
39pub mod schema;
40pub mod traits;
41
42#[cfg(test)]
43mod compat_tests;
44
45pub use cdr::{CdrReader, CdrWriter, LeDecode, LeSliceView};
46pub use error::{DeserError, SerError};
47pub use schema::{Field, FieldType, Message, NestedType};
48pub use traits::{Deserialize, DeserializeBorrowed, Serialize};
49
50/// Length of the CDR encapsulation header (representation identifier + options).
51pub const CDR_HEADER_LEN: usize = 4;
52
53/// CDR encapsulation header for little-endian encoding
54pub const CDR_LE_HEADER: [u8; CDR_HEADER_LEN] = [0x00, 0x01, 0x00, 0x00];
55
56/// CDR encapsulation header for big-endian encoding
57pub const CDR_BE_HEADER: [u8; CDR_HEADER_LEN] = [0x00, 0x00, 0x00, 0x00];
58
59/// Write the little-endian CDR header into the first `CDR_HEADER_LEN` bytes of `dst`.
60///
61/// Returns the remaining payload slice `&mut dst[CDR_HEADER_LEN..]` on success,
62/// or `None` if `dst` is shorter than the header.
63#[inline]
64pub fn write_cdr_le_header(dst: &mut [u8]) -> Option<&mut [u8]> {
65    if dst.len() < CDR_HEADER_LEN {
66        return None;
67    }
68    dst[..CDR_HEADER_LEN].copy_from_slice(&CDR_LE_HEADER);
69    Some(&mut dst[CDR_HEADER_LEN..])
70}
71
72/// Strip the CDR encapsulation header from `src`, returning the payload slice.
73///
74/// Does not verify header contents — callers that need to validate the
75/// representation identifier should do so separately. Returns `src` unchanged
76/// if it is shorter than the header (so downstream parsers fail with a clearer
77/// error than an out-of-bounds slice).
78#[inline]
79pub fn strip_cdr_header(src: &[u8]) -> &[u8] {
80    if src.len() >= CDR_HEADER_LEN {
81        &src[CDR_HEADER_LEN..]
82    } else {
83        src
84    }
85}