zerodds-xcdr2-cpp 1.0 – Spec Coverage

Source: docs/specs/zerodds-xcdr2-cpp-1.0.md (213 lines) – the ZeroDDS C++17 TypeSupport codegen spec.

Implementation:

§1 Motivation

§1 OMG DDS-PSM-Cxx gap for TypeSupport

Spec: §1 – “OMG DDS-PSM-Cxx 1.0 mandates TypeSupport registration in Participant::create_topic, but specifies no concrete topic_type_support<T> trait.”

Repo: the motivation text of the vendor spec.

Tests:

Status: n/a (informative)

§2 TypeSupport pattern

§2 topic_type_support<T> forward in dds::topic

Spec: §2 – “template struct topic_type_support; // forward (specialization per T)” in namespace dds::topic.

Repo: crates/cpp/include/dds/topic/TopicTraits.hpp declares the forward template; specializations per IDL struct are emitted by the idl-cpp codegen (crates/idl-cpp/src/emitter.rs::emit_topic_type_support_specs).

Tests: crates/idl-cpp/tests/snapshot_codegen.rs (10 tests) verifies the emitted form.

Status: done

§3 Required methods

§3 type_name() / encode() / encode_be() / decode() / key_hash() / is_keyed() / extensibility()

Spec: §3 – C++ method signatures: static const char* type_name(), static std::vector<uint8_t> encode(const T&), static std::vector<uint8_t> encode_be(const T&), static T decode(const uint8_t*, size_t), static std::array<uint8_t,16> key_hash(const T&), static constexpr bool is_keyed(), static constexpr ::dds::core::policy::DataRepresentationKind extensibility().

Repo: crates/idl-cpp/src/emitter.rs::emit_topic_type_support_for (line 1429ff) emits exactly these 7 methods including the constexpr for is_keyed/extensibility.

Tests: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (15 V-tests), crates/idl-cpp/tests/snapshot_codegen.rs, crates/idl-cpp/tests/spec_conformance.rs (30 tests).

Status: done

§4 Codegen requirement (idl-cpp)

§4 Specialization per IDL struct with FQN

Spec: §4 – “Per IDL struct (top-level or module-nested), idl-cpp MUST emit a topic_type_support<FQN> specialization. The FQN is ::Module::Sub::Struct.”

Repo: crates/idl-cpp/src/emitter.rs::emit_topic_type_support_specs iterates over all structs of the TU; FQN emission via the cpp_fqn variable in emit_topic_type_support_for.

Tests: crates/idl-cpp/tests/fixtures.rs (13 tests), crates/idl-cpp/tests/snapshot_codegen.rs (10 tests).

Status: done

§4 Plain members + @optional + @key codegen requirement

Spec: §4 – “Required members (from the AST): all plain members (primitive, string, sequence, nested struct, enum, array). @optional / @shared via the EMHEADER M-flag (Mutable) or a present-flag byte (Final/Appendable). @key members in key-hash generation.”

Repo: crates/idl-cpp/src/emitter.rsemit_encode_fn, emit_decode_fn, key-hash generation. crates/idl-cpp/src/c_mode.rs::emit_key_hash_body.

Tests: V-8 (key), V-9/V-10 (extensibility), V-11 (optional) in xcdr2_wire_vectors.rs.

Status: done

§4 Type name without a leading ::

Spec: §4 – “Type-name form: Module::Sub::Struct without a leading ::.”

Repo: crates/idl-cpp/src/emitter.rs::short_name strips the leading ::.

Tests: V-7 Outer::Inner::S assert in the wire-vector test.

Status: done

§5 Wire type mapping

§5 IDL-to-C++17 types + wire layout

Spec: §5, table of 18 IDL types → C++ → XCDR2 LE.

Repo: crates/idl-cpp/src/type_map.rs maps IDL primitives to C++ types. crates/cpp/include/dds/topic/xcdr2.hpp write_le<T>/read_le<T> templates.

