diff --git a/r2r/examples/serialization.rs b/r2r/examples/serialization.rs new file mode 100644 index 000000000..dc9b111f0 --- /dev/null +++ b/r2r/examples/serialization.rs @@ -0,0 +1,31 @@ +use r2r::{WrappedNativeMsgUntyped, WrappedTypesupport}; + +fn main() -> Result<(), Box> { + let msg = r2r::std_msgs::msg::String { + data: "Hello, world".into(), + }; + + let bytes = msg.to_serialized_bytes()?; + + // bytes to "untyped" r2r msg + let mut native = WrappedNativeMsgUntyped::new_from("std_msgs/msg/String")?; + native.from_serialized_bytes(&bytes)?; + + // "untyped" msg to json + let json = native.to_json()?; + + println!("as json\n----\n{}", serde_json::to_string_pretty(&json)?); + + // bytes to r2r msg. + let msg2 = r2r::std_msgs::msg::String::from_serialized_bytes(&bytes)?; + + println!("as r2r msg\n----\n{:#?}", msg2); + + // json to r2r msg + let msg3: r2r::std_msgs::msg::String = serde_json::from_value(json)?; + + assert_eq!(msg, msg2); + assert_eq!(msg2, msg3); + + Ok(()) +} diff --git a/r2r/src/lib.rs b/r2r/src/lib.rs index 3bb5a52e9..122689e3e 100644 --- a/r2r/src/lib.rs +++ b/r2r/src/lib.rs @@ -81,6 +81,7 @@ pub use msg_types::WrappedActionTypeSupport; pub use msg_types::WrappedNativeMsg as NativeMsg; pub use msg_types::WrappedServiceTypeSupport; pub use msg_types::WrappedTypesupport; +pub use msg_types::WrappedNativeMsgUntyped; mod utils; pub use utils::*; diff --git a/r2r/src/msg_types.rs b/r2r/src/msg_types.rs index 78a9f7bfc..da426c121 100644 --- a/r2r/src/msg_types.rs +++ b/r2r/src/msg_types.rs @@ -406,6 +406,37 @@ impl WrappedNativeMsgUntyped { } } + pub fn from_serialized_bytes(&mut self, data: &[u8]) -> Result<()> { + // TODO: Copy paste from above, should refactor later. + use r2r_rcl::*; + + let msg_buf = rcl_serialized_message_t { + buffer: data.as_ptr() as *mut u8, + buffer_length: data.len(), + buffer_capacity: data.len(), + + // Since its read only, this should never be used .. + allocator: unsafe { rcutils_get_default_allocator() }, + }; + + // Note From the docs of rmw_deserialize, its not clear whether this reuses + // any part of msg_buf. However it shouldn't matter since from_native + // clones everything again anyway .. + let result = unsafe { + rmw_deserialize( + &msg_buf as *const rcl_serialized_message_t, + self.ts, + self.msg, + ) + }; + + if result == RCL_RET_OK as i32 { + Ok(()) + } else { + Err(Error::from_rcl_error(result)) + } + } + pub fn to_json(&self) -> Result { let json = (self.msg_to_json)(self.msg); json.map_err(|serde_err| Error::SerdeError {