feat(cdr)!: reflection-driven CDR/XCDR serialization (replaces CdrWriter/CdrReader) - #704
feat(cdr)!: reflection-driven CDR/XCDR serialization (replaces CdrWriter/CdrReader)#704finger563 wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR replaces the manual espp::CdrWriter/espp::CdrReader API (and its Python bindings) with a reflection-driven CDR/XCDR serialization approach using the vendored finger563/cdr library backed by reflect_cpp, and migrates RTPS code/examples plus host/PC support to the new API (C++23).
Changes:
- Migrate RTPS parameter-list encoding/decoding and examples/tests from
espp::CdrWriter/espp::CdrReadertocdr::{serialize,deserialize,serialize_body,deserialize_body}. - Remove CDR Python bindings and update Python RTPS scripts to use pure-
structCDR helpers. - Update build/docs/packaging to support the new header-only CDR library and require C++23 (
std::expected).
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| suppressions.txt | Excludes vendored components/cdr/detail/* from cppcheck, consistent with other vendored trees. |
| python/rtps_subscriber.py | Replaces espp.CdrReader usage with pure-Python struct decoding for uint32. |
| python/rtps_pubsub.py | Replaces espp.CdrWriter/Reader with pure-Python struct packing/unpacking for uint32. |
| python/rtps_publisher.py | Replaces espp.CdrWriter with pure-Python struct packing for uint32. |
| pc/tests/rtps_common.hpp | Migrates test helpers to cdr::serialize/deserialize for uint32 payloads. |
| pc/CMakeLists.txt | Bumps host PC build standard to C++23. |
| lib/python_bindings/module.cpp | Removes registration of CDR Python bindings; keeps RTPS bindings. |
| lib/python_bindings/cdr_bindings.cpp | Deletes the hand-written CDR pybind11 shim. |
| lib/espp.cmake | Drops old cdr source/bindings; adds include paths for vendored CDR + reflect-cpp; bumps Python module to C++23. |
| lib/CMakeLists.txt | Bumps library compile features to C++23. |
| lib/autogenerate_bindings.py | Updates note/exclusion rationale for cdr.hpp now that Python uses pycdr2 instead of bindings. |
| doc/en/data/cdr.rst | Rewrites component docs to describe reflection-driven XCDR1/XCDR2 + std::expected API. |
| components/rtps/src/rtps.cpp | Migrates PL_CDR parameter writing/reading to new CDR helpers; introduces shared padding helper. |
| components/rtps/example/main/rtps_example.cpp | Migrates example payload helpers to cdr::serialize/deserialize. |
| components/esp32-p4-function-ev-board/example/main/esp32_p4_function_ev_board_example.cpp | Migrates example payload helpers to cdr::serialize/deserialize. |
| components/cdr/README.md | Updates component README to new reflection-driven library and capabilities. |
| components/cdr/include/cdr.hpp | Adds umbrella header that forwards to the vendored cdr library headers. |
| components/cdr/idf_component.yml | Updates description/tags; raises minimum IDF to >=5.2; adds dependency on espp/reflect_cpp. |
| components/cdr/example/README.md | Updates example documentation to match new functionality and API. |
| components/cdr/example/main/cdr_example.cpp | Replaces old imperative reader/writer example with reflection-driven struct-based demo. |
| components/cdr/example/CMakeLists.txt | Adds reflect_cpp and bumps example to C++23. |
| components/cdr/CMakeLists.txt | Switches cdr component to header-only registration; includes vendored headers; requires reflect_cpp. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
… library The cdr component now vendors finger563/cdr (detail/ submodule): the compiler generates CDR serialization from plain struct definitions — no IDL, no hand-written write/read sequences. Adds XCDR2 (delimited/ appendable + DHEADER schema evolution), both endiannesses, std::expected errors with field names, bounded types, and PL_CDR parameter-list helpers for RTPS discovery. Wire format is byte-verified against pycdr2 (CycloneDDS). Depends on the new reflect_cpp component; requires C++23 (default on IDF 5.2+ toolchains). BREAKING CHANGE: espp::CdrWriter / espp::CdrReader are gone; use cdr::serialize / cdr::deserialize<T> / cdr::param_list_writer instead. Example builds on ESP32-S3 / IDF 6 (389 KB total image incl. logger+fmt). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… API - rtps: discovery string/octet-sequence parameters serialize via cdr::serialize_body / deserialize_body; PL_CDR encapsulation handled inline (the old CdrWriter/CdrReader helpers are gone) - pc tests + rtps/p4 examples: uint32 payload helpers use cdr::serialize<cdr::xcdr1> / cdr::deserialize<uint32_t> - lib: espp builds C++23; cdr/reflect-cpp detail headers added to the include set; cdr python bindings removed — the python side of a CDR message is a plain pycdr2 dataclass (or struct.pack for primitives), so espp.CdrWriter/CdrReader no longer exist - python: rtps scripts use pure-python CDR helpers for uint32 payloads Verified: rtps example builds on ESP32-S3/IDF 6; host lib + _espp python module build; pc rtps_pubsub end-to-end test passes (16/16 samples through SPDP/SEDP discovery + user data on the new serializer). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Updates the sphinx page and example README for the new struct-based serialize/deserialize API, and excludes the vendored detail/ submodule from cppcheck (matching lib/). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
eac587a to
bbd826b
Compare
|
Applied all review feedback (thanks — the example error-handling one was a real UB bug):
The branch was also rebased as part of fixing the stack split in #703 — the cdr submodule and old-file removals now land in this PR's first commit where they belong. Re-verified after the rewrite: |
Description
Stacked on #703 (
feat/reflect-cpp-component) — merge that first, then re-target this PR tomain.Replaces the manual
espp::CdrWriter/espp::CdrReadercomponent with finger563/cdr, a reflection-driven CDR/XCDR serialization library (vendored as adetail/submodule): the compiler generates serialization code from plain struct definitions — no IDL compiler, no hand-written write/read call sequences.What the new library adds over the old component:
pycdr2dataclass, no native bindingsstd::expectederrors with code, payload offset, and failing field name; bounds-checked, fuzz-tested deserializers (ASan/UBSan-clean incl. a ~46k-case mutation stress suite in the library repo)cdr::bounded_string<N>/bounded_vector<T, N>, PL_CDRparam_list_writer/param_list_readerfor SPDP/SEDP, zero-allocationserialize_into, body-only variantsBREAKING CHANGE
espp::CdrWriter/espp::CdrReaderare gone, including their Python bindings (espp.CdrWriter/espp.CdrReader). Migrations in this PR:cdr::serialize_body/deserialize_body; PL_CDR encapsulation handled inlinecdr::serialize<cdr::xcdr1>/cdr::deserialize<uint32_t>pycdr2/struct.pack)Verification
cdrandrtpsexamples build on ESP32-S3 (IDF 6; also expected green on CI's v5.5.1 — its defaultgnu++2bprovidesstd::expected)espp_pclib +_espppython module build (C++23)pc/build/rtps_pubsubend-to-end test passes: 16/16 samples through SPDP/SEDP discovery + user data on the new serializerNotes
std::expected) — default on IDF 5.2+ toolchains (gnu++2b/gnu++26); manifest declaresidf: >=5.2reflect_cppsubmodule pin and finger563/cdr's FetchContent tag on the same reflect-cpp version (currently v0.25.0)doc/en/data/cdr.rstrewritten; example README updated; vendoreddetail/excluded from cppcheck🤖 Generated with Claude Code