1use spacepackets::{CcsdsPacket, SpHeader};
2
3use crate::{tmtc::PacketSenderRaw, ComponentId};
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq)]
6pub enum SpValidity {
7 Valid,
8 Skip,
11 Invalid,
17}
18
19pub trait SpacePacketValidator {
21 fn validate(&self, sp_header: &SpHeader, raw_buf: &[u8]) -> SpValidity;
22}
23
24#[derive(Default, Debug, PartialEq, Eq)]
25pub struct ParseResult {
26 pub packets_found: u32,
27 pub incomplete_tail_start: Option<usize>,
29}
30
31pub fn parse_buffer_for_ccsds_space_packets<SendError>(
51 buf: &[u8],
52 packet_validator: &(impl SpacePacketValidator + ?Sized),
53 sender_id: ComponentId,
54 packet_sender: &(impl PacketSenderRaw<Error = SendError> + ?Sized),
55) -> Result<ParseResult, SendError> {
56 let mut parse_result = ParseResult::default();
57 let mut current_idx = 0;
58 let buf_len = buf.len();
59 loop {
60 if current_idx + 7 > buf.len() {
61 break;
62 }
63 let sp_header = SpHeader::from_be_bytes(&buf[current_idx..]).unwrap().0;
64 match packet_validator.validate(&sp_header, &buf[current_idx..]) {
65 SpValidity::Valid => {
66 let packet_size = sp_header.total_len();
67 if (current_idx + packet_size) <= buf_len {
68 packet_sender
69 .send_packet(sender_id, &buf[current_idx..current_idx + packet_size])?;
70 parse_result.packets_found += 1;
71 } else {
72 parse_result.incomplete_tail_start = Some(current_idx);
74 }
75 current_idx += packet_size;
76 continue;
77 }
78 SpValidity::Skip => {
79 current_idx += sp_header.total_len();
80 }
81 SpValidity::Invalid => {
83 current_idx += 1;
84 }
85 }
86 }
87 Ok(parse_result)
88}
89
90#[cfg(test)]
91mod tests {
92 use spacepackets::{
93 ecss::{tc::PusTcCreator, WritablePusPacket},
94 CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, SpHeader,
95 };
96
97 use crate::{encoding::tests::TcCacher, ComponentId};
98
99 use super::{parse_buffer_for_ccsds_space_packets, SpValidity, SpacePacketValidator};
100
101 const PARSER_ID: ComponentId = 0x05;
102 const TEST_APID_0: u16 = 0x02;
103 const TEST_APID_1: u16 = 0x10;
104 const TEST_PACKET_ID_0: PacketId = PacketId::new_for_tc(true, TEST_APID_0);
105 const TEST_PACKET_ID_1: PacketId = PacketId::new_for_tc(true, TEST_APID_1);
106
107 #[derive(Default)]
108 struct SimpleVerificator {
109 pub enable_second_id: bool,
110 }
111
112 impl SimpleVerificator {
113 pub fn new_with_second_id() -> Self {
114 Self {
115 enable_second_id: true,
116 }
117 }
118 }
119
120 impl SpacePacketValidator for SimpleVerificator {
121 fn validate(&self, sp_header: &SpHeader, _raw_buf: &[u8]) -> super::SpValidity {
122 if sp_header.packet_id() == TEST_PACKET_ID_0
123 || (self.enable_second_id && sp_header.packet_id() == TEST_PACKET_ID_1)
124 {
125 return SpValidity::Valid;
126 }
127 SpValidity::Skip
128 }
129 }
130
131 #[test]
132 fn test_basic() {
133 let sph = SpHeader::new_from_apid(TEST_APID_0);
134 let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
135 let mut buffer: [u8; 32] = [0; 32];
136 let packet_len = ping_tc
137 .write_to_bytes(&mut buffer)
138 .expect("writing packet failed");
139 let tc_cacher = TcCacher::default();
140 let parse_result = parse_buffer_for_ccsds_space_packets(
141 &buffer,
142 &SimpleVerificator::default(),
143 PARSER_ID,
144 &tc_cacher,
145 );
146 assert!(parse_result.is_ok());
147 let parse_result = parse_result.unwrap();
148 assert_eq!(parse_result.packets_found, 1);
149 let mut queue = tc_cacher.tc_queue.borrow_mut();
150 assert_eq!(queue.len(), 1);
151 let packet_with_sender = queue.pop_front().unwrap();
152 assert_eq!(packet_with_sender.packet, buffer[..packet_len]);
153 assert_eq!(packet_with_sender.sender_id, PARSER_ID);
154 }
155
156 #[test]
157 fn test_multi_packet() {
158 let sph = SpHeader::new_from_apid(TEST_APID_0);
159 let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
160 let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], true);
161 let mut buffer: [u8; 32] = [0; 32];
162 let packet_len_ping = ping_tc
163 .write_to_bytes(&mut buffer)
164 .expect("writing packet failed");
165 let packet_len_action = action_tc
166 .write_to_bytes(&mut buffer[packet_len_ping..])
167 .expect("writing packet failed");
168 let tc_cacher = TcCacher::default();
169 let parse_result = parse_buffer_for_ccsds_space_packets(
170 &buffer,
171 &SimpleVerificator::default(),
172 PARSER_ID,
173 &tc_cacher,
174 );
175 assert!(parse_result.is_ok());
176 let parse_result = parse_result.unwrap();
177 assert_eq!(parse_result.packets_found, 2);
178 let mut queue = tc_cacher.tc_queue.borrow_mut();
179 assert_eq!(queue.len(), 2);
180 let packet_with_addr = queue.pop_front().unwrap();
181 assert_eq!(packet_with_addr.packet, buffer[..packet_len_ping]);
182 assert_eq!(packet_with_addr.sender_id, PARSER_ID);
183 let packet_with_addr = queue.pop_front().unwrap();
184 assert_eq!(packet_with_addr.sender_id, PARSER_ID);
185 assert_eq!(
186 packet_with_addr.packet,
187 buffer[packet_len_ping..packet_len_ping + packet_len_action]
188 );
189 }
190
191 #[test]
192 fn test_multi_apid() {
193 let sph = SpHeader::new_from_apid(TEST_APID_0);
194 let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true);
195 let sph = SpHeader::new_from_apid(TEST_APID_1);
196 let action_tc = PusTcCreator::new_simple(sph, 8, 0, &[], true);
197 let mut buffer: [u8; 32] = [0; 32];
198 let packet_len_ping = ping_tc
199 .write_to_bytes(&mut buffer)
200 .expect("writing packet failed");
201 let packet_len_action = action_tc
202 .write_to_bytes(&mut buffer[packet_len_ping..])
203 .expect("writing packet failed");
204 let tc_cacher = TcCacher::default();
205 let verificator = SimpleVerificator::new_with_second_id();
206 let parse_result =
207 parse_buffer_for_ccsds_space_packets(&buffer, &verificator, PARSER_ID, &tc_cacher);
208 assert!(parse_result.is_ok());
209 let parse_result = parse_result.unwrap();
210 assert_eq!(parse_result.packets_found, 2);
211 let mut queue = tc_cacher.tc_queue.borrow_mut();
212 assert_eq!(queue.len(), 2);
213 let packet_with_addr = queue.pop_front().unwrap();
214 assert_eq!(packet_with_addr.packet, buffer[..packet_len_ping]);
215 let packet_with_addr = queue.pop_front().unwrap();
216 assert_eq!(
217 packet_with_addr.packet,
218 buffer[packet_len_ping..packet_len_ping + packet_len_action]
219 );
220 }
221
222 #[test]
223 fn test_split_packet_multi() {
224 let ping_tc =
225 PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
226 let action_tc =
227 PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_1), 8, 0, &[], true);
228 let mut buffer: [u8; 32] = [0; 32];
229 let packet_len_ping = ping_tc
230 .write_to_bytes(&mut buffer)
231 .expect("writing packet failed");
232 let packet_len_action = action_tc
233 .write_to_bytes(&mut buffer[packet_len_ping..])
234 .expect("writing packet failed");
235 let tc_cacher = TcCacher::default();
236 let verificator = SimpleVerificator::new_with_second_id();
237 let parse_result = parse_buffer_for_ccsds_space_packets(
238 &buffer[..packet_len_ping + packet_len_action - 4],
239 &verificator,
240 PARSER_ID,
241 &tc_cacher,
242 );
243 assert!(parse_result.is_ok());
244 let parse_result = parse_result.unwrap();
245 assert_eq!(parse_result.packets_found, 1);
246 assert!(parse_result.incomplete_tail_start.is_some());
247 let incomplete_tail_idx = parse_result.incomplete_tail_start.unwrap();
248 assert_eq!(incomplete_tail_idx, packet_len_ping);
249
250 let queue = tc_cacher.tc_queue.borrow();
251 assert_eq!(queue.len(), 1);
252 }
255
256 #[test]
257 fn test_one_split_packet() {
258 let ping_tc =
259 PusTcCreator::new_simple(SpHeader::new_from_apid(TEST_APID_0), 17, 1, &[], true);
260 let mut buffer: [u8; 32] = [0; 32];
261 let packet_len_ping = ping_tc
262 .write_to_bytes(&mut buffer)
263 .expect("writing packet failed");
264 let tc_cacher = TcCacher::default();
265
266 let verificator = SimpleVerificator::new_with_second_id();
267 let parse_result = parse_buffer_for_ccsds_space_packets(
268 &buffer[..packet_len_ping - 4],
269 &verificator,
270 PARSER_ID,
271 &tc_cacher,
272 );
273 assert!(parse_result.is_ok());
274 let parse_result = parse_result.unwrap();
275 assert_eq!(parse_result.packets_found, 0);
276 let queue = tc_cacher.tc_queue.borrow();
277 assert_eq!(queue.len(), 0);
278 }
279
280 #[test]
281 fn test_smallest_packet() {
282 let ccsds_header_only = SpHeader::new(
283 PacketId::new(PacketType::Tc, true, TEST_APID_0),
284 PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 0),
285 0,
286 );
287 let mut buf: [u8; 7] = [0; 7];
288 ccsds_header_only
289 .write_to_be_bytes(&mut buf)
290 .expect("writing failed");
291 let verificator = SimpleVerificator::default();
292 let tc_cacher = TcCacher::default();
293 let parse_result =
294 parse_buffer_for_ccsds_space_packets(&buf, &verificator, PARSER_ID, &tc_cacher);
295 assert!(parse_result.is_ok());
296 let parse_result = parse_result.unwrap();
297 assert_eq!(parse_result.packets_found, 1);
298 }
299}