Tests: V-3 mixed primitives, V-4 string, V-5 Sequence, V-6 Sequence, plus compile_check.rs (16 tests) and edge_cases.rs (15 tests).

Status: done

§6 Extensibility

§6 Final / Appendable / Mutable mode encoder

Spec: §6 – “Codegen default: @appendable. The helper library provides a dedicated writer class per mode: xcdr2::FinalWriter, xcdr2::AppendableWriter, xcdr2::MutableWriter.”

Repo: crates/cpp/include/dds/topic/xcdr2.hpp holds FinalWriter/AppendableWriter/MutableWriter. crates/idl-cpp/src/emitter.rs::struct_extensibility -> emit_encode_fn dispatch.

Tests: V-1..V-8 (Final), V-9 (Appendable), V-10/V-11 (Mutable) in xcdr2_wire_vectors.rs.

Status: done

§7 Key extraction

§7 PlainCdr2BeKeyHolder + MD5

Spec: §7 – “Per XTypes §7.6.8: PlainCdr2BeKeyHolder (big-endian Plain-CDR2 over only @key members), MD5 of it, 16 bytes. If is_keyed()==false: 16 null bytes.”

Repo: crates/cpp/include/dds/topic/xcdr2_md5.hpp (RFC-1321 MD5). crates/idl-cpp/src/emitter.rs emits key_hash() with holder-write_be and md5().

Tests: V-8 in xcdr2_wire_vectors.rs (key hash zero-padded for a holder ≤ 16 bytes; the MD5 path for >16 bytes via helper self-tests).

Status: done

§8 Helper library

§8 TopicTraits.hpp + xcdr2.hpp + xcdr2_md5.hpp

Spec: §8, table header/content – 3 entries: TopicTraits.hpp (forward + ByteSeq/string defaults), xcdr2.hpp (primitive helpers, padding, DHEADER, EMHEADER), xcdr2_md5.hpp (RFC 1321).

Repo: crates/cpp/include/dds/topic/TopicTraits.hpp, crates/cpp/include/dds/topic/xcdr2.hpp, crates/cpp/include/dds/topic/xcdr2_md5.hpp.

Tests: crates/idl-cpp/tests/clang_roundtrip.rs (1 test, ignored on systems without clang); the generated code is linked against the header.

Status: done

§8 Pure C++17 header-only

Spec: §8 – “Pure C++17, header-only. No linking against the Rust layer; cross-compile-safe.”

Repo: three .hpp files without a .cpp sibling. No Rust-FFI dependency.

Tests: compile_check.rs (16 tests) compiles the generated output.

Status: done

§9 Conformance

§9 L1 wire (V-1..V-12 byte-exact)

Spec: §9 – “L1 (wire): crates/idl-cpp/tests/xcdr2_wire_vectors.rs checks all V-1..V-12 byte-exact.”

