use std::ops::{Deref, DerefMut};
use rosidl_runtime_rs::RmwMessage;
use crate::{rcl_bindings::*, PublisherState, RclrsError, ToResult};
pub struct LoanedMessage<'a, T>
where
T: RmwMessage,
{
pub(super) msg_ptr: *mut T,
pub(super) publisher: &'a PublisherState<T>,
}
impl<T> Deref for LoanedMessage<'_, T>
where
T: RmwMessage,
{
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.msg_ptr }
}
}
impl<T> DerefMut for LoanedMessage<'_, T>
where
T: RmwMessage,
{
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { &mut *self.msg_ptr }
}
}
impl<T> Drop for LoanedMessage<'_, T>
where
T: RmwMessage,
{
fn drop(&mut self) {
if !self.msg_ptr.is_null() {
unsafe {
rcl_return_loaned_message_from_publisher(
&*self.publisher.handle.rcl_publisher.lock().unwrap(),
self.msg_ptr as *mut _,
)
.ok()
.unwrap()
}
}
}
}
unsafe impl<T> Send for LoanedMessage<'_, T> where T: RmwMessage {}
unsafe impl<T> Sync for LoanedMessage<'_, T> where T: RmwMessage {}
impl<T> LoanedMessage<'_, T>
where
T: RmwMessage,
{
pub fn publish(mut self) -> Result<(), RclrsError> {
unsafe {
rcl_publish_loaned_message(
&*self.publisher.handle.rcl_publisher.lock().unwrap(),
self.msg_ptr as *mut _,
std::ptr::null_mut(),
)
.ok()?;
}
self.msg_ptr = std::ptr::null_mut();
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn traits() {
use crate::{test_helpers::*, vendor::test_msgs};
assert_send::<LoanedMessage<test_msgs::msg::rmw::BoundedSequences>>();
assert_sync::<LoanedMessage<test_msgs::msg::rmw::BoundedSequences>>();
}
}