zerodds-cdr
Layer 1 — Primitives. XCDR1/XCDR2 encoder/decoder + KeyHash + PL_CDR1.
- Source: crates/cdr
- API docs: docs.rs/zerodds-cdr
zerodds-cdr fully implements the OMG XTypes 1.3 §7.4 wire-format family: alignment-tracking buffer I/O, primitive + composite type encoding, struct extensibility (final / appendable / mutable), KeyHash with MD5 fallback, and the XTypes PL_CDR1 member codec.
Pure-Rust no_std + alloc, forbid(unsafe_code).
Spec anchors
- OMG XTypes 1.3 §7.4 (wire encoding) incl. §7.4.1.2 (PL_CDR1), §7.4.2 (Plain CDR2 / Delimited CDR2 / PL_CDR2), §7.4.4 (composite types: string/sequence/array/optional), §7.4.5 (struct extensibility).
- OMG XTypes 1.3 §7.6.8 KeyHash (CDR_BE key holder + MD5 fallback).
- OMG IDL 4.2 §7.4.13 —
fixed<P, S>decimal type (BCD encoding). - DDSI-RTPS 2.5 §10 — wire encapsulation, RepresentationIdentifier bytes.
Public API (selection)
Buffer I/O:
BufferReader<'a>/BufferWriter— alignment-tracking byte-level I/O.Endianness::{Little, Big}.
Trait family:
CdrEncode/CdrDecode— serializer traits for all XCDR2 wire primitives.
Composite-type impls (for str, String, Vec<T>, [T; N], Option<T>):
- via the
compositemodule (XTypes §7.4.4).
Struct-extensibility encoder (struct_enc module):
encode_final/decode_final— XCDR2 Plain CDR2 (§7.4.2.1).encode_appendable/decode_appendable— XCDR2 Delimited CDR2 (§7.4.2.2).MutableStructEncoder— XCDR2 parameter-list encoder with required-members validation (§7.4.2.4).read_mutable_member/read_all_mutable_members— EMHEADER decode with length-code switch.
XCDR1 / PL_CDR1 (xcdr1 module):
encode_pl_cdr1_member/read_pl_cdr1_member— member codec with standard + extended header.write_pl_cdr1_sentinel—PID_LIST_END (0x3F02)terminator.
Fixed decimal:
Fixed<const P: u32, const S: u32>— IDLfixed<P, S>with BCD wire format.
KeyHash (key_hash module):
compute_key_hash(holder: &[u8], max_size: usize) -> [u8; 16]— XTypes §7.6.8.PlainCdr2BeKeyHolder— CDR_BE-encoded key holder.
Serde bridge (serde_bridge module, feature serde-bridge):
encode_via_serde<T: Serialize>/decode_via_serde<T: DeserializeOwned>— XCDR2-string wrap of anyserdetype (JSON intermediate form). Spec:zerodds-xcdr2-rust-1.0§11.3.
XCDR2 bindings conformance:
- 16 wire-vector tests (V-1..V-12) in
tests/xcdr2_wire_vectors.rs, byte-exact againstzerodds-xcdr2-bindings-conformance-1.0§6. - 15 cross-vendor decoder tests in
tests/xcdr2_cross_vendor_fixtures.rs(14 spec-derived + V-2 recorded from Cyclone DDS 0.10.2 via tcpdump).
Quick start
use zerodds_cdr::{BufferWriter, BufferReader, Endianness, CdrEncode, CdrDecode};
// Encoder
let mut w = BufferWriter::new(Endianness::Little);
42u32.encode(&mut w).unwrap();
let bytes = w.into_bytes();
// Decoder
let mut r = BufferReader::new(&bytes, Endianness::Little);
assert_eq!(u32::decode(&mut r).unwrap(), 42);
Structs with extensibility
use zerodds_cdr::struct_enc::{encode_appendable, encode_final, MutableStructEncoder};
use zerodds_cdr::{BufferWriter, Endianness, CdrEncode};
let mut w = BufferWriter::new(Endianness::Little);
// @final: tight-packed, no header
encode_final(&mut w, |w| { 1u32.encode(w)?; 2u8.encode(w) }).unwrap();
// @appendable: 4-byte DHEADER, forward-compatible
encode_appendable(&mut w, |w| { 3u32.encode(w) }).unwrap();
// @mutable: per-member EMHEADER + required-members validation
let mut enc = MutableStructEncoder::new(&mut w, vec![1, 2]);
enc.encode_member(1, false, |w| 10u32.encode(w)).unwrap();
enc.encode_member(2, false, |w| 20u32.encode(w)).unwrap();
enc.finish().unwrap();
Feature flags
| Feature | Default | Purpose |
|---|---|---|
std |
✅ | std re-exports, implies alloc |
alloc |
✅ | enables composite / fixed / key_hash / struct_enc / xcdr1 |
safety |
❌ | Reserved for safety-class hardening (Phase 2) |
Tests
cargo test -p zerodds-cdr: 201 tests (170 unit + 1 compliance_xcdr2 + 7 fuzz_smoke + 7 integration_topic + 15 proptest_roundtrip + 1 doctest).
Bench suite encode_decode_hotpaths (criterion). libFuzzer targets in fuzz/ for PL_CDR1 + composite + struct_enc.
Stability
All public-API items are semver-stable from 1.0.0-rc.3.
zerodds-cdr
Layer 1 — Primitives. XCDR1/XCDR2 Encoder/Decoder + KeyHash + PL_CDR1.
- Quelle: crates/cdr
- API-Docs: docs.rs/zerodds-cdr
zerodds-cdr implementiert die OMG XTypes 1.3 §7.4 Wire-Format-Familie vollständig: alignment-tracking Buffer-I/O, primitive + composite Type-Encoding, Struct-Extensibility (final / appendable / mutable), KeyHash mit MD5-Fallback und den XTypes-PL_CDR1 Member-Codec.
Pure-Rust no_std + alloc, forbid(unsafe_code).
Spec-Anker
- OMG XTypes 1.3 §7.4 (Wire-Encoding) inkl. §7.4.1.2 (PL_CDR1), §7.4.2 (Plain CDR2 / Delimited CDR2 / PL_CDR2), §7.4.4 (Composite Types: String/Sequence/Array/Optional), §7.4.5 (Struct-Extensibility).
- OMG XTypes 1.3 §7.6.8 KeyHash (CDR_BE Key-Holder + MD5-Fallback).
- OMG IDL 4.2 §7.4.13 —
fixed<P, S>Decimal-Type (BCD-Encoding). - DDSI-RTPS 2.5 §10 — Wire-Encapsulation, RepresentationIdentifier-Bytes.
Public API (Auswahl)
Buffer-I/O:
BufferReader<'a>/BufferWriter— alignment-tracking byte-level I/O.Endianness::{Little, Big}.
Trait-Familie:
CdrEncode/CdrDecode— Serializer-Traits für alle XCDR2-Wire-Primitives.
Composite-Type-Impls (für str, String, Vec<T>, [T; N], Option<T>):
- via
composite-Modul (XTypes §7.4.4).
Struct-Extensibility-Encoder (struct_enc-Modul):
encode_final/decode_final— XCDR2 Plain CDR2 (§7.4.2.1).encode_appendable/decode_appendable— XCDR2 Delimited CDR2 (§7.4.2.2).MutableStructEncoder— XCDR2 Parameter-List Encoder mit Required-Members-Validierung (§7.4.2.4).read_mutable_member/read_all_mutable_members— EMHEADER-Decode mit Length-Code-Switch.
XCDR1 / PL_CDR1 (xcdr1-Modul):
encode_pl_cdr1_member/read_pl_cdr1_member— Member-Codec mit Standard- + Extended-Header.write_pl_cdr1_sentinel—PID_LIST_END (0x3F02)Terminator.
Fixed-Decimal:
Fixed<const P: u32, const S: u32>— IDL-fixed<P, S>mit BCD-Wire-Format.
KeyHash (key_hash-Modul):
compute_key_hash(holder: &[u8], max_size: usize) -> [u8; 16]— XTypes §7.6.8.PlainCdr2BeKeyHolder— CDR_BE-encoded Key-Holder.
Serde-Bridge (serde_bridge-Modul, Feature serde-bridge):
encode_via_serde<T: Serialize>/decode_via_serde<T: DeserializeOwned>— XCDR2-string-Wrap eines beliebigenserde-Types (JSON-Zwischenform). Spec:zerodds-xcdr2-rust-1.0§11.3.
XCDR2-Bindings-Conformance:
- 16 Wire-Vector-Tests (V-1..V-12) in
tests/xcdr2_wire_vectors.rs, byte-genau gegenzerodds-xcdr2-bindings-conformance-1.0§6. - 15 Cross-Vendor-Decoder-Tests in
tests/xcdr2_cross_vendor_fixtures.rs(14 spec-derived + V-2 echt von Cyclone DDS 0.10.2 via tcpdump aufgezeichnet).
Quick Start
use zerodds_cdr::{BufferWriter, BufferReader, Endianness, CdrEncode, CdrDecode};
// Encoder
let mut w = BufferWriter::new(Endianness::Little);
42u32.encode(&mut w).unwrap();
let bytes = w.into_bytes();
// Decoder
let mut r = BufferReader::new(&bytes, Endianness::Little);
assert_eq!(u32::decode(&mut r).unwrap(), 42);
Strukturen mit Extensibility
use zerodds_cdr::struct_enc::{encode_appendable, encode_final, MutableStructEncoder};
use zerodds_cdr::{BufferWriter, Endianness, CdrEncode};
let mut w = BufferWriter::new(Endianness::Little);
// @final: tight-packed, kein Header
encode_final(&mut w, |w| { 1u32.encode(w)?; 2u8.encode(w) }).unwrap();
// @appendable: 4-byte DHEADER, forward-kompatibel
encode_appendable(&mut w, |w| { 3u32.encode(w) }).unwrap();
// @mutable: per-Member EMHEADER + Required-Members-Validierung
let mut enc = MutableStructEncoder::new(&mut w, vec![1, 2]);
enc.encode_member(1, false, |w| 10u32.encode(w)).unwrap();
enc.encode_member(2, false, |w| 20u32.encode(w)).unwrap();
enc.finish().unwrap();
Feature-Flags
| Feature | Default | Zweck |
|---|---|---|
std |
✅ | std-Re-Exports, implies alloc |
alloc |
✅ | aktiviert composite / fixed / key_hash / struct_enc / xcdr1 |
safety |
❌ | Reserved für Safety-Class-Hardening (Phase-2) |
Tests
cargo test -p zerodds-cdr: 201 Tests (170 unit + 1 compliance_xcdr2 + 7 fuzz_smoke + 7 integration_topic + 15 proptest_roundtrip + 1 doctest).
Bench-Suite encode_decode_hotpaths (criterion). libFuzzer-Targets in fuzz/ für PL_CDR1 + composite + struct_enc.
Stability
Alle Public-API-Items sind ab 1.0.0-rc.3 semver-stabil.