satrs_core/pus/
verification.rs

1//! # PUS Service 1 Verification Module
2//!
3//! This module allows packaging and sending PUS Service 1 packets. It is conforming to section
4//! 8 of the PUS standard ECSS-E-ST-70-41C.
5//!
6//! The core object to report TC verification progress is the [VerificationReporter]. It exposes
7//! an API which uses type-state programming to avoid calling the verification steps in
8//! an invalid order.
9//!
10//! # Examples
11//!
12//! Basic single-threaded example where a full success sequence for a given ping telecommand is
13//! executed. Note that the verification part could also be done in a separate thread.
14//!
15//! ```
16//! use std::sync::{Arc, mpsc, RwLock};
17//! use std::time::Duration;
18//! use satrs_core::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
19//! use satrs_core::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender};
20//! use satrs_core::seq_count::SeqCountProviderSimple;
21//! use satrs_core::pus::MpscTmInSharedPoolSender;
22//! use satrs_core::tmtc::tm_helper::SharedTmPool;
23//! use spacepackets::ecss::PusPacket;
24//! use spacepackets::SpHeader;
25//! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
26//! use spacepackets::ecss::tm::PusTmReader;
27//!
28//! const EMPTY_STAMP: [u8; 7] = [0; 7];
29//! const TEST_APID: u16 = 0x02;
30//!
31//! let pool_cfg = StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false);
32//! let tm_pool = StaticMemoryPool::new(pool_cfg.clone());
33//! let shared_tm_store = SharedTmPool::new(tm_pool);
34//! let tm_store = shared_tm_store.clone_backing_pool();
35//! let (verif_tx, verif_rx) = mpsc::channel();
36//! let sender = MpscTmInSharedPoolSender::new(0, "Test Sender", shared_tm_store, verif_tx);
37//! let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
38//! let mut  reporter = VerificationReporterWithSender::new(&cfg , Box::new(sender));
39//!
40//! let mut sph = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
41//! let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
42//! let pus_tc_0 = PusTcCreator::new_no_app_data(&mut sph, tc_header, true);
43//! let init_token = reporter.add_tc(&pus_tc_0);
44//!
45//! // Complete success sequence for a telecommand
46//! let accepted_token = reporter.acceptance_success(init_token, Some(&EMPTY_STAMP)).unwrap();
47//! let started_token = reporter.start_success(accepted_token, Some(&EMPTY_STAMP)).unwrap();
48//! reporter.completion_success(started_token, Some(&EMPTY_STAMP)).unwrap();
49//!
50//! // Verify it arrives correctly on receiver end
51//! let mut tm_buf: [u8; 1024] = [0; 1024];
52//! let mut packet_idx = 0;
53//! while packet_idx < 3 {
54//!     let addr = verif_rx.recv_timeout(Duration::from_millis(10)).unwrap();
55//!     let tm_len;
56//!     {
57//!         let mut rg = tm_store.write().expect("Error locking shared pool");
58//!         let store_guard = rg.read_with_guard(addr);
59//!         tm_len = store_guard.read(&mut tm_buf).expect("Error reading TM slice");
60//!     }
61//!     let (pus_tm, _) = PusTmReader::new(&tm_buf[0..tm_len], 7)
62//!        .expect("Error reading verification TM");
63//!     if packet_idx == 0 {
64//!         assert_eq!(pus_tm.subservice(), 1);
65//!     } else if packet_idx == 1 {
66//!         assert_eq!(pus_tm.subservice(), 3);
67//!     } else if packet_idx == 2 {
68//!         assert_eq!(pus_tm.subservice(), 7);
69//!     }
70//!     packet_idx += 1;
71//! }
72//! ```
73//!
74//! The [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/verification_test.rs)
75//! for the verification module contains examples how this module could be used in a more complex
76//! context involving multiple threads
77use crate::pus::{source_buffer_large_enough, EcssTmSenderCore, EcssTmtcError};
78use core::fmt::{Debug, Display, Formatter};
79use core::hash::{Hash, Hasher};
80use core::marker::PhantomData;
81use core::mem::size_of;
82#[cfg(feature = "alloc")]
83use delegate::delegate;
84#[cfg(feature = "serde")]
85use serde::{Deserialize, Serialize};
86use spacepackets::ecss::tc::IsPusTelecommand;
87use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
88use spacepackets::ecss::{EcssEnumeration, PusError, WritablePusPacket};
89use spacepackets::{CcsdsPacket, PacketId, PacketSequenceCtrl};
90use spacepackets::{SpHeader, MAX_APID};
91
92pub use crate::seq_count::SeqCountProviderSimple;
93pub use spacepackets::ecss::verification::*;
94
95#[cfg(feature = "alloc")]
96pub use alloc_mod::{
97    VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender,
98};
99#[cfg(feature = "std")]
100pub use std_mod::*;
101
102/// This is a request identifier as specified in 5.4.11.2 c. of the PUS standard.
103///
104/// This field equivalent to the first two bytes of the CCSDS space packet header.
105/// This version of the request ID is supplied in the verification reports and does not contain
106/// the source ID.
107#[derive(Debug, Eq, Copy, Clone)]
108#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
109pub struct RequestId {
110    version_number: u8,
111    packet_id: PacketId,
112    psc: PacketSequenceCtrl,
113}
114
115impl Display for RequestId {
116    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
117        write!(f, "{:#08x}", self.raw())
118    }
119}
120
121impl Hash for RequestId {
122    fn hash<H: Hasher>(&self, state: &mut H) {
123        self.raw().hash(state);
124    }
125}
126
127// Implement manually to satisfy derive_hash_xor_eq lint
128impl PartialEq for RequestId {
129    fn eq(&self, other: &Self) -> bool {
130        self.version_number == other.version_number
131            && self.packet_id == other.packet_id
132            && self.psc == other.psc
133    }
134}
135
136impl RequestId {
137    pub const SIZE_AS_BYTES: usize = size_of::<u32>();
138
139    pub fn raw(&self) -> u32 {
140        ((self.version_number as u32) << 29)
141            | ((self.packet_id.raw() as u32) << 16)
142            | self.psc.raw() as u32
143    }
144
145    pub fn to_bytes(&self, buf: &mut [u8]) {
146        let raw = self.raw();
147        buf.copy_from_slice(raw.to_be_bytes().as_slice());
148    }
149
150    pub fn from_bytes(buf: &[u8]) -> Option<Self> {
151        if buf.len() < 4 {
152            return None;
153        }
154        let raw = u32::from_be_bytes(buf[0..Self::SIZE_AS_BYTES].try_into().unwrap());
155        Some(Self {
156            version_number: ((raw >> 29) & 0b111) as u8,
157            packet_id: PacketId::from(((raw >> 16) & 0xffff) as u16),
158            psc: PacketSequenceCtrl::from((raw & 0xffff) as u16),
159        })
160    }
161}
162impl RequestId {
163    /// This allows extracting the request ID from a given PUS telecommand.
164    pub fn new(tc: &(impl CcsdsPacket + IsPusTelecommand)) -> Self {
165        RequestId {
166            version_number: tc.ccsds_version(),
167            packet_id: tc.packet_id(),
168            psc: tc.psc(),
169        }
170    }
171}
172
173/// If a verification operation fails, the passed token will be returned as well. This allows
174/// re-trying the operation at a later point.
175#[derive(Debug, Clone)]
176pub struct VerificationOrSendErrorWithToken<T>(pub EcssTmtcError, pub VerificationToken<T>);
177
178#[derive(Debug, Clone)]
179pub struct VerificationErrorWithToken<T>(pub EcssTmtcError, pub VerificationToken<T>);
180
181impl<T> From<VerificationErrorWithToken<T>> for VerificationOrSendErrorWithToken<T> {
182    fn from(value: VerificationErrorWithToken<T>) -> Self {
183        VerificationOrSendErrorWithToken(value.0, value.1)
184    }
185}
186/// Support token to allow type-state programming. This prevents calling the verification
187/// steps in an invalid order.
188#[derive(Debug, Clone, Copy, Eq, PartialEq)]
189pub struct VerificationToken<STATE> {
190    state: PhantomData<STATE>,
191    req_id: RequestId,
192}
193
194pub trait WasAtLeastAccepted {}
195
196#[derive(Copy, Clone, Debug, Eq, PartialEq)]
197pub struct TcStateNone;
198#[derive(Copy, Clone, Debug, Eq, PartialEq)]
199pub struct TcStateAccepted;
200#[derive(Copy, Clone, Debug, Eq, PartialEq)]
201pub struct TcStateStarted;
202#[derive(Copy, Clone, Debug, Eq, PartialEq)]
203pub struct TcStateCompleted;
204
205impl WasAtLeastAccepted for TcStateAccepted {}
206impl WasAtLeastAccepted for TcStateStarted {}
207impl WasAtLeastAccepted for TcStateCompleted {}
208
209/// Token wrapper to model all possible verification tokens. These tokens are used to
210/// enforce the correct order for the verification steps when doing verification reporting.
211#[derive(Debug, Copy, Clone, Eq, PartialEq)]
212pub enum TcStateToken {
213    None(VerificationToken<TcStateNone>),
214    Accepted(VerificationToken<TcStateAccepted>),
215    Started(VerificationToken<TcStateStarted>),
216    Completed(VerificationToken<TcStateCompleted>),
217}
218
219impl From<VerificationToken<TcStateNone>> for TcStateToken {
220    fn from(t: VerificationToken<TcStateNone>) -> Self {
221        TcStateToken::None(t)
222    }
223}
224
225impl TryFrom<TcStateToken> for VerificationToken<TcStateAccepted> {
226    type Error = ();
227
228    fn try_from(value: TcStateToken) -> Result<Self, Self::Error> {
229        if let TcStateToken::Accepted(token) = value {
230            Ok(token)
231        } else {
232            Err(())
233        }
234    }
235}
236
237impl TryFrom<TcStateToken> for VerificationToken<TcStateStarted> {
238    type Error = ();
239
240    fn try_from(value: TcStateToken) -> Result<Self, Self::Error> {
241        if let TcStateToken::Started(token) = value {
242            Ok(token)
243        } else {
244            Err(())
245        }
246    }
247}
248
249impl From<VerificationToken<TcStateAccepted>> for TcStateToken {
250    fn from(t: VerificationToken<TcStateAccepted>) -> Self {
251        TcStateToken::Accepted(t)
252    }
253}
254
255impl From<VerificationToken<TcStateStarted>> for TcStateToken {
256    fn from(t: VerificationToken<TcStateStarted>) -> Self {
257        TcStateToken::Started(t)
258    }
259}
260
261impl From<VerificationToken<TcStateCompleted>> for TcStateToken {
262    fn from(t: VerificationToken<TcStateCompleted>) -> Self {
263        TcStateToken::Completed(t)
264    }
265}
266
267impl<STATE> VerificationToken<STATE> {
268    fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
269        VerificationToken {
270            state: PhantomData,
271            req_id,
272        }
273    }
274
275    pub fn req_id(&self) -> RequestId {
276        self.req_id
277    }
278}
279
280/// Composite helper struct to pass failure parameters to the [VerificationReporter]
281pub struct FailParams<'stamp, 'fargs> {
282    time_stamp: Option<&'stamp [u8]>,
283    failure_code: &'fargs dyn EcssEnumeration,
284    failure_data: Option<&'fargs [u8]>,
285}
286
287impl<'stamp, 'fargs> FailParams<'stamp, 'fargs> {
288    pub fn new(
289        time_stamp: Option<&'stamp [u8]>,
290        failure_code: &'fargs impl EcssEnumeration,
291        failure_data: Option<&'fargs [u8]>,
292    ) -> Self {
293        Self {
294            time_stamp,
295            failure_code,
296            failure_data,
297        }
298    }
299}
300
301/// Composite helper struct to pass step failure parameters to the [VerificationReporter]
302pub struct FailParamsWithStep<'stamp, 'fargs> {
303    bp: FailParams<'stamp, 'fargs>,
304    step: &'fargs dyn EcssEnumeration,
305}
306
307impl<'stamp, 'fargs> FailParamsWithStep<'stamp, 'fargs> {
308    pub fn new(
309        time_stamp: Option<&'stamp [u8]>,
310        step: &'fargs impl EcssEnumeration,
311        failure_code: &'fargs impl EcssEnumeration,
312        failure_data: Option<&'fargs [u8]>,
313    ) -> Self {
314        Self {
315            bp: FailParams::new(time_stamp, failure_code, failure_data),
316            step,
317        }
318    }
319}
320
321#[derive(Clone)]
322pub struct VerificationReporterCore {
323    pub dest_id: u16,
324    apid: u16,
325}
326
327pub enum VerifSuccess {}
328pub enum VerifFailure {}
329
330/// Abstraction for a sendable PUS TM. The user is expected to send the TM packet to a TM sink.
331///
332/// This struct generally mutably borrows the source data buffer.
333pub struct VerificationSendable<'src_data, State, SuccessOrFailure> {
334    token: Option<VerificationToken<State>>,
335    pus_tm: Option<PusTmCreator<'src_data>>,
336    phantom: PhantomData<SuccessOrFailure>,
337}
338
339impl<'src_data, State, SuccessOrFailure> VerificationSendable<'src_data, State, SuccessOrFailure> {
340    pub(crate) fn new(pus_tm: PusTmCreator<'src_data>, token: VerificationToken<State>) -> Self {
341        Self {
342            token: Some(token),
343            pus_tm: Some(pus_tm),
344            phantom: PhantomData,
345        }
346    }
347    pub(crate) fn new_no_token(pus_tm: PusTmCreator<'src_data>) -> Self {
348        Self {
349            token: None,
350            pus_tm: Some(pus_tm),
351            phantom: PhantomData,
352        }
353    }
354
355    pub fn len_packed(&self) -> usize {
356        self.pus_tm.as_ref().unwrap().len_written()
357    }
358
359    pub fn pus_tm(&self) -> &PusTmCreator<'src_data> {
360        self.pus_tm.as_ref().unwrap()
361    }
362
363    pub fn pus_tm_mut(&mut self) -> &mut PusTmCreator<'src_data> {
364        self.pus_tm.as_mut().unwrap()
365    }
366}
367
368impl<'src_data, State> VerificationSendable<'src_data, State, VerifFailure> {
369    pub fn send_success_verif_failure(self) {}
370}
371
372impl<'src_data, State> VerificationSendable<'src_data, State, VerifFailure> {
373    pub fn send_failure(self) -> (PusTmCreator<'src_data>, VerificationToken<State>) {
374        (self.pus_tm.unwrap(), self.token.unwrap())
375    }
376}
377
378impl<'src_data> VerificationSendable<'src_data, TcStateNone, VerifSuccess> {
379    pub fn send_success_acceptance_success(self) -> VerificationToken<TcStateAccepted> {
380        VerificationToken {
381            state: PhantomData,
382            req_id: self.token.unwrap().req_id(),
383        }
384    }
385}
386
387impl<'src_data> VerificationSendable<'src_data, TcStateAccepted, VerifSuccess> {
388    pub fn send_success_start_success(self) -> VerificationToken<TcStateStarted> {
389        VerificationToken {
390            state: PhantomData,
391            req_id: self.token.unwrap().req_id(),
392        }
393    }
394}
395
396impl<'src_data, TcState: WasAtLeastAccepted + Copy>
397    VerificationSendable<'src_data, TcState, VerifSuccess>
398{
399    pub fn send_success_step_or_completion_success(self) {}
400}
401
402/// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets
403/// and verify the various steps of telecommand handling as specified in the PUS standard.
404///
405/// This is the core component which can be used without [`alloc`] support. Please note that
406/// the buffer passed to the API exposes by this struct will be used to serialize the source data.
407/// This buffer may not be re-used to serialize the whole telemetry because that would overwrite
408/// the source data itself.
409impl VerificationReporterCore {
410    pub fn new(apid: u16) -> Option<Self> {
411        if apid > MAX_APID {
412            return None;
413        }
414        Some(Self { apid, dest_id: 0 })
415    }
416
417    pub fn set_apid(&mut self, apid: u16) -> bool {
418        if apid > MAX_APID {
419            return false;
420        }
421        self.apid = apid;
422        true
423    }
424
425    pub fn apid(&self) -> u16 {
426        self.apid
427    }
428
429    pub fn dest_id(&self) -> u16 {
430        self.dest_id
431    }
432
433    pub fn set_dest_id(&mut self, dest_id: u16) {
434        self.dest_id = dest_id;
435    }
436
437    /// Initialize verification handling by passing a TC reference. This returns a token required
438    /// to call the acceptance functions
439    pub fn add_tc(
440        &mut self,
441        pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
442    ) -> VerificationToken<TcStateNone> {
443        self.add_tc_with_req_id(RequestId::new(pus_tc))
444    }
445
446    /// Same as [Self::add_tc] but pass a request ID instead of the direct telecommand.
447    /// This can be useful if the executing thread does not have full access to the telecommand.
448    pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
449        VerificationToken::<TcStateNone>::new(req_id)
450    }
451
452    fn sendable_success_no_step<'src_data, State: Copy>(
453        &self,
454        src_data_buf: &'src_data mut [u8],
455        subservice: u8,
456        token: VerificationToken<State>,
457        seq_count: u16,
458        msg_count: u16,
459        time_stamp: Option<&'src_data [u8]>,
460    ) -> Result<
461        VerificationSendable<'src_data, State, VerifSuccess>,
462        VerificationErrorWithToken<State>,
463    > {
464        Ok(VerificationSendable::new(
465            self.create_pus_verif_success_tm(
466                src_data_buf,
467                subservice,
468                seq_count,
469                msg_count,
470                &token.req_id,
471                time_stamp,
472                None::<&dyn EcssEnumeration>,
473            )
474            .map_err(|e| VerificationErrorWithToken(e, token))?,
475            token,
476        ))
477    }
478
479    // Internal helper function, too many arguments is acceptable for this case.
480    #[allow(clippy::too_many_arguments)]
481    fn sendable_failure_no_step<'src_data, State: Copy>(
482        &self,
483        src_data_buf: &'src_data mut [u8],
484        subservice: u8,
485        token: VerificationToken<State>,
486        seq_count: u16,
487        msg_count: u16,
488        step: Option<&(impl EcssEnumeration + ?Sized)>,
489        params: &FailParams<'src_data, '_>,
490    ) -> Result<
491        VerificationSendable<'src_data, State, VerifFailure>,
492        VerificationErrorWithToken<State>,
493    > {
494        Ok(VerificationSendable::new(
495            self.create_pus_verif_fail_tm(
496                src_data_buf,
497                subservice,
498                seq_count,
499                msg_count,
500                &token.req_id,
501                step,
502                params,
503            )
504            .map_err(|e| VerificationErrorWithToken(e, token))?,
505            token,
506        ))
507    }
508
509    /// Package a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard.
510    pub fn acceptance_success<'src_data>(
511        &self,
512        src_data_buf: &'src_data mut [u8],
513        token: VerificationToken<TcStateNone>,
514        seq_count: u16,
515        msg_count: u16,
516        time_stamp: Option<&'src_data [u8]>,
517    ) -> Result<
518        VerificationSendable<'src_data, TcStateNone, VerifSuccess>,
519        VerificationErrorWithToken<TcStateNone>,
520    > {
521        self.sendable_success_no_step(
522            src_data_buf,
523            Subservice::TmAcceptanceSuccess.into(),
524            token,
525            seq_count,
526            msg_count,
527            time_stamp,
528        )
529    }
530
531    pub fn send_acceptance_success(
532        &self,
533        mut sendable: VerificationSendable<'_, TcStateNone, VerifSuccess>,
534        sender: &(impl EcssTmSenderCore + ?Sized),
535    ) -> Result<VerificationToken<TcStateAccepted>, VerificationOrSendErrorWithToken<TcStateNone>>
536    {
537        sender
538            .send_tm(sendable.pus_tm.take().unwrap().into())
539            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
540        Ok(sendable.send_success_acceptance_success())
541    }
542
543    pub fn send_acceptance_failure(
544        &self,
545        mut sendable: VerificationSendable<'_, TcStateNone, VerifFailure>,
546        sender: &(impl EcssTmSenderCore + ?Sized),
547    ) -> Result<(), VerificationOrSendErrorWithToken<TcStateNone>> {
548        sender
549            .send_tm(sendable.pus_tm.take().unwrap().into())
550            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
551        sendable.send_success_verif_failure();
552        Ok(())
553    }
554
555    /// Package a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard.
556    pub fn acceptance_failure<'src_data>(
557        &self,
558        src_data_buf: &'src_data mut [u8],
559        token: VerificationToken<TcStateNone>,
560        seq_count: u16,
561        msg_count: u16,
562        params: FailParams<'src_data, '_>,
563    ) -> Result<
564        VerificationSendable<'src_data, TcStateNone, VerifFailure>,
565        VerificationErrorWithToken<TcStateNone>,
566    > {
567        self.sendable_failure_no_step(
568            src_data_buf,
569            Subservice::TmAcceptanceFailure.into(),
570            token,
571            seq_count,
572            msg_count,
573            None::<&dyn EcssEnumeration>,
574            &params,
575        )
576    }
577
578    /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard.
579    ///
580    /// Requires a token previously acquired by calling [Self::acceptance_success].
581    pub fn start_success<'src_data>(
582        &self,
583        src_data_buf: &'src_data mut [u8],
584        token: VerificationToken<TcStateAccepted>,
585        seq_count: u16,
586        msg_count: u16,
587        time_stamp: Option<&'src_data [u8]>,
588    ) -> Result<
589        VerificationSendable<'src_data, TcStateAccepted, VerifSuccess>,
590        VerificationErrorWithToken<TcStateAccepted>,
591    > {
592        self.sendable_success_no_step(
593            src_data_buf,
594            Subservice::TmStartSuccess.into(),
595            token,
596            seq_count,
597            msg_count,
598            time_stamp,
599        )
600    }
601
602    pub fn send_start_success(
603        &self,
604        mut sendable: VerificationSendable<'_, TcStateAccepted, VerifSuccess>,
605        sender: &(impl EcssTmSenderCore + ?Sized),
606    ) -> Result<VerificationToken<TcStateStarted>, VerificationOrSendErrorWithToken<TcStateAccepted>>
607    {
608        sender
609            .send_tm(sendable.pus_tm.take().unwrap().into())
610            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
611        Ok(sendable.send_success_start_success())
612    }
613
614    /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
615    ///
616    /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes
617    /// the token because verification handling is done.
618    pub fn start_failure<'src_data>(
619        &self,
620        src_data_buf: &'src_data mut [u8],
621        token: VerificationToken<TcStateAccepted>,
622        seq_count: u16,
623        msg_count: u16,
624        params: FailParams<'src_data, '_>,
625    ) -> Result<
626        VerificationSendable<'src_data, TcStateAccepted, VerifFailure>,
627        VerificationErrorWithToken<TcStateAccepted>,
628    > {
629        self.sendable_failure_no_step(
630            src_data_buf,
631            Subservice::TmStartFailure.into(),
632            token,
633            seq_count,
634            msg_count,
635            None::<&dyn EcssEnumeration>,
636            &params,
637        )
638    }
639
640    pub fn send_start_failure(
641        &self,
642        mut sendable: VerificationSendable<'_, TcStateAccepted, VerifFailure>,
643        sender: &(impl EcssTmSenderCore + ?Sized),
644    ) -> Result<(), VerificationOrSendErrorWithToken<TcStateAccepted>> {
645        sender
646            .send_tm(sendable.pus_tm.take().unwrap().into())
647            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
648        sendable.send_success_verif_failure();
649        Ok(())
650    }
651
652    /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard.
653    ///
654    /// Requires a token previously acquired by calling [Self::start_success].
655    pub fn step_success<'src_data>(
656        &self,
657        src_data_buf: &'src_data mut [u8],
658        token: &VerificationToken<TcStateStarted>,
659        seq_count: u16,
660        msg_count: u16,
661        time_stamp: Option<&'src_data [u8]>,
662        step: impl EcssEnumeration,
663    ) -> Result<VerificationSendable<'src_data, TcStateStarted, VerifSuccess>, EcssTmtcError> {
664        Ok(VerificationSendable::new_no_token(
665            self.create_pus_verif_success_tm(
666                src_data_buf,
667                Subservice::TmStepSuccess.into(),
668                seq_count,
669                msg_count,
670                &token.req_id,
671                time_stamp,
672                Some(&step),
673            )?,
674        ))
675    }
676
677    /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard.
678    ///
679    /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
680    /// token because verification handling is done.
681    pub fn step_failure<'src_data>(
682        &self,
683        src_data_buf: &'src_data mut [u8],
684        token: VerificationToken<TcStateStarted>,
685        seq_count: u16,
686        msg_count: u16,
687        params: FailParamsWithStep<'src_data, '_>,
688    ) -> Result<
689        VerificationSendable<'src_data, TcStateStarted, VerifFailure>,
690        VerificationErrorWithToken<TcStateStarted>,
691    > {
692        Ok(VerificationSendable::new(
693            self.create_pus_verif_fail_tm(
694                src_data_buf,
695                Subservice::TmStepFailure.into(),
696                seq_count,
697                msg_count,
698                &token.req_id,
699                Some(params.step),
700                &params.bp,
701            )
702            .map_err(|e| VerificationErrorWithToken(e, token))?,
703            token,
704        ))
705    }
706
707    /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard.
708    ///
709    /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
710    /// token because verification handling is done.
711    pub fn completion_success<'src_data, TcState: WasAtLeastAccepted + Copy>(
712        &self,
713        src_data_buf: &'src_data mut [u8],
714        token: VerificationToken<TcState>,
715        seq_counter: u16,
716        msg_counter: u16,
717        time_stamp: Option<&'src_data [u8]>,
718    ) -> Result<
719        VerificationSendable<'src_data, TcState, VerifSuccess>,
720        VerificationErrorWithToken<TcState>,
721    > {
722        self.sendable_success_no_step(
723            src_data_buf,
724            Subservice::TmCompletionSuccess.into(),
725            token,
726            seq_counter,
727            msg_counter,
728            time_stamp,
729        )
730    }
731
732    /// Package and send a PUS TM\[1, 8\] packet, see 8.1.2.8 of the PUS standard.
733    ///
734    /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
735    /// token because verification handling is done.
736    pub fn completion_failure<'src_data, TcState: WasAtLeastAccepted + Copy>(
737        &self,
738        src_data_buf: &'src_data mut [u8],
739        token: VerificationToken<TcState>,
740        seq_count: u16,
741        msg_count: u16,
742        params: FailParams<'src_data, '_>,
743    ) -> Result<
744        VerificationSendable<'src_data, TcState, VerifFailure>,
745        VerificationErrorWithToken<TcState>,
746    > {
747        self.sendable_failure_no_step(
748            src_data_buf,
749            Subservice::TmCompletionFailure.into(),
750            token,
751            seq_count,
752            msg_count,
753            None::<&dyn EcssEnumeration>,
754            &params,
755        )
756    }
757
758    pub fn send_step_or_completion_success<TcState: WasAtLeastAccepted + Copy>(
759        &self,
760        mut sendable: VerificationSendable<'_, TcState, VerifSuccess>,
761        sender: &(impl EcssTmSenderCore + ?Sized),
762    ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
763        sender
764            .send_tm(sendable.pus_tm.take().unwrap().into())
765            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
766        sendable.send_success_step_or_completion_success();
767        Ok(())
768    }
769
770    pub fn send_step_or_completion_failure<TcState: WasAtLeastAccepted + Copy>(
771        &self,
772        mut sendable: VerificationSendable<'_, TcState, VerifFailure>,
773        sender: &(impl EcssTmSenderCore + ?Sized),
774    ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
775        sender
776            .send_tm(sendable.pus_tm.take().unwrap().into())
777            .map_err(|e| VerificationOrSendErrorWithToken(e, sendable.token.unwrap()))?;
778        sendable.send_success_verif_failure();
779        Ok(())
780    }
781
782    // Internal helper function, too many arguments is acceptable for this case.
783    #[allow(clippy::too_many_arguments)]
784    fn create_pus_verif_success_tm<'src_data>(
785        &self,
786        src_data_buf: &'src_data mut [u8],
787        subservice: u8,
788        seq_count: u16,
789        msg_counter: u16,
790        req_id: &RequestId,
791        time_stamp: Option<&'src_data [u8]>,
792        step: Option<&(impl EcssEnumeration + ?Sized)>,
793    ) -> Result<PusTmCreator<'src_data>, EcssTmtcError> {
794        let mut source_data_len = size_of::<u32>();
795        if let Some(step) = step {
796            source_data_len += step.size();
797        }
798        source_buffer_large_enough(src_data_buf.len(), source_data_len)?;
799        let mut idx = 0;
800        req_id.to_bytes(&mut src_data_buf[0..RequestId::SIZE_AS_BYTES]);
801        idx += RequestId::SIZE_AS_BYTES;
802        if let Some(step) = step {
803            // Size check was done beforehand
804            step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.size()])
805                .unwrap();
806        }
807        let mut sp_header = SpHeader::tm_unseg(self.apid(), seq_count, 0).unwrap();
808        Ok(self.create_pus_verif_tm_base(
809            src_data_buf,
810            subservice,
811            msg_counter,
812            &mut sp_header,
813            time_stamp,
814            source_data_len,
815        ))
816    }
817
818    // Internal helper function, too many arguments is acceptable for this case.
819    #[allow(clippy::too_many_arguments)]
820    fn create_pus_verif_fail_tm<'src_data>(
821        &self,
822        src_data_buf: &'src_data mut [u8],
823        subservice: u8,
824        seq_count: u16,
825        msg_counter: u16,
826        req_id: &RequestId,
827        step: Option<&(impl EcssEnumeration + ?Sized)>,
828        params: &FailParams<'src_data, '_>,
829    ) -> Result<PusTmCreator<'src_data>, EcssTmtcError> {
830        let mut idx = 0;
831        let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.size();
832        if let Some(step) = step {
833            source_data_len += step.size();
834        }
835        if let Some(failure_data) = params.failure_data {
836            source_data_len += failure_data.len();
837        }
838        source_buffer_large_enough(src_data_buf.len(), source_data_len)?;
839        req_id.to_bytes(&mut src_data_buf[0..RequestId::SIZE_AS_BYTES]);
840        idx += RequestId::SIZE_AS_BYTES;
841        if let Some(step) = step {
842            // Size check done beforehand
843            step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.size()])
844                .unwrap();
845            idx += step.size();
846        }
847        params
848            .failure_code
849            .write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.size()])
850            .map_err(PusError::ByteConversion)?;
851        idx += params.failure_code.size();
852        if let Some(failure_data) = params.failure_data {
853            src_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data);
854        }
855        let mut sp_header = SpHeader::tm_unseg(self.apid(), seq_count, 0).unwrap();
856        Ok(self.create_pus_verif_tm_base(
857            src_data_buf,
858            subservice,
859            msg_counter,
860            &mut sp_header,
861            params.time_stamp,
862            source_data_len,
863        ))
864    }
865
866    fn create_pus_verif_tm_base<'src_data>(
867        &self,
868        src_data_buf: &'src_data mut [u8],
869        subservice: u8,
870        msg_counter: u16,
871        sp_header: &mut SpHeader,
872        time_stamp: Option<&'src_data [u8]>,
873        source_data_len: usize,
874    ) -> PusTmCreator<'src_data> {
875        let tm_sec_header =
876            PusTmSecondaryHeader::new(1, subservice, msg_counter, self.dest_id, time_stamp);
877        PusTmCreator::new(
878            sp_header,
879            tm_sec_header,
880            &src_data_buf[0..source_data_len],
881            true,
882        )
883    }
884}
885
886#[cfg(feature = "alloc")]
887mod alloc_mod {
888    use super::*;
889    use crate::pus::alloc_mod::EcssTmSender;
890    use crate::seq_count::SequenceCountProvider;
891    use alloc::boxed::Box;
892    use alloc::vec;
893    use alloc::vec::Vec;
894    use core::cell::RefCell;
895    use spacepackets::ecss::tc::IsPusTelecommand;
896
897    #[derive(Clone)]
898    pub struct VerificationReporterCfg {
899        apid: u16,
900        pub step_field_width: usize,
901        pub fail_code_field_width: usize,
902        pub max_fail_data_len: usize,
903    }
904
905    impl VerificationReporterCfg {
906        pub fn new(
907            apid: u16,
908            step_field_width: usize,
909            fail_code_field_width: usize,
910            max_fail_data_len: usize,
911        ) -> Option<Self> {
912            if apid > MAX_APID {
913                return None;
914            }
915            Some(Self {
916                apid,
917                step_field_width,
918                fail_code_field_width,
919                max_fail_data_len,
920            })
921        }
922    }
923
924    /// Primary verification handler. It provides an API to send PUS 1 verification telemetry packets
925    /// and verify the various steps of telecommand handling as specified in the PUS standard.
926    /// It is assumed that the sequence counter and message counters are updated in a central
927    /// TM funnel. This helper will always set those fields to 0.
928    #[derive(Clone)]
929    pub struct VerificationReporter {
930        source_data_buf: RefCell<Vec<u8>>,
931        pub seq_count_provider: Option<Box<dyn SequenceCountProvider<u16> + Send>>,
932        pub msg_count_provider: Option<Box<dyn SequenceCountProvider<u16> + Send>>,
933        pub reporter: VerificationReporterCore,
934    }
935
936    impl VerificationReporter {
937        pub fn new(cfg: &VerificationReporterCfg) -> Self {
938            let reporter = VerificationReporterCore::new(cfg.apid).unwrap();
939            Self {
940                source_data_buf: RefCell::new(vec![
941                    0;
942                    RequestId::SIZE_AS_BYTES
943                        + cfg.step_field_width
944                        + cfg.fail_code_field_width
945                        + cfg.max_fail_data_len
946                ]),
947                seq_count_provider: None,
948                msg_count_provider: None,
949                reporter,
950            }
951        }
952
953        delegate!(
954            to self.reporter {
955                pub fn set_apid(&mut self, apid: u16) -> bool;
956                pub fn apid(&self) -> u16;
957                pub fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
958                pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
959                pub fn dest_id(&self) -> u16;
960                pub fn set_dest_id(&mut self, dest_id: u16);
961            }
962        );
963
964        pub fn allowed_source_data_len(&self) -> usize {
965            self.source_data_buf.borrow().capacity()
966        }
967
968        /// Package and send a PUS TM\[1, 1\] packet, see 8.1.2.1 of the PUS standard
969        pub fn acceptance_success(
970            &self,
971            token: VerificationToken<TcStateNone>,
972            sender: &(impl EcssTmSenderCore + ?Sized),
973            time_stamp: Option<&[u8]>,
974        ) -> Result<VerificationToken<TcStateAccepted>, VerificationOrSendErrorWithToken<TcStateNone>>
975        {
976            let seq_count = self
977                .seq_count_provider
978                .as_ref()
979                .map_or(0, |v| v.get_and_increment());
980            let msg_count = self
981                .seq_count_provider
982                .as_ref()
983                .map_or(0, |v| v.get_and_increment());
984            let mut source_data_buf = self.source_data_buf.borrow_mut();
985            let sendable = self.reporter.acceptance_success(
986                source_data_buf.as_mut_slice(),
987                token,
988                seq_count,
989                msg_count,
990                time_stamp,
991            )?;
992            self.reporter.send_acceptance_success(sendable, sender)
993        }
994
995        /// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard
996        pub fn acceptance_failure(
997            &self,
998            token: VerificationToken<TcStateNone>,
999            sender: &(impl EcssTmSenderCore + ?Sized),
1000            params: FailParams,
1001        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateNone>> {
1002            let seq_count = self
1003                .seq_count_provider
1004                .as_ref()
1005                .map_or(0, |v| v.get_and_increment());
1006            let msg_count = self
1007                .seq_count_provider
1008                .as_ref()
1009                .map_or(0, |v| v.get_and_increment());
1010            let mut buf = self.source_data_buf.borrow_mut();
1011            let sendable = self.reporter.acceptance_failure(
1012                buf.as_mut_slice(),
1013                token,
1014                seq_count,
1015                msg_count,
1016                params,
1017            )?;
1018            self.reporter.send_acceptance_failure(sendable, sender)
1019        }
1020
1021        /// Package and send a PUS TM\[1, 3\] packet, see 8.1.2.3 of the PUS standard.
1022        ///
1023        /// Requires a token previously acquired by calling [Self::acceptance_success].
1024        pub fn start_success(
1025            &self,
1026            token: VerificationToken<TcStateAccepted>,
1027            sender: &(impl EcssTmSenderCore + ?Sized),
1028            time_stamp: Option<&[u8]>,
1029        ) -> Result<
1030            VerificationToken<TcStateStarted>,
1031            VerificationOrSendErrorWithToken<TcStateAccepted>,
1032        > {
1033            let seq_count = self
1034                .seq_count_provider
1035                .as_ref()
1036                .map_or(0, |v| v.get_and_increment());
1037            let msg_count = self
1038                .seq_count_provider
1039                .as_ref()
1040                .map_or(0, |v| v.get_and_increment());
1041            let mut buf = self.source_data_buf.borrow_mut();
1042            let sendable = self.reporter.start_success(
1043                buf.as_mut_slice(),
1044                token,
1045                seq_count,
1046                msg_count,
1047                time_stamp,
1048            )?;
1049            self.reporter.send_start_success(sendable, sender)
1050        }
1051
1052        /// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
1053        ///
1054        /// Requires a token previously acquired by calling [Self::acceptance_success]. It consumes
1055        /// the token because verification handling is done.
1056        pub fn start_failure(
1057            &self,
1058            token: VerificationToken<TcStateAccepted>,
1059            sender: &(impl EcssTmSenderCore + ?Sized),
1060            params: FailParams,
1061        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateAccepted>> {
1062            let seq_count = self
1063                .seq_count_provider
1064                .as_ref()
1065                .map_or(0, |v| v.get_and_increment());
1066            let msg_count = self
1067                .seq_count_provider
1068                .as_ref()
1069                .map_or(0, |v| v.get_and_increment());
1070            let mut buf = self.source_data_buf.borrow_mut();
1071            let sendable = self.reporter.start_failure(
1072                buf.as_mut_slice(),
1073                token,
1074                seq_count,
1075                msg_count,
1076                params,
1077            )?;
1078            self.reporter.send_start_failure(sendable, sender)
1079        }
1080
1081        /// Package and send a PUS TM\[1, 5\] packet, see 8.1.2.5 of the PUS standard.
1082        ///
1083        /// Requires a token previously acquired by calling [Self::start_success].
1084        pub fn step_success(
1085            &self,
1086            token: &VerificationToken<TcStateStarted>,
1087            sender: &(impl EcssTmSenderCore + ?Sized),
1088            time_stamp: Option<&[u8]>,
1089            step: impl EcssEnumeration,
1090        ) -> Result<(), EcssTmtcError> {
1091            let seq_count = self
1092                .seq_count_provider
1093                .as_ref()
1094                .map_or(0, |v| v.get_and_increment());
1095            let msg_count = self
1096                .seq_count_provider
1097                .as_ref()
1098                .map_or(0, |v| v.get_and_increment());
1099            let mut buf = self.source_data_buf.borrow_mut();
1100            let sendable = self.reporter.step_success(
1101                buf.as_mut_slice(),
1102                token,
1103                seq_count,
1104                msg_count,
1105                time_stamp,
1106                step,
1107            )?;
1108            self.reporter
1109                .send_step_or_completion_success(sendable, sender)
1110                .map_err(|e| e.0)
1111        }
1112
1113        /// Package and send a PUS TM\[1, 6\] packet, see 8.1.2.6 of the PUS standard.
1114        ///
1115        /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
1116        /// token because verification handling is done.
1117        pub fn step_failure(
1118            &self,
1119            token: VerificationToken<TcStateStarted>,
1120            sender: &(impl EcssTmSenderCore + ?Sized),
1121            params: FailParamsWithStep,
1122        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateStarted>> {
1123            let seq_count = self
1124                .seq_count_provider
1125                .as_ref()
1126                .map_or(0, |v| v.get_and_increment());
1127            let msg_count = self
1128                .seq_count_provider
1129                .as_ref()
1130                .map_or(0, |v| v.get_and_increment());
1131            let mut buf = self.source_data_buf.borrow_mut();
1132            let sendable = self.reporter.step_failure(
1133                buf.as_mut_slice(),
1134                token,
1135                seq_count,
1136                msg_count,
1137                params,
1138            )?;
1139            self.reporter
1140                .send_step_or_completion_failure(sendable, sender)
1141        }
1142
1143        /// Package and send a PUS TM\[1, 7\] packet, see 8.1.2.7 of the PUS standard.
1144        ///
1145        /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
1146        /// token because verification handling is done.
1147        pub fn completion_success<TcState: WasAtLeastAccepted + Copy>(
1148            &self,
1149            token: VerificationToken<TcState>,
1150            sender: &(impl EcssTmSenderCore + ?Sized),
1151            time_stamp: Option<&[u8]>,
1152        ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
1153            let seq_count = self
1154                .seq_count_provider
1155                .as_ref()
1156                .map_or(0, |v| v.get_and_increment());
1157            let msg_count = self
1158                .seq_count_provider
1159                .as_ref()
1160                .map_or(0, |v| v.get_and_increment());
1161            let mut buf = self.source_data_buf.borrow_mut();
1162            let sendable = self.reporter.completion_success(
1163                buf.as_mut_slice(),
1164                token,
1165                seq_count,
1166                msg_count,
1167                time_stamp,
1168            )?;
1169            self.reporter
1170                .send_step_or_completion_success(sendable, sender)
1171        }
1172
1173        /// Package and send a PUS TM\[1, 8\] packet, see 8.1.2.8 of the PUS standard.
1174        ///
1175        /// Requires a token previously acquired by calling [Self::start_success]. It consumes the
1176        /// token because verification handling is done.
1177        pub fn completion_failure<TcState: WasAtLeastAccepted + Copy>(
1178            &self,
1179            token: VerificationToken<TcState>,
1180            sender: &(impl EcssTmSenderCore + ?Sized),
1181            params: FailParams,
1182        ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
1183            let seq_count = self
1184                .seq_count_provider
1185                .as_ref()
1186                .map_or(0, |v| v.get_and_increment());
1187            let msg_count = self
1188                .seq_count_provider
1189                .as_ref()
1190                .map_or(0, |v| v.get_and_increment());
1191            let mut buf = self.source_data_buf.borrow_mut();
1192            let sendable = self.reporter.completion_failure(
1193                buf.as_mut_slice(),
1194                token,
1195                seq_count,
1196                msg_count,
1197                params,
1198            )?;
1199            self.reporter
1200                .send_step_or_completion_failure(sendable, sender)
1201        }
1202    }
1203
1204    /// Helper object which caches the sender passed as a trait object. Provides the same
1205    /// API as [VerificationReporter] but without the explicit sender arguments.
1206    #[derive(Clone)]
1207    pub struct VerificationReporterWithSender {
1208        pub reporter: VerificationReporter,
1209        pub sender: Box<dyn EcssTmSender>,
1210    }
1211
1212    impl VerificationReporterWithSender {
1213        pub fn new(cfg: &VerificationReporterCfg, sender: Box<dyn EcssTmSender>) -> Self {
1214            let reporter = VerificationReporter::new(cfg);
1215            Self::new_from_reporter(reporter, sender)
1216        }
1217
1218        pub fn new_from_reporter(
1219            reporter: VerificationReporter,
1220            sender: Box<dyn EcssTmSender>,
1221        ) -> Self {
1222            Self { reporter, sender }
1223        }
1224
1225        delegate! {
1226            to self.reporter {
1227                pub fn set_apid(&mut self, apid: u16) -> bool;
1228                pub fn apid(&self) -> u16;
1229                pub fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
1230                pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
1231                pub fn dest_id(&self) -> u16;
1232                pub fn set_dest_id(&mut self, dest_id: u16);
1233            }
1234        }
1235
1236        pub fn acceptance_success(
1237            &self,
1238            token: VerificationToken<TcStateNone>,
1239            time_stamp: Option<&[u8]>,
1240        ) -> Result<VerificationToken<TcStateAccepted>, VerificationOrSendErrorWithToken<TcStateNone>>
1241        {
1242            self.reporter
1243                .acceptance_success(token, self.sender.as_ref(), time_stamp)
1244        }
1245
1246        pub fn acceptance_failure(
1247            &self,
1248            token: VerificationToken<TcStateNone>,
1249            params: FailParams,
1250        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateNone>> {
1251            self.reporter
1252                .acceptance_failure(token, self.sender.as_ref(), params)
1253        }
1254
1255        pub fn start_success(
1256            &self,
1257            token: VerificationToken<TcStateAccepted>,
1258            time_stamp: Option<&[u8]>,
1259        ) -> Result<
1260            VerificationToken<TcStateStarted>,
1261            VerificationOrSendErrorWithToken<TcStateAccepted>,
1262        > {
1263            self.reporter
1264                .start_success(token, self.sender.as_ref(), time_stamp)
1265        }
1266
1267        pub fn start_failure(
1268            &self,
1269            token: VerificationToken<TcStateAccepted>,
1270            params: FailParams,
1271        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateAccepted>> {
1272            self.reporter
1273                .start_failure(token, self.sender.as_ref(), params)
1274        }
1275
1276        pub fn step_success(
1277            &self,
1278            token: &VerificationToken<TcStateStarted>,
1279            time_stamp: Option<&[u8]>,
1280            step: impl EcssEnumeration,
1281        ) -> Result<(), EcssTmtcError> {
1282            self.reporter
1283                .step_success(token, self.sender.as_ref(), time_stamp, step)
1284        }
1285
1286        pub fn step_failure(
1287            &self,
1288            token: VerificationToken<TcStateStarted>,
1289            params: FailParamsWithStep,
1290        ) -> Result<(), VerificationOrSendErrorWithToken<TcStateStarted>> {
1291            self.reporter
1292                .step_failure(token, self.sender.as_ref(), params)
1293        }
1294
1295        pub fn completion_success<TcState: WasAtLeastAccepted + Copy>(
1296            &self,
1297            token: VerificationToken<TcState>,
1298            time_stamp: Option<&[u8]>,
1299        ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
1300            self.reporter
1301                .completion_success(token, self.sender.as_ref(), time_stamp)
1302        }
1303
1304        pub fn completion_failure<TcState: WasAtLeastAccepted + Copy>(
1305            &self,
1306            token: VerificationToken<TcState>,
1307            params: FailParams,
1308        ) -> Result<(), VerificationOrSendErrorWithToken<TcState>> {
1309            self.reporter
1310                .completion_failure(token, self.sender.as_ref(), params)
1311        }
1312    }
1313}
1314
1315#[cfg(feature = "std")]
1316mod std_mod {
1317    use crate::pus::verification::VerificationReporterWithSender;
1318    use std::sync::{Arc, Mutex};
1319
1320    pub type StdVerifReporterWithSender = VerificationReporterWithSender;
1321    pub type SharedStdVerifReporterWithSender = Arc<Mutex<StdVerifReporterWithSender>>;
1322}
1323
1324#[cfg(test)]
1325mod tests {
1326    use crate::pool::{PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
1327    use crate::pus::tests::CommonTmInfo;
1328    use crate::pus::verification::{
1329        EcssTmSenderCore, EcssTmtcError, FailParams, FailParamsWithStep, RequestId, TcStateNone,
1330        VerificationReporter, VerificationReporterCfg, VerificationReporterWithSender,
1331        VerificationToken,
1332    };
1333    use crate::pus::{EcssChannel, MpscTmInSharedPoolSender, PusTmWrapper};
1334    use crate::tmtc::tm_helper::SharedTmPool;
1335    use crate::ChannelId;
1336    use alloc::boxed::Box;
1337    use alloc::format;
1338    use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
1339    use spacepackets::ecss::tm::PusTmReader;
1340    use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, PusError, PusPacket};
1341    use spacepackets::util::UnsignedEnum;
1342    use spacepackets::{ByteConversionError, CcsdsPacket, SpHeader};
1343    use std::cell::RefCell;
1344    use std::collections::VecDeque;
1345    use std::sync::mpsc;
1346    use std::time::Duration;
1347    use std::vec;
1348    use std::vec::Vec;
1349
1350    fn is_send<T: Send>(_: &T) {}
1351    #[allow(dead_code)]
1352    fn is_sync<T: Sync>(_: &T) {}
1353
1354    const TEST_APID: u16 = 0x02;
1355    const EMPTY_STAMP: [u8; 7] = [0; 7];
1356
1357    #[derive(Debug, Eq, PartialEq, Clone)]
1358    struct TmInfo {
1359        pub common: CommonTmInfo,
1360        pub req_id: RequestId,
1361        pub additional_data: Option<Vec<u8>>,
1362    }
1363
1364    #[derive(Default, Clone)]
1365    struct TestSender {
1366        pub service_queue: RefCell<VecDeque<TmInfo>>,
1367    }
1368
1369    impl EcssChannel for TestSender {
1370        fn id(&self) -> ChannelId {
1371            0
1372        }
1373        fn name(&self) -> &'static str {
1374            "test_sender"
1375        }
1376    }
1377
1378    impl EcssTmSenderCore for TestSender {
1379        fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
1380            match tm {
1381                PusTmWrapper::InStore(_) => {
1382                    panic!("TestSender: Can not deal with addresses");
1383                }
1384                PusTmWrapper::Direct(tm) => {
1385                    assert_eq!(PusPacket::service(&tm), 1);
1386                    assert!(!tm.source_data().is_empty());
1387                    let mut time_stamp = [0; 7];
1388                    time_stamp.clone_from_slice(&tm.timestamp()[0..7]);
1389                    let src_data = tm.source_data();
1390                    assert!(src_data.len() >= 4);
1391                    let req_id =
1392                        RequestId::from_bytes(&src_data[0..RequestId::SIZE_AS_BYTES]).unwrap();
1393                    let mut vec = None;
1394                    if src_data.len() > 4 {
1395                        let mut new_vec = Vec::new();
1396                        new_vec.extend_from_slice(&src_data[RequestId::SIZE_AS_BYTES..]);
1397                        vec = Some(new_vec);
1398                    }
1399                    self.service_queue.borrow_mut().push_back(TmInfo {
1400                        common: CommonTmInfo::new_from_tm(&tm),
1401                        req_id,
1402                        additional_data: vec,
1403                    });
1404                    Ok(())
1405                }
1406            }
1407        }
1408    }
1409
1410    struct TestBase<'a> {
1411        vr: VerificationReporter,
1412        #[allow(dead_code)]
1413        tc: PusTcCreator<'a>,
1414    }
1415
1416    impl<'a> TestBase<'a> {
1417        fn rep(&mut self) -> &mut VerificationReporter {
1418            &mut self.vr
1419        }
1420    }
1421    struct TestBaseWithHelper<'a> {
1422        helper: VerificationReporterWithSender,
1423        #[allow(dead_code)]
1424        tc: PusTcCreator<'a>,
1425    }
1426
1427    impl<'a> TestBaseWithHelper<'a> {
1428        fn rep(&mut self) -> &mut VerificationReporter {
1429            &mut self.helper.reporter
1430        }
1431    }
1432
1433    fn base_reporter() -> VerificationReporter {
1434        let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
1435        VerificationReporter::new(&cfg)
1436    }
1437
1438    fn base_tc_init(app_data: Option<&[u8]>) -> (PusTcCreator, RequestId) {
1439        let mut sph = SpHeader::tc_unseg(TEST_APID, 0x34, 0).unwrap();
1440        let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
1441        let app_data = app_data.unwrap_or(&[]);
1442        let pus_tc = PusTcCreator::new(&mut sph, tc_header, app_data, true);
1443        let req_id = RequestId::new(&pus_tc);
1444        (pus_tc, req_id)
1445    }
1446
1447    fn base_init(api_sel: bool) -> (TestBase<'static>, VerificationToken<TcStateNone>) {
1448        let mut reporter = base_reporter();
1449        let (tc, req_id) = base_tc_init(None);
1450        let init_tok = if api_sel {
1451            reporter.add_tc_with_req_id(req_id)
1452        } else {
1453            reporter.add_tc(&tc)
1454        };
1455        (TestBase { vr: reporter, tc }, init_tok)
1456    }
1457
1458    fn base_with_helper_init() -> (TestBaseWithHelper<'static>, VerificationToken<TcStateNone>) {
1459        let mut reporter = base_reporter();
1460        let (tc, _) = base_tc_init(None);
1461        let init_tok = reporter.add_tc(&tc);
1462        let sender = TestSender::default();
1463        let helper = VerificationReporterWithSender::new_from_reporter(reporter, Box::new(sender));
1464        (TestBaseWithHelper { helper, tc }, init_tok)
1465    }
1466
1467    fn acceptance_check(sender: &mut TestSender, req_id: &RequestId) {
1468        let cmp_info = TmInfo {
1469            common: CommonTmInfo {
1470                subservice: 1,
1471                apid: TEST_APID,
1472                msg_counter: 0,
1473                dest_id: 0,
1474                time_stamp: EMPTY_STAMP,
1475            },
1476            additional_data: None,
1477            req_id: *req_id,
1478        };
1479        let mut service_queue = sender.service_queue.borrow_mut();
1480        assert_eq!(service_queue.len(), 1);
1481        let info = service_queue.pop_front().unwrap();
1482        assert_eq!(info, cmp_info);
1483    }
1484
1485    #[test]
1486    fn test_mpsc_verif_send_sync() {
1487        let pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![(8, 8)], false));
1488        let shared_tm_store = SharedTmPool::new(pool);
1489        let (tx, _) = mpsc::channel();
1490        let mpsc_verif_sender =
1491            MpscTmInSharedPoolSender::new(0, "verif_sender", shared_tm_store, tx);
1492        is_send(&mpsc_verif_sender);
1493    }
1494
1495    #[test]
1496    fn test_state() {
1497        let (mut b, _) = base_init(false);
1498        assert_eq!(b.vr.apid(), TEST_APID);
1499        b.vr.set_apid(TEST_APID + 1);
1500        assert_eq!(b.vr.apid(), TEST_APID + 1);
1501    }
1502
1503    #[test]
1504    fn test_basic_acceptance_success() {
1505        let (b, tok) = base_init(false);
1506        let mut sender = TestSender::default();
1507        b.vr.acceptance_success(tok, &sender, Some(&EMPTY_STAMP))
1508            .expect("Sending acceptance success failed");
1509        acceptance_check(&mut sender, &tok.req_id);
1510    }
1511
1512    #[test]
1513    fn test_basic_acceptance_success_with_helper() {
1514        let (mut b, tok) = base_with_helper_init();
1515        b.helper
1516            .acceptance_success(tok, Some(&EMPTY_STAMP))
1517            .expect("Sending acceptance success failed");
1518        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
1519        acceptance_check(sender, &tok.req_id);
1520    }
1521
1522    fn acceptance_fail_check(sender: &mut TestSender, req_id: RequestId, stamp_buf: [u8; 7]) {
1523        let cmp_info = TmInfo {
1524            common: CommonTmInfo {
1525                subservice: 2,
1526                apid: TEST_APID,
1527                msg_counter: 0,
1528                dest_id: 5,
1529                time_stamp: stamp_buf,
1530            },
1531            additional_data: Some([0, 2].to_vec()),
1532            req_id,
1533        };
1534        let mut service_queue = sender.service_queue.borrow_mut();
1535        assert_eq!(service_queue.len(), 1);
1536        let info = service_queue.pop_front().unwrap();
1537        assert_eq!(info, cmp_info);
1538    }
1539
1540    #[test]
1541    fn test_basic_acceptance_failure() {
1542        let (mut b, tok) = base_init(true);
1543        b.rep().reporter.dest_id = 5;
1544        let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
1545        let mut sender = TestSender::default();
1546        let fail_code = EcssEnumU16::new(2);
1547        let fail_params = FailParams::new(Some(stamp_buf.as_slice()), &fail_code, None);
1548        b.vr.acceptance_failure(tok, &sender, fail_params)
1549            .expect("Sending acceptance success failed");
1550        acceptance_fail_check(&mut sender, tok.req_id, stamp_buf);
1551    }
1552
1553    #[test]
1554    fn test_basic_acceptance_failure_with_helper() {
1555        let (mut b, tok) = base_with_helper_init();
1556        b.rep().reporter.dest_id = 5;
1557        let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
1558        let fail_code = EcssEnumU16::new(2);
1559        let fail_params = FailParams::new(Some(stamp_buf.as_slice()), &fail_code, None);
1560        b.helper
1561            .acceptance_failure(tok, fail_params)
1562            .expect("Sending acceptance success failed");
1563        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
1564        acceptance_fail_check(sender, tok.req_id, stamp_buf);
1565    }
1566
1567    #[test]
1568    fn test_acceptance_fail_data_too_large() {
1569        let (mut b, tok) = base_with_helper_init();
1570        b.rep().reporter.dest_id = 5;
1571        let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
1572        let fail_code = EcssEnumU16::new(2);
1573        let fail_data: [u8; 16] = [0; 16];
1574        // 4 req ID + 1 byte step + 2 byte error code + 8 byte fail data
1575        assert_eq!(b.rep().allowed_source_data_len(), 15);
1576        let fail_params = FailParams::new(
1577            Some(stamp_buf.as_slice()),
1578            &fail_code,
1579            Some(fail_data.as_slice()),
1580        );
1581        let res = b.helper.acceptance_failure(tok, fail_params);
1582        assert!(res.is_err());
1583        let err_with_token = res.unwrap_err();
1584        assert_eq!(err_with_token.1, tok);
1585        match err_with_token.0 {
1586            EcssTmtcError::Pus(PusError::ByteConversion(e)) => match e {
1587                ByteConversionError::ToSliceTooSmall { found, expected } => {
1588                    assert_eq!(
1589                        expected,
1590                        fail_data.len() + RequestId::SIZE_AS_BYTES + fail_code.size()
1591                    );
1592                    assert_eq!(found, b.rep().allowed_source_data_len());
1593                }
1594                _ => {
1595                    panic!("{}", format!("Unexpected error {:?}", e))
1596                }
1597            },
1598            _ => {
1599                panic!("{}", format!("Unexpected error {:?}", err_with_token.0))
1600            }
1601        }
1602    }
1603
1604    #[test]
1605    fn test_basic_acceptance_failure_with_fail_data() {
1606        let (b, tok) = base_init(false);
1607        let sender = TestSender::default();
1608        let fail_code = EcssEnumU8::new(10);
1609        let fail_data = EcssEnumU32::new(12);
1610        let mut fail_data_raw = [0; 4];
1611        fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap();
1612        let fail_params = FailParams::new(
1613            Some(&EMPTY_STAMP),
1614            &fail_code,
1615            Some(fail_data_raw.as_slice()),
1616        );
1617        b.vr.acceptance_failure(tok, &sender, fail_params)
1618            .expect("Sending acceptance success failed");
1619        let cmp_info = TmInfo {
1620            common: CommonTmInfo {
1621                subservice: 2,
1622                apid: TEST_APID,
1623                msg_counter: 0,
1624                dest_id: 0,
1625                time_stamp: EMPTY_STAMP,
1626            },
1627            additional_data: Some([10, 0, 0, 0, 12].to_vec()),
1628            req_id: tok.req_id,
1629        };
1630        let mut service_queue = sender.service_queue.borrow_mut();
1631        assert_eq!(service_queue.len(), 1);
1632        let info = service_queue.pop_front().unwrap();
1633        assert_eq!(info, cmp_info);
1634    }
1635
1636    fn start_fail_check(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) {
1637        let mut srv_queue = sender.service_queue.borrow_mut();
1638        assert_eq!(srv_queue.len(), 2);
1639        let mut cmp_info = TmInfo {
1640            common: CommonTmInfo {
1641                subservice: 1,
1642                apid: TEST_APID,
1643                msg_counter: 0,
1644                dest_id: 0,
1645                time_stamp: EMPTY_STAMP,
1646            },
1647            additional_data: None,
1648            req_id,
1649        };
1650        let mut info = srv_queue.pop_front().unwrap();
1651        assert_eq!(info, cmp_info);
1652
1653        cmp_info = TmInfo {
1654            common: CommonTmInfo {
1655                subservice: 4,
1656                apid: TEST_APID,
1657                msg_counter: 0,
1658                dest_id: 0,
1659                time_stamp: EMPTY_STAMP,
1660            },
1661            additional_data: Some([&[22], fail_data_raw.as_slice()].concat().to_vec()),
1662            req_id,
1663        };
1664        info = srv_queue.pop_front().unwrap();
1665        assert_eq!(info, cmp_info);
1666    }
1667
1668    #[test]
1669    fn test_start_failure() {
1670        let (b, tok) = base_init(false);
1671        let mut sender = TestSender::default();
1672        let fail_code = EcssEnumU8::new(22);
1673        let fail_data: i32 = -12;
1674        let mut fail_data_raw = [0; 4];
1675        fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice());
1676        let fail_params = FailParams::new(
1677            Some(&EMPTY_STAMP),
1678            &fail_code,
1679            Some(fail_data_raw.as_slice()),
1680        );
1681
1682        let accepted_token =
1683            b.vr.acceptance_success(tok, &sender, Some(&EMPTY_STAMP))
1684                .expect("Sending acceptance success failed");
1685        b.vr.start_failure(accepted_token, &mut sender, fail_params)
1686            .expect("Start failure failure");
1687        start_fail_check(&mut sender, tok.req_id, fail_data_raw);
1688    }
1689
1690    #[test]
1691    fn test_start_failure_with_helper() {
1692        let (mut b, tok) = base_with_helper_init();
1693        let fail_code = EcssEnumU8::new(22);
1694        let fail_data: i32 = -12;
1695        let mut fail_data_raw = [0; 4];
1696        fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice());
1697        let fail_params = FailParams::new(
1698            Some(&EMPTY_STAMP),
1699            &fail_code,
1700            Some(fail_data_raw.as_slice()),
1701        );
1702
1703        let accepted_token = b
1704            .helper
1705            .acceptance_success(tok, Some(&EMPTY_STAMP))
1706            .expect("Sending acceptance success failed");
1707        let empty = b
1708            .helper
1709            .start_failure(accepted_token, fail_params)
1710            .expect("Start failure failure");
1711        assert_eq!(empty, ());
1712        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
1713        start_fail_check(sender, tok.req_id, fail_data_raw);
1714    }
1715
1716    fn step_success_check(sender: &mut TestSender, req_id: RequestId) {
1717        let mut cmp_info = TmInfo {
1718            common: CommonTmInfo {
1719                subservice: 1,
1720                apid: TEST_APID,
1721                msg_counter: 0,
1722                dest_id: 0,
1723                time_stamp: EMPTY_STAMP,
1724            },
1725            additional_data: None,
1726            req_id,
1727        };
1728        let mut srv_queue = sender.service_queue.borrow_mut();
1729        let mut info = srv_queue.pop_front().unwrap();
1730        assert_eq!(info, cmp_info);
1731        cmp_info = TmInfo {
1732            common: CommonTmInfo {
1733                subservice: 3,
1734                apid: TEST_APID,
1735                msg_counter: 0,
1736                dest_id: 0,
1737                time_stamp: [0, 1, 0, 1, 0, 1, 0],
1738            },
1739            additional_data: None,
1740            req_id,
1741        };
1742        info = srv_queue.pop_front().unwrap();
1743        assert_eq!(info, cmp_info);
1744        cmp_info = TmInfo {
1745            common: CommonTmInfo {
1746                subservice: 5,
1747                apid: TEST_APID,
1748                msg_counter: 0,
1749                dest_id: 0,
1750                time_stamp: EMPTY_STAMP,
1751            },
1752            additional_data: Some([0].to_vec()),
1753            req_id,
1754        };
1755        info = srv_queue.pop_front().unwrap();
1756        assert_eq!(info, cmp_info);
1757        cmp_info = TmInfo {
1758            common: CommonTmInfo {
1759                subservice: 5,
1760                apid: TEST_APID,
1761                msg_counter: 0,
1762                dest_id: 0,
1763                time_stamp: EMPTY_STAMP,
1764            },
1765            additional_data: Some([1].to_vec()),
1766            req_id,
1767        };
1768        info = srv_queue.pop_front().unwrap();
1769        assert_eq!(info, cmp_info);
1770    }
1771
1772    #[test]
1773    fn test_steps_success() {
1774        let (mut b, tok) = base_init(false);
1775        let mut sender = TestSender::default();
1776        let accepted_token = b
1777            .rep()
1778            .acceptance_success(tok, &sender, Some(&EMPTY_STAMP))
1779            .expect("Sending acceptance success failed");
1780        let started_token = b
1781            .rep()
1782            .start_success(accepted_token, &sender, Some(&[0, 1, 0, 1, 0, 1, 0]))
1783            .expect("Sending start success failed");
1784        b.rep()
1785            .step_success(
1786                &started_token,
1787                &sender,
1788                Some(&EMPTY_STAMP),
1789                EcssEnumU8::new(0),
1790            )
1791            .expect("Sending step 0 success failed");
1792        b.vr.step_success(
1793            &started_token,
1794            &sender,
1795            Some(&EMPTY_STAMP),
1796            EcssEnumU8::new(1),
1797        )
1798        .expect("Sending step 1 success failed");
1799        assert_eq!(sender.service_queue.borrow().len(), 4);
1800        step_success_check(&mut sender, tok.req_id);
1801    }
1802
1803    #[test]
1804    fn test_steps_success_with_helper() {
1805        let (mut b, tok) = base_with_helper_init();
1806        let accepted_token = b
1807            .helper
1808            .acceptance_success(tok, Some(&EMPTY_STAMP))
1809            .expect("Sending acceptance success failed");
1810        let started_token = b
1811            .helper
1812            .start_success(accepted_token, Some(&[0, 1, 0, 1, 0, 1, 0]))
1813            .expect("Sending start success failed");
1814        b.helper
1815            .step_success(&started_token, Some(&EMPTY_STAMP), EcssEnumU8::new(0))
1816            .expect("Sending step 0 success failed");
1817        b.helper
1818            .step_success(&started_token, Some(&EMPTY_STAMP), EcssEnumU8::new(1))
1819            .expect("Sending step 1 success failed");
1820        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
1821        assert_eq!(sender.service_queue.borrow().len(), 4);
1822        step_success_check(sender, tok.req_id);
1823    }
1824
1825    fn check_step_failure(sender: &mut TestSender, req_id: RequestId, fail_data_raw: [u8; 4]) {
1826        assert_eq!(sender.service_queue.borrow().len(), 4);
1827        let mut cmp_info = TmInfo {
1828            common: CommonTmInfo {
1829                subservice: 1,
1830                apid: TEST_APID,
1831                msg_counter: 0,
1832                dest_id: 0,
1833                time_stamp: EMPTY_STAMP,
1834            },
1835            additional_data: None,
1836            req_id,
1837        };
1838        let mut info = sender.service_queue.borrow_mut().pop_front().unwrap();
1839        assert_eq!(info, cmp_info);
1840
1841        cmp_info = TmInfo {
1842            common: CommonTmInfo {
1843                subservice: 3,
1844                apid: TEST_APID,
1845                msg_counter: 0,
1846                dest_id: 0,
1847                time_stamp: [0, 1, 0, 1, 0, 1, 0],
1848            },
1849            additional_data: None,
1850            req_id,
1851        };
1852        info = sender.service_queue.borrow_mut().pop_front().unwrap();
1853        assert_eq!(info, cmp_info);
1854
1855        cmp_info = TmInfo {
1856            common: CommonTmInfo {
1857                subservice: 5,
1858                apid: TEST_APID,
1859                msg_counter: 0,
1860                dest_id: 0,
1861                time_stamp: EMPTY_STAMP,
1862            },
1863            additional_data: Some([0].to_vec()),
1864            req_id,
1865        };
1866        info = sender.service_queue.get_mut().pop_front().unwrap();
1867        assert_eq!(info, cmp_info);
1868
1869        cmp_info = TmInfo {
1870            common: CommonTmInfo {
1871                subservice: 6,
1872                apid: TEST_APID,
1873                msg_counter: 0,
1874                dest_id: 0,
1875                time_stamp: EMPTY_STAMP,
1876            },
1877            additional_data: Some(
1878                [
1879                    [1].as_slice(),
1880                    &[0, 0, 0x10, 0x20],
1881                    fail_data_raw.as_slice(),
1882                ]
1883                .concat()
1884                .to_vec(),
1885            ),
1886            req_id,
1887        };
1888        info = sender.service_queue.get_mut().pop_front().unwrap();
1889        assert_eq!(info, cmp_info);
1890    }
1891
1892    #[test]
1893    fn test_step_failure() {
1894        let (b, tok) = base_init(false);
1895        let mut sender = TestSender::default();
1896        let req_id = tok.req_id;
1897        let fail_code = EcssEnumU32::new(0x1020);
1898        let fail_data: f32 = -22.3232;
1899        let mut fail_data_raw = [0; 4];
1900        fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice());
1901        let fail_step = EcssEnumU8::new(1);
1902        let fail_params = FailParamsWithStep::new(
1903            Some(&EMPTY_STAMP),
1904            &fail_step,
1905            &fail_code,
1906            Some(fail_data_raw.as_slice()),
1907        );
1908
1909        let accepted_token =
1910            b.vr.acceptance_success(tok, &mut sender, Some(&EMPTY_STAMP))
1911                .expect("Sending acceptance success failed");
1912        let started_token =
1913            b.vr.start_success(accepted_token, &mut sender, Some(&[0, 1, 0, 1, 0, 1, 0]))
1914                .expect("Sending start success failed");
1915        let mut empty =
1916            b.vr.step_success(
1917                &started_token,
1918                &mut sender,
1919                Some(&EMPTY_STAMP),
1920                EcssEnumU8::new(0),
1921            )
1922            .expect("Sending completion success failed");
1923        assert_eq!(empty, ());
1924        empty =
1925            b.vr.step_failure(started_token, &mut sender, fail_params)
1926                .expect("Step failure failed");
1927        assert_eq!(empty, ());
1928        check_step_failure(&mut sender, req_id, fail_data_raw);
1929    }
1930
1931    #[test]
1932    fn test_steps_failure_with_helper() {
1933        let (mut b, tok) = base_with_helper_init();
1934        let req_id = tok.req_id;
1935        let fail_code = EcssEnumU32::new(0x1020);
1936        let fail_data: f32 = -22.3232;
1937        let mut fail_data_raw = [0; 4];
1938        fail_data_raw.copy_from_slice(fail_data.to_be_bytes().as_slice());
1939        let fail_step = EcssEnumU8::new(1);
1940        let fail_params = FailParamsWithStep::new(
1941            Some(&EMPTY_STAMP),
1942            &fail_step,
1943            &fail_code,
1944            Some(fail_data_raw.as_slice()),
1945        );
1946
1947        let accepted_token = b
1948            .helper
1949            .acceptance_success(tok, Some(&EMPTY_STAMP))
1950            .expect("Sending acceptance success failed");
1951        let started_token = b
1952            .helper
1953            .start_success(accepted_token, Some(&[0, 1, 0, 1, 0, 1, 0]))
1954            .expect("Sending start success failed");
1955        let mut empty = b
1956            .helper
1957            .step_success(&started_token, Some(&EMPTY_STAMP), EcssEnumU8::new(0))
1958            .expect("Sending completion success failed");
1959        assert_eq!(empty, ());
1960        empty = b
1961            .helper
1962            .step_failure(started_token, fail_params)
1963            .expect("Step failure failed");
1964        assert_eq!(empty, ());
1965        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
1966        check_step_failure(sender, req_id, fail_data_raw);
1967    }
1968
1969    fn completion_fail_check(sender: &mut TestSender, req_id: RequestId) {
1970        assert_eq!(sender.service_queue.borrow().len(), 3);
1971
1972        let mut cmp_info = TmInfo {
1973            common: CommonTmInfo {
1974                subservice: 1,
1975                apid: TEST_APID,
1976                msg_counter: 0,
1977                dest_id: 0,
1978                time_stamp: EMPTY_STAMP,
1979            },
1980            additional_data: None,
1981            req_id,
1982        };
1983        let mut info = sender.service_queue.get_mut().pop_front().unwrap();
1984        assert_eq!(info, cmp_info);
1985
1986        cmp_info = TmInfo {
1987            common: CommonTmInfo {
1988                subservice: 3,
1989                apid: TEST_APID,
1990                msg_counter: 0,
1991                dest_id: 0,
1992                time_stamp: [0, 1, 0, 1, 0, 1, 0],
1993            },
1994            additional_data: None,
1995            req_id,
1996        };
1997        info = sender.service_queue.get_mut().pop_front().unwrap();
1998        assert_eq!(info, cmp_info);
1999
2000        cmp_info = TmInfo {
2001            common: CommonTmInfo {
2002                subservice: 8,
2003                apid: TEST_APID,
2004                msg_counter: 0,
2005                dest_id: 0,
2006                time_stamp: EMPTY_STAMP,
2007            },
2008            additional_data: Some([0, 0, 0x10, 0x20].to_vec()),
2009            req_id,
2010        };
2011        info = sender.service_queue.get_mut().pop_front().unwrap();
2012        assert_eq!(info, cmp_info);
2013    }
2014
2015    #[test]
2016    fn test_completion_failure() {
2017        let (b, tok) = base_init(false);
2018        let mut sender = TestSender::default();
2019        let req_id = tok.req_id;
2020        let fail_code = EcssEnumU32::new(0x1020);
2021        let fail_params = FailParams::new(Some(&EMPTY_STAMP), &fail_code, None);
2022
2023        let accepted_token =
2024            b.vr.acceptance_success(tok, &mut sender, Some(&EMPTY_STAMP))
2025                .expect("Sending acceptance success failed");
2026        let started_token =
2027            b.vr.start_success(accepted_token, &mut sender, Some(&[0, 1, 0, 1, 0, 1, 0]))
2028                .expect("Sending start success failed");
2029        let empty =
2030            b.vr.completion_failure(started_token, &mut sender, fail_params)
2031                .expect("Completion failure");
2032        assert_eq!(empty, ());
2033        completion_fail_check(&mut sender, req_id);
2034    }
2035
2036    #[test]
2037    fn test_completion_failure_with_helper() {
2038        let (mut b, tok) = base_with_helper_init();
2039        let req_id = tok.req_id;
2040        let fail_code = EcssEnumU32::new(0x1020);
2041        let fail_params = FailParams::new(Some(&EMPTY_STAMP), &fail_code, None);
2042
2043        let accepted_token = b
2044            .helper
2045            .acceptance_success(tok, Some(&EMPTY_STAMP))
2046            .expect("Sending acceptance success failed");
2047        let started_token = b
2048            .helper
2049            .start_success(accepted_token, Some(&[0, 1, 0, 1, 0, 1, 0]))
2050            .expect("Sending start success failed");
2051        let empty = b
2052            .helper
2053            .completion_failure(started_token, fail_params)
2054            .expect("Completion failure");
2055        assert_eq!(empty, ());
2056        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
2057        completion_fail_check(sender, req_id);
2058    }
2059
2060    fn completion_success_check(sender: &mut TestSender, req_id: RequestId) {
2061        assert_eq!(sender.service_queue.borrow().len(), 3);
2062        let cmp_info = TmInfo {
2063            common: CommonTmInfo {
2064                subservice: 1,
2065                apid: TEST_APID,
2066                msg_counter: 0,
2067                dest_id: 0,
2068                time_stamp: EMPTY_STAMP,
2069            },
2070            additional_data: None,
2071            req_id,
2072        };
2073        let mut info = sender.service_queue.borrow_mut().pop_front().unwrap();
2074        assert_eq!(info, cmp_info);
2075
2076        let cmp_info = TmInfo {
2077            common: CommonTmInfo {
2078                subservice: 3,
2079                apid: TEST_APID,
2080                msg_counter: 0,
2081                dest_id: 0,
2082                time_stamp: [0, 1, 0, 1, 0, 1, 0],
2083            },
2084            additional_data: None,
2085            req_id,
2086        };
2087        info = sender.service_queue.borrow_mut().pop_front().unwrap();
2088        assert_eq!(info, cmp_info);
2089        let cmp_info = TmInfo {
2090            common: CommonTmInfo {
2091                subservice: 7,
2092                apid: TEST_APID,
2093                msg_counter: 0,
2094                dest_id: 0,
2095                time_stamp: EMPTY_STAMP,
2096            },
2097            additional_data: None,
2098            req_id,
2099        };
2100        info = sender.service_queue.borrow_mut().pop_front().unwrap();
2101        assert_eq!(info, cmp_info);
2102    }
2103
2104    #[test]
2105    fn test_complete_success_sequence() {
2106        let (b, tok) = base_init(false);
2107        let mut sender = TestSender::default();
2108        let accepted_token =
2109            b.vr.acceptance_success(tok, &mut sender, Some(&EMPTY_STAMP))
2110                .expect("Sending acceptance success failed");
2111        let started_token =
2112            b.vr.start_success(accepted_token, &mut sender, Some(&[0, 1, 0, 1, 0, 1, 0]))
2113                .expect("Sending start success failed");
2114        b.vr.completion_success(started_token, &mut sender, Some(&EMPTY_STAMP))
2115            .expect("Sending completion success failed");
2116        completion_success_check(&mut sender, tok.req_id);
2117    }
2118
2119    #[test]
2120    fn test_complete_success_sequence_with_helper() {
2121        let (mut b, tok) = base_with_helper_init();
2122        let accepted_token = b
2123            .helper
2124            .acceptance_success(tok, Some(&EMPTY_STAMP))
2125            .expect("Sending acceptance success failed");
2126        let started_token = b
2127            .helper
2128            .start_success(accepted_token, Some(&[0, 1, 0, 1, 0, 1, 0]))
2129            .expect("Sending start success failed");
2130        b.helper
2131            .completion_success(started_token, Some(&EMPTY_STAMP))
2132            .expect("Sending completion success failed");
2133        let sender: &mut TestSender = b.helper.sender.downcast_mut().unwrap();
2134        completion_success_check(sender, tok.req_id);
2135    }
2136
2137    #[test]
2138    fn test_seq_count_increment() {
2139        let pool_cfg =
2140            StaticPoolConfig::new(vec![(10, 32), (10, 64), (10, 128), (10, 1024)], false);
2141        let tm_pool = StaticMemoryPool::new(pool_cfg.clone());
2142        let shared_tm_store = SharedTmPool::new(tm_pool);
2143        let shared_tm_pool = shared_tm_store.clone_backing_pool();
2144        let (verif_tx, verif_rx) = mpsc::channel();
2145        let sender =
2146            MpscTmInSharedPoolSender::new(0, "Verification Sender", shared_tm_store, verif_tx);
2147        let cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
2148        let mut reporter = VerificationReporterWithSender::new(&cfg, Box::new(sender));
2149
2150        let mut sph = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
2151        let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
2152        let pus_tc_0 = PusTcCreator::new_no_app_data(&mut sph, tc_header, true);
2153        let init_token = reporter.add_tc(&pus_tc_0);
2154
2155        // Complete success sequence for a telecommand
2156        let accepted_token = reporter
2157            .acceptance_success(init_token, Some(&EMPTY_STAMP))
2158            .unwrap();
2159        let started_token = reporter
2160            .start_success(accepted_token, Some(&EMPTY_STAMP))
2161            .unwrap();
2162        reporter
2163            .completion_success(started_token, Some(&EMPTY_STAMP))
2164            .unwrap();
2165
2166        // Verify it arrives correctly on receiver end
2167        let mut tm_buf: [u8; 1024] = [0; 1024];
2168        let mut packet_idx = 0;
2169        while packet_idx < 3 {
2170            let addr = verif_rx.recv_timeout(Duration::from_millis(10)).unwrap();
2171            let tm_len;
2172            {
2173                let mut rg = shared_tm_pool.write().expect("Error locking shared pool");
2174                let store_guard = rg.read_with_guard(addr);
2175                tm_len = store_guard
2176                    .read(&mut tm_buf)
2177                    .expect("Error reading TM slice");
2178            }
2179            let (pus_tm, _) =
2180                PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
2181            if packet_idx == 0 {
2182                assert_eq!(pus_tm.subservice(), 1);
2183                assert_eq!(pus_tm.sp_header.seq_count(), 0);
2184            } else if packet_idx == 1 {
2185                assert_eq!(pus_tm.subservice(), 3);
2186                assert_eq!(pus_tm.sp_header.seq_count(), 0);
2187            } else if packet_idx == 2 {
2188                assert_eq!(pus_tm.subservice(), 7);
2189                assert_eq!(pus_tm.sp_header.seq_count(), 0);
2190            }
2191            packet_idx += 1;
2192        }
2193    }
2194}