almost completed PDU header impl

This commit is contained in:
Robin Müller 2023-05-18 11:08:46 +02:00
parent 0a3848d0a2
commit 02bae5de6c
Signed by: muellerr
GPG Key ID: A649FB78196E3849

View File

@ -76,7 +76,7 @@ pub struct CommonPduConfig {
pub direction: Direction, pub direction: Direction,
} }
// TODO: Build might be applicable here.. // TODO: Builder pattern might be applicable here..
impl CommonPduConfig { impl CommonPduConfig {
pub fn new( pub fn new(
source_id: impl Into<UnsignedByteField>, source_id: impl Into<UnsignedByteField>,
@ -148,7 +148,7 @@ impl CommonPduConfig {
} }
} }
const MIN_HEADER_LEN: usize = 4; const FIXED_HEADER_LEN: usize = 4;
/// Abstraction for the PDU header common to all CFDP PDUs /// Abstraction for the PDU header common to all CFDP PDUs
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -195,13 +195,13 @@ impl PduHeader {
))); )));
} }
if buf.len() if buf.len()
< MIN_HEADER_LEN < FIXED_HEADER_LEN
+ self.pdu_conf.source_entity_id.len() + self.pdu_conf.source_entity_id.len()
+ self.pdu_conf.transaction_seq_num.len() + self.pdu_conf.transaction_seq_num.len()
{ {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(), found: buf.len(),
expected: MIN_HEADER_LEN, expected: FIXED_HEADER_LEN,
}) })
.into()); .into());
} }
@ -235,12 +235,12 @@ impl PduHeader {
Ok(current_idx) Ok(current_idx)
} }
pub fn from_be_bytes(buf: &[u8]) -> Result<Self, PduError> { pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, usize), PduError> {
if buf.len() < MIN_HEADER_LEN { if buf.len() < FIXED_HEADER_LEN {
return Err(PduError::ByteConversionError( return Err(PduError::ByteConversionError(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
found: buf.len(), found: buf.len(),
expected: MIN_HEADER_LEN, expected: FIXED_HEADER_LEN,
}), }),
)); ));
} }
@ -296,6 +296,7 @@ impl PduHeader {
let dest_id = let dest_id =
UnsignedByteField::new_from_be_bytes(expected_len_entity_ids, &buf[current_idx..]) UnsignedByteField::new_from_be_bytes(expected_len_entity_ids, &buf[current_idx..])
.unwrap(); .unwrap();
current_idx += expected_len_entity_ids;
let common_pdu_conf = CommonPduConfig::new( let common_pdu_conf = CommonPduConfig::new(
source_id, source_id,
dest_id, dest_id,
@ -306,13 +307,16 @@ impl PduHeader {
direction, direction,
) )
.unwrap(); .unwrap();
Ok(PduHeader { Ok((
PduHeader {
pdu_type, pdu_type,
pdu_conf: common_pdu_conf, pdu_conf: common_pdu_conf,
seg_metadata_flag, seg_metadata_flag,
seg_ctrl, seg_ctrl,
pdu_datafield_len, pdu_datafield_len,
}) },
current_idx,
))
} }
pub fn pdu_type(&self) -> PduType { pub fn pdu_type(&self) -> PduType {
self.pdu_type self.pdu_type
@ -332,12 +336,13 @@ impl PduHeader {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::cfdp::pdu::{CommonPduConfig, PduHeader}; use crate::cfdp::pdu::{CommonPduConfig, PduError, PduHeader, FIXED_HEADER_LEN};
use crate::cfdp::{ use crate::cfdp::{
CrcFlag, Direction, LargeFileFlag, PduType, SegmentMetadataFlag, SegmentationControl, CrcFlag, Direction, LargeFileFlag, PduType, SegmentMetadataFlag, SegmentationControl,
TransmissionMode, CFDP_VERSION_2, TransmissionMode, CFDP_VERSION_2,
}; };
use crate::util::{UnsignedU16, UnsignedU8}; use crate::util::{UnsignedU16, UnsignedU8};
use crate::ByteConversionError;
use std::format; use std::format;
#[test] #[test]
@ -360,26 +365,7 @@ mod tests {
pdu_header.seg_ctrl(), pdu_header.seg_ctrl(),
SegmentationControl::NoRecordBoundaryPreservation SegmentationControl::NoRecordBoundaryPreservation
); );
}
#[test]
fn test_state() {
let src_id = UnsignedU8::new(1);
let dest_id = UnsignedU8::new(2);
let transaction_id = UnsignedU8::new(3);
let common_pdu_cfg = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_id)
.expect("common config creation failed");
let pdu_header = PduHeader::new_no_file_data(common_pdu_cfg, 5);
assert_eq!(pdu_header.pdu_type, PduType::FileDirective);
assert_eq!(pdu_header.pdu_datafield_len, 5); assert_eq!(pdu_header.pdu_datafield_len, 5);
assert_eq!(
pdu_header.seg_ctrl,
SegmentationControl::NoRecordBoundaryPreservation
);
assert_eq!(
pdu_header.seg_metadata_flag,
SegmentMetadataFlag::NotPresent
);
} }
#[test] #[test]
@ -421,6 +407,24 @@ mod tests {
assert_eq!(buf[6], 2); assert_eq!(buf[6], 2);
} }
#[test]
fn test_deserialization_1() {
let src_id = UnsignedU8::new(1);
let dest_id = UnsignedU8::new(2);
let transaction_id = UnsignedU8::new(3);
let common_pdu_cfg = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_id)
.expect("common config creation failed");
let pdu_header = PduHeader::new_no_file_data(common_pdu_cfg, 5);
let mut buf: [u8; 7] = [0; 7];
let res = pdu_header.write_to_be_bytes(&mut buf);
assert!(res.is_ok());
let deser_res = PduHeader::from_be_bytes(&buf);
assert!(deser_res.is_ok());
let (header_read_back, read_size) = deser_res.unwrap();
assert_eq!(read_size, 7);
assert_eq!(header_read_back, pdu_header);
}
#[test] #[test]
fn test_serialization_2() { fn test_serialization_2() {
let src_id = UnsignedU16::new(0x0001); let src_id = UnsignedU16::new(0x0001);
@ -471,5 +475,91 @@ mod tests {
} }
#[test] #[test]
fn test_deserialization_1() {} fn test_deserialization_2() {
let src_id = UnsignedU16::new(0x0001);
let dest_id = UnsignedU16::new(0x0203);
let transaction_id = UnsignedU16::new(0x0405);
let mut common_pdu_cfg =
CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_id)
.expect("common config creation failed");
common_pdu_cfg.crc_flag = CrcFlag::WithCrc;
common_pdu_cfg.direction = Direction::TowardsSender;
common_pdu_cfg.trans_mode = TransmissionMode::Unacknowledged;
common_pdu_cfg.file_flag = LargeFileFlag::Large;
let pdu_header = PduHeader::new_for_file_data(
common_pdu_cfg,
5,
SegmentMetadataFlag::Present,
SegmentationControl::WithRecordBoundaryPreservation,
);
let mut buf: [u8; 16] = [0; 16];
let res = pdu_header.write_to_be_bytes(&mut buf);
assert!(res.is_ok());
let deser_res = PduHeader::from_be_bytes(&buf);
assert!(deser_res.is_ok());
let (header_read_back, read_size) = deser_res.unwrap();
assert_eq!(read_size, 10);
assert_eq!(header_read_back, pdu_header);
}
#[test]
fn test_invalid_raw_version() {
let src_id = UnsignedU8::new(1);
let dest_id = UnsignedU8::new(2);
let transaction_id = UnsignedU8::new(3);
let common_pdu_cfg = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_id)
.expect("common config creation failed");
let pdu_header = PduHeader::new_no_file_data(common_pdu_cfg, 5);
let mut buf: [u8; 7] = [0; 7];
let res = pdu_header.write_to_be_bytes(&mut buf);
assert!(res.is_ok());
buf[0] &= !0b1110_0000;
buf[0] |= (CFDP_VERSION_2 + 1) << 5;
let res = PduHeader::from_be_bytes(&buf);
assert!(res.is_err());
let error = res.unwrap_err();
if let PduError::CfdpVersionMissmatch(raw_version) = error {
assert_eq!(raw_version, CFDP_VERSION_2 + 1);
} else {
panic!("invalid exception: {}", error);
}
}
#[test]
fn test_buf_too_small_1() {
let buf: [u8; 3] = [0; 3];
let res = PduHeader::from_be_bytes(&buf);
assert!(res.is_err());
let error = res.unwrap_err();
if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall(missmatch)) =
error
{
assert_eq!(missmatch.found, 3);
assert_eq!(missmatch.expected, FIXED_HEADER_LEN);
} else {
panic!("invalid exception: {}", error);
}
}
#[test]
fn test_buf_too_small_2() {
let src_id = UnsignedU8::new(1);
let dest_id = UnsignedU8::new(2);
let transaction_id = UnsignedU8::new(3);
let common_pdu_cfg = CommonPduConfig::new_with_defaults(src_id, dest_id, transaction_id)
.expect("common config creation failed");
let pdu_header = PduHeader::new_no_file_data(common_pdu_cfg, 5);
let mut buf: [u8; 7] = [0; 7];
let res = pdu_header.write_to_be_bytes(&mut buf);
assert!(res.is_ok());
let header = PduHeader::from_be_bytes(&buf[0..6]);
assert!(header.is_err());
let error = header.unwrap_err();
if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall(missmatch)) =
error
{
assert_eq!(missmatch.found, 6);
assert_eq!(missmatch.expected, 7);
}
}
} }