Skip to content

Commit cd0b7cd

Browse files
committed
add creator with reserved datafield
1 parent 64d53ea commit cd0b7cd

1 file changed

Lines changed: 242 additions & 0 deletions

File tree

src/uslp/mod.rs

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! # Support of the CCSDS Unified Space Data Link Protocol (USLP)
22
#![deny(missing_docs)]
3+
34
use arbitrary_int::{prelude::*, u4, u6};
45

56
use crate::{crc::CRC_CCITT_FALSE, ByteConversionError};
@@ -577,6 +578,100 @@ impl<'data> TransferFrameCreator<'data> {
577578
}
578579
}
579580

581+
/// USLP transfer frame creator which can reduce copy operations.
582+
///
583+
/// This structure provides direct mutable access to the data zone. This avoids the need for an
584+
/// additional slice which would be required to hold the transfer data. Instead, user data can be
585+
/// copied into the frame field directly. The full length of the user data needs to be known
586+
/// beforehand.
587+
pub struct TransferFrameCreatorWithReservedData<'data> {
588+
buf: &'data mut [u8],
589+
len_written: usize,
590+
data_index: usize,
591+
data_size: usize,
592+
has_fecf: bool,
593+
}
594+
595+
impl<'data> TransferFrameCreatorWithReservedData<'data> {
596+
/// Constructor.
597+
///
598+
/// If the operational control field is present, the OCF flag in the primary header will
599+
/// be set accordingly. The frame length field of the [PrimaryHeader] is also updated according
600+
/// to the provided arguments.
601+
pub fn new(
602+
buf: &'data mut [u8],
603+
mut primary_header: PrimaryHeader,
604+
data_field_header: TransferFrameDataFieldHeader,
605+
data_size: usize,
606+
op_control_field: Option<u32>,
607+
has_fecf: bool,
608+
) -> Result<TransferFrameCreatorWithReservedData<'data>, ByteConversionError> {
609+
let len_written = primary_header.len_header()
610+
+ data_field_header.len_header()
611+
+ data_size
612+
+ if op_control_field.is_some() { 4 } else { 0 }
613+
+ if has_fecf { 2 } else { 0 };
614+
primary_header.set_frame_len(len_written);
615+
if op_control_field.is_some() {
616+
primary_header.ocf_flag = true;
617+
}
618+
if len_written > buf.len() {
619+
return Err(ByteConversionError::ToSliceTooSmall {
620+
found: buf.len(),
621+
expected: len_written,
622+
});
623+
}
624+
let mut current_index = 0;
625+
current_index += primary_header.write_to_bytes(buf)?;
626+
627+
current_index +=
628+
data_field_header.write_to_bytes(&mut buf[primary_header.len_header()..])?;
629+
let data_index = current_index;
630+
//buf[current_index..current_index + self.data.len()].copy_from_slice(self.data);
631+
current_index += data_size;
632+
633+
if let Some(ocf) = op_control_field {
634+
buf[current_index..current_index + 4].copy_from_slice(&ocf.to_be_bytes());
635+
}
636+
Ok(Self {
637+
buf,
638+
data_size,
639+
data_index,
640+
len_written,
641+
has_fecf,
642+
})
643+
}
644+
645+
/// Length of the frame when written to bytes.
646+
pub fn len_written(&self) -> usize {
647+
self.len_written
648+
}
649+
650+
/// Mutable accesss to user data buffer.
651+
pub fn data_mut(&mut self) -> &mut [u8] {
652+
&mut self.buf[self.data_index..self.data_index + self.data_size]
653+
}
654+
655+
/// Shared accesss to user data buffer.
656+
pub fn data(&self) -> &[u8] {
657+
&self.buf[self.data_index..self.data_index + self.data_size]
658+
}
659+
660+
/// Write [self] to the provided byte buffer.
661+
///
662+
/// Calculates and writes the checksum if the `has_fecf` field is set.
663+
/// Returns the frame size.
664+
pub fn finish(self) -> usize {
665+
if self.has_fecf {
666+
let mut digest = CRC_CCITT_FALSE.digest();
667+
digest.update(&self.buf[0..self.len_written - 2]);
668+
let crc = digest.finalize();
669+
self.buf[self.len_written - 2..self.len_written].copy_from_slice(&crc.to_be_bytes());
670+
}
671+
self.len_written
672+
}
673+
}
674+
580675
/// Simple USLP transfer frame reader.
581676
///
582677
/// Currently, only insert zone lengths of 0 are supported.
@@ -1199,6 +1294,38 @@ mod tests {
11991294
assert_eq!(reader.len_frame(), 14);
12001295
}
12011296

