Skip to main content

leodos_protocols/transport/cfdp/pdu/file_directive/nak/
mod.rs

1use core::slice::Iter;
2
3use crate::transport::cfdp::pdu::file_directive::nak::large::NakSegmentLarge;
4use crate::transport::cfdp::pdu::file_directive::nak::small::NakSegmentSmall;
5use crate::transport::cfdp::CfdpError;
6
7/// NAK PDU for large file transactions (64-bit offsets).
8pub mod large;
9/// NAK PDU for small file transactions (32-bit offsets).
10pub mod small;
11
12/// The maximum number of missing segment requests that can be included in a single NAK PDU.
13pub const MAX_NAK_SEGMENTS: usize = 32;
14
15/// A parsed NAK PDU, dispatching between small and large file variants.
16#[derive(Debug)]
17pub enum NakPdu<'a> {
18    /// NAK PDU for small file transactions (32-bit offsets).
19    Small(&'a small::NakPduSmall),
20    /// NAK PDU for large file transactions (64-bit offsets).
21    Large(&'a large::NakPduLarge),
22}
23
24/// A size-independent representation of a single NAK segment request.
25#[derive(Debug, Copy, Clone, PartialEq, Eq)]
26pub struct NakSegmentRequest {
27    /// Start offset of the missing data segment.
28    start_offset: u64,
29    /// End offset of the missing data segment.
30    end_offset: u64,
31}
32
33impl NakSegmentRequest {
34    /// Get the start_offset of the missing segment.
35    pub fn start_offset(&self) -> u64 {
36        self.start_offset
37    }
38
39    /// Get the end_offset of the missing segment.
40    pub fn end_offset(&self) -> u64 {
41        self.end_offset
42    }
43}
44
45impl<'a> NakPdu<'a> {
46    /// Get the start_of_scope field as a u64.
47    pub fn start_of_scope(&self) -> u64 {
48        match self {
49            NakPdu::Small(pdu) => pdu.start_of_scope() as u64,
50            NakPdu::Large(pdu) => pdu.start_of_scope(),
51        }
52    }
53
54    /// Get the end_of_scope field as a u64.
55    pub fn end_of_scope(&self) -> u64 {
56        match self {
57            NakPdu::Small(pdu) => pdu.end_of_scope() as u64,
58            NakPdu::Large(pdu) => pdu.end_of_scope(),
59        }
60    }
61
62    /// Get the segment requests as a vector of NakSegmentRequest.
63    pub fn segment_requests(&self) -> Result<NakSegmentsIterator<'a>, CfdpError> {
64        match self {
65            NakPdu::Small(pdu) => {
66                let segments = pdu.segment_requests()?;
67                Ok(NakSegmentsIterator::Small(segments.iter()))
68            }
69            NakPdu::Large(pdu) => {
70                let segments = pdu.segment_requests()?;
71                Ok(NakSegmentsIterator::Large(segments.iter()))
72            }
73        }
74    }
75
76    /// Returns the raw trailing bytes after the scope fields.
77    pub fn rest(&self) -> &[u8] {
78        match self {
79            NakPdu::Small(pdu) => pdu.rest(),
80            NakPdu::Large(pdu) => pdu.rest(),
81        }
82    }
83}
84
85/// An iterator over NAK segment requests, abstracting small and large variants.
86#[derive(Debug)]
87pub enum NakSegmentsIterator<'a> {
88    /// Iterator over 32-bit NAK segments.
89    Small(Iter<'a, NakSegmentSmall>),
90    /// Iterator over 64-bit NAK segments.
91    Large(Iter<'a, NakSegmentLarge>),
92}
93
94impl<'a> Iterator for NakSegmentsIterator<'a> {
95    type Item = NakSegmentRequest;
96
97    fn next(&mut self) -> Option<Self::Item> {
98        match self {
99            NakSegmentsIterator::Small(iter) => iter.next().map(|seg| NakSegmentRequest {
100                start_offset: seg.start_offset() as u64,
101                end_offset: seg.end_offset() as u64,
102            }),
103            NakSegmentsIterator::Large(iter) => iter.next().map(|seg| NakSegmentRequest {
104                start_offset: seg.start_offset(),
105                end_offset: seg.end_offset(),
106            }),
107        }
108    }
109}
110