added ACK PDU impl
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
Some checks failed
Rust/spacepackets/pipeline/head There was a failure building this commit
This commit is contained in:
parent
9976b53f65
commit
fdf6e1de90
@ -48,6 +48,24 @@ pub enum CrcFlag {
|
|||||||
WithCrc = 1,
|
WithCrc = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<bool> for CrcFlag {
|
||||||
|
fn from(value: bool) -> Self {
|
||||||
|
if value {
|
||||||
|
return CrcFlag::WithCrc;
|
||||||
|
}
|
||||||
|
CrcFlag::NoCrc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CrcFlag> for bool {
|
||||||
|
fn from(value: CrcFlag) -> Self {
|
||||||
|
if value == CrcFlag::WithCrc {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Always 0 and ignored for File Directive PDUs (CCSDS 727.0-B-5 P.75)
|
/// Always 0 and ignored for File Directive PDUs (CCSDS 727.0-B-5 P.75)
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
@ -119,6 +137,22 @@ pub enum LargeFileFlag {
|
|||||||
Large = 1,
|
Large = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transaction status for the ACK PDU field according to chapter 5.2.4 of the CFDP standard.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum TransactionStatus {
|
||||||
|
/// Transaction is not currently active and the CFDP implementation does not retain a
|
||||||
|
/// transaction history.
|
||||||
|
Undefined = 0b00,
|
||||||
|
Active = 0b01,
|
||||||
|
/// Transaction was active in the past and was terminated.
|
||||||
|
Terminated = 0b10,
|
||||||
|
/// The CFDP implementation does retain a tranaction history, and the transaction is not and
|
||||||
|
/// never was active at this entity.
|
||||||
|
Unrecognized = 0b11,
|
||||||
|
}
|
||||||
|
|
||||||
/// Checksum types according to the
|
/// Checksum types according to the
|
||||||
/// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/)
|
/// [SANA Checksum Types registry](https://sanaregistry.org/r/checksum_identifiers/)
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||||
|
199
src/cfdp/pdu/ack.rs
Normal file
199
src/cfdp/pdu/ack.rs
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
use crate::{
|
||||||
|
cfdp::{ConditionCode, CrcFlag, Direction, TransactionStatus},
|
||||||
|
ByteConversionError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
add_pdu_crc, generic_length_checks_pdu_deserialization, CfdpPdu, FileDirectiveType, PduError,
|
||||||
|
PduHeader, WritablePduPacket,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// ACK PDU abstraction.
|
||||||
|
///
|
||||||
|
/// For more information, refer to CFDP chapter 5.2.4.
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct AckPdu {
|
||||||
|
pdu_header: PduHeader,
|
||||||
|
directive_code_of_acked_pdu: FileDirectiveType,
|
||||||
|
condition_code: ConditionCode,
|
||||||
|
transaction_status: TransactionStatus,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AckPdu {
|
||||||
|
pub fn new(
|
||||||
|
mut pdu_header: PduHeader,
|
||||||
|
directive_code_of_acked_pdu: FileDirectiveType,
|
||||||
|
condition_code: ConditionCode,
|
||||||
|
transaction_status: TransactionStatus,
|
||||||
|
) -> Result<Self, PduError> {
|
||||||
|
if directive_code_of_acked_pdu == FileDirectiveType::EofPdu {
|
||||||
|
pdu_header.pdu_conf.direction = Direction::TowardsSender;
|
||||||
|
} else if directive_code_of_acked_pdu == FileDirectiveType::FinishedPdu {
|
||||||
|
pdu_header.pdu_conf.direction = Direction::TowardsReceiver;
|
||||||
|
} else {
|
||||||
|
return Err(PduError::InvalidDirectiveType {
|
||||||
|
found: directive_code_of_acked_pdu as u8,
|
||||||
|
expected: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Force correct direction flag.
|
||||||
|
let mut ack_pdu = Self {
|
||||||
|
pdu_header,
|
||||||
|
directive_code_of_acked_pdu,
|
||||||
|
condition_code,
|
||||||
|
transaction_status,
|
||||||
|
};
|
||||||
|
ack_pdu.pdu_header.pdu_datafield_len = ack_pdu.calc_pdu_datafield_len() as u16;
|
||||||
|
Ok(ack_pdu)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_for_eof_pdu(
|
||||||
|
pdu_header: PduHeader,
|
||||||
|
condition_code: ConditionCode,
|
||||||
|
transaction_status: TransactionStatus,
|
||||||
|
) -> Self {
|
||||||
|
// Unwrap okay here, [new] can only fail on invalid directive codes.
|
||||||
|
Self::new(
|
||||||
|
pdu_header,
|
||||||
|
FileDirectiveType::EofPdu,
|
||||||
|
condition_code,
|
||||||
|
transaction_status,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_for_finished_pdu(
|
||||||
|
pdu_header: PduHeader,
|
||||||
|
condition_code: ConditionCode,
|
||||||
|
transaction_status: TransactionStatus,
|
||||||
|
) -> Self {
|
||||||
|
// Unwrap okay here, [new] can only fail on invalid directive codes.
|
||||||
|
Self::new(
|
||||||
|
pdu_header,
|
||||||
|
FileDirectiveType::FinishedPdu,
|
||||||
|
condition_code,
|
||||||
|
transaction_status,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pdu_header(&self) -> &PduHeader {
|
||||||
|
&self.pdu_header
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn directive_code_of_acked_pdu(&self) -> FileDirectiveType {
|
||||||
|
self.directive_code_of_acked_pdu
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn condition_code(&self) -> ConditionCode {
|
||||||
|
self.condition_code
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transaction_status(&self) -> TransactionStatus {
|
||||||
|
self.transaction_status
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calc_pdu_datafield_len(&self) -> usize {
|
||||||
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
3
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_bytes(buf: &[u8]) -> Result<AckPdu, PduError> {
|
||||||
|
let (pdu_header, mut current_idx) = PduHeader::from_bytes(buf)?;
|
||||||
|
let full_len_without_crc = pdu_header.verify_length_and_checksum(buf)?;
|
||||||
|
generic_length_checks_pdu_deserialization(buf, current_idx + 3, full_len_without_crc)?;
|
||||||
|
let directive_type = FileDirectiveType::try_from(buf[current_idx]).map_err(|_| {
|
||||||
|
PduError::InvalidDirectiveType {
|
||||||
|
found: buf[current_idx],
|
||||||
|
expected: Some(FileDirectiveType::AckPdu),
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
if directive_type != FileDirectiveType::AckPdu {
|
||||||
|
return Err(PduError::WrongDirectiveType {
|
||||||
|
found: directive_type,
|
||||||
|
expected: FileDirectiveType::AckPdu,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
current_idx += 1;
|
||||||
|
let acked_directive_type =
|
||||||
|
FileDirectiveType::try_from(buf[current_idx] >> 4).map_err(|_| {
|
||||||
|
PduError::InvalidDirectiveType {
|
||||||
|
found: buf[current_idx],
|
||||||
|
expected: None,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
if acked_directive_type != FileDirectiveType::EofPdu
|
||||||
|
&& acked_directive_type != FileDirectiveType::FinishedPdu
|
||||||
|
{
|
||||||
|
return Err(PduError::InvalidDirectiveType {
|
||||||
|
found: acked_directive_type as u8,
|
||||||
|
expected: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
current_idx += 1;
|
||||||
|
let condition_code = ConditionCode::try_from((buf[current_idx] >> 4) & 0b1111)
|
||||||
|
.map_err(|_| PduError::InvalidConditionCode((buf[current_idx] >> 4) & 0b1111))?;
|
||||||
|
let transaction_status = TransactionStatus::try_from(buf[current_idx] & 0b11).unwrap();
|
||||||
|
Self::new(
|
||||||
|
pdu_header,
|
||||||
|
acked_directive_type,
|
||||||
|
condition_code,
|
||||||
|
transaction_status,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CfdpPdu for AckPdu {
|
||||||
|
fn pdu_header(&self) -> &PduHeader {
|
||||||
|
&self.pdu_header
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||||
|
Some(FileDirectiveType::AckPdu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WritablePduPacket for AckPdu {
|
||||||
|
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||||
|
let expected_len = self.len_written();
|
||||||
|
if buf.len() < expected_len {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: expected_len,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let mut current_idx = self.pdu_header.write_to_bytes(buf)?;
|
||||||
|
buf[current_idx] = FileDirectiveType::AckPdu as u8;
|
||||||
|
current_idx += 1;
|
||||||
|
|
||||||
|
buf[current_idx] = (self.directive_code_of_acked_pdu as u8) << 4;
|
||||||
|
if self.directive_code_of_acked_pdu == FileDirectiveType::FinishedPdu {
|
||||||
|
// This is the directive subtype code. It needs to be set to 0b0001 if the ACK PDU
|
||||||
|
// acknowledges a Finished PDU, and to 0b0000 otherwise.
|
||||||
|
buf[current_idx] |= 0b0001;
|
||||||
|
}
|
||||||
|
current_idx += 1;
|
||||||
|
buf[current_idx] = ((self.condition_code as u8) << 4) | (self.transaction_status as u8);
|
||||||
|
current_idx += 1;
|
||||||
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
|
}
|
||||||
|
Ok(current_idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn len_written(&self) -> usize {
|
||||||
|
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn test_basic() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
@ -63,6 +63,9 @@ impl EofPdu {
|
|||||||
if let Some(fault_location) = self.fault_location {
|
if let Some(fault_location) = self.fault_location {
|
||||||
len += fault_location.len_full();
|
len += fault_location.len_full();
|
||||||
}
|
}
|
||||||
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
len
|
len
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +149,7 @@ impl WritablePduPacket for EofPdu {
|
|||||||
if let Some(fault_location) = self.fault_location {
|
if let Some(fault_location) = self.fault_location {
|
||||||
current_idx += fault_location.write_to_be_bytes(buf)?;
|
current_idx += fault_location.write_to_be_bytes(buf)?;
|
||||||
}
|
}
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
current_idx = add_pdu_crc(buf, current_idx);
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
}
|
}
|
||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
@ -160,9 +163,11 @@ impl WritablePduPacket for EofPdu {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::cfdp::pdu::tests::{common_pdu_conf, verify_raw_header};
|
use crate::cfdp::pdu::tests::{
|
||||||
|
common_pdu_conf, verify_raw_header, TEST_DEST_ID, TEST_SEQ_NUM, TEST_SRC_ID,
|
||||||
|
};
|
||||||
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
|
use crate::cfdp::pdu::{FileDirectiveType, PduHeader};
|
||||||
use crate::cfdp::{ConditionCode, CrcFlag, LargeFileFlag};
|
use crate::cfdp::{ConditionCode, CrcFlag, LargeFileFlag, PduType, TransmissionMode};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
@ -173,6 +178,19 @@ mod tests {
|
|||||||
assert_eq!(eof_pdu.file_checksum(), 0x01020304);
|
assert_eq!(eof_pdu.file_checksum(), 0x01020304);
|
||||||
assert_eq!(eof_pdu.file_size(), 12);
|
assert_eq!(eof_pdu.file_size(), 12);
|
||||||
assert_eq!(eof_pdu.condition_code(), ConditionCode::NoError);
|
assert_eq!(eof_pdu.condition_code(), ConditionCode::NoError);
|
||||||
|
|
||||||
|
assert_eq!(eof_pdu.crc_flag(), CrcFlag::NoCrc);
|
||||||
|
assert_eq!(eof_pdu.file_flag(), LargeFileFlag::Normal);
|
||||||
|
assert_eq!(eof_pdu.pdu_type(), PduType::FileDirective);
|
||||||
|
assert_eq!(
|
||||||
|
eof_pdu.file_directive_type(),
|
||||||
|
Some(FileDirectiveType::EofPdu)
|
||||||
|
);
|
||||||
|
assert_eq!(eof_pdu.transmission_mode(), TransmissionMode::Acknowledged);
|
||||||
|
assert_eq!(eof_pdu.direction(), Direction::TowardsReceiver);
|
||||||
|
assert_eq!(eof_pdu.source_id(), TEST_SRC_ID.into());
|
||||||
|
assert_eq!(eof_pdu.dest_id(), TEST_DEST_ID.into());
|
||||||
|
assert_eq!(eof_pdu.transaction_seq_num(), TEST_SEQ_NUM.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -215,8 +233,7 @@ mod tests {
|
|||||||
let mut buf: [u8; 64] = [0; 64];
|
let mut buf: [u8; 64] = [0; 64];
|
||||||
eof_pdu.write_to_bytes(&mut buf).unwrap();
|
eof_pdu.write_to_bytes(&mut buf).unwrap();
|
||||||
let eof_read_back = EofPdu::from_bytes(&buf);
|
let eof_read_back = EofPdu::from_bytes(&buf);
|
||||||
if eof_read_back.is_err() {
|
if let Err(e) = eof_read_back {
|
||||||
let e = eof_read_back.unwrap_err();
|
|
||||||
panic!("deserialization failed with: {e}")
|
panic!("deserialization failed with: {e}")
|
||||||
}
|
}
|
||||||
let eof_read_back = eof_read_back.unwrap();
|
let eof_read_back = eof_read_back.unwrap();
|
||||||
@ -233,4 +250,9 @@ mod tests {
|
|||||||
let pdu_vec = eof_pdu.to_vec().unwrap();
|
let pdu_vec = eof_pdu.to_vec().unwrap();
|
||||||
assert_eq!(buf[0..written], pdu_vec);
|
assert_eq!(buf[0..written], pdu_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_crc() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
|
|||||||
len += self.segment_metadata.as_ref().unwrap().written_len()
|
len += self.segment_metadata.as_ref().unwrap().written_len()
|
||||||
}
|
}
|
||||||
len += self.file_data.len();
|
len += self.file_data.len();
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
len
|
len
|
||||||
@ -225,7 +225,7 @@ impl WritablePduPacket for FileDataPdu<'_, '_> {
|
|||||||
)?;
|
)?;
|
||||||
buf[current_idx..current_idx + self.file_data.len()].copy_from_slice(self.file_data);
|
buf[current_idx..current_idx + self.file_data.len()].copy_from_slice(self.file_data);
|
||||||
current_idx += self.file_data.len();
|
current_idx += self.file_data.len();
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
current_idx = add_pdu_crc(buf, current_idx);
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
}
|
}
|
||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
@ -242,7 +242,6 @@ mod tests {
|
|||||||
use crate::cfdp::pdu::tests::{TEST_DEST_ID, TEST_SEQ_NUM, TEST_SRC_ID};
|
use crate::cfdp::pdu::tests::{TEST_DEST_ID, TEST_SEQ_NUM, TEST_SRC_ID};
|
||||||
use crate::cfdp::pdu::{CommonPduConfig, PduHeader};
|
use crate::cfdp::pdu::{CommonPduConfig, PduHeader};
|
||||||
use crate::cfdp::{Direction, SegmentMetadataFlag, SegmentationControl, TransmissionMode};
|
use crate::cfdp::{Direction, SegmentMetadataFlag, SegmentationControl, TransmissionMode};
|
||||||
use crate::util::UbfU8;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
@ -330,6 +329,11 @@ mod tests {
|
|||||||
assert_eq!(fd_pdu_read_back, fd_pdu);
|
assert_eq!(fd_pdu_read_back, fd_pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_crc() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_with_seg_metadata_serialization() {
|
fn test_with_seg_metadata_serialization() {
|
||||||
let common_conf =
|
let common_conf =
|
||||||
|
@ -120,14 +120,17 @@ impl<'fs_responses> FinishedPdu<'fs_responses> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn calc_pdu_datafield_len(&self) -> usize {
|
fn calc_pdu_datafield_len(&self) -> usize {
|
||||||
let mut base_len = 2;
|
let mut datafield_len = 2;
|
||||||
if let Some(fs_responses) = self.fs_responses {
|
if let Some(fs_responses) = self.fs_responses {
|
||||||
base_len += fs_responses.len();
|
datafield_len += fs_responses.len();
|
||||||
}
|
}
|
||||||
if let Some(fault_location) = self.fault_location {
|
if let Some(fault_location) = self.fault_location {
|
||||||
base_len += fault_location.len_full();
|
datafield_len += fault_location.len_full();
|
||||||
}
|
}
|
||||||
base_len
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
|
datafield_len += 2;
|
||||||
|
}
|
||||||
|
datafield_len
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates [Self] from a raw bytestream.
|
/// Generates [Self] from a raw bytestream.
|
||||||
@ -246,7 +249,7 @@ impl WritablePduPacket for FinishedPdu<'_> {
|
|||||||
if let Some(fault_location) = self.fault_location {
|
if let Some(fault_location) = self.fault_location {
|
||||||
current_idx += fault_location.write_to_be_bytes(&mut buf[current_idx..])?;
|
current_idx += fault_location.write_to_be_bytes(&mut buf[current_idx..])?;
|
||||||
}
|
}
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
current_idx = add_pdu_crc(buf, current_idx);
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
}
|
}
|
||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
@ -389,4 +392,9 @@ mod tests {
|
|||||||
let read_back = read_back.unwrap();
|
let read_back = read_back.unwrap();
|
||||||
assert_eq!(finished_pdu, read_back);
|
assert_eq!(finished_pdu, read_back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_with_crc() {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
|
|||||||
if let Some(opts) = self.options {
|
if let Some(opts) = self.options {
|
||||||
len += opts.len();
|
len += opts.len();
|
||||||
}
|
}
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
len += 2;
|
len += 2;
|
||||||
}
|
}
|
||||||
len
|
len
|
||||||
@ -288,7 +288,7 @@ impl WritablePduPacket for MetadataPdu<'_, '_, '_> {
|
|||||||
buf[current_idx..current_idx + opts.len()].copy_from_slice(opts);
|
buf[current_idx..current_idx + opts.len()].copy_from_slice(opts);
|
||||||
current_idx += opts.len();
|
current_idx += opts.len();
|
||||||
}
|
}
|
||||||
if self.pdu_header.pdu_conf.crc_flag == CrcFlag::WithCrc {
|
if self.crc_flag() == CrcFlag::WithCrc {
|
||||||
current_idx = add_pdu_crc(buf, current_idx);
|
current_idx = add_pdu_crc(buf, current_idx);
|
||||||
}
|
}
|
||||||
Ok(current_idx)
|
Ok(current_idx)
|
||||||
@ -453,6 +453,7 @@ pub mod tests {
|
|||||||
+ dest_filename.len_full()
|
+ dest_filename.len_full()
|
||||||
+ 2
|
+ 2
|
||||||
);
|
);
|
||||||
|
assert_eq!(written, metadata_pdu.len_written());
|
||||||
let pdu_read_back = MetadataPdu::from_bytes(&buf).unwrap();
|
let pdu_read_back = MetadataPdu::from_bytes(&buf).unwrap();
|
||||||
assert_eq!(pdu_read_back, metadata_pdu);
|
assert_eq!(pdu_read_back, metadata_pdu);
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@ use core::fmt::{Display, Formatter};
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub mod ack;
|
||||||
pub mod eof;
|
pub mod eof;
|
||||||
pub mod file_data;
|
pub mod file_data;
|
||||||
pub mod finished;
|
pub mod finished;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
pub mod nak;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
@ -41,11 +43,14 @@ pub enum PduError {
|
|||||||
src_id_len: usize,
|
src_id_len: usize,
|
||||||
dest_id_len: usize,
|
dest_id_len: usize,
|
||||||
},
|
},
|
||||||
|
/// Wrong directive type, for example when parsing the directive field for a file directive
|
||||||
|
/// PDU.
|
||||||
WrongDirectiveType {
|
WrongDirectiveType {
|
||||||
found: FileDirectiveType,
|
found: FileDirectiveType,
|
||||||
expected: FileDirectiveType,
|
expected: FileDirectiveType,
|
||||||
},
|
},
|
||||||
/// The directive type field contained a value not in the range of permitted values.
|
/// The directive type field contained a value not in the range of permitted values. This can
|
||||||
|
/// also happen if an invalid value is passed to the ACK PDU constructor.
|
||||||
InvalidDirectiveType {
|
InvalidDirectiveType {
|
||||||
found: u8,
|
found: u8,
|
||||||
expected: Option<FileDirectiveType>,
|
expected: Option<FileDirectiveType>,
|
||||||
|
1
src/cfdp/pdu/nak.rs
Normal file
1
src/cfdp/pdu/nak.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
Loading…
Reference in New Issue
Block a user