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 🥰
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-derivecrate provides a derive macro for theDdsTypetrait, which is actually defined in thedcpscrate, making the naming misleading and confusing.Moreover, implementing (manually) or deriving
DdsTypecorrectly is extremely challenging because it has to handle the full matrix of possible combinations, including big and little endian encodings as well as the differentCDR``XTypesversions.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 aserializer/deserializerabstraction and correspondingSerialize/Deserializetraits.Each
serializer/deserializerimplementation is specialized for a specific endianness andCDR/XTypesversion, 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 fromserdeagain and introduce a dedicated abstraction similar toSerializeStruct.With this architecture, the
serialization/deserializationmechanism becomes easily extensible, allowing support for new mechanisms or protocol versions without requiring changes to existing implementations.I agree with keeping the
DdsTypetrait 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
DdsTypecould be thatSelfmust also implement bothSerializeandDeserialize.We could also go further by introducing marker traits, such as
DdsKey, which would be required when invoking operations likedisposeon a typeT.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 🥰