use rosidl_runtime_rs::Message;
use crate::{
subscription::SubscriptionHandle, MessageInfo, RclrsError, RclrsErrorFilter,
ReadOnlyLoanedMessage,
};
use std::{any::Any, sync::Arc};
pub enum WorkerSubscriptionCallback<T: Message, Payload> {
Regular(Box<dyn FnMut(&mut Payload, T) + Send>),
RegularWithMessageInfo(Box<dyn FnMut(&mut Payload, T, MessageInfo) + Send>),
Boxed(Box<dyn FnMut(&mut Payload, Box<T>) + Send>),
BoxedWithMessageInfo(Box<dyn FnMut(&mut Payload, Box<T>, MessageInfo) + Send>),
Loaned(Box<dyn FnMut(&mut Payload, ReadOnlyLoanedMessage<T>) + Send>),
LoanedWithMessageInfo(
Box<dyn FnMut(&mut Payload, ReadOnlyLoanedMessage<T>, MessageInfo) + Send>,
),
}
impl<T: Message, Payload: 'static> WorkerSubscriptionCallback<T, Payload> {
pub(super) fn execute(
&mut self,
handle: &Arc<SubscriptionHandle>,
any_payload: &mut dyn Any,
) -> Result<(), RclrsError> {
let Some(payload) = any_payload.downcast_mut::<Payload>() else {
return Err(RclrsError::InvalidPayload {
expected: std::any::TypeId::of::<Payload>(),
received: (*any_payload).type_id(),
});
};
let mut evalute = || {
match self {
WorkerSubscriptionCallback::Regular(cb) => {
let (msg, _) = handle.take::<T>()?;
cb(payload, msg);
}
WorkerSubscriptionCallback::RegularWithMessageInfo(cb) => {
let (msg, msg_info) = handle.take::<T>()?;
cb(payload, msg, msg_info);
}
WorkerSubscriptionCallback::Boxed(cb) => {
let (msg, _) = handle.take_boxed::<T>()?;
cb(payload, msg);
}
WorkerSubscriptionCallback::BoxedWithMessageInfo(cb) => {
let (msg, msg_info) = handle.take_boxed::<T>()?;
cb(payload, msg, msg_info);
}
WorkerSubscriptionCallback::Loaned(cb) => {
let (msg, _) = handle.take_loaned::<T>()?;
cb(payload, msg);
}
WorkerSubscriptionCallback::LoanedWithMessageInfo(cb) => {
let (msg, msg_info) = handle.take_loaned::<T>()?;
cb(payload, msg, msg_info);
}
}
Ok(())
};
evalute().take_failed_ok()
}
}