leodos_protocols/datalink/framing/sdlp/
aos.rs1use bon::bon;
10use zerocopy::FromBytes;
11use zerocopy::Immutable;
12use zerocopy::IntoBytes;
13use zerocopy::KnownLayout;
14use zerocopy::Unaligned;
15use zerocopy::byteorder::network_endian::U16;
16
17use crate::coding::randomizer::Randomizer;
18use crate::utils::get_bits_u8;
19use crate::utils::get_bits_u16;
20use crate::utils::set_bits_u8;
21use crate::utils::set_bits_u16;
22
23#[repr(C, packed)]
47#[derive(IntoBytes, FromBytes, Unaligned, KnownLayout, Immutable)]
48pub struct AosTransferFrame {
49 pub header: AosPrimaryHeader,
51 pub data_field: [u8],
53}
54
55#[repr(C)]
57#[derive(FromBytes, IntoBytes, KnownLayout, Unaligned, Immutable, Debug, Copy, Clone)]
58pub struct AosPrimaryHeader {
59 version_scid_vcid_field: U16,
60 vc_frame_count: [u8; 3],
61 replay_usage_spare_field: u8,
62}
63
64#[derive(Debug, Copy, Clone, Eq, PartialEq)]
66pub enum BuildError {
67 InvalidScid(Scid),
69 InvalidVcid(Vcid),
71 BufferTooSmall {
73 required: usize,
75 provided: usize,
77 },
78}
79
80#[derive(Debug, Copy, Clone, Eq, PartialEq)]
82pub enum ParseError {
83 TooShortForHeader,
85 InvalidVersion(u8),
87}
88
89#[rustfmt::skip]
91pub mod bitmasks {
92 pub const VERSION_MASK: u16 = 0b_11000000_00000000;
94 pub const SCID_MASK: u16 = 0b_00111111_11000000;
96 pub const VCID_MASK: u16 = 0b_00000000_00111111;
98
99 pub const REPLAY_FLAG_MASK: u8 = 0b_10000000;
101 pub const USAGE_FLAG_MASK: u8 = 0b_01000000;
103 pub const _SPARE_MASK: u8 = 0b_00111111;
105}
106
107use bitmasks::*;
108use crate::ids::{Scid, Vcid};
109
110#[bon]
111impl AosTransferFrame {
112 pub const AOS_VERSION: u8 = 0b01;
114
115 pub fn parse<'a>(
119 bytes: &[u8],
120 output_buffer: &'a mut [u8],
121 randomizer: Option<&impl Randomizer>,
122 ) -> Result<&'a AosTransferFrame, ParseError> {
123 if bytes.len() < size_of::<AosPrimaryHeader>() {
124 return Err(ParseError::TooShortForHeader);
125 }
126 if output_buffer.len() < bytes.len() {
127 return Err(ParseError::TooShortForHeader);
129 }
130
131 let frame_buf = &mut output_buffer[..bytes.len()];
133 frame_buf.copy_from_slice(bytes);
134
135 if let Some(r) = randomizer {
137 r.apply(frame_buf);
138 }
139
140 let frame = AosTransferFrame::ref_from_bytes(frame_buf)
142 .map_err(|_| ParseError::TooShortForHeader)?;
143
144 if frame.header.version() != Self::AOS_VERSION {
146 return Err(ParseError::InvalidVersion(frame.header.version()));
147 }
148
149 Ok(frame)
150 }
151
152 #[builder]
154 pub fn new<'a>(
155 buffer: &'a mut [u8],
156 scid: Scid,
157 vcid: Vcid,
158 vc_frame_count: u32,
159 replay_flag: bool,
160 usage_flag: bool,
161 payload: &'a [u8],
162 ) -> Result<&'a mut Self, BuildError> {
163 let total_len = size_of::<AosPrimaryHeader>() + payload.len();
164 if buffer.len() < total_len {
165 return Err(BuildError::BufferTooSmall {
166 required: total_len,
167 provided: buffer.len(),
168 });
169 }
170 if vcid.num_bits() > 6 {
171 return Err(BuildError::InvalidVcid(vcid));
172 }
173
174 let frame = AosTransferFrame::mut_from_bytes(&mut buffer[..total_len]).unwrap();
175
176 frame.header.set_version(Self::AOS_VERSION);
177 frame.header.set_scid(scid);
178 frame.header.set_vcid(vcid);
179 frame.header.set_vc_frame_count(vc_frame_count);
180 frame.header.set_replay(replay_flag);
181 frame.header.set_usage_flag(usage_flag);
182 frame.data_field.copy_from_slice(payload);
183
184 Ok(frame)
185 }
186
187 pub fn header(&self) -> &AosPrimaryHeader {
189 &self.header
190 }
191
192 pub fn data(&self) -> &[u8] {
194 &self.data_field
195 }
196}
197
198impl AosPrimaryHeader {
199 pub fn version(&self) -> u8 {
201 get_bits_u16(self.version_scid_vcid_field, VERSION_MASK) as u8
202 }
203 pub fn set_version(&mut self, version: u8) {
205 set_bits_u16(
206 &mut self.version_scid_vcid_field,
207 VERSION_MASK,
208 version as u16,
209 );
210 }
211
212 pub fn scid(&self) -> Scid {
214 Scid::new(get_bits_u16(self.version_scid_vcid_field, SCID_MASK) as u32)
215 }
216 pub fn set_scid(&mut self, scid: Scid) {
218 set_bits_u16(&mut self.version_scid_vcid_field, SCID_MASK, scid.get() as u16);
219 }
220
221 pub fn vcid(&self) -> Vcid {
223 Vcid::new(get_bits_u16(self.version_scid_vcid_field, VCID_MASK) as u32)
224 }
225 pub fn set_vcid(&mut self, vcid: Vcid) {
227 set_bits_u16(&mut self.version_scid_vcid_field, VCID_MASK, vcid.get() as u16);
228 }
229
230 pub fn vc_frame_count(&self) -> u32 {
232 let b = self.vc_frame_count;
233 u32::from_be_bytes([0, b[0], b[1], b[2]])
234 }
235 pub fn set_vc_frame_count(&mut self, count: u32) {
237 let bytes = count.to_be_bytes();
238 self.vc_frame_count.copy_from_slice(&bytes[1..4]);
239 }
240
241 pub fn is_replay(&self) -> bool {
243 get_bits_u8(self.replay_usage_spare_field, REPLAY_FLAG_MASK) != 0
244 }
245 pub fn set_replay(&mut self, replay: bool) {
247 set_bits_u8(
248 &mut self.replay_usage_spare_field,
249 REPLAY_FLAG_MASK,
250 if replay { 1 } else { 0 },
251 );
252 }
253
254 pub fn usage_flag(&self) -> bool {
256 get_bits_u8(self.replay_usage_spare_field, USAGE_FLAG_MASK) != 0
257 }
258 pub fn set_usage_flag(&mut self, usage: bool) {
260 set_bits_u8(
261 &mut self.replay_usage_spare_field,
262 USAGE_FLAG_MASK,
263 if usage { 1 } else { 0 },
264 );
265 }
266}
267
268impl AosTransferFrame {
269 pub const HEADER_SIZE: usize = 6;
271
272 pub fn parse_raw(bytes: &[u8]) -> Result<&AosTransferFrame, ParseError> {
277 if bytes.len() < Self::HEADER_SIZE {
278 return Err(ParseError::TooShortForHeader);
279 }
280 let frame = AosTransferFrame::ref_from_bytes(bytes)
281 .map_err(|_| ParseError::TooShortForHeader)?;
282 if frame.header.version() != Self::AOS_VERSION {
283 return Err(ParseError::InvalidVersion(frame.header.version()));
284 }
285 Ok(frame)
286 }
287}
288
289use super::super::{FrameRead, FrameWrite, PushError};
292
293#[derive(Debug, Clone)]
295pub struct AosFrameWriterConfig {
296 pub scid: Scid,
298 pub vcid: Vcid,
300 pub max_data_field_len: usize,
302}
303
304pub struct AosFrameWriter<const BUF: usize> {
311 config: AosFrameWriterConfig,
312 vc_frame_count: u32,
313 data_len: usize,
314 buf: [u8; BUF],
315}
316
317impl<const BUF: usize> AosFrameWriter<BUF> {
318 pub fn new(config: AosFrameWriterConfig) -> Self {
320 Self {
321 config,
322 vc_frame_count: 0,
323 data_len: 0,
324 buf: [0u8; BUF],
325 }
326 }
327}
328
329impl<const BUF: usize> AosFrameWriter<BUF> {
330 fn remaining(&self) -> usize {
331 self.config
332 .max_data_field_len
333 .saturating_sub(self.data_len)
334 }
335}
336
337impl<const BUF: usize> FrameWrite for AosFrameWriter<BUF> {
338 type Error = BuildError;
339
340 fn is_empty(&self) -> bool {
341 self.data_len == 0
342 }
343
344 fn push(&mut self, data: &[u8]) -> Result<(), PushError> {
345 if data.len() > self.config.max_data_field_len {
346 return Err(PushError::TooLarge);
347 }
348 if data.len() > self.remaining() {
349 return Err(PushError::Full);
350 }
351 let off =
352 AosTransferFrame::HEADER_SIZE + self.data_len;
353 self.buf[off..off + data.len()].copy_from_slice(data);
354 self.data_len += data.len();
355 Ok(())
356 }
357
358 fn finish(&mut self) -> Result<&[u8], BuildError> {
359 let total =
360 AosTransferFrame::HEADER_SIZE + self.data_len;
361 let count = self.vc_frame_count;
362 self.vc_frame_count =
363 self.vc_frame_count.wrapping_add(1) & 0xFF_FFFF;
364
365 let buf_len = self.buf.len();
366 let frame =
367 AosTransferFrame::mut_from_bytes(&mut self.buf[..total])
368 .map_err(|_| BuildError::BufferTooSmall {
369 required: total,
370 provided: buf_len,
371 })?;
372
373 frame.header.set_version(AosTransferFrame::AOS_VERSION);
374 frame.header.set_scid(self.config.scid);
375 frame.header.set_vcid(self.config.vcid);
376 frame.header.set_vc_frame_count(count);
377 frame.header.set_replay(false);
378 frame.header.set_usage_flag(false);
379
380 self.data_len = 0;
381 Ok(&self.buf[..total])
382 }
383}
384
385pub struct AosFrameReader<const BUF: usize> {
393 buf: [u8; BUF],
394 data_start: usize,
395 data_end: usize,
396}
397
398impl<const BUF: usize> AosFrameReader<BUF> {
399 pub fn new() -> Self {
401 Self {
402 buf: [0u8; BUF],
403 data_start: 0,
404 data_end: 0,
405 }
406 }
407}
408
409impl<const BUF: usize> FrameRead for AosFrameReader<BUF> {
410 type Error = ParseError;
411
412 fn buffer_mut(&mut self) -> &mut [u8] {
413 &mut self.buf
414 }
415
416 fn feed(&mut self, len: usize) -> Result<(), ParseError> {
417 let parsed =
418 AosTransferFrame::parse_raw(&self.buf[..len])?;
419 let data = parsed.data();
420 self.data_start = AosTransferFrame::HEADER_SIZE;
421 self.data_end = self.data_start + data.len();
422 Ok(())
423 }
424
425 fn data_field(&self) -> &[u8] {
426 &self.buf[self.data_start..self.data_end]
427 }
428}
429
430#[cfg(test)]
431mod tests {
432 use super::*;
433 use crate::ids::{Scid, Vcid};
434
435 #[test]
436 fn test_aos_builder_and_parser() {
437 let mut buf = [0u8; 1024];
438 let payload = [0xAA, 0xBB, 0xCC];
439
440 let frame = AosTransferFrame::builder()
441 .buffer(&mut buf)
442 .scid(Scid::new(0x12))
443 .vcid(Vcid::new(0x3F)) .vc_frame_count(0x123456)
445 .replay_flag(true)
446 .usage_flag(false)
447 .payload(&payload)
448 .build()
449 .unwrap();
450
451 assert_eq!(frame.header.scid(), Scid::new(0x12));
452 assert_eq!(frame.header.vcid(), Vcid::new(0x3F));
453 assert_eq!(frame.header.vc_frame_count(), 0x123456);
454 assert!(frame.header.is_replay());
455 assert_eq!(frame.data(), &payload);
456 }
457}