improve CFDP module

This commit is contained in:
Robin Mueller
2025-09-11 09:09:41 +02:00
parent 272a961a70
commit c68e71a25e
13 changed files with 368 additions and 145 deletions
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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> {
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
+20 -6
View File
@@ -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()
}