jhelovuo / RustDDS

Rust implementation of Data Distribution Service

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Raw read/write and keyed messages

curiousmindflow opened this issue · comments

Hello,

I'm working on a C FFI and a CLI (similar to Ros2 CLI) on top of this lib.
Currently, i've done a FFI that works well but i have to build the whole system each time there is a message creation/delete/update.

I designed a way to let each message be stand-alone .so/.rs/.h and load it dynamically at runtime with the message name as input.
I'm using libloading for the .so dyn loading part, define a common trait that is implemented by each message and known by the loader.
The loader load the .so in the form of a trait object.

There is the beginning of my issue.
Because my message is in the form of a trait object and Serialize / Deserialize are not object safe, i can't do something like:

trait Plugin: Serialize + DeserializeOwned {
...
}

Because of that, i can't give to DataWriter::write(...) and DataReader::read(...) those trait objects.
My idea is to implement the CDR serialization / deserialization inside the message, this way, the trait objects are able to pass from a representation to another (raw -> cdr, cdr -> raw, without ever needing the concrete type).

---> RustDDS currently don't expose method to write/read directly with &[u8].

The second point i identified is the Keyed trait issue. This trait is object safe, so i can do something like:

trait Plugin: Keyed {
...
}

So in theory i can give the trait object where a bound is constraining on a Keyed trait.

---> How is used the Keyed trait ? is it used at each write/reader ? Or is it used for "registering" a type on a topic and it's saved afterward ?

---> RustDDS currently don't expose method to write/read directly with &[u8].

That is right, there is no such method currently. It should be possible to add such methods to DataReader/DataWriter, but that is not very straightforward, because DataReader/DataWriter have to be parameterized by the payload type. Some resarchitecting would be needed here, such as restructuring DataReader/DataWriter to a raw binary processing part and a type-specific part.

---> How is used the Keyed trait ? is it used at each write/reader ? Or is it used for "registering" a type on a topic and it's saved afterward ?

The Keyed trait is needed (only) when communicating over a WITH_KEY topic, which is like a distributed map of key/value-pairs. NO_KEY topics do not need Keyed.

DDS works so that keys are considered to be embedded into the data samples (values), and there should be a sample type specific function to extract the key. The extractor function may be a simple field accessor, or any arbitrary computation on a data sample. DDS needs to extract and possibly hash that key, because removing key/value-pairs ("instances") from a topic requires communicating the key over the network.

---> RustDDS currently don't expose method to write/read directly with &[u8].

WITH_KEY ("keyed" for short) topics also complicate this a bit: When a data instance is updated, the serialized data sample is sent, as is the expected base case. However, when an instance is disposed (a key-value pair is removed from the map). Then, by an arbitrary choice of the Writer, either the serialized key is sent, OR an MD5 hash of the serialized key is sent. Any implementation that wants to decode the raw serialized contents of DATA submessages must be able to handle both.

---> How is used the Keyed trait ? is it used at each write/reader ? Or is it used for "registering" a type on a topic and it's saved afterward ?

To extend on the previous answer: The Keyed trait is how RustDDS is able to perform the key extraction described above.

There is now a new SimpleDataReader in branch 0.8. Version 0.8 is not yet released.

Please take a look at functions try_take_undecoded and try_take_one. Maybe you could use/modify these to get access to undecoded CDR data?