CDR (Common Data Representation)
The cdr component provides a small, standalone Common Data Representation
reader/writer utility aimed at standards-oriented protocols such as DDS/RTPS.
This initial slice focuses on the pieces needed to start building interoperable payloads without forcing applications to adopt DDS or RTPS as a whole:
CDR / PL_CDR encapsulation identifiers
endian-aware primitive serialization helpers
CDR alignment and padding handling
string helpers using the standard CDR length-prefix + null terminator layout
body helpers for CDR fields embedded inside larger protocol elements
fixed-array helpers and zero-copy payload/span views
primitive sequence helpers
standalone usage outside RTPS
Current scope:
useful as a reusable building block for future DDS/RTPS payload work
suitable for direct use in other protocols that want CDR-style payloads
not yet a full XTypes / XCDR2 implementation
API Reference
Header File
Classes
-
class CdrWriter
Small helper for building CDR/XCDR1-style byte streams.
CDR Example
espp::CdrWriter writer({ .encapsulation = espp::CdrEncapsulation::CDR_LE, .include_encapsulation = true, }); writer.write<uint32_t>(42); writer.write<float>(3.25f); writer.write_string("hello cdr"); writer.write_sequence<uint16_t>(input_values); auto payload = writer.take_buffer(); logger.info("Serialized {} bytes of CDR data", payload.size()); auto inline_writer = espp::CdrWriter::make_body_writer(espp::CdrEncapsulation::CDR_LE); inline_writer.write_array(input_magic); inline_writer.write_string("embedded field"); auto inline_payload = espp::CdrWriter::encapsulate(inline_writer.payload(), espp::CdrEncapsulation::PL_CDR_LE); espp::CdrReader reader(payload); espp::CdrReader inline_reader(inline_payload); uint32_t decoded_count = 0; float decoded_scale = 0.0f; std::string decoded_text; std::vector<uint16_t> decoded_values; std::array<uint8_t, 4> decoded_magic{}; std::string decoded_inline_text; bool ok = reader.read<uint32_t>(decoded_count) && reader.read<float>(decoded_scale) && reader.read_string(decoded_text) && reader.read_sequence<uint16_t>(decoded_values); bool inline_ok = inline_reader.encapsulation() == espp::CdrEncapsulation::PL_CDR_LE && inline_reader.read_array(decoded_magic) && inline_reader.read_string(decoded_inline_text);
Public Functions
-
inline CdrWriter()
Construct a writer using the default little-endian encapsulated configuration.
-
inline explicit CdrWriter(const Config &config)
Construct a writer using an explicit configuration.
- Parameters:
config – Writer configuration controlling encapsulation and endianness behavior.
-
inline void reset()
Clear the current buffer and reinitialize the encapsulation header if configured.
-
inline CdrEncapsulation encapsulation() const
Get the configured encapsulation kind for this writer.
- Returns:
The encapsulation kind associated with this writer.
-
inline bool uses_little_endian() const
Determine whether values are encoded in little-endian order.
- Returns:
True for little-endian encapsulations, false for big-endian ones.
-
inline size_t size() const
Get the total number of bytes currently written.
- Returns:
The size of the backing byte buffer, including any encapsulation header.
-
inline const std::vector<uint8_t> &buffer() const
Access the full serialized buffer built so far.
- Returns:
A const reference to the complete buffer, including any encapsulation header.
-
inline std::span<const uint8_t> payload() const
Access only the payload portion of the buffer.
- Returns:
A view over the serialized bytes after any encapsulation header.
-
inline std::vector<uint8_t> take_buffer()
Move the complete serialized buffer out of the writer.
- Returns:
The current buffer contents, including any encapsulation header.
-
inline bool align(size_t alignment)
Pad the buffer with zeros until it satisfies the requested alignment.
- Parameters:
alignment – Required alignment in bytes. Values less than or equal to 1 are ignored.
- Returns:
Always returns true. This matches the reader API even though writer-side alignment cannot currently fail.
-
template<typename T>
inline bool write(T value) Append a primitive scalar using CDR alignment and endianness rules.
- Template Parameters:
T – Primitive integral or floating-point type to encode.
- Parameters:
value – Value to append to the serialized buffer.
- Returns:
True after the value has been encoded and appended.
-
inline bool write_bool(bool value)
Append a boolean value using the standard CDR 1-byte representation.
- Parameters:
value – Boolean value to encode.
- Returns:
True after the value has been appended.
-
inline bool write_string(std::string_view text)
Append a CDR string.
- Parameters:
text – UTF-8 text to encode. A terminating null byte is written automatically.
- Returns:
True after the string length, contents, terminator, and alignment padding are written.
-
inline bool write_bytes(std::span<const uint8_t> bytes, size_t alignment = 1)
Append raw bytes with optional alignment.
- Parameters:
bytes – Bytes to copy into the serialized buffer.
alignment – Alignment in bytes to satisfy before appending the data.
- Returns:
True after the bytes have been appended.
-
template<typename T, size_t N>
inline bool write_array(const std::array<T, N> &values) Append a fixed-size array of primitive values.
- Template Parameters:
T – Primitive integral or floating-point element type.
N – Number of elements in the array.
- Parameters:
values – Array to encode element-by-element.
- Returns:
True after all elements have been encoded.
-
template<typename T>
inline bool write_sequence(std::span<const T> values) Append a variable-length CDR sequence of primitive values.
- Template Parameters:
T – Primitive integral or floating-point element type.
- Parameters:
values – Sequence elements to encode.
- Returns:
True after the sequence length and all elements have been encoded.
Public Static Functions
-
static inline Config body_config(CdrEncapsulation encapsulation = CdrEncapsulation::CDR_LE)
Create a configuration for writing a CDR body without an encapsulation header.
- Parameters:
encapsulation – Endianness/encapsulation rules to use for the body payload.
- Returns:
A configuration with encapsulation emission disabled.
-
static inline CdrWriter make_body_writer(CdrEncapsulation encapsulation = CdrEncapsulation::CDR_LE)
Create a writer configured for a headerless/body-only CDR payload.
Note
CDR alignment is measured from the start of the buffer. Because a body-only writer has no 4-byte encapsulation header, 8-byte-aligned members (e.g. int64/double) land at different offsets than in an encapsulated writer. A body produced here and later wrapped with encapsulate() is therefore not byte-compatible with a directly-encapsulated buffer when it contains 8-byte-aligned types. Current RTPS usage only emits <= 4-byte-aligned types.
- Parameters:
encapsulation – Endianness/encapsulation rules to use for the body payload.
- Returns:
A ready-to-use writer with no encapsulation header in its output.
-
static inline std::vector<uint8_t> encapsulate(std::span<const uint8_t> payload, CdrEncapsulation encapsulation = CdrEncapsulation::CDR_LE)
Wrap an existing payload with a CDR encapsulation header.
- Parameters:
payload – Raw bytes to append after the generated encapsulation header.
encapsulation – Encapsulation header to prepend.
- Returns:
A new byte buffer containing the encapsulation header followed by the payload.
-
struct Config
Configuration for a CDR writer instance.
-
inline CdrWriter()
-
class CdrReader
Small helper for parsing CDR/XCDR1-style byte streams.
Public Functions
-
inline explicit CdrReader(std::span<const uint8_t> data)
Construct a reader that expects a standard encapsulated CDR payload.
- Parameters:
data – Serialized bytes to parse.
-
inline CdrReader(std::span<const uint8_t> data, const Config &config)
Construct a reader with an explicit configuration.
- Parameters:
data – Serialized bytes to parse.
config – Reader configuration controlling encapsulation handling.
-
inline void reset(std::span<const uint8_t> data)
Reset the reader to the beginning of a new serialized buffer.
- Parameters:
data – Serialized bytes to parse.
-
inline bool valid() const
Check whether the reader is still in a valid state.
- Returns:
True if parsing can continue, false if a prior operation failed.
-
inline CdrEncapsulation encapsulation() const
Get the active encapsulation for the current buffer.
- Returns:
The parsed or assumed encapsulation value.
-
inline bool uses_little_endian() const
Determine whether values are decoded as little-endian.
- Returns:
True for little-endian encapsulations, false for big-endian ones.
-
inline std::span<const uint8_t> payload() const
Access only the payload bytes after any encapsulation header.
- Returns:
A view over the unread buffer excluding the encapsulation header.
-
inline size_t remaining() const
Get the number of unread bytes remaining.
- Returns:
Remaining unread byte count, or 0 if the offset is beyond the buffer.
-
inline std::span<const uint8_t> remaining_view() const
Access a view of the unread bytes without copying.
- Returns:
A span over the unread tail of the buffer, or an empty span if the reader is invalid.
-
inline bool skip(size_t length)
Advance the read cursor by a fixed number of bytes.
- Parameters:
length – Number of bytes to skip.
- Returns:
True if the bytes were skipped, false if the reader became invalid.
-
inline bool align(size_t alignment)
Advance the read cursor to satisfy an alignment requirement.
- Parameters:
alignment – Required alignment in bytes. Values less than or equal to 1 are ignored.
- Returns:
True if the padding bytes were skipped successfully, false if the reader became invalid.
-
template<typename T>
inline bool read(T &value) Read a primitive scalar using CDR alignment and endianness rules.
- Template Parameters:
T – Primitive integral or floating-point type to decode.
- Parameters:
value – Output variable that receives the decoded value on success.
- Returns:
True if a complete value was decoded, false otherwise.
-
inline bool read_bool(bool &value)
Read a boolean value encoded with the CDR 1-byte representation.
- Parameters:
value – Output variable that receives the decoded boolean on success.
- Returns:
True if the boolean was read successfully, false otherwise.
-
inline bool read_string(std::string &text)
Read a CDR string.
- Parameters:
text – Output string receiving the decoded text without the trailing null terminator.
- Returns:
True if the string was decoded successfully, false otherwise.
-
inline std::span<const uint8_t> read_span(size_t length, size_t alignment = 1)
Read a fixed number of bytes as a zero-copy span.
- Parameters:
length – Number of bytes to expose.
alignment – Alignment in bytes to satisfy before reading.
- Returns:
A span over the requested bytes, or an empty span if the read failed.
-
inline bool read_bytes(std::span<uint8_t> bytes, size_t alignment = 1)
Read bytes into a caller-provided mutable span.
- Parameters:
bytes – Destination span that receives the copied bytes.
alignment – Alignment in bytes to satisfy before reading.
- Returns:
True if all requested bytes were read successfully, false otherwise.
-
inline bool read_bytes(std::vector<uint8_t> &bytes, size_t length, size_t alignment = 1)
Read bytes into a vector.
- Parameters:
bytes – Output vector replaced with the decoded bytes on success.
length – Number of bytes to read.
alignment – Alignment in bytes to satisfy before reading.
- Returns:
True if the requested bytes were read successfully, false otherwise.
-
template<typename T, size_t N>
inline bool read_array(std::array<T, N> &values) Read a fixed-size array of primitive values.
- Template Parameters:
T – Primitive integral or floating-point element type.
N – Number of elements in the array.
- Parameters:
values – Output array receiving the decoded elements.
- Returns:
True if all array elements were read successfully, false otherwise.
-
template<typename T>
inline bool read_sequence(std::vector<T> &values) Read a variable-length CDR sequence of primitive values.
- Template Parameters:
T – Primitive integral or floating-point element type.
- Parameters:
values – Output vector replaced with the decoded sequence elements on success.
- Returns:
True if the sequence length and all elements were decoded successfully, false otherwise.
Public Static Functions
-
static inline Config body_config(CdrEncapsulation encapsulation = CdrEncapsulation::CDR_LE)
Create a configuration for reading a headerless/body-only CDR payload.
- Parameters:
encapsulation – Encapsulation/endian rules to assume for the payload body.
- Returns:
A configuration with encapsulation consumption disabled.
-
static inline CdrReader make_body_reader(std::span<const uint8_t> data, CdrEncapsulation encapsulation = CdrEncapsulation::CDR_LE)
Create a reader for a headerless/body-only CDR payload.
- Parameters:
data – Serialized payload bytes to read.
encapsulation – Encapsulation/endian rules to assume for the payload body.
- Returns:
A reader initialized for body-only parsing.
-
struct Config
Configuration for a CDR reader instance.
-
inline explicit CdrReader(std::span<const uint8_t> data)