1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
//! DeserializerAdapter is used to fit serde Deserializer implementations and
//! DataReader together.
//!
//! DataReader/DataWriter cannot assume a specific serialization
//! format, so it needs to be given as a parameter when instantiating.
//! For WITH_KEY topics, we need to be able to (de)serialize the key in addition
//! to data values.
//!
//! Type parameter `D` is the type resulting from (successful) deserialization.
//!
//! Deserialization consists of two steps: decode and transform. Decode inputs a
//! byte slice and outputs an intermediate type `Decoded`. Transform step maps
//! `Decoded`into `D`.
//!
//! It is a common case that `Decoded` and `D` are the same and the
//! transform step is the identity function.
//!
//! # How to implement `DeserializerAdapter<D>`
//!
//! We call the imaginary example serialization format `MyDataFormat`.
//!
//! 0. Define a type `MyDataFormatAdapter<D>`, that is used as a link between
//! RustDDS and MyDataFormat decoder routines. The decoder routines may
//! reside in
//! a pre-existing Rust crate. The adapter type is
//! necessary to bridge together RustDDS and MyDataFormat, because Rust's
//! orphan implementation rule prevents an application crate from implementing
//! RustDDS-defined traits on types in MyDataFormat crate.
//!
//! 1. Implement `no_key::DeserializerAdapter<D> for MyDataFormatAdapter<D>`
//! * Define `Error` type to indicate deserialization failures
//! * Define the `Decoded` type.
//! * Implement `supported_encodings` function. This function defines which
//! RTPS data encodings are decodable by this adapter.
//! * Implement the `transform_decoded` function.
//! * Do not implement the provided functions in this trait.
//!
//! At this point, you should be all set for deserializing no_key data with
//! run-time seed, i.e. you are required to provide a decoder function at run
//! time, every time.
//!
//! If you do not need/want provide the decoder object at every deserialization
//! call, and can define a deserializer that only depends on type `D`, and the
//! incoming byte slice, then extend your `MyDataFormatAdapter<D>` as
//! follows
//!
//! 2. Implement `no_key::DefaultDecoder<D> for MyDataFormatAdapter<D>`
//! * Define a type, e.g. `MyDataFormatDecoder<D>`, that implements trait
//! `no_key::Decode<Decoded>`
//! * Implement the `decode_bytes` function to do the decoding from byte
//! slice to `Decoded`
//! * The decoder may minimally be a struct with no actual fields, possibly
//! only a `PhantomData<D>`, which makes it zero size and no cost to
//! clone. But this depends on the workings of MyDataFormat.
//! * Implement `no_key::DefaultDecoder<D> for MyDataFormatAdapter<D>`
//! * Define the associated type `Decoder = MyDataFormatDecoder<D>`
//! * Define a const `DECODER` as an instance of `MyDataFormatDecoder`
//! * Implement or derive `Clone` for `MyDataFormatDecoder`. The cloning
//! should be cheap, as a new instance is needed for each deserialization
//! operation.
//!
//! Now you should be able to deserialize no_key data with a default decoder
//! function.
//!
//! If you need to handle also with_key deserialization, then we need more
//! implementations to also handle the instance keys.
//!
//! 3. Implement `with_key::DeserializerAdapter<D> for MyDataFormatAdapter<D>`
//! * Define the `DecodedKey` type.
//! * Implement the `transform_decoded_key` function.
//!
//! To use a default decoder for with_key deserialization also:
//!
//! 4. Implement `with_key::DefaultDecoder<D> for MyDataFormatAdapter<D>`
//! * Implement also `with_key::Decode<DecodedValue, DecodedKey>` for
//! `MyDataFormatDecoder`.
//! * One member function `decode_key_bytes` is needed. It defines how to
//! decode a key.
/// Deserializer/Serializer adapters for `no_key` data types.
pub mod no_key {
use bytes::Bytes;
use crate::RepresentationIdentifier;
/// trait for connecting a Deserializer implementation and DataReader
/// together - no_key version.
///
/// Deserialization is done in two steps: decode and transform.
/// The basic pipeline is:
///
/// byte slice → decode → value of type `Self::Decoded` → call
/// [`Self::transform_decoded`] → value of type `D`
///
/// The transform step may be an identity function, which means that
/// `Self::Decoded` and `D` are the same.
///
/// The decoding step can be parameterized at run time, if the decoder is
/// defined suitaby. If there is no need for such parameterization (i.e.
/// decoder object), use subtrait `DefaultDecoder`, which defines decoding
/// that needs no decoder "seed" object at run time. In that case decoding is
/// dependent only on the type of the decoder and incoming byte stream.
pub trait DeserializerAdapter<D> {
/// The error type returned when decoding fails.
type Error: std::error::Error;
/// Type after decoding.
///
/// The adapter might apply additional operations or wrapper types to the
/// decoded value, so this type might be different from `D`.
type Decoded;
/// Which data representations can the DeserializerAdapter read?
/// See RTPS specification Section 10 and Table 10.3
fn supported_encodings() -> &'static [RepresentationIdentifier];
/// Transform the `Self::Decoded` type returned by the decoder into a
/// value of type `D`.
///
/// If [`Self::Decoded`] is set to `D`, this method can be the identity
/// function.
fn transform_decoded(decoded: Self::Decoded) -> D;
/// Deserialize data from bytes to an object using the given decoder.
///
/// `encoding` must be something given by `supported_encodings()`, or
/// implementation may fail with Err or `panic!()`.
fn from_bytes_with<S>(
input_bytes: &[u8],
encoding: RepresentationIdentifier,
decoder: S,
) -> Result<D, S::Error>
where
S: Decode<Self::Decoded>,
{
decoder
.decode_bytes(input_bytes, encoding)
.map(Self::transform_decoded)
}
/// Deserialize data from bytes to an object.
/// `encoding` must be something given by `supported_encodings()`, or
/// implementation may fail with Err or `panic!()`.
///
/// Only usable if the adapter has a default decoder, i.e. implements
/// `DefaultDecoder`.
fn from_bytes(input_bytes: &[u8], encoding: RepresentationIdentifier) -> Result<D, Self::Error>
where
Self: DefaultDecoder<D>,
{
Self::from_bytes_with(input_bytes, encoding, Self::DECODER)
}
}
/// The `DeserializerAdapter` can be used without a decoder object as there is
/// a default one.
pub trait DefaultDecoder<D>: DeserializerAdapter<D> {
/// Type of the default decoder.
///
/// The default decoder needs to be clonable to be usable for async stream
/// creation (as it's needed multiple times).
type Decoder: Decode<Self::Decoded, Error = Self::Error> + Clone;
/// The default decoder value.
///
/// This default decoder is typically implemented by forwarding to a
/// different trait, e.g. `serde::Deserialize`.
const DECODER: Self::Decoder;
}
/// The trait `Decode` defines a decoder object that produced a value of type
/// `Dec` from a slice of bytes and a [`RepresentationIdentifier`]. Note
/// that `Decoded` maps to associated type `Decoded` in
/// `DeserializerAdapter` , not `D`.
pub trait Decode<Decoded> {
/// The decoding error type returned by [`Self::decode_bytes`].
type Error: std::error::Error;
/// Tries to decode the given byte slice to a value of type `D` using the
/// given encoding.
fn decode_bytes(
self,
input_bytes: &[u8],
encoding: RepresentationIdentifier,
) -> Result<Decoded, Self::Error>;
}
/// trait for connecting a Serializer implementation and DataWriter
/// together - no_key version.
///
/// This is much simpler that the Deserializer above, because any the starting
/// point is an application-defined type, than can be generated by any
/// means.
pub trait SerializerAdapter<D> {
type Error: std::error::Error; // Error type
// what encoding do we produce?
fn output_encoding() -> RepresentationIdentifier;
fn to_bytes(value: &D) -> Result<Bytes, Self::Error>;
}
}
/// Deserializer/Serializer adapters for `with_key` data types.
pub mod with_key {
use bytes::Bytes;
use crate::{Keyed, RepresentationIdentifier};
use super::no_key;
/// trait for connecting a Deserializer implementation and DataReader
/// together - with_key version.
///
/// The keyed versions inherit the no_key versions,
/// but here the payload type `D` implements `Keyed`, which means that thre is
/// an associated key type `D::K`. The `with_key` versions extend the
/// deserialization functionality to also handle that key type.
///
/// `with_key` functionality is needed in DDS topics that have a key, e.g. DDS
/// Discovery topics. ROS 2 (as of Iron Irwini) has no concept of with_key
/// topics.
pub trait DeserializerAdapter<D>: no_key::DeserializerAdapter<D>
where
D: Keyed,
{
/// Key type after decoding and before transformation.
///
/// The adapter might apply additional operations or wrapper types to the
/// decoded value, so this type might be different from `D`.
type DecodedKey;
/// Transform the `Self::DecodedKey` type returned by the decoder into a
/// value of type `D`.
///
/// If [`Self::DecodedKey`] is set to `D`, this method can be the identity
/// function.
fn transform_decoded_key(decoded_key: Self::DecodedKey) -> D::K;
/// Deserialize data from bytes to an object using the given decoder.
///
/// `encoding` must be something given by `supported_encodings()`, or
/// implementation may fail with Err or `panic!()`.
fn key_from_bytes_with<S>(
input_bytes: &[u8],
encoding: RepresentationIdentifier,
decoder: S,
) -> Result<D::K, S::Error>
where
S: Decode<Self::Decoded, Self::DecodedKey>,
{
decoder
.decode_key_bytes(input_bytes, encoding)
.map(Self::transform_decoded_key)
}
/// Deserialize data from bytes to an object.
/// `encoding` must be something given by `supported_encodings()`, or
/// implementation may fail with Err or `panic!()`.
///
/// Only usable if the adapter has a default decoder.
fn key_from_bytes(
input_bytes: &[u8],
encoding: RepresentationIdentifier,
) -> Result<D::K, Self::Error>
where
Self: DefaultDecoder<D>,
{
Self::key_from_bytes_with(input_bytes, encoding, Self::DECODER)
}
}
/// The `DeserializerAdapter` can be used without a decoder object as there is
/// a default one. This trait defines the default.
pub trait DefaultDecoder<D>: DeserializerAdapter<D>
where
D: Keyed,
{
/// Type of the default decoder.
///
/// The default decoder needs to be clonable to be usable for async stream
/// creation (as it's needed multiple times).
type Decoder: Decode<Self::Decoded, Self::DecodedKey, Error = Self::Error> + Clone;
/// The default decoder value.
///
/// This default decoder is typically implemented by forwarding to a
/// different trait, e.g. `serde::Deserialize`.
const DECODER: Self::Decoder;
}
/// Decodes a value of type `Dec` from a slice of bytes and a
/// [`RepresentationIdentifier`]. Note that `Dec` maps to associated type
/// `Decoded` in `DeserializerAdapter` , not `D`.
pub trait Decode<Dec, DecKey>: no_key::Decode<Dec> {
/// Tries to decode the given byte slice to a value of type `D` using the
/// given encoding.
fn decode_key_bytes(
self,
input_key_bytes: &[u8],
encoding: RepresentationIdentifier,
) -> Result<DecKey, Self::Error>;
}
/// trait for connecting a Serializer implementation and DataWriter
/// together - with_key version.
pub trait SerializerAdapter<D>: no_key::SerializerAdapter<D>
where
D: Keyed,
{
/// serialize a key `D::K` to Bytes.
fn key_to_bytes(value: &D::K) -> Result<Bytes, Self::Error>;
}
}