1use core::{fmt, marker::PhantomData};
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4
5#[cfg(feature = "alloc")]
6pub use alloc_mod::*;
7
8#[cfg(feature = "std")]
9pub use std_mod::*;
10
11use spacepackets::{
12 ecss::{tc::IsPusTelecommand, PusPacket},
13 ByteConversionError,
14};
15
16use crate::{queue::GenericTargetedMessagingError, ComponentId};
17
18pub type RequestId = u32;
21
22pub type Apid = u16;
24
25#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
26pub struct UniqueApidTargetId {
27 pub apid: Apid,
28 pub unique_id: u32,
29}
30
31impl UniqueApidTargetId {
32 pub const fn new(apid: Apid, target: u32) -> Self {
33 Self {
34 apid,
35 unique_id: target,
36 }
37 }
38
39 pub fn raw(&self) -> ComponentId {
40 ((self.apid as u64) << 32) | (self.unique_id as u64)
41 }
42
43 pub fn id(&self) -> ComponentId {
44 self.raw()
45 }
46
47 pub fn from_pus_tc(
50 tc: &(impl PusPacket + IsPusTelecommand),
51 ) -> Result<Self, ByteConversionError> {
52 if tc.user_data().len() < 4 {
53 return Err(ByteConversionError::FromSliceTooSmall {
54 found: tc.user_data().len(),
55 expected: 4,
56 });
57 }
58 Ok(Self::new(
59 tc.apid(),
60 u32::from_be_bytes(tc.user_data()[0..4].try_into().unwrap()),
61 ))
62 }
63}
64
65impl From<u64> for UniqueApidTargetId {
66 fn from(raw: u64) -> Self {
67 Self {
68 apid: (raw >> 32) as u16,
69 unique_id: raw as u32,
70 }
71 }
72}
73
74impl From<UniqueApidTargetId> for u64 {
75 fn from(target_and_apid_id: UniqueApidTargetId) -> Self {
76 target_and_apid_id.raw()
77 }
78}
79
80impl fmt::Display for UniqueApidTargetId {
81 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
82 write!(
83 f,
84 "Target and APID ID with APID {:#03x} and target {}",
85 self.apid, self.unique_id
86 )
87 }
88}
89
90#[derive(Debug, Copy, PartialEq, Eq, Clone)]
95#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96pub struct MessageMetadata {
97 request_id: RequestId,
98 sender_id: ComponentId,
99}
100
101impl MessageMetadata {
102 pub const fn new(request_id: RequestId, sender_id: ComponentId) -> Self {
103 Self {
104 request_id,
105 sender_id,
106 }
107 }
108
109 pub fn request_id(&self) -> RequestId {
110 self.request_id
111 }
112
113 pub fn sender_id(&self) -> ComponentId {
114 self.sender_id
115 }
116}
117
118#[derive(Debug, Clone, PartialEq, Eq)]
120#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
121pub struct GenericMessage<Message> {
122 pub requestor_info: MessageMetadata,
123 pub message: Message,
124}
125
126impl<Message> GenericMessage<Message> {
127 pub fn new(requestor_info: MessageMetadata, message: Message) -> Self {
128 Self {
129 requestor_info,
130 message,
131 }
132 }
133
134 delegate::delegate! {
135 to self.requestor_info {
136 pub fn request_id(&self) -> RequestId;
137 pub fn sender_id(&self) -> ComponentId;
138 }
139 }
140}
141
142pub trait MessageSender<MSG>: Send {
144 fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError>;
145}
146
147pub trait MessageReceiver<MSG> {
149 fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError>;
150}
151
152pub struct MessageWithSenderIdReceiver<MSG, R: MessageReceiver<MSG>>(pub R, PhantomData<MSG>);
153
154impl<MSG, R: MessageReceiver<MSG>> From<R> for MessageWithSenderIdReceiver<MSG, R> {
155 fn from(receiver: R) -> Self {
156 MessageWithSenderIdReceiver(receiver, PhantomData)
157 }
158}
159
160impl<MSG, R: MessageReceiver<MSG>> MessageWithSenderIdReceiver<MSG, R> {
161 pub fn try_recv_message(
162 &self,
163 ) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
164 self.0.try_recv()
165 }
166}
167
168pub struct MessageReceiverWithId<MSG, R: MessageReceiver<MSG>> {
169 local_channel_id: ComponentId,
170 reply_receiver: MessageWithSenderIdReceiver<MSG, R>,
171}
172
173impl<MSG, R: MessageReceiver<MSG>> MessageReceiverWithId<MSG, R> {
174 pub fn new(local_channel_id: ComponentId, reply_receiver: R) -> Self {
175 Self {
176 local_channel_id,
177 reply_receiver: MessageWithSenderIdReceiver::from(reply_receiver),
178 }
179 }
180
181 pub fn local_channel_id(&self) -> ComponentId {
182 self.local_channel_id
183 }
184}
185
186impl<MSG, R: MessageReceiver<MSG>> MessageReceiverWithId<MSG, R> {
187 pub fn try_recv_message(
188 &self,
189 ) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
190 self.reply_receiver.0.try_recv()
191 }
192}
193
194#[cfg(feature = "alloc")]
195pub mod alloc_mod {
196 use crate::queue::GenericSendError;
197
198 use super::*;
199 use hashbrown::HashMap;
200
201 pub struct MessageSenderMap<MSG, S: MessageSender<MSG>>(
202 pub HashMap<ComponentId, S>,
203 pub(crate) PhantomData<MSG>,
204 );
205
206 impl<MSG, S: MessageSender<MSG>> Default for MessageSenderMap<MSG, S> {
207 fn default() -> Self {
208 Self(Default::default(), PhantomData)
209 }
210 }
211
212 impl<MSG, S: MessageSender<MSG>> MessageSenderMap<MSG, S> {
213 pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
214 self.0.insert(target_id, message_sender);
215 }
216
217 pub fn send_message(
218 &self,
219 requestor_info: MessageMetadata,
220 target_channel_id: ComponentId,
221 message: MSG,
222 ) -> Result<(), GenericTargetedMessagingError> {
223 if self.0.contains_key(&target_channel_id) {
224 return self
225 .0
226 .get(&target_channel_id)
227 .unwrap()
228 .send(GenericMessage::new(requestor_info, message));
229 }
230 Err(GenericSendError::TargetDoesNotExist(target_channel_id).into())
231 }
232 }
233
234 pub struct MessageSenderAndReceiver<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>> {
235 pub local_channel_id: ComponentId,
236 pub message_sender_map: MessageSenderMap<TO, S>,
237 pub message_receiver: MessageWithSenderIdReceiver<FROM, R>,
238 }
239
240 impl<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>>
241 MessageSenderAndReceiver<TO, FROM, S, R>
242 {
243 pub fn new(local_channel_id: ComponentId, message_receiver: R) -> Self {
244 Self {
245 local_channel_id,
246 message_sender_map: Default::default(),
247 message_receiver: MessageWithSenderIdReceiver::from(message_receiver),
248 }
249 }
250
251 pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
252 self.message_sender_map
253 .add_message_target(target_id, message_sender)
254 }
255
256 pub fn local_channel_id_generic(&self) -> ComponentId {
257 self.local_channel_id
258 }
259
260 pub fn send_message(
262 &self,
263 request_id: RequestId,
264 target_id: ComponentId,
265 message: TO,
266 ) -> Result<(), GenericTargetedMessagingError> {
267 self.message_sender_map.send_message(
268 MessageMetadata::new(request_id, self.local_channel_id_generic()),
269 target_id,
270 message,
271 )
272 }
273
274 pub fn try_recv_message(
276 &self,
277 ) -> Result<Option<GenericMessage<FROM>>, GenericTargetedMessagingError> {
278 self.message_receiver.try_recv_message()
279 }
280 }
281
282 pub struct RequestAndReplySenderAndReceiver<
283 REQUEST,
284 REPLY,
285 S0: MessageSender<REQUEST>,
286 R0: MessageReceiver<REPLY>,
287 S1: MessageSender<REPLY>,
288 R1: MessageReceiver<REQUEST>,
289 > {
290 pub local_channel_id: ComponentId,
291 pub request_sender_map: MessageSenderMap<REQUEST, S0>,
293 pub reply_receiver: MessageWithSenderIdReceiver<REPLY, R0>,
294 pub request_receiver: MessageWithSenderIdReceiver<REQUEST, R1>,
296 pub reply_sender_map: MessageSenderMap<REPLY, S1>,
297 }
298
299 impl<
300 REQUEST,
301 REPLY,
302 S0: MessageSender<REQUEST>,
303 R0: MessageReceiver<REPLY>,
304 S1: MessageSender<REPLY>,
305 R1: MessageReceiver<REQUEST>,
306 > RequestAndReplySenderAndReceiver<REQUEST, REPLY, S0, R0, S1, R1>
307 {
308 pub fn new(
309 local_channel_id: ComponentId,
310 request_receiver: R1,
311 reply_receiver: R0,
312 ) -> Self {
313 Self {
314 local_channel_id,
315 request_receiver: request_receiver.into(),
316 reply_receiver: reply_receiver.into(),
317 request_sender_map: Default::default(),
318 reply_sender_map: Default::default(),
319 }
320 }
321
322 pub fn local_channel_id_generic(&self) -> ComponentId {
323 self.local_channel_id
324 }
325 }
326}
327
328#[cfg(feature = "std")]
329pub mod std_mod {
330
331 use super::*;
332 use std::sync::mpsc;
333
334 use crate::queue::{GenericReceiveError, GenericSendError};
335
336 impl<MSG: Send> MessageSender<MSG> for mpsc::Sender<GenericMessage<MSG>> {
337 fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError> {
338 self.send(message)
339 .map_err(|_| GenericSendError::RxDisconnected)?;
340 Ok(())
341 }
342 }
343 impl<MSG: Send> MessageSender<MSG> for mpsc::SyncSender<GenericMessage<MSG>> {
344 fn send(&self, message: GenericMessage<MSG>) -> Result<(), GenericTargetedMessagingError> {
345 if let Err(e) = self.try_send(message) {
346 return match e {
347 mpsc::TrySendError::Full(_) => Err(GenericSendError::QueueFull(None).into()),
348 mpsc::TrySendError::Disconnected(_) => {
349 Err(GenericSendError::RxDisconnected.into())
350 }
351 };
352 }
353 Ok(())
354 }
355 }
356
357 pub type MessageSenderMapMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::Sender<MSG>>;
358 pub type MessageSenderMapBoundedMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::SyncSender<MSG>>;
359
360 impl<MSG> MessageReceiver<MSG> for mpsc::Receiver<GenericMessage<MSG>> {
361 fn try_recv(&self) -> Result<Option<GenericMessage<MSG>>, GenericTargetedMessagingError> {
362 match self.try_recv() {
363 Ok(msg) => Ok(Some(msg)),
364 Err(e) => match e {
365 mpsc::TryRecvError::Empty => Ok(None),
366 mpsc::TryRecvError::Disconnected => {
367 Err(GenericReceiveError::TxDisconnected(None).into())
368 }
369 },
370 }
371 }
372 }
373
374 pub type MessageReceiverWithIdMpsc<MSG> = MessageReceiverWithId<MSG, mpsc::Receiver<MSG>>;
375}
376
377#[cfg(test)]
378mod tests {
379 use std::sync::mpsc;
380
381 use alloc::string::ToString;
382 use spacepackets::{
383 ecss::tc::{PusTcCreator, PusTcSecondaryHeader},
384 ByteConversionError, SpHeader,
385 };
386
387 use crate::{
388 queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError},
389 request::{MessageMetadata, MessageSenderMap},
390 };
391
392 use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
393
394 const TEST_CHANNEL_ID_0: u64 = 1;
395 const TEST_CHANNEL_ID_1: u64 = 2;
396 const TEST_CHANNEL_ID_2: u64 = 3;
397
398 #[test]
399 fn test_basic_target_id_with_apid() {
400 let id = UniqueApidTargetId::new(0x111, 0x01);
401 assert_eq!(id.apid, 0x111);
402 assert_eq!(id.unique_id, 0x01);
403 assert_eq!(id.id(), id.raw());
404 assert_eq!(u64::from(id), id.raw());
405 let id_raw = id.raw();
406 let id_from_raw = UniqueApidTargetId::from(id_raw);
407 assert_eq!(id_from_raw, id);
408 assert_eq!(id.id(), (0x111 << 32) | 0x01);
409 let string = id.to_string();
410 assert_eq!(
411 string,
412 "Target and APID ID with APID 0x111 and target 1".to_string()
413 );
414 }
415
416 #[test]
417 fn test_basic_target_id_with_apid_from_pus_tc() {
418 let sp_header = SpHeader::new_for_unseg_tc(0x111, 5, 0);
419 let app_data = 1_u32.to_be_bytes();
420 let pus_tc = PusTcCreator::new_simple(sp_header, 17, 1, &app_data, true);
421 let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
422 assert_eq!(id.apid, 0x111);
423 assert_eq!(id.unique_id, 1);
424 }
425
426 #[test]
427 fn test_basic_target_id_with_apid_from_pus_tc_invalid_app_data() {
428 let sp_header = SpHeader::new_for_unseg_tc(0x111, 5, 0);
429 let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
430 let pus_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
431 let error = UniqueApidTargetId::from_pus_tc(&pus_tc);
432 assert!(error.is_err());
433 let error = error.unwrap_err();
434 if let ByteConversionError::FromSliceTooSmall { found, expected } = error {
435 assert_eq!(found, 0);
436 assert_eq!(expected, 4);
437 } else {
438 panic!("Unexpected error type");
439 }
440 }
441
442 #[test]
443 fn test_receiver_only() {
444 let (sender, receiver) = mpsc::channel();
445 let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
447 let request_id = 5;
448 sender
449 .send(GenericMessage::new(
450 MessageMetadata::new(request_id, TEST_CHANNEL_ID_1),
451 5,
452 ))
453 .unwrap();
454 let reply = receiver.try_recv_message().unwrap();
455 assert!(reply.is_some());
456 assert_eq!(receiver.local_channel_id(), TEST_CHANNEL_ID_0);
457 let reply = reply.unwrap();
458 assert_eq!(reply.requestor_info.request_id, request_id);
459 assert_eq!(reply.requestor_info.sender_id, TEST_CHANNEL_ID_1);
460 assert_eq!(reply.message, 5);
461 }
462
463 #[test]
464 fn test_receiver_empty() {
465 let (_sender, receiver) = mpsc::sync_channel::<GenericMessage<i32>>(2);
466 let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
468 let reply = receiver.try_recv_message().unwrap();
469 assert!(reply.is_none());
470 }
471
472 #[test]
473 fn test_all_tx_disconnected() {
474 let (sender, receiver) = mpsc::sync_channel::<GenericMessage<i32>>(2);
475 let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
477 drop(sender);
478 let reply = receiver.try_recv_message();
479 assert!(reply.is_err());
480 let error = reply.unwrap_err();
481 if let GenericTargetedMessagingError::Receive(GenericReceiveError::TxDisconnected(None)) =
482 error
483 {
484 } else {
485 panic!("unexpected error type");
486 }
487 }
488
489 #[test]
490 fn test_sender_map() {
491 let (sender0, receiver0) = mpsc::channel();
492 let (sender1, receiver1) = mpsc::channel();
493 let mut sender_map = MessageSenderMap::default();
494 sender_map.add_message_target(TEST_CHANNEL_ID_1, sender0);
495 sender_map.add_message_target(TEST_CHANNEL_ID_2, sender1);
496 sender_map
497 .send_message(
498 MessageMetadata::new(1, TEST_CHANNEL_ID_0),
499 TEST_CHANNEL_ID_1,
500 5,
501 )
502 .expect("sending message failed");
503 let mut reply = receiver0.recv().expect("receiving message failed");
504 assert_eq!(reply.request_id(), 1);
505 assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
506 assert_eq!(reply.message, 5);
507 sender_map
508 .send_message(
509 MessageMetadata::new(2, TEST_CHANNEL_ID_0),
510 TEST_CHANNEL_ID_2,
511 10,
512 )
513 .expect("sending message failed");
514 reply = receiver1.recv().expect("receiving message failed");
515 assert_eq!(reply.request_id(), 2);
516 assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
517 assert_eq!(reply.message, 10);
518 }
519
520 #[test]
521 fn test_sender_map_target_does_not_exist() {
522 let (sender0, _) = mpsc::channel();
523 let mut sender_map_with_id = MessageSenderMap::default();
524 sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
525 let result = sender_map_with_id.send_message(
526 MessageMetadata::new(1, TEST_CHANNEL_ID_0),
527 TEST_CHANNEL_ID_2,
528 5,
529 );
530 assert!(result.is_err());
531 let error = result.unwrap_err();
532 if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) =
533 error
534 {
535 assert_eq!(target, TEST_CHANNEL_ID_2);
536 } else {
537 panic!("Unexpected error type");
538 }
539 }
540 #[test]
541 fn test_sender_map_queue_full() {
542 let (sender0, _receiver0) = mpsc::sync_channel(1);
543 let mut sender_map_with_id = MessageSenderMap::default();
544 sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
545 sender_map_with_id
546 .send_message(
547 MessageMetadata::new(1, TEST_CHANNEL_ID_0),
548 TEST_CHANNEL_ID_1,
549 5,
550 )
551 .expect("sending message failed");
552 let result = sender_map_with_id.send_message(
553 MessageMetadata::new(1, TEST_CHANNEL_ID_0),
554 TEST_CHANNEL_ID_1,
555 5,
556 );
557 assert!(result.is_err());
558 let error = result.unwrap_err();
559 if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error {
560 assert!(capacity.is_none());
561 } else {
562 panic!("Unexpected error type {}", error);
563 }
564 }
565
566 #[test]
567 fn test_sender_map_queue_receiver_disconnected() {
568 let (sender0, receiver0) = mpsc::sync_channel(1);
569 let mut sender_map_with_id = MessageSenderMap::default();
570 sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
571 drop(receiver0);
572 let result = sender_map_with_id.send_message(
573 MessageMetadata::new(1, TEST_CHANNEL_ID_0),
574 TEST_CHANNEL_ID_1,
575 5,
576 );
577 assert!(result.is_err());
578 let error = result.unwrap_err();
579 if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error {
580 } else {
581 panic!("Unexpected error type {}", error);
582 }
583 }
584}