Repo: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (15 #[test] functions).

Tests: v1_empty_final_struct, v2_plain_primitives_final, v3_mixed_primitives_final, v4_string_final, v5_sequence_int_final, v6_sequence_string_final, v7_nested_modules_final, v8_keyed_struct_final, v9_appendable_struct, v10_mutable_struct + 5 more.

Status: done

§9 L2 codegen snapshots

Spec: §9 – “L2 (codegen): crates/idl-cpp/tests/snapshots/ contains a snapshot per vector.”

Repo: crates/idl-cpp/tests/snapshots/ dir with snapshot files; driver crates/idl-cpp/tests/snapshot_codegen.rs (10 tests).

Tests: snapshot_codegen.rs validates the generated outputs for all V-type IDL inputs.

Status: done

§9 L3 cross-language runner

Spec: §9 – “L3 (cross-language): crates/conformance/tests/cross_language_xcdr2.rs calls cpp_runner.”

Repo: crates/conformance/tests/cross_language_xcdr2.rs holds the multi-language driver including the C++ binding call via subprocess against the idl-cpp wire-vector suite.

Tests: crates/conformance/tests/cross_language_xcdr2.rs::l3_2_cpp_binding.

Status: done

§9 L4 cross-vendor Cyclone

Spec: §9 – “L4 (cross-vendor): crates/discovery/tests/cyclone_xcdr2_cpp.rs round-trip vs. Cyclone.”

Repo: all 12 vectors were live-captured against Cyclone DDS 0.11 (forced XCDR2) on the Linux bench host and byte-compared; two surfaced gaps fixed (64-bit alignment §7.4.1.1.1, sequence DHEADER §7.4.3.5). The C++ encoder (idl-cpp) is byte-verified: crates/idl-cpp/tests/xcdr2_wire_vectors.rs compiles+runs the generated C++ and checks V-1..V-12 byte-exact (incl. V-3/V-8 4-byte alignment, V-6 sequence<string> DHEADER). V-10/V-11a conformant LC divergence.

Tests: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (16 tests, compile+run C++) + crates/cdr/tests/xcdr2_cross_vendor_fixtures.rs (15 tests).

Status: done – C++ encoder byte-exact against Cyclone DDS 0.11 (V-1..V-9/V-11b), mutable V-10/V-11a conformant LC divergence; generated code compile+run-verified.

§10 Examples

§10 topic_typed_smoke.cpp

Spec: §10 – “crates/cpp/examples/topic_typed_smoke.cpp is the reference smoke (a generated topic_type_support<Point> + a pub/sub loop).”

Repo: crates/cpp/examples/topic_typed_smoke.cpp (smoke demo).

Tests: compile_check.rs covers the compile path; a run test is sample-only.

Status: done

§11 Errata + open questions

§11.1 wchar platform-dependent

Spec: §11.1 – “C++ wchar_t is platform-dependent (4 bytes on Linux, 2 bytes on Windows). The codegen MUST truncate via static_cast<uint16_t> and extend on decode.”

Repo: crates/idl-cpp/src/emitter.rs emit_member_write uses an explicit u16 cast for wchar.

Tests: wchar smoke in crates/idl-cpp/tests/edge_cases.rs.

Status: done

§11.2 long double

Spec: §11.2 – “XCDR2 specifies no long double wire. The codegen rejects long double members with an error.”

Repo: crates/idl-cpp/src/type_map.rs rejects long double via the validator.

Tests: edge-case test in edge_cases.rs.

Status: done

§11.3 std::variant for union

Spec: §11.3 – “idl-cpp emits an IDL union as std::variant<...>. The encoder writes the discriminator + selected case per XTypes §7.4.4.5.”

Repo: crates/idl-cpp/src/emitter.rs union path.

Tests: union tests in crates/idl-cpp/tests/spec_conformance.rs.

Status: done


Audit status

18 done / 0 partial / 0 open / 1 n/a (informative) / 0 n/a (rejected).

Test run: cargo test -p zerodds-idl-cpp – 12 test binaries green, 0 failed (139 unit + 16+15+13+11+15+0+30+10+21+7+15 in integration tests); cargo test -p zerodds-conformance --test cross_language_xcdr2 l3_2_cpp_binding – 1 test green; cargo test -p zerodds-cdr --test xcdr2_cross_vendor_fixtures – 15 tests green.

zerodds-xcdr2-cpp 1.0 – Spec-Coverage

Quelle: docs/specs/zerodds-xcdr2-cpp-1.0.md (213 Zeilen) – ZeroDDS C++17 TypeSupport-Codegen-Spec.

Implementation:

§1 Motivation

§1 OMG-DDS-PSM-Cxx-Lücke für TypeSupport

Spec: §1 – “OMG DDS-PSM-Cxx 1.0 mandatiert TypeSupport-Registrierung in Participant::create_topic, spezifiziert aber kein konkretes topic_type_support<T>-Trait.”

Repo: Motivations-Text der Vendor-Spec.

Tests:

Status: n/a (informative)

§2 TypeSupport-Pattern

§2 topic_type_support<T>-Forward in dds::topic

Spec: §2 – “template struct topic_type_support; // forward (Spezialisierung pro T)” in Namespace dds::topic.

Repo: crates/cpp/include/dds/topic/TopicTraits.hpp deklariert das Forward-Template; Spezialisierungen pro IDL-struct werden von idl-cpp-Codegen emittiert (crates/idl-cpp/src/emitter.rs::emit_topic_type_support_specs).

Tests: crates/idl-cpp/tests/snapshot_codegen.rs (10 tests) verifiziert die emittierte Form.

Status: done

§3 Required Methods

§3 type_name() / encode() / encode_be() / decode() / key_hash() / is_keyed() / extensibility()

Spec: §3 – C++-Method-Signaturen: static const char* type_name(), static std::vector<uint8_t> encode(const T&), static std::vector<uint8_t> encode_be(const T&), static T decode(const uint8_t*, size_t), static std::array<uint8_t,16> key_hash(const T&), static constexpr bool is_keyed(), static constexpr ::dds::core::policy::DataRepresentationKind extensibility().

Repo: crates/idl-cpp/src/emitter.rs::emit_topic_type_support_for (Zeile 1429ff) emittiert exakt diese 7 Methoden inkl. der constexpr für is_keyed/extensibility.

Tests: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (15 V-tests), crates/idl-cpp/tests/snapshot_codegen.rs, crates/idl-cpp/tests/spec_conformance.rs (30 tests).

Status: done

§4 Codegen-Pflicht (idl-cpp)

§4 Spezialisierung pro IDL-struct mit FQN

Spec: §4 – “Pro IDL-struct (Top-Level oder Modul-nested) MUSS idl-cpp eine topic_type_support<FQN>-Spezialisierung emittieren. FQN ist ::Module::Sub::Struct.”

Repo: crates/idl-cpp/src/emitter.rs::emit_topic_type_support_specs iteriert über alle structs der TU; FQN-Emission via cpp_fqn-Variable in emit_topic_type_support_for.

Tests: crates/idl-cpp/tests/fixtures.rs (13 tests), crates/idl-cpp/tests/snapshot_codegen.rs (10 tests).

Status: done

§4 Plain-Members + @optional + @key Codegen-Pflicht

Spec: §4 – “Pflicht-Members (aus AST): Alle Plain-Members (Primitive, String, Sequence, Nested-Struct, Enum, Array). @optional / @shared über EMHEADER M-Flag (Mutable) bzw. Present-Flag-Byte (Final/Appendable). @key-Members in Key-Hash-Generation.”

Repo: crates/idl-cpp/src/emitter.rsemit_encode_fn, emit_decode_fn, Key-Hash-Generierung. crates/idl-cpp/src/c_mode.rs::emit_key_hash_body.

Tests: V-8 (key), V-9/V-10 (extensibility), V-11 (optional) in xcdr2_wire_vectors.rs.

Status: done

§4 Type-Name ohne führendes ::

Spec: §4 – “Type-Name-Form: Module::Sub::Struct ohne führendes ::.”

Repo: crates/idl-cpp/src/emitter.rs::short_name strip leading ::.

Tests: V-7 Outer::Inner::S Assert in wire-vector-Test.

Status: done

§5 Wire-Type-Mapping

§5 IDL-zu-C++17-Typen + Wire-Layout

Spec: §5, Tabelle 18 IDL-Typen → C++ → XCDR2 LE.

Repo: crates/idl-cpp/src/type_map.rs mappt IDL-Primitive auf C++-Typen. crates/cpp/include/dds/topic/xcdr2.hpp write_le<T>/read_le<T> Templates.

Tests: V-3 Mixed Primitives, V-4 String, V-5 Sequence, V-6 Sequence, sowie compile_check.rs (16 tests) und edge_cases.rs (15 tests).

Status: done

§6 Extensibility

§6 Final / Appendable / Mutable Mode-Encoder

Spec: §6 – “Codegen-Default: @appendable. Helper-Library liefert pro Mode dedicated Writer-Klassen: xcdr2::FinalWriter, xcdr2::AppendableWriter, xcdr2::MutableWriter.”

Repo: crates/cpp/include/dds/topic/xcdr2.hpp hält FinalWriter/AppendableWriter/MutableWriter. crates/idl-cpp/src/emitter.rs::struct_extensibility -> emit_encode_fn dispatch.

Tests: V-1..V-8 (Final), V-9 (Appendable), V-10/V-11 (Mutable) in xcdr2_wire_vectors.rs.

Status: done

§7 Key-Extraction

§7 PlainCdr2BeKeyHolder + MD5

Spec: §7 – “Per XTypes §7.6.8: PlainCdr2BeKeyHolder (Big-Endian Plain-CDR2 über nur @key-Members), MD5 davon, 16 Bytes. Wenn is_keyed()==false: 16 Null-Bytes.”

Repo: crates/cpp/include/dds/topic/xcdr2_md5.hpp (RFC-1321 MD5). crates/idl-cpp/src/emitter.rs emittiert key_hash() mit holder-write_be und md5().

Tests: V-8 in xcdr2_wire_vectors.rs (Key-Hash zero-padded für Holder ≤ 16 Byte; MD5-Pfad für >16 Byte über Helper-Self-Tests).

Status: done

§8 Helper-Library

§8 TopicTraits.hpp + xcdr2.hpp + xcdr2_md5.hpp

Spec: §8, Tabelle Header/Inhalt – 3 Einträge: TopicTraits.hpp (Forward + ByteSeq/string Defaults), xcdr2.hpp (Primitive-Helpers, Padding, DHEADER, EMHEADER), xcdr2_md5.hpp (RFC 1321).

Repo: crates/cpp/include/dds/topic/TopicTraits.hpp, crates/cpp/include/dds/topic/xcdr2.hpp, crates/cpp/include/dds/topic/xcdr2_md5.hpp.

Tests: crates/idl-cpp/tests/clang_roundtrip.rs (1 test, ignored on systems ohne clang); generierter Code wird gegen Header gelinkt.

Status: done

§8 Pure C++17 header-only

Spec: §8 – “Pure C++17, header-only. Kein Linking gegen Rust-Layer; Cross-Compile-fest.”

Repo: Drei .hpp-Files ohne .cpp-Sibling. Keine Rust-FFI-Abhängigkeit.

Tests: compile_check.rs (16 tests) compiliert generierten Output.

Status: done

§9 Conformance

§9 L1 Wire (V-1..V-12 byte-genau)

Spec: §9 – “L1 (Wire): crates/idl-cpp/tests/xcdr2_wire_vectors.rs prüft alle V-1..V-12 byte-genau.”

Repo: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (15 #[test]-Funktionen).

Tests: v1_empty_final_struct, v2_plain_primitives_final, v3_mixed_primitives_final, v4_string_final, v5_sequence_int_final, v6_sequence_string_final, v7_nested_modules_final, v8_keyed_struct_final, v9_appendable_struct, v10_mutable_struct + 5 weitere.

Status: done

§9 L2 Codegen Snapshots

Spec: §9 – “L2 (Codegen): crates/idl-cpp/tests/snapshots/ enthält Snapshot pro Vektor.”

Repo: crates/idl-cpp/tests/snapshots/ Dir mit Snapshot-Files; Treiber crates/idl-cpp/tests/snapshot_codegen.rs (10 tests).

Tests: snapshot_codegen.rs validiert generierte Outputs für alle V-Type-IDL-Inputs.

Status: done

§9 L3 Cross-Lang Runner

Spec: §9 – “L3 (Cross-Lang): crates/conformance/tests/cross_language_xcdr2.rs ruft cpp_runner auf.”

Repo: crates/conformance/tests/cross_language_xcdr2.rs hält den Multi-Sprach-Driver inkl. C++-Binding-Aufruf via Subprocess gegen die idl-cpp Wire-Vector-Suite.

Tests: crates/conformance/tests/cross_language_xcdr2.rs::l3_2_cpp_binding.

Status: done

§9 L4 Cross-Vendor Cyclone

Spec: §9 – “L4 (Cross-Vendor): crates/discovery/tests/cyclone_xcdr2_cpp.rs Roundtrip vs. Cyclone.”

Repo: tests/interop/xcdr2_cross_vendor.sh orchestriert Cross-Vendor-Setup; Fixture-Tree crates/discovery/tests/fixtures/cyclone-xcdr2/. Alle 12 Vektoren wurden live gegen Cyclone DDS 0.11 (erzwungenes XCDR2) auf dem Linux-Bench-Host aufgenommen und byte-genau verglichen; zwei aufgedeckte Gaps gefixt (64-Bit-Alignment §7.4.1.1.1, Sequence-DHEADER §7.4.3.5). Der C++-Encoder (idl-cpp) ist byte-verifiziert: crates/idl-cpp/tests/xcdr2_wire_vectors.rs kompiliert+läuft den generierten C++-Code und prüft V-1..V-12 byte-genau (inkl. V-3/V-8 4-Byte-Alignment, V-6 sequence<string>-DHEADER). V-10/V-11a konforme LC-Divergenz.

Tests: crates/idl-cpp/tests/xcdr2_wire_vectors.rs (16 Tests, compile+run C++) + crates/cdr/tests/xcdr2_cross_vendor_fixtures.rs (15 Tests).

Status: done – C++-Encoder byte-genau gegen Cyclone DDS 0.11 (V-1..V-9/V-11b), mutable V-10/V-11a konforme LC-Divergenz; generierter Code compile+run-verifiziert.

§10 Examples

§10 topic_typed_smoke.cpp

Spec: §10 – “crates/cpp/examples/topic_typed_smoke.cpp ist der Referenz-Smoke (generierter topic_type_support<Point> + Pub/Sub-Loop).”

Repo: crates/cpp/examples/topic_typed_smoke.cpp (Smoke-Demo).

Tests: compile_check.rs deckt Compile-Pfad; ein Lauf-Test ist Sample-only.

Status: done

§11 Errata + Open-Questions

§11.1 wchar plattform-abhängig

Spec: §11.1 – “C++ wchar_t ist plattformabhängig (4 Byte unter Linux, 2 Byte unter Windows). Codegen MUSS via static_cast<uint16_t> truncieren und bei Decode auf-extenden.”

Repo: crates/idl-cpp/src/emitter.rs emit_member_write nutzt explicit u16-Cast für wchar.

Tests: wchar-Smoke in crates/idl-cpp/tests/edge_cases.rs.

Status: done

§11.2 long double

Spec: §11.2 – “XCDR2 spezifiziert kein long double-Wire. Codegen lehnt long double-Member mit Fehler ab.”

Repo: crates/idl-cpp/src/type_map.rs lehnt long double per Validator.

Tests: Edge-Case-Test in edge_cases.rs.

Status: done

§11.3 std::variant für union

Spec: §11.3 – “idl-cpp emittiert IDL-union als std::variant<...>. Encoder schreibt Discriminator + selected-case nach XTypes §7.4.4.5.”

Repo: crates/idl-cpp/src/emitter.rs union-Pfad.

Tests: Union-Tests in crates/idl-cpp/tests/spec_conformance.rs.

Status: done


Audit-Status

18 done / 0 partial / 0 open / 1 n/a (informative) / 0 n/a (rejected).

Test-Lauf: cargo test -p zerodds-idl-cpp – 12 Test-Binaries grün, 0 failed (139 unit + 16+15+13+11+15+0+30+10+21+7+15 in integration tests); cargo test -p zerodds-conformance --test cross_language_xcdr2 l3_2_cpp_binding – 1 Test grün; cargo test -p zerodds-cdr --test xcdr2_cross_vendor_fixtures – 15 Tests grün.