diff --git a/rmw/include/rmw/rmw.h b/rmw/include/rmw/rmw.h index d57809d1..f9d19cbd 100644 --- a/rmw/include/rmw/rmw.h +++ b/rmw/include/rmw/rmw.h @@ -556,7 +556,25 @@ rmw_publisher_assert_liveliness(const rmw_publisher_t * publisher); /** * The ROS message is serialized into a byte stream contained within the * rmw_serialized_message_t structure. - * The serialization format depends on the underlying middleware. + * The serialization format depends on the underlying implementation. + * + * \pre Given ROS message must be a valid non-null instance, initialized + * by the caller and matching the provided typesupport. + * \pre Given typesupport must be a valid non-null instance, as provided + * by `rosidl` APIs. + * \pre Given serialized message must be a valid non-null instance, initialized + * by the caller. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Maybe [1] + * Thread-Safe | No + * Uses Atomics | Maybe [2] + * Lock-Free | Maybe [2] + * [1] if the given serialized message does not have enough capacity to hold + * the ROS message serialization + * [2] rmw implementation defined, check the implementation documentation * * \param[in] ros_message the typed ROS message * \param[in] type_support the typesupport for the ROS message @@ -577,10 +595,26 @@ rmw_serialize( /** * The given rmw_serialized_message_t's internal byte stream buffer is deserialized * into the given ROS message. - * The ROS message must already be allocated and initialized, and must match - * the given typesupport structure. * The serialization format expected in the rmw_serialized_message_t depends on the - * underlying middleware. + * underlying implementation. + * + * \pre Given serialized message must be a valid non-null instance, such + * as that returned by `rmw_serialize()`, matching provided typesupport + * and ROS message. + * \pre Given typesupport must be a valid non-null instance, as provided + * by `rosidl` APIs. + * \pre Given ROS message must be a valid non-null instance, initialized + * by the caller. + * + *
+ * Attribute | Adherence + * ------------------ | ------------- + * Allocates Memory | Maybe [1] + * Thread-Safe | No + * Uses Atomics | Maybe [2] + * Lock-Free | Maybe [2] + * [1] if the given ROS message contains unbounded fields + * [2] rmw implementation defined, check the implementation documentation * * \param[in] serialized_message the serialized message holding the byte stream * \param[in] type_support the typesupport for the typed ros message diff --git a/rmw/include/rmw/serialized_message.h b/rmw/include/rmw/serialized_message.h index 08ed3ac9..4f2d34c3 100644 --- a/rmw/include/rmw/serialized_message.h +++ b/rmw/include/rmw/serialized_message.h @@ -22,17 +22,81 @@ extern "C" #include "rcutils/types/uint8_array.h" -// aliases for rcutils_uint8_array_t -/* - * For now this is a simple aliasing from a serialized message to a uint8 array. +/** + * \struct rmw_serialized_message_t + * + * \brief Serialized message as a string of bytes. + * + * It includes (but it is not limited to) the following members: + * \i \c buffer the reference to internal storage, as a pointer + * \i \c buffer_length the size of stored contents, as an unsigned integer + * \i \c buffer_capacity the capacity of internal storage, as an unsigned integer + */ + +/* For now this is a simple aliasing from a serialized message to a uint8 array. * However, in future developments this serialized message can become something * more complex and is therefore aliased. */ typedef rcutils_uint8_array_t rmw_serialized_message_t; + +/// Return a zero initialized serialized message struct. #define rmw_get_zero_initialized_serialized_message rcutils_get_zero_initialized_uint8_array -#define rmw_serialized_message_init rcutils_uint8_array_init -#define rmw_serialized_message_fini rcutils_uint8_array_fini -#define rmw_serialized_message_resize rcutils_uint8_array_resize + +/// Initialize a serialized message, zero initializing its contents. +/** + * \pre Given serialized message must have been zero initialized. + * + * \param[inout] serialized_message a pointer to the serialized message to initialize + * \param[in] message_capacity the size of the memory to allocate + * \param[in] allocator the allocator to use for the memory allocation + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if any arguments are invalid, or + * \return 'RMW_RET_BAD_ALLOC` if no memory could be allocated correctly, or + * \return `RMW_RET_ERROR` if an unexpected error occurs + */ +#define rmw_serialized_message_init(serialized_message, message_capacity, allocator) \ + rcutils_uint8_array_init(serialized_message, message_capacity, allocator) + +/// Finalize a serialized message. +/** + * \pre Given serialized message must have been initialized with `rmw_serialized_message_init()`. + * + * \remarks If serialized message is zero initialized, then `RMW_RET_INVALID_ARGUMENT` is returned. + * + * \param[in] serialized_message pointer to the serialized message to be cleaned up + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if serialized_message is invalid, or + * \return `RMW_RET_ERROR` if an unexpected error occurs + */ +#define rmw_serialized_message_fini(serialized_message) \ + rcutils_uint8_array_fini(serialized_message) + +/// Resize the internal buffer of the serialized message. +/** + * The internal buffer of the serialized message can be resized dynamically + * if needed. + * If the new size is smaller than the current capacity, then the memory is + * truncated. + * + * \pre Given serialized message must have been initialized with `rmw_serialized_message_init()`. + * + * \remarks If serialized message is zero initialized, then `RMW_RET_INVALID_ARGUMENT` + * is returned. + * + * \warning Be aware that this might deallocate the memory and therefore + * invalidate any pointers to the internal buffer. + * + * \param[inout] serialized_message pointer to the serialized message + * to be resized + * \param[in] new_size the new size of the internal buffer + * \return `RMW_RET_OK` if successful, or + * \return `RMW_RET_INVALID_ARGUMENT` if serialized_message is invalid + * or new_size is set to zero, or + * \return `RMW_RET_BAD_ALLOC` if memory allocation failed, or + * \return `RMW_RET_ERROR` if an unexpected error occurs + */ +#define rmw_serialized_message_resize(serialized_message, new_size) \ + rcutils_uint8_array_resize(serialized_message, new_size) #if __cplusplus }