Skip to content

refactor: encoding/decoding architecture #40

Description

@carlocorradini

The current encoding/decoding mechanism for both primitive types (CdrEncode) and struct (DdsType) is quite cumbersome because it relies on two separate traits defined in different crates.
cdr-derive crate provides a derive macro for the DdsType trait, which is actually defined in the dcps crate, making the naming misleading and confusing.

Moreover, implementing (manually) or deriving DdsType correctly is extremely challenging because it has to handle the full matrix of possible combinations, including big and little endian encodings as well as the different CDR``XTypes versions.

A standardized and well-defined serialization/deserialization mechanism that abstracts away the different endianness options and protocol versions is essential. A good starting point would be to take inspiration from the design of serde, not to use it directly, but to follow a similar approach based on a serializer/deserializer abstraction and corresponding Serialize/Deserialize traits.

Each serializer/deserializer implementation is specialized for a specific endianness and CDR/XTypes version, removing this complexity from implementors. Of course, we still need to provide specialized handling for serializing structs and unions with different extensibility kinds, but we can take inspiration from serde again and introduce a dedicated abstraction similar to SerializeStruct.
With this architecture, the serialization/deserialization mechanism becomes easily extensible, allowing support for new mechanisms or protocol versions without requiring changes to existing implementations.

I agree with keeping the DdsType trait for more complex data types such as structs, unions, and similar constructs. It should provide information such as the type name, extensibility, and key metadata for data types that can be published through a topic.
A requirement for implementing DdsType could be that Self must also implement both Serialize and Deserialize.

We could also go further by introducing marker traits, such as DdsKey, which would be required when invoking operations like dispose on a type T.

Finally, the entire ecosystem becomes simpler, from the derive implementation to the Rust IDL generator, since the latter can rely directly on the former.

PS: I know this represents a significant amount of work and a substantial refactoring effort, but it could significantly improve zerodds. Having a well-designed and solid core architecture would provide a strong foundation and greatly improve all the other components that depend on it 🥰

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions