use rosidl_runtime_rs::Message;
use futures::channel::oneshot::{channel, Sender};
use crate::{rcl_bindings::rmw_service_info_t, Promise, RequestId, ServiceInfo};
pub trait ClientOutput<Response>: Sized {
fn create_channel() -> (AnyClientOutputSender<Response>, Promise<Self>);
}
impl<Response: Message> ClientOutput<Response> for Response {
fn create_channel() -> (AnyClientOutputSender<Response>, Promise<Self>) {
let (sender, receiver) = channel();
(AnyClientOutputSender::ResponseOnly(sender), receiver)
}
}
impl<Response: Message> ClientOutput<Response> for (Response, RequestId) {
fn create_channel() -> (AnyClientOutputSender<Response>, Promise<Self>) {
let (sender, receiver) = channel();
(AnyClientOutputSender::WithId(sender), receiver)
}
}
impl<Response: Message> ClientOutput<Response> for (Response, ServiceInfo) {
fn create_channel() -> (AnyClientOutputSender<Response>, Promise<Self>) {
let (sender, receiver) = channel();
(AnyClientOutputSender::WithServiceInfo(sender), receiver)
}
}
pub enum AnyClientOutputSender<Response> {
ResponseOnly(Sender<Response>),
WithId(Sender<(Response, RequestId)>),
WithServiceInfo(Sender<(Response, ServiceInfo)>),
}
impl<Response: Message> AnyClientOutputSender<Response> {
pub(super) fn send_response(self, response: Response, service_info: rmw_service_info_t) {
match self {
Self::ResponseOnly(sender) => {
let _ = sender.send(response);
}
Self::WithId(sender) => {
let _ = sender.send((
response,
RequestId::from_rmw_request_id(&service_info.request_id),
));
}
Self::WithServiceInfo(sender) => {
let _ = sender.send((response, ServiceInfo::from_rmw_service_info(&service_info)));
}
}
}
}