Merge pull request 'improve CFDP module' (#153) from cfdp-module-improvements into main
Reviewed-on: #153
This commit was merged in pull request #153.
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 {
|
||||
|
||||
@@ -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::{
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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.
|
||||
///
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -583,6 +583,7 @@ impl<'buf> PusTcCreatorWithReservedAppData<'buf> {
|
||||
/// * `sec_header` - Information contained in the secondary header, including the service
|
||||
/// and subservice type
|
||||
/// * `app_data_len` - Custom application data length
|
||||
/// * `has_checksum` - Packet should have a CRC-16-CCITT checksum appended at the end
|
||||
#[inline]
|
||||
pub fn new(
|
||||
buf: &'buf mut [u8],
|
||||
@@ -716,6 +717,7 @@ impl<'buf> PusTcCreatorWithReservedAppData<'buf> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder API to create a [PusTcCreator].
|
||||
#[derive(Debug)]
|
||||
pub struct PusTcBuilder<'a> {
|
||||
sp_header: SpHeader,
|
||||
@@ -813,6 +815,7 @@ impl<'a> PusTcBuilder<'a> {
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_app_data(mut self, app_data: &'a [u8]) -> Self {
|
||||
self.app_data = app_data;
|
||||
self
|
||||
@@ -844,10 +847,7 @@ pub struct PusTcReader<'raw_data> {
|
||||
|
||||
impl<'raw_data> PusTcReader<'raw_data> {
|
||||
/// Create a [PusTcReader] instance from a raw slice. The given packet should have a
|
||||
/// a CRC16-CCITT checksum which is also verified.
|
||||
///
|
||||
/// On success, it returns a tuple containing the instance and the found byte length of the
|
||||
/// packet. This function also expects a CRC16 checksum and will verify it.
|
||||
/// a CRC-16-CCITT checksum which is also verified.
|
||||
pub fn new(slice: &'raw_data [u8]) -> Result<Self, PusError> {
|
||||
let pus_tc = Self::new_no_checksum_verification(slice, true)?;
|
||||
// Unwrap for CRC16 okay, should always have some value.
|
||||
|
||||
@@ -920,8 +920,7 @@ pub struct PusTmReader<'raw_data> {
|
||||
}
|
||||
|
||||
impl<'raw_data> PusTmReader<'raw_data> {
|
||||
/// Create a [PusTmReader] instance from a raw slice. On success, it returns a tuple containing
|
||||
/// the instance and the found byte length of the packet. The timestamp length needs to be
|
||||
/// Create a [PusTmReader] instance from a raw slice. The timestamp length needs to be
|
||||
/// known beforehand.
|
||||
///
|
||||
/// This function will verify the CRC-16-CCITT of the PUS packet and will return an appropriate
|
||||
@@ -957,6 +956,8 @@ impl<'raw_data> PusTmReader<'raw_data> {
|
||||
Ok(tc)
|
||||
}
|
||||
|
||||
/// Create a [PusTmReader] instance from a raw slice. The timestamp length needs to be
|
||||
/// known beforehand. This variant can be used to parse packets without a checksum.
|
||||
pub fn new_no_checksum(slice: &'raw_data [u8], timestamp_len: usize) -> Result<Self, PusError> {
|
||||
Self::new_no_checksum_verification(
|
||||
slice,
|
||||
@@ -966,6 +967,7 @@ impl<'raw_data> PusTmReader<'raw_data> {
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_no_checksum_verification(
|
||||
slice: &'raw_data [u8],
|
||||
reader_config: ReaderConfig,
|
||||
@@ -1200,16 +1202,13 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
|
||||
Some(writer)
|
||||
}
|
||||
|
||||
/// Set the sequence count. Returns false and does not update the value if the passed value
|
||||
/// exceeds [MAX_APID].
|
||||
#[inline]
|
||||
pub fn set_apid(&mut self, apid: u11) -> bool {
|
||||
pub fn set_apid(&mut self, apid: u11) {
|
||||
// Clear APID part of the raw packet ID
|
||||
let updated_apid = ((((self.raw_tm[0] as u16) << 8) | self.raw_tm[1] as u16)
|
||||
& !MAX_APID.as_u16())
|
||||
| apid.as_u16();
|
||||
self.raw_tm[0..2].copy_from_slice(&updated_apid.to_be_bytes());
|
||||
true
|
||||
}
|
||||
|
||||
/// This function sets the message counter in the PUS TM secondary header.
|
||||
@@ -1243,11 +1242,10 @@ impl<'raw> PusTmZeroCopyWriter<'raw> {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_seq_count(&mut self, seq_count: u14) -> bool {
|
||||
pub fn set_seq_count(&mut self, seq_count: u14) {
|
||||
let new_psc = (u16::from_be_bytes(self.raw_tm[2..4].try_into().unwrap()) & 0xC000)
|
||||
| seq_count.as_u16();
|
||||
self.raw_tm[2..4].copy_from_slice(&new_psc.to_be_bytes());
|
||||
true
|
||||
}
|
||||
|
||||
/// This method has to be called after modifying fields to ensure the CRC16 of the telemetry
|
||||
|
||||
36
src/lib.rs
36
src/lib.rs
@@ -203,10 +203,10 @@ impl PacketId {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn new(ptype: PacketType, sec_header: bool, apid: u11) -> Self {
|
||||
pub const fn new(packet_type: PacketType, sec_header_flag: bool, apid: u11) -> Self {
|
||||
PacketId {
|
||||
packet_type: ptype,
|
||||
sec_header_flag: sec_header,
|
||||
packet_type,
|
||||
sec_header_flag,
|
||||
apid,
|
||||
}
|
||||
}
|
||||
@@ -412,6 +412,8 @@ impl Default for SpHeader {
|
||||
}
|
||||
|
||||
impl SpHeader {
|
||||
pub const HEADER_LEN: usize = CCSDS_HEADER_LEN;
|
||||
|
||||
#[inline]
|
||||
pub const fn new(packet_id: PacketId, psc: PacketSequenceControl, data_len: u16) -> Self {
|
||||
Self {
|
||||
@@ -424,8 +426,6 @@ impl SpHeader {
|
||||
|
||||
/// This constructor sets the sequence flag field to [SequenceFlags::Unsegmented] and the data
|
||||
/// length to 0.
|
||||
///
|
||||
/// This constructor will panic if the APID exceeds [MAX_APID].
|
||||
#[inline]
|
||||
pub const fn new_from_apid(apid: u11) -> Self {
|
||||
SpHeader {
|
||||
@@ -439,10 +439,6 @@ impl SpHeader {
|
||||
}
|
||||
}
|
||||
|
||||
/// This constructor panics if the passed APID exceeds [MAX_APID] or the passed packet sequence
|
||||
/// count exceeds [MAX_SEQ_COUNT].
|
||||
///
|
||||
/// The checked constructor variants can be used to avoid panics.
|
||||
#[inline]
|
||||
pub const fn new_from_fields(
|
||||
ptype: PacketType,
|
||||
@@ -460,7 +456,6 @@ impl SpHeader {
|
||||
}
|
||||
}
|
||||
|
||||
/// This is an unchecked constructor which can panic on invalid input.
|
||||
#[inline]
|
||||
pub const fn new_for_tm(
|
||||
apid: u11,
|
||||
@@ -471,7 +466,6 @@ impl SpHeader {
|
||||
Self::new_from_fields(PacketType::Tm, false, apid, seq_flags, seq_count, data_len)
|
||||
}
|
||||
|
||||
/// This is an unchecked constructor which can panic on invalid input.
|
||||
#[inline]
|
||||
pub const fn new_for_tc(
|
||||
apid: u11,
|
||||
@@ -483,16 +477,12 @@ impl SpHeader {
|
||||
}
|
||||
|
||||
/// Variant of [SpHeader::new_for_tc] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
||||
///
|
||||
/// This is an unchecked constructor which can panic on invalid input.
|
||||
#[inline]
|
||||
pub const fn new_for_unseg_tc(apid: u11, seq_count: u14, data_len: u16) -> Self {
|
||||
Self::new_for_tc(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||
}
|
||||
|
||||
/// Variant of [SpHeader::new_for_tm] which sets the sequence flag field to [SequenceFlags::Unsegmented].
|
||||
///
|
||||
/// This is an unchecked constructor which can panic on invalid input.
|
||||
#[inline]
|
||||
pub const fn new_for_unseg_tm(apid: u11, seq_count: u14, data_len: u16) -> Self {
|
||||
Self::new_for_tm(apid, SequenceFlags::Unsegmented, seq_count, data_len)
|
||||
@@ -508,7 +498,7 @@ impl SpHeader {
|
||||
/// Retrieve the total packet size based on the data length field
|
||||
#[inline]
|
||||
fn packet_len(&self) -> usize {
|
||||
usize::from(self.data_len()) + CCSDS_HEADER_LEN + 1
|
||||
usize::from(self.data_len()) + Self::HEADER_LEN + 1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -540,15 +530,15 @@ impl SpHeader {
|
||||
/// This function also returns the remaining part of the passed slice starting past the read
|
||||
/// CCSDS header.
|
||||
pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, &[u8]), ByteConversionError> {
|
||||
if buf.len() < CCSDS_HEADER_LEN {
|
||||
if buf.len() < Self::HEADER_LEN {
|
||||
return Err(ByteConversionError::FromSliceTooSmall {
|
||||
found: buf.len(),
|
||||
expected: CCSDS_HEADER_LEN,
|
||||
});
|
||||
}
|
||||
// Unwrap okay, this can not fail.
|
||||
let zc_header = zc::SpHeader::read_from_bytes(&buf[0..CCSDS_HEADER_LEN]).unwrap();
|
||||
Ok((Self::from(zc_header), &buf[CCSDS_HEADER_LEN..]))
|
||||
let zc_header = zc::SpHeader::read_from_bytes(&buf[0..Self::HEADER_LEN]).unwrap();
|
||||
Ok((Self::from(zc_header), &buf[Self::HEADER_LEN..]))
|
||||
}
|
||||
|
||||
/// Write the header to a raw buffer using big endian format. This function returns the
|
||||
@@ -557,7 +547,7 @@ impl SpHeader {
|
||||
&self,
|
||||
buf: &'a mut [u8],
|
||||
) -> Result<&'a mut [u8], ByteConversionError> {
|
||||
if buf.len() < CCSDS_HEADER_LEN {
|
||||
if buf.len() < Self::HEADER_LEN {
|
||||
return Err(ByteConversionError::FromSliceTooSmall {
|
||||
found: buf.len(),
|
||||
expected: CCSDS_HEADER_LEN,
|
||||
@@ -565,14 +555,14 @@ impl SpHeader {
|
||||
}
|
||||
let zc_header: zc::SpHeader = zc::SpHeader::from(*self);
|
||||
// Unwrap okay, this can not fail.
|
||||
zc_header.write_to(&mut buf[0..CCSDS_HEADER_LEN]).unwrap();
|
||||
Ok(&mut buf[CCSDS_HEADER_LEN..])
|
||||
zc_header.write_to(&mut buf[0..Self::HEADER_LEN]).unwrap();
|
||||
Ok(&mut buf[Self::HEADER_LEN..])
|
||||
}
|
||||
|
||||
/// Create a vector containing the CCSDS header.
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
|
||||
let mut vec = alloc::vec![0; CCSDS_HEADER_LEN];
|
||||
let mut vec = alloc::vec![0; Self::HEADER_LEN];
|
||||
// This can not fail.
|
||||
self.write_to_be_bytes(&mut vec[..]).unwrap();
|
||||
vec
|
||||
|
||||
Reference in New Issue
Block a user