use heapless::Vec as HVec;
use crate::protocol::dds::api::dds_type::Sample;
use crate::protocol::dds::api::error::DdsApiError;
use crate::protocol::dds::api::participant::Participant;
use crate::protocol::dds::api::publisher::Publisher;
use crate::protocol::dds::api::subscription::Subscription;
use super::sample_identity::SampleIdentity;
use super::wrappers::{ReplyWrapper, RequestWrapper, Service};
const MAX_PENDING: usize = 16;
pub struct ServiceClient<S: Service> {
request_pub: Publisher<RequestWrapper<S>>,
reply_sub: Subscription<ReplyWrapper<S>>,
my_request_writer_guid: [u8; 16],
next_request_seq: i64,
pending: HVec<i64, MAX_PENDING>,
}
impl<S: Service> ServiceClient<S> {
pub(super) fn new(
request_pub: Publisher<RequestWrapper<S>>,
reply_sub: Subscription<ReplyWrapper<S>>,
my_request_writer_guid: [u8; 16],
) -> Self {
Self {
request_pub,
reply_sub,
my_request_writer_guid,
next_request_seq: 1,
pending: HVec::new(),
}
}
pub fn send_request(
&mut self,
participant: &mut Participant,
request: &S::Request,
) -> Result<i64, DdsApiError> {
let seq = self.next_request_seq;
self.next_request_seq += 1;
if self.pending.is_full() {
self.pending.remove(0);
}
let _ = self.pending.push(seq);
let wrapper = RequestWrapper::<S> {
header: SampleIdentity::new(self.my_request_writer_guid, seq),
body: request.clone(),
};
participant.publish(&self.request_pub, &wrapper)?;
Ok(seq)
}
pub fn take_responses(&mut self, participant: &mut Participant) -> Vec<(i64, S::Response)> {
let samples: Vec<Sample<ReplyWrapper<S>>> = participant.take(&self.reply_sub);
let my_guid = self.my_request_writer_guid;
let mut results = Vec::with_capacity(samples.len());
for sample in samples {
let ReplyWrapper { header, body } = sample.data;
if header.writer_guid != my_guid {
continue;
}
let seq = header.sequence_number;
if let Some(pos) = self.pending.iter().position(|&s| s == seq) {
self.pending.remove(pos);
}
results.push((seq, body));
}
results
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn client_seq_starts_at_one() {
let id1 = SampleIdentity::new([1u8; 16], 1);
let id2 = SampleIdentity::new([1u8; 16], 2);
assert_eq!(id1.sequence_number, 1);
assert_eq!(id2.sequence_number, 2);
}
}