improve CFDP module
This commit is contained in:
@@ -63,6 +63,8 @@ pub(crate) fn generic_len_check_deserialization(
|
||||
}
|
||||
|
||||
impl<'data> Lv<'data> {
|
||||
pub const MIN_LEN: usize = MIN_LV_LEN;
|
||||
|
||||
#[inline]
|
||||
pub fn new(data: &[u8]) -> Result<Lv<'_>, TlvLvDataTooLargeError> {
|
||||
if data.len() > u8::MAX as usize {
|
||||
|
||||
+30
-14
@@ -81,22 +81,27 @@ impl AckPdu {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn directive_code_of_acked_pdu(&self) -> FileDirectiveType {
|
||||
self.directive_code_of_acked_pdu
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn condition_code(&self) -> ConditionCode {
|
||||
self.condition_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn transaction_status(&self) -> TransactionStatus {
|
||||
self.transaction_status
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn calc_pdu_datafield_len(&self) -> usize {
|
||||
if self.crc_flag() == CrcFlag::WithCrc {
|
||||
return 5;
|
||||
@@ -147,20 +152,9 @@ impl AckPdu {
|
||||
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> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub 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 {
|
||||
@@ -188,11 +182,33 @@ impl WritablePduPacket for AckPdu {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
pub fn len_written(&self) -> usize {
|
||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for AckPdu {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::cfdp::{
|
||||
|
||||
+29
-14
@@ -55,18 +55,22 @@ impl EofPdu {
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn condition_code(&self) -> ConditionCode {
|
||||
self.condition_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn file_checksum(&self) -> u32 {
|
||||
self.file_checksum
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn file_size(&self) -> u64 {
|
||||
self.file_size
|
||||
}
|
||||
@@ -129,20 +133,9 @@ impl EofPdu {
|
||||
fault_location,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for EofPdu {
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::EofPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for EofPdu {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub 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 {
|
||||
@@ -172,11 +165,33 @@ impl WritablePduPacket for EofPdu {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
pub fn len_written(&self) -> usize {
|
||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for EofPdu {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::EofPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for EofPdu {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
+52
-21
@@ -10,8 +10,10 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{CfdpPdu, FileDirectiveType, WritablePduPacket};
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, IntoPrimitive)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[bitbybit::bitenum(u2, exhaustive = true)]
|
||||
#[repr(u8)]
|
||||
pub enum RecordContinuationState {
|
||||
NoStartNoEnd = 0b00,
|
||||
@@ -43,24 +45,27 @@ impl<'seg_meta> SegmentMetadata<'seg_meta> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn record_continuation_state(&self) -> RecordContinuationState {
|
||||
self.record_continuation_state
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn metadata(&self) -> Option<&'seg_meta [u8]> {
|
||||
self.metadata
|
||||
}
|
||||
|
||||
pub fn written_len(&self) -> usize {
|
||||
#[inline]
|
||||
pub fn len_written(&self) -> usize {
|
||||
// Map empty metadata to 0 and slice to its length.
|
||||
1 + self.metadata.map_or(0, |meta| meta.len())
|
||||
}
|
||||
|
||||
pub(crate) fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
if buf.len() < self.written_len() {
|
||||
if buf.len() < self.len_written() {
|
||||
return Err(ByteConversionError::ToSliceTooSmall {
|
||||
found: buf.len(),
|
||||
expected: self.written_len(),
|
||||
expected: self.len_written(),
|
||||
});
|
||||
}
|
||||
buf[0] = ((self.record_continuation_state as u8) << 6)
|
||||
@@ -68,7 +73,7 @@ impl<'seg_meta> SegmentMetadata<'seg_meta> {
|
||||
if let Some(metadata) = self.metadata {
|
||||
buf[1..1 + metadata.len()].copy_from_slice(metadata)
|
||||
}
|
||||
Ok(self.written_len())
|
||||
Ok(self.len_written())
|
||||
}
|
||||
|
||||
pub(crate) fn from_bytes(buf: &'seg_meta [u8]) -> Result<Self, ByteConversionError> {
|
||||
@@ -102,10 +107,12 @@ struct FdPduBase<'seg_meta> {
|
||||
}
|
||||
|
||||
impl CfdpPdu for FdPduBase<'_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
None
|
||||
}
|
||||
@@ -118,7 +125,7 @@ impl FdPduBase<'_> {
|
||||
len += 4;
|
||||
}
|
||||
if self.segment_metadata.is_some() {
|
||||
len += self.segment_metadata.as_ref().unwrap().written_len()
|
||||
len += self.segment_metadata.as_ref().unwrap().len_written()
|
||||
}
|
||||
len += file_data_len as usize;
|
||||
if self.crc_flag() == CrcFlag::WithCrc {
|
||||
@@ -143,6 +150,11 @@ impl FdPduBase<'_> {
|
||||
)?;
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
}
|
||||
|
||||
/// File Data PDU abstraction.
|
||||
@@ -201,14 +213,22 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
|
||||
.calc_pdu_datafield_len(self.file_data.len() as u64)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn segment_metadata(&self) -> Option<&SegmentMetadata<'_>> {
|
||||
self.common.segment_metadata.as_ref()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
self.common.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn offset(&self) -> u64 {
|
||||
self.common.offset
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn file_data(&self) -> &'file_data [u8] {
|
||||
self.file_data
|
||||
}
|
||||
@@ -221,7 +241,7 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
|
||||
let mut segment_metadata = None;
|
||||
if pdu_header.seg_metadata_flag == SegmentMetadataFlag::Present {
|
||||
segment_metadata = Some(SegmentMetadata::from_bytes(&buf[current_idx..])?);
|
||||
current_idx += segment_metadata.as_ref().unwrap().written_len();
|
||||
current_idx += segment_metadata.as_ref().unwrap().len_written();
|
||||
}
|
||||
let (fss, offset) = read_fss_field(pdu_header.pdu_conf.file_flag, &buf[current_idx..]);
|
||||
current_idx += fss;
|
||||
@@ -241,19 +261,9 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
|
||||
file_data: &buf[current_idx..full_len_without_crc],
|
||||
})
|
||||
}
|
||||
}
|
||||
impl CfdpPdu for FileDataPdu<'_, '_> {
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.common.pdu_header
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for FileDataPdu<'_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
if buf.len() < self.len_written() {
|
||||
return Err(ByteConversionError::ToSliceTooSmall {
|
||||
found: buf.len(),
|
||||
@@ -271,10 +281,31 @@ impl WritablePduPacket for FileDataPdu<'_, '_> {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
pub fn len_written(&self) -> usize {
|
||||
self.common.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
impl CfdpPdu for FileDataPdu<'_, '_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.common.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for FileDataPdu<'_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
/// File Data PDU creator abstraction.
|
||||
///
|
||||
|
||||
+49
-15
@@ -109,23 +109,33 @@ impl<'fs_responses> FinishedPduCreator<'fs_responses> {
|
||||
finished_pdu
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn condition_code(&self) -> ConditionCode {
|
||||
self.condition_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn delivery_code(&self) -> DeliveryCode {
|
||||
self.delivery_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn file_status(&self) -> FileStatus {
|
||||
self.file_status
|
||||
}
|
||||
|
||||
// If there are no filestore responses, an empty slice will be returned.
|
||||
#[inline]
|
||||
pub fn filestore_responses(&self) -> &[FilestoreResponseTlv<'_, '_, '_>] {
|
||||
self.fs_responses
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fault_location(&self) -> Option<EntityIdTlv> {
|
||||
self.fault_location
|
||||
}
|
||||
@@ -143,20 +153,9 @@ impl<'fs_responses> FinishedPduCreator<'fs_responses> {
|
||||
}
|
||||
datafield_len
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for FinishedPduCreator<'_> {
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::FinishedPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for FinishedPduCreator<'_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub 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 {
|
||||
@@ -185,11 +184,33 @@ impl WritablePduPacket for FinishedPduCreator<'_> {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
pub fn len_written(&self) -> usize {
|
||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for FinishedPduCreator<'_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::FinishedPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for FinishedPduCreator<'_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper structure to loop through all filestore responses of a read Finished PDU. It should be
|
||||
/// noted that iterators in Rust are not fallible, but the TLV creation can fail, for example if
|
||||
/// the raw TLV data is invalid for some reason. In that case, the iterator will yield [None]
|
||||
@@ -276,10 +297,12 @@ impl<'buf> FinishedPduReader<'buf> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fs_responses_raw(&self) -> &[u8] {
|
||||
self.fs_responses_raw
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fs_responses_iter(&self) -> FilestoreResponseIterator<'_> {
|
||||
FilestoreResponseIterator {
|
||||
responses_buf: self.fs_responses_raw,
|
||||
@@ -287,22 +310,31 @@ impl<'buf> FinishedPduReader<'buf> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn condition_code(&self) -> ConditionCode {
|
||||
self.condition_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn delivery_code(&self) -> DeliveryCode {
|
||||
self.delivery_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn file_status(&self) -> FileStatus {
|
||||
self.file_status
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fault_location(&self) -> Option<EntityIdTlv> {
|
||||
self.fault_location
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
fn parse_tlv_fields(
|
||||
mut current_idx: usize,
|
||||
full_len_without_crc: usize,
|
||||
@@ -360,10 +392,12 @@ impl<'buf> FinishedPduReader<'buf> {
|
||||
}
|
||||
|
||||
impl CfdpPdu for FinishedPduReader<'_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::FinishedPdu)
|
||||
}
|
||||
|
||||
+45
-15
@@ -128,18 +128,27 @@ impl<'src_name, 'dest_name, 'opts> MetadataPduCreator<'src_name, 'dest_name, 'op
|
||||
pdu
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn metadata_params(&self) -> &MetadataGenericParams {
|
||||
&self.metadata_params
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn src_file_name(&self) -> Lv<'src_name> {
|
||||
self.src_file_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dest_file_name(&self) -> Lv<'dest_name> {
|
||||
self.dest_file_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn options(&self) -> &'opts [u8] {
|
||||
self.options
|
||||
}
|
||||
@@ -169,20 +178,9 @@ impl<'src_name, 'dest_name, 'opts> MetadataPduCreator<'src_name, 'dest_name, 'op
|
||||
}
|
||||
len
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for MetadataPduCreator<'_, '_, '_> {
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::MetadataPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for MetadataPduCreator<'_, '_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub 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 {
|
||||
@@ -217,11 +215,33 @@ impl WritablePduPacket for MetadataPduCreator<'_, '_, '_> {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
pub fn len_written(&self) -> usize {
|
||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for MetadataPduCreator<'_, '_, '_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::MetadataPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for MetadataPduCreator<'_, '_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper structure to loop through all options of a metadata PDU. It should be noted that
|
||||
/// iterators in Rust are not fallible, but the TLV creation can fail, for example if the raw TLV
|
||||
/// data is invalid for some reason. In that case, the iterator will yield [None] because there
|
||||
@@ -330,26 +350,36 @@ impl<'raw> MetadataPduReader<'raw> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn options(&self) -> &'raw [u8] {
|
||||
self.options
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn metadata_params(&self) -> &MetadataGenericParams {
|
||||
&self.metadata_params
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn src_file_name(&self) -> Lv<'_> {
|
||||
self.src_file_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn dest_file_name(&self) -> Lv<'_> {
|
||||
self.dest_file_name
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for MetadataPduReader<'_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
|
||||
@@ -311,6 +311,8 @@ pub struct PduHeader {
|
||||
}
|
||||
|
||||
impl PduHeader {
|
||||
pub const FIXED_LEN: usize = FIXED_HEADER_LEN;
|
||||
|
||||
#[inline]
|
||||
pub fn new_for_file_data(
|
||||
pdu_conf: CommonPduConfig,
|
||||
@@ -565,6 +567,7 @@ impl PduHeader {
|
||||
&self.pdu_conf
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn seg_metadata_flag(&self) -> SegmentMetadataFlag {
|
||||
self.seg_metadata_flag
|
||||
}
|
||||
|
||||
+31
-13
@@ -18,6 +18,7 @@ pub enum SegmentRequests<'a> {
|
||||
}
|
||||
|
||||
impl SegmentRequests<'_> {
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
SegmentRequests::U32Pairs(pairs) => pairs.is_empty(),
|
||||
@@ -122,14 +123,17 @@ impl<'seg_reqs> NakPduCreator<'seg_reqs> {
|
||||
Ok(nak_pdu)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn start_of_scope(&self) -> u64 {
|
||||
self.start_of_scope
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn end_of_scope(&self) -> u64 {
|
||||
self.end_of_scope
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn segment_requests(&self) -> Option<&SegmentRequests<'_>> {
|
||||
self.segment_requests.as_ref()
|
||||
}
|
||||
@@ -144,6 +148,7 @@ impl<'seg_reqs> NakPduCreator<'seg_reqs> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
@@ -162,20 +167,9 @@ impl<'seg_reqs> NakPduCreator<'seg_reqs> {
|
||||
}
|
||||
datafield_len
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for NakPduCreator<'_> {
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
&self.pdu_header
|
||||
}
|
||||
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::NakPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for NakPduCreator<'_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
/// Write [Self] to the provided buffer and returns the written size.
|
||||
pub 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 {
|
||||
@@ -238,11 +232,35 @@ impl WritablePduPacket for NakPduCreator<'_> {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.pdu_header.header_len() + self.calc_pdu_datafield_len()
|
||||
}
|
||||
}
|
||||
|
||||
impl CfdpPdu for NakPduCreator<'_> {
|
||||
#[inline]
|
||||
fn pdu_header(&self) -> &PduHeader {
|
||||
self.pdu_header()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn file_directive_type(&self) -> Option<FileDirectiveType> {
|
||||
Some(FileDirectiveType::NakPdu)
|
||||
}
|
||||
}
|
||||
|
||||
impl WritablePduPacket for NakPduCreator<'_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
/// Special iterator type for the NAK PDU which allows to iterate over both normal and large file
|
||||
/// segment requests.
|
||||
#[derive(Debug)]
|
||||
|
||||
+84
-12
@@ -26,6 +26,7 @@ pub trait GenericTlv {
|
||||
|
||||
/// Checks whether the type field contains one of the standard types specified in the CFDP
|
||||
/// standard and is part of the [TlvType] enum.
|
||||
#[inline]
|
||||
fn is_standard_tlv(&self) -> bool {
|
||||
if let TlvTypeField::Standard(_) = self.tlv_type_field() {
|
||||
return true;
|
||||
@@ -34,6 +35,7 @@ pub trait GenericTlv {
|
||||
}
|
||||
|
||||
/// Returns the standard TLV type if the TLV field is not a custom field
|
||||
#[inline]
|
||||
fn tlv_type(&self) -> Option<TlvType> {
|
||||
if let TlvTypeField::Standard(tlv_type) = self.tlv_type_field() {
|
||||
Some(tlv_type)
|
||||
@@ -47,17 +49,20 @@ pub trait ReadableTlv {
|
||||
fn value(&self) -> &[u8];
|
||||
|
||||
/// Checks whether the value field is empty.
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.value().is_empty()
|
||||
}
|
||||
|
||||
/// Helper method to retrieve the length of the value. Simply calls the [slice::len] method of
|
||||
/// [Self::value]
|
||||
#[inline]
|
||||
fn len_value(&self) -> usize {
|
||||
self.value().len()
|
||||
}
|
||||
|
||||
/// Returns the full raw length, including the length byte.
|
||||
#[inline]
|
||||
fn len_full(&self) -> usize {
|
||||
self.len_value() + 2
|
||||
}
|
||||
@@ -153,6 +158,8 @@ pub struct Tlv<'data> {
|
||||
}
|
||||
|
||||
impl<'data> Tlv<'data> {
|
||||
pub const MIN_LEN: usize = MIN_TLV_LEN;
|
||||
|
||||
pub fn new(tlv_type: TlvType, data: &[u8]) -> Result<Tlv<'_>, TlvLvDataTooLargeError> {
|
||||
Ok(Tlv {
|
||||
tlv_type_field: TlvTypeField::Standard(tlv_type),
|
||||
@@ -196,6 +203,7 @@ impl<'data> Tlv<'data> {
|
||||
|
||||
/// If the TLV was generated from a raw bytestream using [Self::from_bytes], the raw start
|
||||
/// of the TLV can be retrieved with this method.
|
||||
#[inline]
|
||||
pub fn raw_data(&self) -> Option<&[u8]> {
|
||||
self.lv.raw_data()
|
||||
}
|
||||
@@ -229,12 +237,15 @@ impl WritableTlv for Tlv<'_> {
|
||||
self.lv.write_to_be_bytes_no_len_check(&mut buf[1..]);
|
||||
Ok(self.len_full())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_full()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for Tlv<'_> {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
self.tlv_type_field
|
||||
}
|
||||
@@ -277,6 +288,19 @@ pub mod alloc_mod {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
generic_len_check_data_serialization(buf, self.data.len(), MIN_TLV_LEN)?;
|
||||
buf[0] = self.tlv_type_field.into();
|
||||
buf[1] = self.data.len() as u8;
|
||||
buf[2..2 + self.data.len()].copy_from_slice(&self.data);
|
||||
Ok(self.len_written())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.data.len() + 2
|
||||
}
|
||||
|
||||
pub fn as_tlv(&self) -> Tlv<'_> {
|
||||
Tlv {
|
||||
tlv_type_field: self.tlv_type_field,
|
||||
@@ -288,6 +312,7 @@ pub mod alloc_mod {
|
||||
}
|
||||
|
||||
impl ReadableTlv for TlvOwned {
|
||||
#[inline]
|
||||
fn value(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
@@ -295,19 +320,17 @@ pub mod alloc_mod {
|
||||
|
||||
impl WritableTlv for TlvOwned {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
generic_len_check_data_serialization(buf, self.data.len(), MIN_TLV_LEN)?;
|
||||
buf[0] = self.tlv_type_field.into();
|
||||
buf[1] = self.data.len() as u8;
|
||||
buf[2..2 + self.data.len()].copy_from_slice(&self.data);
|
||||
Ok(self.len_written())
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.data.len() + 2
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for TlvOwned {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
self.tlv_type_field
|
||||
}
|
||||
@@ -334,6 +357,7 @@ pub struct EntityIdTlv {
|
||||
}
|
||||
|
||||
impl EntityIdTlv {
|
||||
#[inline]
|
||||
pub fn new(entity_id: UnsignedByteField) -> Self {
|
||||
Self { entity_id }
|
||||
}
|
||||
@@ -348,14 +372,17 @@ impl EntityIdTlv {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn entity_id(&self) -> &UnsignedByteField {
|
||||
&self.entity_id
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_value(&self) -> usize {
|
||||
self.entity_id.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_full(&self) -> usize {
|
||||
2 + self.entity_id.size()
|
||||
}
|
||||
@@ -380,9 +407,7 @@ impl EntityIdTlv {
|
||||
// Can't fail.
|
||||
Ok(Tlv::new(TlvType::EntityId, &buf[2..2 + self.entity_id.size()]).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for EntityIdTlv {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
Self::len_check(buf)?;
|
||||
buf[0] = TlvType::EntityId as u8;
|
||||
@@ -390,12 +415,25 @@ impl WritableTlv for EntityIdTlv {
|
||||
Ok(2 + self.entity_id.write_to_be_bytes(&mut buf[2..])?)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_full()
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for EntityIdTlv {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for EntityIdTlv {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
TlvTypeField::Standard(TlvType::EntityId)
|
||||
}
|
||||
@@ -440,6 +478,7 @@ impl TryFrom<Tlv<'_>> for EntityIdTlv {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fs_request_has_second_filename(action_code: FilestoreActionCode) -> bool {
|
||||
if action_code == FilestoreActionCode::RenameFile
|
||||
|| action_code == FilestoreActionCode::AppendFile
|
||||
@@ -462,6 +501,7 @@ struct FilestoreTlvBase<'first_name, 'second_name> {
|
||||
}
|
||||
|
||||
impl FilestoreTlvBase<'_, '_> {
|
||||
#[inline]
|
||||
fn base_len_value(&self) -> usize {
|
||||
let mut len = 1 + self.first_name.len_full();
|
||||
if let Some(second_name) = self.second_name {
|
||||
@@ -571,22 +611,27 @@ impl<'first_name, 'second_name> FilestoreRequestTlv<'first_name, 'second_name> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn action_code(&self) -> FilestoreActionCode {
|
||||
self.base.action_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn first_name(&self) -> Lv<'first_name> {
|
||||
self.base.first_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn second_name(&self) -> Option<Lv<'second_name>> {
|
||||
self.base.second_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_value(&self) -> usize {
|
||||
self.base.base_len_value()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_full(&self) -> usize {
|
||||
2 + self.len_value()
|
||||
}
|
||||
@@ -625,9 +670,7 @@ impl<'first_name, 'second_name> FilestoreRequestTlv<'first_name, 'second_name> {
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for FilestoreRequestTlv<'_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
if buf.len() < self.len_full() {
|
||||
return Err(ByteConversionError::ToSliceTooSmall {
|
||||
@@ -653,12 +696,25 @@ impl WritableTlv for FilestoreRequestTlv<'_, '_> {
|
||||
Ok(current_idx)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_full()
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for FilestoreRequestTlv<'_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for FilestoreRequestTlv<'_, '_> {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
TlvTypeField::Standard(TlvType::FilestoreRequest)
|
||||
}
|
||||
@@ -733,26 +789,32 @@ impl<'first_name, 'second_name, 'fs_msg> FilestoreResponseTlv<'first_name, 'seco
|
||||
false
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn action_code(&self) -> FilestoreActionCode {
|
||||
self.base.action_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn status_code(&self) -> u8 {
|
||||
self.status_code
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn first_name(&self) -> Lv<'first_name> {
|
||||
self.base.first_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn second_name(&self) -> Option<Lv<'second_name>> {
|
||||
self.base.second_name
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_value(&self) -> usize {
|
||||
self.base.base_len_value() + self.filestore_message.len_full()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len_full(&self) -> usize {
|
||||
2 + self.len_value()
|
||||
}
|
||||
@@ -810,9 +872,7 @@ impl<'first_name, 'second_name, 'fs_msg> FilestoreResponseTlv<'first_name, 'seco
|
||||
filestore_message,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for FilestoreResponseTlv<'_, '_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
if buf.len() < self.len_full() {
|
||||
return Err(ByteConversionError::ToSliceTooSmall {
|
||||
@@ -845,7 +905,19 @@ impl WritableTlv for FilestoreResponseTlv<'_, '_, '_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl WritableTlv for FilestoreResponseTlv<'_, '_, '_> {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
self.write_to_bytes(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_written()
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for FilestoreResponseTlv<'_, '_, '_> {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
TlvTypeField::Standard(TlvType::FilestoreResponse)
|
||||
}
|
||||
|
||||
@@ -37,10 +37,12 @@ impl<'data> MsgToUserTlv<'data> {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_standard_tlv(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tlv_type(&self) -> Option<TlvType> {
|
||||
Some(TlvType::MsgToUser)
|
||||
}
|
||||
@@ -83,6 +85,7 @@ impl<'data> MsgToUserTlv<'data> {
|
||||
Ok(msg_to_user)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_tlv(&self) -> Tlv<'data> {
|
||||
self.tlv
|
||||
}
|
||||
@@ -91,6 +94,17 @@ impl<'data> MsgToUserTlv<'data> {
|
||||
pub fn to_owned(&self) -> TlvOwned {
|
||||
self.tlv.to_owned()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_full()
|
||||
}
|
||||
|
||||
delegate!(
|
||||
to self.tlv {
|
||||
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
impl<'a> From<MsgToUserTlv<'a>> for Tlv<'a> {
|
||||
@@ -100,18 +114,18 @@ impl<'a> From<MsgToUserTlv<'a>> for Tlv<'a> {
|
||||
}
|
||||
|
||||
impl WritableTlv for MsgToUserTlv<'_> {
|
||||
#[inline]
|
||||
fn len_written(&self) -> usize {
|
||||
self.len_full()
|
||||
self.len_written()
|
||||
}
|
||||
|
||||
delegate!(
|
||||
to self.tlv {
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
|
||||
}
|
||||
);
|
||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||
self.tlv.write_to_bytes(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl GenericTlv for MsgToUserTlv<'_> {
|
||||
#[inline]
|
||||
fn tlv_type_field(&self) -> TlvTypeField {
|
||||
self.tlv.tlv_type_field()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user