Trait Message

Source
pub trait Message:
    Clone
    + Debug
    + Default
    + 'static
    + Send
    + Sync {
    type RmwMsg: RmwMessage;

    // Required methods
    fn into_rmw_message(msg_cow: Cow<'_, Self>) -> Cow<'_, Self::RmwMsg>;
    fn from_rmw_message(msg: Self::RmwMsg) -> Self;
}
Expand description

Trait for types that can be used in a rclrs::Subscription and a rclrs::Publisher.

rosidl_generator_rs generates two types of messages that implement this trait:

  • An “idiomatic” message type, in the ${package_name}::msg module
  • An “RMW-native” message type, in the ${package_name}::msg::rmw module

§Idiomatic message type

The idiomatic message type aims to be familiar to Rust developers and ROS 2 developers coming from rclcpp. To this end, it translates the original ROS 2 message into a version that uses idiomatic Rust structs: std::vec::Vec for sequences and std::string::String for strings. All other fields are the same as in an RMW-native message.

This conversion incurs some overhead when reading and publishing messages.

It’s possible to use the idiomatic type for a publisher and the RMW-native type for a corresponding subscription, and vice versa.

§RMW-native message type

The RMW-native message type aims to achieve higher performance by avoiding the conversion step to an idiomatic message.

It uses the following type mapping:

Message field typeRust type
stringString
wstringWString
string<=N, for example string<=10BoundedString
wstring<=N, for example wstring<=10BoundedWString
T[], for example int32[]Sequence
T[<=N], for example int32[<=32]BoundedSequence
T[N], for example float32[8]standard Rust arrays
primitive type, for example float64corresponding Rust primitive type

The linked Rust types provided by this package are equivalents of types defined in C that are used by the RMW layer.

The API for these types, and the message as a whole, is still memory-safe and as convenient as possible. For instance, the Sequence struct that is used for sequences supports iteration and all of the functionality of slices. However, it doesn’t have an equivalent of Vec::push(), among others.

§What does “RMW-native” mean in detail?

The message can be directly passed to and from the RMW layer because (1) its layout is identical to the layout of the type generated by rosidl_generator_c and (2) the dynamic memory inside the message is owned by the C allocator.

The above type mapping, together with a #[repr(C)] annotation on the message, guarantees these two properties.

This means the user of a message does not need to care about memory ownership, because that is managed by the relevant functions and trait impls.

§I need even more detail, please

rosidl_runtime_c and the code generated by rosidl_generator_c manages memory by means of four functions for each message: init(), fini(), create(), and destroy().

init() does the following:

  • for a message, it calls init() on all its members that are of non-primitive type, and applies default values
  • for a primitive sequence, it allocates the space requested
  • for a string, it constructs a string containing a single null terminator byte
  • for a non-primitive sequence, it zero-allocates the space requested and calls init() on all its elements

fini() does the following (which means after a call to fini(), everything inside the message has been deallocated):

  • for a message, it calls fini() on all its members that are of non-primitive type
  • for a primitive sequence, it deallocates
  • for a string, it deallocates
  • for a non-primitive sequence, it calls fini() on all its elements, and then deallocates

create() simply allocates space for the message itself, and calls init().

destroy() simply deallocates the message itself, and calls fini().

Memory ownership by C is achieved by calling init() when any string or sequence is created, as well as in the Default impl for messages. User code can still create messages explicitly, which will not call init(), but this is not a problem, since nothing is allocated this way. The Drop impl for any sequence or string will call fini().

Required Associated Types§

Source

type RmwMsg: RmwMessage

The corresponding RMW-native message type.

Required Methods§

Source

fn into_rmw_message(msg_cow: Cow<'_, Self>) -> Cow<'_, Self::RmwMsg>

Converts the idiomatic message into an RMW-native message.

If the idiomatic message is owned, a slightly more efficient conversion is possible. This is why the function takes a Cow.

If this function receives a borrowed message that is already RMW-native, it should directly return that borrowed message. This is why the return type is also Cow.

Source

fn from_rmw_message(msg: Self::RmwMsg) -> Self

Converts the RMW-native message into an idiomatic message.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§