1use crate::pool::{PoolAddr, PoolError};
6use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
7use crate::queue::{GenericReceiveError, GenericSendError};
8use crate::request::{GenericMessage, MessageMetadata, RequestId};
9#[cfg(feature = "alloc")]
10use crate::tmtc::PacketAsVec;
11use crate::tmtc::PacketInPool;
12use crate::ComponentId;
13use core::fmt::{Display, Formatter};
14use core::time::Duration;
15#[cfg(feature = "alloc")]
16use downcast_rs::{impl_downcast, Downcast};
17#[cfg(feature = "alloc")]
18use dyn_clone::DynClone;
19#[cfg(feature = "std")]
20use std::error::Error;
21
22use spacepackets::ecss::tc::{PusTcCreator, PusTcReader};
23use spacepackets::ecss::tm::PusTmCreator;
24use spacepackets::ecss::PusError;
25use spacepackets::{ByteConversionError, SpHeader};
26
27pub mod action;
28pub mod event;
29pub mod event_man;
30#[cfg(feature = "std")]
31pub mod event_srv;
32pub mod mode;
33pub mod scheduler;
34#[cfg(feature = "std")]
35pub mod scheduler_srv;
36#[cfg(feature = "std")]
37pub mod test;
38pub mod verification;
39
40#[cfg(feature = "alloc")]
41pub use alloc_mod::*;
42
43#[cfg(feature = "std")]
44pub use std_mod::*;
45
46use self::verification::VerificationReportingProvider;
47
48#[derive(Debug, PartialEq, Eq, Copy, Clone)]
51#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
52pub enum HandlingStatus {
53 HandledOne,
54 Empty,
55}
56
57#[derive(Debug, PartialEq, Eq, Clone)]
58pub enum PusTmVariant<'time, 'src_data> {
59 InStore(PoolAddr),
60 Direct(PusTmCreator<'time, 'src_data>),
61}
62
63impl From<PoolAddr> for PusTmVariant<'_, '_> {
64 fn from(value: PoolAddr) -> Self {
65 Self::InStore(value)
66 }
67}
68
69impl<'time, 'src_data> From<PusTmCreator<'time, 'src_data>> for PusTmVariant<'time, 'src_data> {
70 fn from(value: PusTmCreator<'time, 'src_data>) -> Self {
71 Self::Direct(value)
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq)]
76pub enum EcssTmtcError {
77 Store(PoolError),
78 ByteConversion(ByteConversionError),
79 Pus(PusError),
80 CantSendAddr(PoolAddr),
81 CantSendDirectTm,
82 Send(GenericSendError),
83 Receive(GenericReceiveError),
84}
85
86impl Display for EcssTmtcError {
87 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
88 match self {
89 EcssTmtcError::Store(store) => {
90 write!(f, "ecss tmtc error: {store}")
91 }
92 EcssTmtcError::ByteConversion(e) => {
93 write!(f, "ecss tmtc error: {e}")
94 }
95 EcssTmtcError::Pus(e) => {
96 write!(f, "ecss tmtc error: {e}")
97 }
98 EcssTmtcError::CantSendAddr(addr) => {
99 write!(f, "can not send address {addr}")
100 }
101 EcssTmtcError::CantSendDirectTm => {
102 write!(f, "can not send TM directly")
103 }
104 EcssTmtcError::Send(e) => {
105 write!(f, "ecss tmtc error: {e}")
106 }
107 EcssTmtcError::Receive(e) => {
108 write!(f, "ecss tmtc error {e}")
109 }
110 }
111 }
112}
113
114impl From<PoolError> for EcssTmtcError {
115 fn from(value: PoolError) -> Self {
116 Self::Store(value)
117 }
118}
119
120impl From<PusError> for EcssTmtcError {
121 fn from(value: PusError) -> Self {
122 Self::Pus(value)
123 }
124}
125
126impl From<GenericSendError> for EcssTmtcError {
127 fn from(value: GenericSendError) -> Self {
128 Self::Send(value)
129 }
130}
131
132impl From<ByteConversionError> for EcssTmtcError {
133 fn from(value: ByteConversionError) -> Self {
134 Self::ByteConversion(value)
135 }
136}
137
138impl From<GenericReceiveError> for EcssTmtcError {
139 fn from(value: GenericReceiveError) -> Self {
140 Self::Receive(value)
141 }
142}
143
144#[cfg(feature = "std")]
145impl Error for EcssTmtcError {
146 fn source(&self) -> Option<&(dyn Error + 'static)> {
147 match self {
148 EcssTmtcError::Store(e) => Some(e),
149 EcssTmtcError::ByteConversion(e) => Some(e),
150 EcssTmtcError::Pus(e) => Some(e),
151 EcssTmtcError::Send(e) => Some(e),
152 EcssTmtcError::Receive(e) => Some(e),
153 _ => None,
154 }
155 }
156}
157pub trait ChannelWithId: Send {
158 fn id(&self) -> ComponentId;
160 fn name(&self) -> &'static str {
161 "unset"
162 }
163}
164
165pub trait EcssTmSender: Send {
169 fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>;
170}
171
172pub trait EcssTcSender {
177 fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
178}
179
180#[derive(Default)]
182pub struct EcssTmDummySender {}
183
184impl EcssTmSender for EcssTmDummySender {
185 fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> {
186 Ok(())
187 }
188}
189
190#[non_exhaustive]
194#[derive(Debug, Clone, PartialEq, Eq)]
195pub enum TcInMemory {
196 Pool(PacketInPool),
197 #[cfg(feature = "alloc")]
198 Vec(PacketAsVec),
199}
200
201impl From<PacketInPool> for TcInMemory {
202 fn from(value: PacketInPool) -> Self {
203 Self::Pool(value)
204 }
205}
206
207#[cfg(feature = "alloc")]
208impl From<PacketAsVec> for TcInMemory {
209 fn from(value: PacketAsVec) -> Self {
210 Self::Vec(value)
211 }
212}
213
214#[derive(Debug, Clone, PartialEq, Eq)]
216pub struct EcssTcAndToken {
217 pub tc_in_memory: TcInMemory,
218 pub token: Option<TcStateToken>,
219}
220
221impl EcssTcAndToken {
222 pub fn new(tc_in_memory: impl Into<TcInMemory>, token: impl Into<TcStateToken>) -> Self {
223 Self {
224 tc_in_memory: tc_in_memory.into(),
225 token: Some(token.into()),
226 }
227 }
228}
229
230pub struct AcceptedEcssTcAndToken {
232 pub tc_in_memory: TcInMemory,
233 pub token: VerificationToken<TcStateAccepted>,
234}
235
236impl From<AcceptedEcssTcAndToken> for EcssTcAndToken {
237 fn from(value: AcceptedEcssTcAndToken) -> Self {
238 EcssTcAndToken {
239 tc_in_memory: value.tc_in_memory,
240 token: Some(value.token.into()),
241 }
242 }
243}
244
245impl TryFrom<EcssTcAndToken> for AcceptedEcssTcAndToken {
246 type Error = ();
247
248 fn try_from(value: EcssTcAndToken) -> Result<Self, Self::Error> {
249 if let Some(TcStateToken::Accepted(token)) = value.token {
250 return Ok(AcceptedEcssTcAndToken {
251 tc_in_memory: value.tc_in_memory,
252 token,
253 });
254 }
255 Err(())
256 }
257}
258
259#[derive(Debug, Clone)]
260pub enum TryRecvTmtcError {
261 Tmtc(EcssTmtcError),
262 Empty,
263}
264
265impl From<EcssTmtcError> for TryRecvTmtcError {
266 fn from(value: EcssTmtcError) -> Self {
267 Self::Tmtc(value)
268 }
269}
270
271impl From<PusError> for TryRecvTmtcError {
272 fn from(value: PusError) -> Self {
273 Self::Tmtc(value.into())
274 }
275}
276
277impl From<PoolError> for TryRecvTmtcError {
278 fn from(value: PoolError) -> Self {
279 Self::Tmtc(value.into())
280 }
281}
282
283pub trait EcssTcReceiver {
285 fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
286}
287
288pub trait PacketSenderPusTc: Send {
290 type Error;
291 fn send_pus_tc(
292 &self,
293 sender_id: ComponentId,
294 header: &SpHeader,
295 pus_tc: &PusTcReader,
296 ) -> Result<(), Self::Error>;
297}
298
299pub trait ActiveRequestMapProvider<V>: Sized {
300 fn insert(&mut self, request_id: &RequestId, request_info: V);
301 fn get(&self, request_id: RequestId) -> Option<&V>;
302 fn get_mut(&mut self, request_id: RequestId) -> Option<&mut V>;
303 fn remove(&mut self, request_id: RequestId) -> bool;
304
305 fn for_each<F: FnMut(&RequestId, &V)>(&self, f: F);
307
308 fn for_each_mut<F: FnMut(&RequestId, &mut V)>(&mut self, f: F);
310}
311
312pub trait ActiveRequestProvider {
313 fn target_id(&self) -> ComponentId;
314 fn token(&self) -> TcStateToken;
315 fn set_token(&mut self, token: TcStateToken);
316 fn has_timed_out(&self) -> bool;
317 fn timeout(&self) -> Duration;
318}
319
320pub trait PusRequestRouter<Request> {
323 type Error;
324
325 fn route(
326 &self,
327 requestor_info: MessageMetadata,
328 target_id: ComponentId,
329 request: Request,
330 ) -> Result<(), Self::Error>;
331}
332
333pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
334 type Error;
335
336 fn handle_reply(
339 &mut self,
340 reply: &GenericMessage<ReplyType>,
341 active_request: &ActiveRequestInfo,
342 tm_sender: &impl EcssTmSender,
343 verification_handler: &impl VerificationReportingProvider,
344 time_stamp: &[u8],
345 ) -> Result<bool, Self::Error>;
346
347 fn handle_unrequested_reply(
348 &mut self,
349 reply: &GenericMessage<ReplyType>,
350 tm_sender: &impl EcssTmSender,
351 ) -> Result<(), Self::Error>;
352
353 fn handle_request_timeout(
355 &mut self,
356 active_request: &ActiveRequestInfo,
357 tm_sender: &impl EcssTmSender,
358 verification_handler: &impl VerificationReportingProvider,
359 time_stamp: &[u8],
360 ) -> Result<(), Self::Error>;
361}
362
363#[cfg(feature = "alloc")]
364pub mod alloc_mod {
365 use hashbrown::HashMap;
366
367 use super::*;
368
369 #[cfg(feature = "alloc")]
380 pub trait EcssTmSenderExt: EcssTmSender + Downcast + DynClone {
381 fn upcast(&self) -> &dyn EcssTmSender;
384 fn upcast_mut(&mut self) -> &mut dyn EcssTmSender;
387 }
388
389 impl<T> EcssTmSenderExt for T
391 where
392 T: EcssTmSender + Clone + 'static,
393 {
394 fn upcast(&self) -> &dyn EcssTmSender {
397 self
398 }
399 fn upcast_mut(&mut self) -> &mut dyn EcssTmSender {
402 self
403 }
404 }
405
406 dyn_clone::clone_trait_object!(EcssTmSenderExt);
407 impl_downcast!(EcssTmSenderExt);
408
409 #[cfg(feature = "alloc")]
420 pub trait EcssTcSenderExt: EcssTcSender + Downcast + DynClone {}
421
422 impl<T> EcssTcSenderExt for T where T: EcssTcSender + Clone + 'static {}
424
425 dyn_clone::clone_trait_object!(EcssTcSenderExt);
426 impl_downcast!(EcssTcSenderExt);
427
428 #[cfg(feature = "alloc")]
439 pub trait EcssTcReceiverExt: EcssTcReceiver + Downcast {}
440
441 impl<T> EcssTcReceiverExt for T where T: EcssTcReceiver + 'static {}
443
444 impl_downcast!(EcssTcReceiverExt);
445
446 pub trait PusTcToRequestConverter<ActiveRequestInfo: ActiveRequestProvider, Request> {
463 type Error;
464 fn convert(
465 &mut self,
466 token: VerificationToken<TcStateAccepted>,
467 tc: &PusTcReader,
468 tm_sender: &(impl EcssTmSender + ?Sized),
469 verif_reporter: &impl VerificationReportingProvider,
470 time_stamp: &[u8],
471 ) -> Result<(ActiveRequestInfo, Request), Self::Error>;
472 }
473
474 #[derive(Clone, Debug)]
475 pub struct DefaultActiveRequestMap<V>(pub HashMap<RequestId, V>);
476
477 impl<V> Default for DefaultActiveRequestMap<V> {
478 fn default() -> Self {
479 Self(HashMap::new())
480 }
481 }
482
483 impl<V> ActiveRequestMapProvider<V> for DefaultActiveRequestMap<V> {
484 fn insert(&mut self, request_id: &RequestId, request: V) {
485 self.0.insert(*request_id, request);
486 }
487
488 fn get(&self, request_id: RequestId) -> Option<&V> {
489 self.0.get(&request_id)
490 }
491
492 fn get_mut(&mut self, request_id: RequestId) -> Option<&mut V> {
493 self.0.get_mut(&request_id)
494 }
495
496 fn remove(&mut self, request_id: RequestId) -> bool {
497 self.0.remove(&request_id).is_some()
498 }
499
500 fn for_each<F: FnMut(&RequestId, &V)>(&self, mut f: F) {
501 for (req_id, active_req) in &self.0 {
502 f(req_id, active_req);
503 }
504 }
505
506 fn for_each_mut<F: FnMut(&RequestId, &mut V)>(&mut self, mut f: F) {
507 for (req_id, active_req) in &mut self.0 {
508 f(req_id, active_req);
509 }
510 }
511 }
512
513 }
658
659#[cfg(feature = "std")]
660pub mod std_mod {
661 use super::*;
662 use crate::pool::{
663 PoolAddr, PoolError, PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool,
664 };
665 use crate::pus::verification::{TcStateAccepted, VerificationToken};
666 use crate::tmtc::{PacketAsVec, PacketSenderWithSharedPool};
667 use crate::ComponentId;
668 use alloc::vec::Vec;
669 use core::time::Duration;
670 use spacepackets::ecss::tc::PusTcReader;
671 use spacepackets::ecss::WritablePusPacket;
672 use spacepackets::time::StdTimestampError;
673 use spacepackets::ByteConversionError;
674 use std::string::String;
675 use std::sync::mpsc;
676 use std::sync::mpsc::TryRecvError;
677 use thiserror::Error;
678
679 #[cfg(feature = "crossbeam")]
680 pub use cb_mod::*;
681
682 use super::verification::{TcStateToken, VerificationReportingProvider};
683 use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory};
684 use crate::tmtc::PacketInPool;
685
686 impl From<mpsc::SendError<PoolAddr>> for EcssTmtcError {
687 fn from(_: mpsc::SendError<PoolAddr>) -> Self {
688 Self::Send(GenericSendError::RxDisconnected)
689 }
690 }
691
692 impl EcssTmSender for mpsc::Sender<PacketInPool> {
693 fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
694 match tm {
695 PusTmVariant::InStore(store_addr) => self
696 .send(PacketInPool {
697 sender_id: source_id,
698 store_addr,
699 })
700 .map_err(|_| GenericSendError::RxDisconnected)?,
701 PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
702 };
703 Ok(())
704 }
705 }
706
707 impl EcssTmSender for mpsc::SyncSender<PacketInPool> {
708 fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
709 match tm {
710 PusTmVariant::InStore(store_addr) => self
711 .try_send(PacketInPool {
712 sender_id: source_id,
713 store_addr,
714 })
715 .map_err(|e| EcssTmtcError::Send(e.into()))?,
716 PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
717 };
718 Ok(())
719 }
720 }
721
722 pub type MpscTmAsVecSender = mpsc::Sender<PacketAsVec>;
723
724 impl EcssTmSender for MpscTmAsVecSender {
725 fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
726 match tm {
727 PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
728 PusTmVariant::Direct(tm) => self
729 .send(PacketAsVec {
730 sender_id: source_id,
731 packet: tm.to_vec()?,
732 })
733 .map_err(|e| EcssTmtcError::Send(e.into()))?,
734 };
735 Ok(())
736 }
737 }
738
739 pub type MpscTmAsVecSenderBounded = mpsc::SyncSender<PacketAsVec>;
740
741 impl EcssTmSender for MpscTmAsVecSenderBounded {
742 fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
743 match tm {
744 PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
745 PusTmVariant::Direct(tm) => self
746 .send(PacketAsVec {
747 sender_id: source_id,
748 packet: tm.to_vec()?,
749 })
750 .map_err(|e| EcssTmtcError::Send(e.into()))?,
751 };
752 Ok(())
753 }
754 }
755
756 pub type MpscTcReceiver = mpsc::Receiver<EcssTcAndToken>;
757
758 impl EcssTcReceiver for MpscTcReceiver {
759 fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
760 self.try_recv().map_err(|e| match e {
761 TryRecvError::Empty => TryRecvTmtcError::Empty,
762 TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
763 GenericReceiveError::TxDisconnected(None),
764 )),
765 })
766 }
767 }
768
769 #[cfg(feature = "crossbeam")]
770 pub mod cb_mod {
771 use super::*;
772 use crossbeam_channel as cb;
773
774 impl From<cb::SendError<PoolAddr>> for EcssTmtcError {
775 fn from(_: cb::SendError<PoolAddr>) -> Self {
776 Self::Send(GenericSendError::RxDisconnected)
777 }
778 }
779
780 impl From<cb::TrySendError<PoolAddr>> for EcssTmtcError {
781 fn from(value: cb::TrySendError<PoolAddr>) -> Self {
782 match value {
783 cb::TrySendError::Full(_) => Self::Send(GenericSendError::QueueFull(None)),
784 cb::TrySendError::Disconnected(_) => {
785 Self::Send(GenericSendError::RxDisconnected)
786 }
787 }
788 }
789 }
790
791 impl EcssTmSender for cb::Sender<PacketInPool> {
792 fn send_tm(
793 &self,
794 sender_id: ComponentId,
795 tm: PusTmVariant,
796 ) -> Result<(), EcssTmtcError> {
797 match tm {
798 PusTmVariant::InStore(addr) => self
799 .try_send(PacketInPool::new(sender_id, addr))
800 .map_err(|e| EcssTmtcError::Send(e.into()))?,
801 PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
802 };
803 Ok(())
804 }
805 }
806 impl EcssTmSender for cb::Sender<PacketAsVec> {
807 fn send_tm(
808 &self,
809 sender_id: ComponentId,
810 tm: PusTmVariant,
811 ) -> Result<(), EcssTmtcError> {
812 match tm {
813 PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
814 PusTmVariant::Direct(tm) => self
815 .send(PacketAsVec::new(sender_id, tm.to_vec()?))
816 .map_err(|e| EcssTmtcError::Send(e.into()))?,
817 };
818 Ok(())
819 }
820 }
821
822 pub type CrossbeamTcReceiver = cb::Receiver<EcssTcAndToken>;
823 }
824
825 #[derive(Debug, Clone, PartialEq, Eq)]
826 pub struct ActivePusRequestStd {
827 target_id: ComponentId,
828 token: TcStateToken,
829 start_time: std::time::Instant,
830 timeout: Duration,
831 }
832
833 impl ActivePusRequestStd {
834 pub fn new(
835 target_id: ComponentId,
836 token: impl Into<TcStateToken>,
837 timeout: Duration,
838 ) -> Self {
839 Self {
840 target_id,
841 token: token.into(),
842 start_time: std::time::Instant::now(),
843 timeout,
844 }
845 }
846 }
847
848 impl ActiveRequestProvider for ActivePusRequestStd {
849 fn target_id(&self) -> ComponentId {
850 self.target_id
851 }
852
853 fn token(&self) -> TcStateToken {
854 self.token
855 }
856
857 fn timeout(&self) -> Duration {
858 self.timeout
859 }
860 fn set_token(&mut self, token: TcStateToken) {
861 self.token = token;
862 }
863
864 fn has_timed_out(&self) -> bool {
865 std::time::Instant::now() - self.start_time > self.timeout
866 }
867 }
868
869 #[derive(Debug, Clone, Error)]
874 pub enum PusTcFromMemError {
875 #[error("generic PUS error: {0}")]
876 EcssTmtc(#[from] EcssTmtcError),
877 #[error("invalid format of TC in memory: {0:?}")]
878 InvalidFormat(TcInMemory),
879 }
880
881 #[derive(Debug, Clone, Error)]
882 pub enum GenericRoutingError {
883 #[error("Unknown target ID {0}")]
886 UnknownTargetId(ComponentId),
887 #[error("Sending action request failed: {0}")]
888 Send(GenericSendError),
889 }
890
891 #[derive(Debug, Clone, Error)]
896 pub enum GenericConversionError {
897 #[error("wrong service number {0} for packet handler")]
898 WrongService(u8),
899 #[error("invalid subservice {0}")]
900 InvalidSubservice(u8),
901 #[error("not enough application data, expected at least {expected}, found {found}")]
902 NotEnoughAppData { expected: usize, found: usize },
903 #[error("invalid application data")]
904 InvalidAppData(String),
905 }
906
907 #[derive(Debug, Clone, Error)]
909 pub enum PusPacketHandlingError {
910 #[error("error polling PUS TC packet: {0}")]
911 TcPolling(#[from] EcssTmtcError),
912 #[error("error generating PUS reader from memory: {0}")]
913 TcFromMem(#[from] PusTcFromMemError),
914 #[error("generic request conversion error: {0}")]
915 RequestConversion(#[from] GenericConversionError),
916 #[error("request routing error: {0}")]
917 RequestRouting(#[from] GenericRoutingError),
918 #[error("invalid verification token")]
919 InvalidVerificationToken,
920 #[error("other error {0}")]
921 Other(String),
922 }
923
924 #[derive(Debug, Clone, Error)]
925 pub enum PartialPusHandlingError {
926 #[error("generic timestamp generation error")]
927 Time(#[from] StdTimestampError),
928 #[error("error sending telemetry: {0}")]
929 TmSend(EcssTmtcError),
930 #[error("error sending verification message")]
931 Verification(EcssTmtcError),
932 #[error("invalid verification token")]
933 NoVerificationToken,
934 }
935
936 #[derive(Debug, Clone)]
938 pub enum DirectPusPacketHandlerResult {
939 Handled(HandlingStatus),
940 SubserviceNotImplemented(u8, VerificationToken<TcStateAccepted>),
941 CustomSubservice(u8, VerificationToken<TcStateAccepted>),
942 }
943
944 impl From<HandlingStatus> for DirectPusPacketHandlerResult {
945 fn from(value: HandlingStatus) -> Self {
946 Self::Handled(value)
947 }
948 }
949
950 pub trait EcssTcInMemConverter {
951 fn cache(&mut self, possible_packet: &TcInMemory) -> Result<(), PusTcFromMemError>;
952
953 fn tc_slice_raw(&self) -> &[u8];
954
955 fn sender_id(&self) -> Option<ComponentId>;
956
957 fn cache_and_convert(
958 &mut self,
959 possible_packet: &TcInMemory,
960 ) -> Result<PusTcReader<'_>, PusTcFromMemError> {
961 self.cache(possible_packet)?;
962 Ok(PusTcReader::new(self.tc_slice_raw())
963 .map_err(EcssTmtcError::Pus)?
964 .0)
965 }
966
967 fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> {
968 Ok(PusTcReader::new(self.tc_slice_raw())
969 .map_err(EcssTmtcError::Pus)?
970 .0)
971 }
972 }
973
974 #[derive(Default, Clone)]
978 pub struct EcssTcInVecConverter {
979 sender_id: Option<ComponentId>,
980 pub pus_tc_raw: Option<Vec<u8>>,
981 }
982
983 impl EcssTcInMemConverter for EcssTcInVecConverter {
984 fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
985 self.pus_tc_raw = None;
986 match tc_in_memory {
987 super::TcInMemory::Pool(_packet_in_pool) => {
988 return Err(PusTcFromMemError::InvalidFormat(tc_in_memory.clone()));
989 }
990 super::TcInMemory::Vec(packet_with_sender) => {
991 self.pus_tc_raw = Some(packet_with_sender.packet.clone());
992 self.sender_id = Some(packet_with_sender.sender_id);
993 }
994 };
995 Ok(())
996 }
997
998 fn sender_id(&self) -> Option<ComponentId> {
999 self.sender_id
1000 }
1001
1002 fn tc_slice_raw(&self) -> &[u8] {
1003 if self.pus_tc_raw.is_none() {
1004 return &[];
1005 }
1006 self.pus_tc_raw.as_ref().unwrap()
1007 }
1008 }
1009
1010 pub struct EcssTcInSharedStoreConverter {
1015 sender_id: Option<ComponentId>,
1016 shared_tc_store: SharedStaticMemoryPool,
1017 pus_buf: Vec<u8>,
1018 }
1019
1020 impl EcssTcInSharedStoreConverter {
1021 pub fn new(shared_tc_store: SharedStaticMemoryPool, max_expected_tc_size: usize) -> Self {
1022 Self {
1023 sender_id: None,
1024 shared_tc_store,
1025 pus_buf: alloc::vec![0; max_expected_tc_size],
1026 }
1027 }
1028
1029 pub fn copy_tc_to_buf(&mut self, addr: PoolAddr) -> Result<(), PusTcFromMemError> {
1030 let mut tc_pool = self.shared_tc_store.write().map_err(|_| {
1032 PusTcFromMemError::EcssTmtc(EcssTmtcError::Store(PoolError::LockError))
1033 })?;
1034 let tc_size = tc_pool.len_of_data(&addr).map_err(EcssTmtcError::Store)?;
1035 if tc_size > self.pus_buf.len() {
1036 return Err(
1037 EcssTmtcError::ByteConversion(ByteConversionError::ToSliceTooSmall {
1038 found: self.pus_buf.len(),
1039 expected: tc_size,
1040 })
1041 .into(),
1042 );
1043 }
1044 let tc_guard = tc_pool.read_with_guard(addr);
1045 tc_guard.read(&mut self.pus_buf[0..tc_size]).unwrap();
1047 Ok(())
1048 }
1049 }
1050
1051 impl EcssTcInMemConverter for EcssTcInSharedStoreConverter {
1052 fn cache(&mut self, tc_in_memory: &TcInMemory) -> Result<(), PusTcFromMemError> {
1053 match tc_in_memory {
1054 super::TcInMemory::Pool(packet_in_pool) => {
1055 self.copy_tc_to_buf(packet_in_pool.store_addr)?;
1056 self.sender_id = Some(packet_in_pool.sender_id);
1057 }
1058 super::TcInMemory::Vec(_) => {
1059 return Err(PusTcFromMemError::InvalidFormat(tc_in_memory.clone()));
1060 }
1061 };
1062 Ok(())
1063 }
1064
1065 fn tc_slice_raw(&self) -> &[u8] {
1066 self.pus_buf.as_ref()
1067 }
1068
1069 fn sender_id(&self) -> Option<ComponentId> {
1070 self.sender_id
1071 }
1072 }
1073
1074 pub struct PusServiceBase<
1075 TcReceiver: EcssTcReceiver,
1076 TmSender: EcssTmSender,
1077 VerificationReporter: VerificationReportingProvider,
1078 > {
1079 pub id: ComponentId,
1080 pub tc_receiver: TcReceiver,
1081 pub tm_sender: TmSender,
1082 pub verif_reporter: VerificationReporter,
1083 }
1084
1085 pub struct PusServiceHelper<
1095 TcReceiver: EcssTcReceiver,
1096 TmSender: EcssTmSender,
1097 TcInMemConverter: EcssTcInMemConverter,
1098 VerificationReporter: VerificationReportingProvider,
1099 > {
1100 pub common: PusServiceBase<TcReceiver, TmSender, VerificationReporter>,
1101 pub tc_in_mem_converter: TcInMemConverter,
1102 }
1103
1104 impl<
1105 TcReceiver: EcssTcReceiver,
1106 TmSender: EcssTmSender,
1107 TcInMemConverter: EcssTcInMemConverter,
1108 VerificationReporter: VerificationReportingProvider,
1109 > PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
1110 {
1111 pub fn new(
1112 id: ComponentId,
1113 tc_receiver: TcReceiver,
1114 tm_sender: TmSender,
1115 verification_handler: VerificationReporter,
1116 tc_in_mem_converter: TcInMemConverter,
1117 ) -> Self {
1118 Self {
1119 common: PusServiceBase {
1120 id,
1121 tc_receiver,
1122 tm_sender,
1123 verif_reporter: verification_handler,
1124 },
1125 tc_in_mem_converter,
1126 }
1127 }
1128
1129 pub fn id(&self) -> ComponentId {
1130 self.common.id
1131 }
1132
1133 pub fn tm_sender(&self) -> &TmSender {
1134 &self.common.tm_sender
1135 }
1136
1137 pub fn retrieve_and_accept_next_packet(
1143 &mut self,
1144 ) -> Result<Option<AcceptedEcssTcAndToken>, PusPacketHandlingError> {
1145 match self.common.tc_receiver.recv_tc() {
1146 Ok(EcssTcAndToken {
1147 tc_in_memory,
1148 token,
1149 }) => {
1150 if token.is_none() {
1151 return Err(PusPacketHandlingError::InvalidVerificationToken);
1152 }
1153 let token = token.unwrap();
1154 let accepted_token = VerificationToken::<TcStateAccepted>::try_from(token)
1155 .map_err(|_| PusPacketHandlingError::InvalidVerificationToken)?;
1156 Ok(Some(AcceptedEcssTcAndToken {
1157 tc_in_memory,
1158 token: accepted_token,
1159 }))
1160 }
1161 Err(e) => match e {
1162 TryRecvTmtcError::Tmtc(e) => Err(PusPacketHandlingError::TcPolling(e)),
1163 TryRecvTmtcError::Empty => Ok(None),
1164 },
1165 }
1166 }
1167
1168 pub fn verif_reporter(&self) -> &VerificationReporter {
1169 &self.common.verif_reporter
1170 }
1171 pub fn verif_reporter_mut(&mut self) -> &mut VerificationReporter {
1172 &mut self.common.verif_reporter
1173 }
1174
1175 pub fn tc_in_mem_converter(&self) -> &TcInMemConverter {
1176 &self.tc_in_mem_converter
1177 }
1178
1179 pub fn tc_in_mem_converter_mut(&mut self) -> &mut TcInMemConverter {
1180 &mut self.tc_in_mem_converter
1181 }
1182 }
1183
1184 pub type PusServiceHelperDynWithMpsc<TcInMemConverter, VerificationReporter> =
1185 PusServiceHelper<MpscTcReceiver, MpscTmAsVecSender, TcInMemConverter, VerificationReporter>;
1186 pub type PusServiceHelperDynWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
1187 PusServiceHelper<
1188 MpscTcReceiver,
1189 MpscTmAsVecSenderBounded,
1190 TcInMemConverter,
1191 VerificationReporter,
1192 >;
1193 pub type PusServiceHelperStaticWithMpsc<TcInMemConverter, VerificationReporter> =
1194 PusServiceHelper<
1195 MpscTcReceiver,
1196 PacketSenderWithSharedPool,
1197 TcInMemConverter,
1198 VerificationReporter,
1199 >;
1200 pub type PusServiceHelperStaticWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
1201 PusServiceHelper<
1202 MpscTcReceiver,
1203 PacketSenderWithSharedPool,
1204 TcInMemConverter,
1205 VerificationReporter,
1206 >;
1207}
1208
1209pub(crate) fn source_buffer_large_enough(
1210 cap: usize,
1211 len: usize,
1212) -> Result<(), ByteConversionError> {
1213 if len > cap {
1214 return Err(ByteConversionError::ToSliceTooSmall {
1215 found: cap,
1216 expected: len,
1217 });
1218 }
1219 Ok(())
1220}
1221
1222#[cfg(any(feature = "test_util", test))]
1223pub mod test_util {
1224 use crate::request::UniqueApidTargetId;
1225 use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
1226
1227 use super::{
1228 verification::{self, TcStateAccepted, VerificationToken},
1229 DirectPusPacketHandlerResult, PusPacketHandlingError,
1230 };
1231
1232 pub const TEST_APID: u16 = 0x101;
1233 pub const TEST_UNIQUE_ID_0: u32 = 0x05;
1234 pub const TEST_UNIQUE_ID_1: u32 = 0x06;
1235 pub const TEST_COMPONENT_ID_0: UniqueApidTargetId =
1236 UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_0);
1237 pub const TEST_COMPONENT_ID_1: UniqueApidTargetId =
1238 UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_1);
1239
1240 pub trait PusTestHarness {
1241 fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
1242 fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
1243 fn read_next_tm(&mut self) -> PusTmReader<'_>;
1244 fn check_no_tm_available(&self) -> bool;
1245 fn check_next_verification_tm(
1246 &self,
1247 subservice: u8,
1248 expected_request_id: verification::RequestId,
1249 );
1250 }
1251
1252 pub trait SimplePusPacketHandler {
1253 fn handle_one_tc(&mut self)
1254 -> Result<DirectPusPacketHandlerResult, PusPacketHandlingError>;
1255 }
1256}
1257
1258#[cfg(test)]
1259pub mod tests {
1260 use core::cell::RefCell;
1261 use std::sync::mpsc::TryRecvError;
1262 use std::sync::{mpsc, RwLock};
1263
1264 use alloc::collections::VecDeque;
1265 use alloc::vec::Vec;
1266 use satrs_shared::res_code::ResultU16;
1267 use spacepackets::ecss::tc::{PusTcCreator, PusTcReader};
1268 use spacepackets::ecss::tm::{GenericPusTmSecondaryHeader, PusTmCreator, PusTmReader};
1269 use spacepackets::ecss::{PusPacket, WritablePusPacket};
1270 use spacepackets::CcsdsPacket;
1271
1272 use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
1273 use crate::pus::verification::{RequestId, VerificationReporter};
1274 use crate::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool, SharedPacketPool};
1275 use crate::ComponentId;
1276
1277 use super::test_util::{TEST_APID, TEST_COMPONENT_ID_0};
1278
1279 use super::verification::test_util::TestVerificationReporter;
1280 use super::verification::{
1281 TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
1282 };
1283 use super::*;
1284
1285 #[derive(Debug, Eq, PartialEq, Clone)]
1286 pub(crate) struct CommonTmInfo {
1287 pub subservice: u8,
1288 pub apid: u16,
1289 pub seq_count: u16,
1290 pub msg_counter: u16,
1291 pub dest_id: u16,
1292 pub timestamp: Vec<u8>,
1293 }
1294
1295 impl CommonTmInfo {
1296 pub fn new(
1297 subservice: u8,
1298 apid: u16,
1299 seq_count: u16,
1300 msg_counter: u16,
1301 dest_id: u16,
1302 timestamp: &[u8],
1303 ) -> Self {
1304 Self {
1305 subservice,
1306 apid,
1307 seq_count,
1308 msg_counter,
1309 dest_id,
1310 timestamp: timestamp.to_vec(),
1311 }
1312 }
1313 pub fn new_zero_seq_count(
1314 subservice: u8,
1315 apid: u16,
1316 dest_id: u16,
1317 timestamp: &[u8],
1318 ) -> Self {
1319 Self::new(subservice, apid, 0, 0, dest_id, timestamp)
1320 }
1321
1322 pub fn new_from_tm(tm: &PusTmCreator) -> Self {
1323 let mut timestamp = [0; 7];
1324 timestamp.clone_from_slice(&tm.timestamp()[0..7]);
1325 Self {
1326 subservice: PusPacket::subservice(tm),
1327 apid: tm.apid(),
1328 seq_count: tm.seq_count(),
1329 msg_counter: tm.msg_counter(),
1330 dest_id: tm.dest_id(),
1331 timestamp: timestamp.to_vec(),
1332 }
1333 }
1334 }
1335
1336 pub struct PusServiceHandlerWithSharedStoreCommon {
1338 pus_buf: RefCell<[u8; 2048]>,
1339 tm_buf: [u8; 2048],
1340 tc_pool: SharedStaticMemoryPool,
1341 tm_pool: SharedPacketPool,
1342 tc_sender: mpsc::SyncSender<EcssTcAndToken>,
1343 tm_receiver: mpsc::Receiver<PacketInPool>,
1344 }
1345
1346 pub type PusServiceHelperStatic = PusServiceHelper<
1347 MpscTcReceiver,
1348 PacketSenderWithSharedPool,
1349 EcssTcInSharedStoreConverter,
1350 VerificationReporter,
1351 >;
1352
1353 impl PusServiceHandlerWithSharedStoreCommon {
1354 pub fn new(id: ComponentId) -> (Self, PusServiceHelperStatic) {
1359 let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
1360 let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
1361 let tm_pool = StaticMemoryPool::new(pool_cfg);
1362 let shared_tc_pool = SharedStaticMemoryPool::new(RwLock::new(tc_pool));
1363 let shared_tm_pool = SharedStaticMemoryPool::new(RwLock::new(tm_pool));
1364 let shared_tm_pool_wrapper = SharedPacketPool::new(&shared_tm_pool);
1365 let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10);
1366 let (tm_tx, tm_rx) = mpsc::sync_channel(10);
1367
1368 let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
1369 let verification_handler =
1370 VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &verif_cfg);
1371 let test_srv_tm_sender =
1372 PacketSenderWithSharedPool::new(tm_tx, shared_tm_pool_wrapper.clone());
1373 let in_store_converter =
1374 EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
1375 (
1376 Self {
1377 pus_buf: RefCell::new([0; 2048]),
1378 tm_buf: [0; 2048],
1379 tc_pool: shared_tc_pool,
1380 tm_pool: shared_tm_pool_wrapper,
1381 tc_sender: test_srv_tc_tx,
1382 tm_receiver: tm_rx,
1383 },
1384 PusServiceHelper::new(
1385 id,
1386 test_srv_tc_rx,
1387 test_srv_tm_sender,
1388 verification_handler,
1389 in_store_converter,
1390 ),
1391 )
1392 }
1393 pub fn send_tc(
1394 &self,
1395 sender_id: ComponentId,
1396 token: &VerificationToken<TcStateAccepted>,
1397 tc: &PusTcCreator,
1398 ) {
1399 let mut mut_buf = self.pus_buf.borrow_mut();
1400 let tc_size = tc.write_to_bytes(mut_buf.as_mut_slice()).unwrap();
1401 let mut tc_pool = self.tc_pool.write().unwrap();
1402 let addr = tc_pool.add(&mut_buf[..tc_size]).unwrap();
1403 drop(tc_pool);
1404 self.tc_sender
1406 .send(EcssTcAndToken::new(
1407 PacketInPool::new(sender_id, addr),
1408 *token,
1409 ))
1410 .expect("sending tc failed");
1411 }
1412
1413 pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
1414 let next_msg = self.tm_receiver.try_recv();
1415 assert!(next_msg.is_ok());
1416 let tm_in_pool = next_msg.unwrap();
1417 let tm_pool = self.tm_pool.0.read().unwrap();
1418 let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
1419 self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
1420 PusTmReader::new(&self.tm_buf, 7).unwrap().0
1421 }
1422
1423 pub fn check_no_tm_available(&self) -> bool {
1424 let next_msg = self.tm_receiver.try_recv();
1425 if let TryRecvError::Empty = next_msg.unwrap_err() {
1426 return true;
1427 }
1428 false
1429 }
1430
1431 pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) {
1432 let next_msg = self.tm_receiver.try_recv();
1433 assert!(next_msg.is_ok());
1434 let tm_in_pool = next_msg.unwrap();
1435 let tm_pool = self.tm_pool.0.read().unwrap();
1436 let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
1437 let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
1438 assert_eq!(PusPacket::service(&tm), 1);
1439 assert_eq!(PusPacket::subservice(&tm), subservice);
1440 assert_eq!(tm.apid(), TEST_APID);
1441 let req_id =
1442 RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");
1443 assert_eq!(req_id, expected_request_id);
1444 }
1445 }
1446
1447 pub struct PusServiceHandlerWithVecCommon {
1448 current_tm: Option<Vec<u8>>,
1449 tc_sender: mpsc::Sender<EcssTcAndToken>,
1450 tm_receiver: mpsc::Receiver<PacketAsVec>,
1451 }
1452 pub type PusServiceHelperDynamic = PusServiceHelper<
1453 MpscTcReceiver,
1454 MpscTmAsVecSender,
1455 EcssTcInVecConverter,
1456 VerificationReporter,
1457 >;
1458
1459 impl PusServiceHandlerWithVecCommon {
1460 pub fn new_with_standard_verif_reporter(
1461 id: ComponentId,
1462 ) -> (Self, PusServiceHelperDynamic) {
1463 let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
1464 let (tm_tx, tm_rx) = mpsc::channel();
1465
1466 let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
1467 let verification_handler =
1468 VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &verif_cfg);
1469 let in_store_converter = EcssTcInVecConverter::default();
1470 (
1471 Self {
1472 current_tm: None,
1473 tc_sender: test_srv_tc_tx,
1474 tm_receiver: tm_rx,
1475 },
1476 PusServiceHelper::new(
1477 id,
1478 test_srv_tc_rx,
1479 tm_tx,
1480 verification_handler,
1481 in_store_converter,
1482 ),
1483 )
1484 }
1485 }
1486
1487 impl PusServiceHandlerWithVecCommon {
1488 pub fn new_with_test_verif_sender(
1489 id: ComponentId,
1490 ) -> (
1491 Self,
1492 PusServiceHelper<
1493 MpscTcReceiver,
1494 MpscTmAsVecSender,
1495 EcssTcInVecConverter,
1496 TestVerificationReporter,
1497 >,
1498 ) {
1499 let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
1500 let (tm_tx, tm_rx) = mpsc::channel();
1501
1502 let in_store_converter = EcssTcInVecConverter::default();
1503 let verification_handler = TestVerificationReporter::new(id);
1504 (
1505 Self {
1506 current_tm: None,
1507 tc_sender: test_srv_tc_tx,
1508 tm_receiver: tm_rx,
1509 },
1511 PusServiceHelper::new(
1512 id,
1513 test_srv_tc_rx,
1514 tm_tx,
1515 verification_handler,
1516 in_store_converter,
1517 ),
1518 )
1519 }
1520 }
1521
1522 impl PusServiceHandlerWithVecCommon {
1523 pub fn send_tc(
1524 &self,
1525 sender_id: ComponentId,
1526 token: &VerificationToken<TcStateAccepted>,
1527 tc: &PusTcCreator,
1528 ) {
1529 self.tc_sender
1531 .send(EcssTcAndToken::new(
1532 TcInMemory::Vec(PacketAsVec::new(
1533 sender_id,
1534 tc.to_vec().expect("pus tc conversion to vec failed"),
1535 )),
1536 *token,
1537 ))
1538 .expect("sending tc failed");
1539 }
1540
1541 pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
1542 let next_msg = self.tm_receiver.try_recv();
1543 assert!(next_msg.is_ok());
1544 self.current_tm = Some(next_msg.unwrap().packet);
1545 PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
1546 .unwrap()
1547 .0
1548 }
1549
1550 pub fn check_no_tm_available(&self) -> bool {
1551 let next_msg = self.tm_receiver.try_recv();
1552 if let TryRecvError::Empty = next_msg.unwrap_err() {
1553 return true;
1554 }
1555 false
1556 }
1557
1558 pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) {
1559 let next_msg = self.tm_receiver.try_recv();
1560 assert!(next_msg.is_ok());
1561 let next_msg = next_msg.unwrap();
1562 let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0;
1563 assert_eq!(PusPacket::service(&tm), 1);
1564 assert_eq!(PusPacket::subservice(&tm), subservice);
1565 assert_eq!(tm.apid(), TEST_APID);
1566 let req_id =
1567 RequestId::from_bytes(tm.user_data()).expect("generating request ID failed");
1568 assert_eq!(req_id, expected_request_id);
1569 }
1570 }
1571
1572 pub const APP_DATA_TOO_SHORT: ResultU16 = ResultU16::new(1, 1);
1573
1574 #[derive(Default)]
1575 pub struct TestConverter<const SERVICE: u8> {
1576 pub conversion_request: VecDeque<Vec<u8>>,
1577 }
1578
1579 impl<const SERVICE: u8> TestConverter<SERVICE> {
1580 pub fn check_service(&self, tc: &PusTcReader) -> Result<(), PusPacketHandlingError> {
1581 if tc.service() != SERVICE {
1582 return Err(PusPacketHandlingError::RequestConversion(
1583 GenericConversionError::WrongService(tc.service()),
1584 ));
1585 }
1586 Ok(())
1587 }
1588
1589 pub fn is_empty(&self) {
1590 self.conversion_request.is_empty();
1591 }
1592
1593 pub fn check_next_conversion(&mut self, tc: &PusTcCreator) {
1594 assert!(!self.conversion_request.is_empty());
1595 assert_eq!(
1596 self.conversion_request.pop_front().unwrap(),
1597 tc.to_vec().unwrap()
1598 );
1599 }
1600 }
1601
1602 pub struct TestRouter<REQUEST> {
1603 pub routing_requests: RefCell<VecDeque<(ComponentId, REQUEST)>>,
1604 pub routing_errors: RefCell<VecDeque<(ComponentId, GenericRoutingError)>>,
1605 pub injected_routing_failure: RefCell<Option<GenericRoutingError>>,
1606 }
1607
1608 impl<REQUEST> Default for TestRouter<REQUEST> {
1609 fn default() -> Self {
1610 Self {
1611 routing_requests: Default::default(),
1612 routing_errors: Default::default(),
1613 injected_routing_failure: Default::default(),
1614 }
1615 }
1616 }
1617
1618 impl<REQUEST> TestRouter<REQUEST> {
1619 pub fn check_for_injected_error(&self) -> Result<(), GenericRoutingError> {
1620 if self.injected_routing_failure.borrow().is_some() {
1621 return Err(self.injected_routing_failure.borrow_mut().take().unwrap());
1622 }
1623 Ok(())
1624 }
1625
1626 pub fn handle_error(
1627 &self,
1628 target_id: ComponentId,
1629 _token: VerificationToken<TcStateAccepted>,
1630 _tc: &PusTcReader,
1631 error: GenericRoutingError,
1632 _time_stamp: &[u8],
1633 _verif_reporter: &impl VerificationReportingProvider,
1634 ) {
1635 self.routing_errors
1636 .borrow_mut()
1637 .push_back((target_id, error));
1638 }
1639
1640 pub fn no_routing_errors(&self) -> bool {
1641 self.routing_errors.borrow().is_empty()
1642 }
1643
1644 pub fn retrieve_next_routing_error(&mut self) -> (ComponentId, GenericRoutingError) {
1645 if self.routing_errors.borrow().is_empty() {
1646 panic!("no routing request available");
1647 }
1648 self.routing_errors.borrow_mut().pop_front().unwrap()
1649 }
1650
1651 pub fn inject_routing_error(&mut self, error: GenericRoutingError) {
1652 *self.injected_routing_failure.borrow_mut() = Some(error);
1653 }
1654
1655 pub fn is_empty(&self) -> bool {
1656 self.routing_requests.borrow().is_empty()
1657 }
1658
1659 pub fn retrieve_next_request(&mut self) -> (ComponentId, REQUEST) {
1660 if self.routing_requests.borrow().is_empty() {
1661 panic!("no routing request available");
1662 }
1663 self.routing_requests.borrow_mut().pop_front().unwrap()
1664 }
1665 }
1666}