1297+
#[test]
1298+
fn test_frame_creator_no_fecf() {
1299+
let mut primary_header = PrimaryHeader::new(
1300+
0x1234,
1301+
SourceOrDestField::Source,
1302+
u6::new(0b101010),
1303+
u4::new(0b0101),
1304+
0,
1305+
)
1306+
.unwrap();
1307+
let data_field_header = TransferFrameDataFieldHeader {
1308+
construction_rule: ConstructionRule::NoSegmentation,
1309+
uslp_protocol_id: UslpProtocolId::UserDefinedOctetStream,
1310+
fhp_or_lvo: None,
1311+
};
1312+
let data = [1, 2, 3, 4];
1313+
let frame_creator =
1314+
TransferFrameCreator::new(primary_header, data_field_header, &data, None, false);
1315+
let mut buf: [u8; 64] = [0; 64];
1316+
assert_eq!(frame_creator.len_written(), 12);
1317+
let written = frame_creator.write_to_bytes(&mut buf).unwrap();
1318+
assert_eq!(written, 12);
1319+
assert_eq!(written, frame_creator.len_written());
1320+
let reader = TransferFrameReader::from_bytes(&buf, false).unwrap();
1321+
primary_header.set_frame_len(written);
1322+
assert_eq!(reader.primary_header(), &primary_header);
1323+
assert_eq!(reader.data_field_header(), &data_field_header);
1324+
assert_eq!(reader.data(), &data);
1325+
assert!(reader.operational_control_field().is_none());
1326+
assert_eq!(reader.len_frame(), 12);
1327+
}
1328+
12021329
#[test]
12031330
fn test_frame_creator_using_vec() {
12041331
// Relying on the reader implementation for now.
@@ -1263,4 +1390,119 @@ mod tests {
12631390
assert_eq!(reader.operational_control_field().unwrap(), 4);
12641391
assert_eq!(reader.len_frame(), 18);
12651392
}
1393+
1394+
#[test]
1395+
fn test_creator_with_reserved_data() {
1396+
let mut primary_header = PrimaryHeader::new(
1397+
0x1234,
1398+
SourceOrDestField::Source,
1399+
u6::new(0b101010),
1400+
u4::new(0b0101),
1401+
0,
1402+
)
1403+
.unwrap();
1404+
let data_field_header = TransferFrameDataFieldHeader::new(
1405+
ConstructionRule::NoSegmentation,
1406+
UslpProtocolId::UserDefinedOctetStream,
1407+
None,
1408+
)
1409+
.unwrap();
1410+
let mut buf: [u8; 32] = [0; 32];
1411+
let mut frame_creator = TransferFrameCreatorWithReservedData::new(
1412+
&mut buf,
1413+
primary_header,
1414+
data_field_header,
1415+
4,
1416+
None,
1417+
true,
1418+
)
1419+
.unwrap();
1420+
assert_eq!(frame_creator.data().len(), 4);
1421+
frame_creator.data_mut().copy_from_slice(&[1, 2, 3, 4]);
1422+
let frame_size = frame_creator.finish();
1423+
let reader = TransferFrameReader::from_bytes(&buf[0..frame_size], true).unwrap();
1424+
primary_header.set_frame_len(frame_size);
1425+
assert_eq!(reader.primary_header(), &primary_header);
1426+
assert_eq!(reader.data_field_header(), &data_field_header);
1427+
assert_eq!(reader.data(), &[1, 2, 3, 4]);
1428+
assert!(reader.operational_control_field().is_none());
1429+
assert_eq!(reader.len_frame(), 14);
1430+
}
1431+
1432+
#[test]
1433+
fn test_creator_with_reserved_data_and_ocf_field() {
1434+
let mut primary_header = PrimaryHeader::new(
1435+
0x1234,
1436+
SourceOrDestField::Source,
1437+
u6::new(0b101010),
1438+
u4::new(0b0101),
1439+
0,
1440+
)
1441+
.unwrap();
1442+
let data_field_header = TransferFrameDataFieldHeader::new(
1443+
ConstructionRule::NoSegmentation,
1444+
UslpProtocolId::UserDefinedOctetStream,
1445+
None,
1446+
)
1447+
.unwrap();
1448+
let mut buf: [u8; 32] = [0; 32];
1449+
let mut frame_creator = TransferFrameCreatorWithReservedData::new(
1450+
&mut buf,
1451+
primary_header,
1452+
data_field_header,
1453+
4,
1454+
Some(4),
1455+
true,
1456+
)
1457+
.unwrap();
1458+
assert_eq!(frame_creator.data().len(), 4);
1459+
frame_creator.data_mut().copy_from_slice(&[1, 2, 3, 4]);
1460+
let frame_size = frame_creator.finish();
1461+
let reader = TransferFrameReader::from_bytes(&buf[0..frame_size], true).unwrap();
1462+
primary_header.set_frame_len(frame_size);
1463+
primary_header.ocf_flag = true;
1464+
assert_eq!(reader.primary_header(), &primary_header);
1465+
assert_eq!(reader.data_field_header(), &data_field_header);
1466+
assert_eq!(reader.data(), &[1, 2, 3, 4]);
1467+
assert_eq!(reader.operational_control_field().unwrap(), 4);
1468+
assert_eq!(reader.len_frame(), 18);
1469+
}
1470+
1471+
#[test]
1472+
fn test_creator_no_fecf() {
1473+
let mut primary_header = PrimaryHeader::new(
1474+
0x1234,
1475+
SourceOrDestField::Source,
1476+
u6::new(0b101010),
1477+
u4::new(0b0101),
1478+
0,
1479+
)
1480+
.unwrap();
1481+
let data_field_header = TransferFrameDataFieldHeader::new(
1482+
ConstructionRule::NoSegmentation,
1483+
UslpProtocolId::UserDefinedOctetStream,
1484+
None,
1485+
)
1486+
.unwrap();
1487+
let mut buf: [u8; 32] = [0; 32];
1488+
let mut frame_creator = TransferFrameCreatorWithReservedData::new(
1489+
&mut buf,
1490+
primary_header,
1491+
data_field_header,
1492+
4,
1493+
None,
1494+
false,
1495+
)
1496+
.unwrap();
1497+
assert_eq!(frame_creator.data().len(), 4);
1498+
frame_creator.data_mut().copy_from_slice(&[1, 2, 3, 4]);
1499+
let frame_size = frame_creator.finish();
1500+
let reader = TransferFrameReader::from_bytes(&buf[0..frame_size], false).unwrap();
1501+
primary_header.set_frame_len(frame_size);
1502+
assert_eq!(reader.primary_header(), &primary_header);
1503+
assert_eq!(reader.data_field_header(), &data_field_header);
1504+
assert_eq!(reader.data(), &[1, 2, 3, 4]);
1505+
assert!(reader.operational_control_field().is_none());
1506+
assert_eq!(reader.len_frame(), 12);
1507+
}
12661508
}

0 commit comments

Comments
 (0)