invalid time code struct variant #26

Merged
muellerr merged 5 commits from invalid-time-code-struct-variant into main 2023-08-28 17:42:47 +02:00
16 changed files with 171 additions and 154 deletions
Showing only changes of commit 94c378fa3b - Show all commits

View File

@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed ## Changed
- The `Tlv` and `Lv` API return `&[u8]` instead of `Option<&[u8]>`. - The `Tlv` and `Lv` API return `&[u8]` instead of `Option<&[u8]>`.
- `ByteConversionError` error variants `ToSliceTooSmall` and `FromSliceTooSmall` are struct
variants now. `SizeMissmatch` was removed appropriately.
## Added ## Added
@ -25,6 +27,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added `pdu_datafield_len` getter function for `PduHeader` - Added `pdu_datafield_len` getter function for `PduHeader`
## Removed
- `SizeMissmatch` because it is not required for the `ByteConversionError` error enumeration
anymore.
# [v0.7.0-beta.0] 2023-08-16 # [v0.7.0-beta.0] 2023-08-16
- Moved MSRV from v1.60 to v1.61. - Moved MSRV from v1.60 to v1.61.

View File

@ -1,6 +1,6 @@
//! Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8. //! Generic CFDP length-value (LV) abstraction as specified in CFDP 5.1.8.
use crate::cfdp::TlvLvError; use crate::cfdp::TlvLvError;
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use core::str::Utf8Error; use core::str::Utf8Error;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -39,10 +39,10 @@ pub(crate) fn generic_len_check_data_serialization(
min_overhead: usize, min_overhead: usize,
) -> Result<(), ByteConversionError> { ) -> Result<(), ByteConversionError> {
if buf.len() < data_len + min_overhead { if buf.len() < data_len + min_overhead {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: data_len + min_overhead, expected: data_len + min_overhead,
})); });
} }
Ok(()) Ok(())
} }
@ -52,10 +52,10 @@ pub(crate) fn generic_len_check_deserialization(
min_overhead: usize, min_overhead: usize,
) -> Result<(), ByteConversionError> { ) -> Result<(), ByteConversionError> {
if buf.len() < min_overhead { if buf.len() < min_overhead {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: min_overhead, expected: min_overhead,
})); });
} }
Ok(()) Ok(())
} }
@ -272,9 +272,9 @@ pub mod tests {
let res = lv.write_to_be_bytes(&mut buf); let res = lv.write_to_be_bytes(&mut buf);
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
if let ByteConversionError::ToSliceTooSmall(missmatch) = error { if let ByteConversionError::ToSliceTooSmall { found, expected } = error {
assert_eq!(missmatch.expected, 5); assert_eq!(expected, 5);
assert_eq!(missmatch.found, 3); assert_eq!(found, 3);
} else { } else {
panic!("invalid error {}", error); panic!("invalid error {}", error);
} }
@ -287,9 +287,9 @@ pub mod tests {
let res = Lv::from_bytes(&buf); let res = Lv::from_bytes(&buf);
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
if let ByteConversionError::FromSliceTooSmall(missmatch) = error { if let ByteConversionError::FromSliceTooSmall { found, expected } = error {
assert_eq!(missmatch.found, 3); assert_eq!(found, 3);
assert_eq!(missmatch.expected, 5); assert_eq!(expected, 5);
} else { } else {
panic!("invalid error {}", error); panic!("invalid error {}", error);
} }

View File

@ -4,7 +4,7 @@ use crate::cfdp::pdu::{
}; };
use crate::cfdp::tlv::EntityIdTlv; use crate::cfdp::tlv::EntityIdTlv;
use crate::cfdp::{ConditionCode, CrcFlag, LargeFileFlag}; use crate::cfdp::{ConditionCode, CrcFlag, LargeFileFlag};
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -69,10 +69,10 @@ impl EofPdu {
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> { pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
let expected_len = self.written_len(); let expected_len = self.written_len();
if buf.len() < expected_len { if buf.len() < expected_len {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: expected_len, expected: expected_len,
}) }
.into()); .into());
} }
let mut current_idx = self.pdu_header.write_to_bytes(buf)?; let mut current_idx = self.pdu_header.write_to_bytes(buf)?;

View File

@ -3,7 +3,7 @@ use crate::cfdp::pdu::{
PduError, PduHeader, PduError, PduHeader,
}; };
use crate::cfdp::{CrcFlag, LargeFileFlag, PduType, SegmentMetadataFlag}; use crate::cfdp::{CrcFlag, LargeFileFlag, PduType, SegmentMetadataFlag};
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -48,10 +48,10 @@ impl<'seg_meta> SegmentMetadata<'seg_meta> {
pub(crate) fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> { pub(crate) fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
if buf.len() < self.written_len() { if buf.len() < self.written_len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: self.written_len(), expected: self.written_len(),
})); });
} }
buf[0] = ((self.record_continuation_state as u8) << 6) buf[0] = ((self.record_continuation_state as u8) << 6)
| self.metadata.map_or(0, |meta| meta.len() as u8); | self.metadata.map_or(0, |meta| meta.len() as u8);
@ -63,10 +63,10 @@ impl<'seg_meta> SegmentMetadata<'seg_meta> {
pub(crate) fn from_bytes(buf: &'seg_meta [u8]) -> Result<Self, ByteConversionError> { pub(crate) fn from_bytes(buf: &'seg_meta [u8]) -> Result<Self, ByteConversionError> {
if buf.is_empty() { if buf.is_empty() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: 2, expected: 2,
})); });
} }
let mut metadata = None; let mut metadata = None;
let seg_metadata_len = (buf[0] & 0b111111) as usize; let seg_metadata_len = (buf[0] & 0b111111) as usize;
@ -165,10 +165,10 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> { pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
if buf.len() < self.written_len() { if buf.len() < self.written_len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: self.written_len(), expected: self.written_len(),
}) }
.into()); .into());
} }
let mut current_idx = self.pdu_header.write_to_bytes(buf)?; let mut current_idx = self.pdu_header.write_to_bytes(buf)?;
@ -207,10 +207,10 @@ impl<'seg_meta, 'file_data> FileDataPdu<'seg_meta, 'file_data> {
let (fss, offset) = read_fss_field(pdu_header.pdu_conf.file_flag, &buf[current_idx..]); let (fss, offset) = read_fss_field(pdu_header.pdu_conf.file_flag, &buf[current_idx..]);
current_idx += fss; current_idx += fss;
if current_idx > full_len_without_crc { if current_idx > full_len_without_crc {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: current_idx, found: current_idx,
expected: full_len_without_crc, expected: full_len_without_crc,
}) }
.into()); .into());
} }
Ok(Self { Ok(Self {

View File

@ -3,7 +3,7 @@ use crate::cfdp::pdu::{
}; };
use crate::cfdp::tlv::{EntityIdTlv, Tlv, TlvType, TlvTypeField}; use crate::cfdp::tlv::{EntityIdTlv, Tlv, TlvType, TlvTypeField};
use crate::cfdp::{ConditionCode, CrcFlag, PduType, TlvLvError}; use crate::cfdp::{ConditionCode, CrcFlag, PduType, TlvLvError};
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -136,10 +136,10 @@ impl<'fs_responses> FinishedPdu<'fs_responses> {
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> { pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
let expected_len = self.written_len(); let expected_len = self.written_len();
if buf.len() < expected_len { if buf.len() < expected_len {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: expected_len, expected: expected_len,
}) }
.into()); .into());
} }

View File

@ -5,7 +5,7 @@ use crate::cfdp::pdu::{
}; };
use crate::cfdp::tlv::Tlv; use crate::cfdp::tlv::Tlv;
use crate::cfdp::{ChecksumType, CrcFlag, LargeFileFlag, PduType}; use crate::cfdp::{ChecksumType, CrcFlag, LargeFileFlag, PduType};
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -201,10 +201,10 @@ impl<'src_name, 'dest_name, 'opts> MetadataPdu<'src_name, 'dest_name, 'opts> {
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> { pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, PduError> {
let expected_len = self.written_len(); let expected_len = self.written_len();
if buf.len() < expected_len { if buf.len() < expected_len {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: expected_len, expected: expected_len,
}) }
.into()); .into());
} }

View File

@ -1,8 +1,8 @@
//! CFDP Packet Data Unit (PDU) support. //! CFDP Packet Data Unit (PDU) support.
use crate::cfdp::*; use crate::cfdp::*;
use crate::util::{UnsignedByteField, UnsignedByteFieldU8, UnsignedEnum}; use crate::util::{UnsignedByteField, UnsignedByteFieldU8, UnsignedEnum};
use crate::ByteConversionError;
use crate::CRC_CCITT_FALSE; use crate::CRC_CCITT_FALSE;
use crate::{ByteConversionError, SizeMissmatch};
use core::fmt::{Display, Formatter}; use core::fmt::{Display, Formatter};
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::error::Error; use std::error::Error;
@ -369,10 +369,10 @@ impl PduHeader {
+ self.pdu_conf.source_entity_id.size() + self.pdu_conf.source_entity_id.size()
+ self.pdu_conf.transaction_seq_num.size() + self.pdu_conf.transaction_seq_num.size()
{ {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: FIXED_HEADER_LEN, expected: FIXED_HEADER_LEN,
}) }
.into()); .into());
} }
let mut current_idx = 0; let mut current_idx = 0;
@ -413,10 +413,10 @@ impl PduHeader {
/// flag is not set, it will simply return the PDU length. /// flag is not set, it will simply return the PDU length.
pub fn verify_length_and_checksum(&self, buf: &[u8]) -> Result<usize, PduError> { pub fn verify_length_and_checksum(&self, buf: &[u8]) -> Result<usize, PduError> {
if buf.len() < self.pdu_len() { if buf.len() < self.pdu_len() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: self.pdu_len(), expected: self.pdu_len(),
}) }
.into()); .into());
} }
if self.pdu_conf.crc_flag == CrcFlag::WithCrc { if self.pdu_conf.crc_flag == CrcFlag::WithCrc {
@ -443,10 +443,10 @@ impl PduHeader {
pub fn from_bytes(buf: &[u8]) -> Result<(Self, usize), PduError> { pub fn from_bytes(buf: &[u8]) -> Result<(Self, usize), PduError> {
if buf.len() < FIXED_HEADER_LEN { if buf.len() < FIXED_HEADER_LEN {
return Err(PduError::ByteConversionError( return Err(PduError::ByteConversionError(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: FIXED_HEADER_LEN, expected: FIXED_HEADER_LEN,
}), },
)); ));
} }
let cfdp_version_raw = (buf[0] >> 5) & 0b111; let cfdp_version_raw = (buf[0] >> 5) & 0b111;
@ -481,10 +481,10 @@ impl PduHeader {
)); ));
} }
if buf.len() < (4 + 2 * expected_len_entity_ids + expected_len_seq_num) { if buf.len() < (4 + 2 * expected_len_entity_ids + expected_len_seq_num) {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: 4 + 2 * expected_len_entity_ids + expected_len_seq_num, expected: 4 + 2 * expected_len_entity_ids + expected_len_seq_num,
}) }
.into()); .into());
} }
let mut current_idx = 4; let mut current_idx = 4;
@ -580,17 +580,17 @@ pub(crate) fn generic_length_checks_pdu_deserialization(
) -> Result<(), ByteConversionError> { ) -> Result<(), ByteConversionError> {
// Buffer too short to hold additional expected minimum datasize. // Buffer too short to hold additional expected minimum datasize.
if buf.len() < min_expected_len { if buf.len() < min_expected_len {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: min_expected_len, expected: min_expected_len,
})); });
} }
// This can happen if the PDU datafield length value is invalid. // This can happen if the PDU datafield length value is invalid.
if full_len_without_crc < min_expected_len { if full_len_without_crc < min_expected_len {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: full_len_without_crc, found: full_len_without_crc,
expected: min_expected_len, expected: min_expected_len,
})); });
} }
Ok(()) Ok(())
} }
@ -862,11 +862,13 @@ mod tests {
let res = PduHeader::from_bytes(&buf); let res = PduHeader::from_bytes(&buf);
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall(missmatch)) = if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall {
error found,
expected,
}) = error
{ {
assert_eq!(missmatch.found, 3); assert_eq!(found, 3);
assert_eq!(missmatch.expected, FIXED_HEADER_LEN); assert_eq!(expected, FIXED_HEADER_LEN);
} else { } else {
panic!("invalid exception: {}", error); panic!("invalid exception: {}", error);
} }
@ -886,11 +888,13 @@ mod tests {
let header = PduHeader::from_bytes(&buf[0..6]); let header = PduHeader::from_bytes(&buf[0..6]);
assert!(header.is_err()); assert!(header.is_err());
let error = header.unwrap_err(); let error = header.unwrap_err();
if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall(missmatch)) = if let PduError::ByteConversionError(ByteConversionError::FromSliceTooSmall {
error found,
expected,
}) = error
{ {
assert_eq!(missmatch.found, 6); assert_eq!(found, 6);
assert_eq!(missmatch.expected, 7); assert_eq!(expected, 7);
} }
} }

View File

@ -4,7 +4,7 @@ use crate::cfdp::lv::{
}; };
use crate::cfdp::TlvLvError; use crate::cfdp::TlvLvError;
use crate::util::{UnsignedByteField, UnsignedByteFieldError, UnsignedEnum}; use crate::util::{UnsignedByteField, UnsignedByteFieldError, UnsignedEnum};
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_enum::{IntoPrimitive, TryFromPrimitive};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -200,10 +200,10 @@ impl EntityIdTlv {
fn len_check(buf: &[u8]) -> Result<(), ByteConversionError> { fn len_check(buf: &[u8]) -> Result<(), ByteConversionError> {
if buf.len() < 2 { if buf.len() < 2 {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: 2, expected: 2,
})); });
} }
Ok(()) Ok(())
} }
@ -422,10 +422,10 @@ impl<'first_name, 'second_name> FilestoreRequestTlv<'first_name, 'second_name> {
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> { pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
if buf.len() < self.len_full() { if buf.len() < self.len_full() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: self.len_full(), expected: self.len_full(),
})); });
} }
buf[0] = TlvType::FilestoreRequest as u8; buf[0] = TlvType::FilestoreRequest as u8;
buf[1] = self.len_value() as u8; buf[1] = self.len_value() as u8;
@ -449,10 +449,10 @@ impl<'first_name, 'second_name> FilestoreRequestTlv<'first_name, 'second_name> {
buf: &'longest [u8], buf: &'longest [u8],
) -> Result<Self, TlvLvError> { ) -> Result<Self, TlvLvError> {
if buf.len() < 2 { if buf.len() < 2 {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: 2, expected: 2,
}) }
.into()); .into());
} }
verify_tlv_type(buf[0], TlvType::FilestoreRequest)?; verify_tlv_type(buf[0], TlvType::FilestoreRequest)?;

View File

@ -397,9 +397,9 @@ mod tests {
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
match error { match error {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.expected, 2); assert_eq!(expected, 2);
assert_eq!(missmatch.found, 1); assert_eq!(found, 1);
} }
_ => { _ => {
panic!("Unexpected error {:?}", error); panic!("Unexpected error {:?}", error);
@ -428,9 +428,9 @@ mod tests {
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
match error { match error {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.expected, 4); assert_eq!(expected, 4);
assert_eq!(missmatch.found, 3); assert_eq!(found, 3);
} }
_ => { _ => {
panic!("Unexpected error {:?}", error); panic!("Unexpected error {:?}", error);

View File

@ -36,9 +36,7 @@ use crate::ecss::{
verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, PusError, PusPacket, PusVersion, verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, PusError, PusPacket, PusVersion,
SerializablePusPacket, SerializablePusPacket,
}; };
use crate::{ use crate::{ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, CCSDS_HEADER_LEN};
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN,
};
use crate::{SpHeader, CRC_CCITT_FALSE}; use crate::{SpHeader, CRC_CCITT_FALSE};
use core::mem::size_of; use core::mem::size_of;
use delegate::delegate; use delegate::delegate;
@ -223,9 +221,7 @@ pub mod legacy_tc {
}; };
use crate::ecss::{user_data_from_raw, PusVersion}; use crate::ecss::{user_data_from_raw, PusVersion};
use crate::SequenceFlags; use crate::SequenceFlags;
use crate::{ use crate::{ByteConversionError, CcsdsPacket, PacketType, SpHeader, CRC_CCITT_FALSE};
ByteConversionError, CcsdsPacket, PacketType, SizeMissmatch, SpHeader, CRC_CCITT_FALSE,
};
use core::mem::size_of; use core::mem::size_of;
use delegate::delegate; use delegate::delegate;
use zerocopy::AsBytes; use zerocopy::AsBytes;
@ -462,10 +458,10 @@ pub mod legacy_tc {
let tc_header_len = size_of::<zc::PusTcSecondaryHeader>(); let tc_header_len = size_of::<zc::PusTcSecondaryHeader>();
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
}) }
.into()); .into());
} }
self.sp_header.write_to_be_bytes(slice)?; self.sp_header.write_to_be_bytes(slice)?;
@ -668,10 +664,10 @@ impl SerializablePusPacket for PusTcCreator<'_> {
let tc_header_len = size_of::<zc::PusTcSecondaryHeader>(); let tc_header_len = size_of::<zc::PusTcSecondaryHeader>();
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
}) }
.into()); .into());
} }
self.sp_header.write_to_be_bytes(slice)?; self.sp_header.write_to_be_bytes(slice)?;
@ -996,9 +992,9 @@ mod tests {
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
PusError::ByteConversion(err) => match err { PusError::ByteConversion(err) => match err {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.expected, pus_tc.len_packed()); assert_eq!(expected, pus_tc.len_packed());
assert_eq!(missmatch.found, 12); assert_eq!(found, 12);
} }
_ => panic!("Unexpected error"), _ => panic!("Unexpected error"),
}, },

View File

@ -6,8 +6,8 @@ use crate::ecss::{
SerializablePusPacket, SerializablePusPacket,
}; };
use crate::{ use crate::{
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, SpHeader, ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SpHeader, CCSDS_HEADER_LEN,
CCSDS_HEADER_LEN, CRC_CCITT_FALSE, MAX_APID, MAX_SEQ_COUNT, CRC_CCITT_FALSE, MAX_APID, MAX_SEQ_COUNT,
}; };
use core::mem::size_of; use core::mem::size_of;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -207,9 +207,7 @@ pub mod legacy_tm {
CCSDS_HEADER_LEN, CCSDS_HEADER_LEN,
}; };
use crate::SequenceFlags; use crate::SequenceFlags;
use crate::{ use crate::{ByteConversionError, CcsdsPacket, PacketType, SpHeader, CRC_CCITT_FALSE};
ByteConversionError, CcsdsPacket, PacketType, SizeMissmatch, SpHeader, CRC_CCITT_FALSE,
};
use core::mem::size_of; use core::mem::size_of;
use zerocopy::AsBytes; use zerocopy::AsBytes;
@ -436,10 +434,10 @@ pub mod legacy_tm {
let mut curr_idx = 0; let mut curr_idx = 0;
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
}) }
.into()); .into());
} }
self.sp_header self.sp_header
@ -663,10 +661,10 @@ impl SerializablePusPacket for PusTmCreator<'_> {
let mut curr_idx = 0; let mut curr_idx = 0;
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
}) }
.into()); .into());
} }
self.sp_header self.sp_header
@ -1055,9 +1053,9 @@ mod tests {
assert!(matches!(error, PusError::ByteConversion { .. })); assert!(matches!(error, PusError::ByteConversion { .. }));
match error { match error {
PusError::ByteConversion(err) => match err { PusError::ByteConversion(err) => match err {
ByteConversionError::ToSliceTooSmall(size_missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(size_missmatch.expected, 22); assert_eq!(expected, 22);
assert_eq!(size_missmatch.found, 16); assert_eq!(found, 16);
} }
_ => panic!("Invalid PUS error {:?}", err), _ => panic!("Invalid PUS error {:?}", err),
}, },

View File

@ -87,20 +87,20 @@ pub const CRC_CCITT_FALSE: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_3740);
pub const MAX_APID: u16 = 2u16.pow(11) - 1; pub const MAX_APID: u16 = 2u16.pow(11) - 1;
pub const MAX_SEQ_COUNT: u16 = 2u16.pow(14) - 1; pub const MAX_SEQ_COUNT: u16 = 2u16.pow(14) - 1;
#[derive(Debug, Copy, Clone, PartialEq, Eq)] /// Generic error type when converting to and from raw byte slices.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SizeMissmatch {
pub found: usize,
pub expected: usize,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ByteConversionError { pub enum ByteConversionError {
/// The passed slice is too small. Returns the passed slice length and expected minimum size /// The passed slice is too small. Returns the passed slice length and expected minimum size
ToSliceTooSmall(SizeMissmatch), ToSliceTooSmall {
found: usize,
expected: usize,
},
/// The provider buffer is too small. Returns the passed slice length and expected minimum size /// The provider buffer is too small. Returns the passed slice length and expected minimum size
FromSliceTooSmall(SizeMissmatch), FromSliceTooSmall {
found: usize,
expected: usize,
},
/// The [zerocopy] library failed to write to bytes /// The [zerocopy] library failed to write to bytes
ZeroCopyToError, ZeroCopyToError,
ZeroCopyFromError, ZeroCopyFromError,
@ -109,18 +109,18 @@ pub enum ByteConversionError {
impl Display for ByteConversionError { impl Display for ByteConversionError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self { match self {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
write!( write!(
f, f,
"target slice with size {} is too small, expected size of at least {}", "target slice with size {} is too small, expected size of at least {}",
missmatch.found, missmatch.expected found, expected
) )
} }
ByteConversionError::FromSliceTooSmall(missmatch) => { ByteConversionError::FromSliceTooSmall { found, expected } => {
write!( write!(
f, f,
"source slice with size {} too small, expected at least {} bytes", "source slice with size {} too small, expected at least {} bytes",
missmatch.found, missmatch.expected found, expected
) )
} }
ByteConversionError::ZeroCopyToError => { ByteConversionError::ZeroCopyToError => {
@ -564,10 +564,10 @@ impl SpHeader {
/// CCSDS header. /// CCSDS header.
pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, &[u8]), ByteConversionError> { pub fn from_be_bytes(buf: &[u8]) -> Result<(Self, &[u8]), ByteConversionError> {
if buf.len() < CCSDS_HEADER_LEN { if buf.len() < CCSDS_HEADER_LEN {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: CCSDS_HEADER_LEN, expected: CCSDS_HEADER_LEN,
})); });
} }
let zc_header = zc::SpHeader::from_bytes(&buf[0..CCSDS_HEADER_LEN]) let zc_header = zc::SpHeader::from_bytes(&buf[0..CCSDS_HEADER_LEN])
.ok_or(ByteConversionError::ZeroCopyFromError)?; .ok_or(ByteConversionError::ZeroCopyFromError)?;
@ -581,10 +581,10 @@ impl SpHeader {
buf: &'a mut [u8], buf: &'a mut [u8],
) -> Result<&'a mut [u8], ByteConversionError> { ) -> Result<&'a mut [u8], ByteConversionError> {
if buf.len() < CCSDS_HEADER_LEN { if buf.len() < CCSDS_HEADER_LEN {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: CCSDS_HEADER_LEN, expected: CCSDS_HEADER_LEN,
})); });
} }
let zc_header: zc::SpHeader = zc::SpHeader::from(*self); let zc_header: zc::SpHeader = zc::SpHeader::from(*self);
zc_header zc_header

View File

@ -515,10 +515,10 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
) -> Result<SubmillisPrecision, TimestampError> { ) -> Result<SubmillisPrecision, TimestampError> {
if buf.len() < MIN_CDS_FIELD_LEN { if buf.len() < MIN_CDS_FIELD_LEN {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall {
expected: MIN_CDS_FIELD_LEN, expected: MIN_CDS_FIELD_LEN,
found: buf.len(), found: buf.len(),
}), },
)); ));
} }
let pfield = buf[0]; let pfield = buf[0];
@ -549,10 +549,10 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
let stamp_len = Self::calc_stamp_len(pfield); let stamp_len = Self::calc_stamp_len(pfield);
if buf.len() < stamp_len { if buf.len() < stamp_len {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall {
expected: stamp_len, expected: stamp_len,
found: buf.len(), found: buf.len(),
}), },
)); ));
} }
Ok(precision_from_pfield(pfield)) Ok(precision_from_pfield(pfield))
@ -606,10 +606,10 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), TimestampError> { fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), TimestampError> {
if buf.len() < len_as_bytes { if buf.len() < len_as_bytes {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::ToSliceTooSmall(SizeMissmatch { ByteConversionError::ToSliceTooSmall {
expected: len_as_bytes, expected: len_as_bytes,
found: buf.len(), found: buf.len(),
}), },
)); ));
} }
Ok(()) Ok(())
@ -1448,9 +1448,9 @@ mod tests {
let res = time_stamper.write_to_bytes(&mut buf[0..i]); let res = time_stamper.write_to_bytes(&mut buf[0..i]);
assert!(res.is_err()); assert!(res.is_err());
match res.unwrap_err() { match res.unwrap_err() {
ByteConversion(ToSliceTooSmall(missmatch)) => { ByteConversion(ToSliceTooSmall { found, expected }) => {
assert_eq!(missmatch.found, i); assert_eq!(found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(expected, 7);
} }
_ => panic!( _ => panic!(
"{}", "{}",
@ -1469,9 +1469,9 @@ mod tests {
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
ByteConversion(e) => match e { ByteConversion(e) => match e {
FromSliceTooSmall(missmatch) => { FromSliceTooSmall { found, expected } => {
assert_eq!(missmatch.found, i); assert_eq!(found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(expected, 7);
} }
_ => panic!("{}", format!("Invalid error {:?} detected", e)), _ => panic!("{}", format!("Invalid error {:?} detected", e)),
}, },
@ -1764,7 +1764,7 @@ mod tests {
fn generic_dt_case_1_us_prec(subsec_millis: u32) -> DateTime<Utc> { fn generic_dt_case_1_us_prec(subsec_millis: u32) -> DateTime<Utc> {
// 250 ms + 500 us // 250 ms + 500 us
let subsec_micros = subsec_millis * 1000 + 500; let subsec_micros = subsec_millis * 1000 + 500;
let naivedatetime_utc = NaiveDate::from_ymd_opt(2023, 01, 14) let naivedatetime_utc = NaiveDate::from_ymd_opt(2023, 1, 14)
.unwrap() .unwrap()
.and_hms_micro_opt(16, 49, 30, subsec_micros) .and_hms_micro_opt(16, 49, 30, subsec_micros)
.unwrap(); .unwrap();
@ -1815,7 +1815,7 @@ mod tests {
// 250 ms + 500 us // 250 ms + 500 us
let subsec_nanos = subsec_millis * 1000 * 1000 + 500 * 1000; let subsec_nanos = subsec_millis * 1000 * 1000 + 500 * 1000;
let submilli_nanos = subsec_nanos % 10_u32.pow(6); let submilli_nanos = subsec_nanos % 10_u32.pow(6);
let naivedatetime_utc = NaiveDate::from_ymd_opt(2023, 01, 14) let naivedatetime_utc = NaiveDate::from_ymd_opt(2023, 1, 14)
.unwrap() .unwrap()
.and_hms_nano_opt(16, 49, 30, subsec_nanos) .and_hms_nano_opt(16, 49, 30, subsec_nanos)
.unwrap(); .unwrap();

View File

@ -454,10 +454,10 @@ impl TimeReader for TimeProviderCcsdsEpoch {
{ {
if buf.len() < MIN_CUC_LEN { if buf.len() < MIN_CUC_LEN {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall {
expected: MIN_CUC_LEN, expected: MIN_CUC_LEN,
found: buf.len(), found: buf.len(),
}), },
)); ));
} }
match ccsds_time_code_from_p_field(buf[0]) { match ccsds_time_code_from_p_field(buf[0]) {
@ -480,10 +480,10 @@ impl TimeReader for TimeProviderCcsdsEpoch {
Self::len_components_and_total_from_pfield(buf[0]); Self::len_components_and_total_from_pfield(buf[0]);
if buf.len() < total_len { if buf.len() < total_len {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall {
expected: total_len, expected: total_len,
found: buf.len(), found: buf.len(),
}), },
)); ));
} }
let mut current_idx = 1; let mut current_idx = 1;
@ -536,10 +536,10 @@ impl TimeWriter for TimeProviderCcsdsEpoch {
// Cross check the sizes of the counters against byte widths in the ctor // Cross check the sizes of the counters against byte widths in the ctor
if bytes.len() < self.len_as_bytes() { if bytes.len() < self.len_as_bytes() {
return Err(TimestampError::ByteConversion( return Err(TimestampError::ByteConversion(
ByteConversionError::ToSliceTooSmall(SizeMissmatch { ByteConversionError::ToSliceTooSmall {
found: bytes.len(), found: bytes.len(),
expected: self.len_as_bytes(), expected: self.len_as_bytes(),
}), },
)); ));
} }
bytes[0] = self.pfield; bytes[0] = self.pfield;
@ -797,9 +797,13 @@ mod tests {
let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]); let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]);
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err { if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall {
assert_eq!(e.found, i); found,
assert_eq!(e.expected, 2); expected,
}) = err
{
assert_eq!(found, i);
assert_eq!(expected, 2);
} }
} }
let large_stamp = TimeProviderCcsdsEpoch::new_with_fine_fractions(22, 300).unwrap(); let large_stamp = TimeProviderCcsdsEpoch::new_with_fine_fractions(22, 300).unwrap();
@ -808,9 +812,13 @@ mod tests {
let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]); let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]);
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err { if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall {
assert_eq!(e.found, i); found,
assert_eq!(e.expected, large_stamp.len_as_bytes()); expected,
}) = err
{
assert_eq!(found, i);
assert_eq!(expected, large_stamp.len_as_bytes());
} }
} }
} }
@ -882,9 +890,13 @@ mod tests {
let err = cuc.write_to_bytes(&mut buf[0..i]); let err = cuc.write_to_bytes(&mut buf[0..i]);
assert!(err.is_err()); assert!(err.is_err());
let err = err.unwrap_err(); let err = err.unwrap_err();
if let TimestampError::ByteConversion(ByteConversionError::ToSliceTooSmall(e)) = err { if let TimestampError::ByteConversion(ByteConversionError::ToSliceTooSmall {
assert_eq!(e.expected, cuc.len_as_bytes()); found,
assert_eq!(e.found, i); expected,
}) = err
{
assert_eq!(expected, cuc.len_as_bytes());
assert_eq!(found, i);
} else { } else {
panic!("unexpected error: {}", err); panic!("unexpected error: {}", err);
} }

View File

@ -1,5 +1,5 @@
//! CCSDS Time Code Formats according to [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf) //! CCSDS Time Code Formats according to [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf)
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use chrono::{DateTime, LocalResult, TimeZone, Utc}; use chrono::{DateTime, LocalResult, TimeZone, Utc};
use core::cmp::Ordering; use core::cmp::Ordering;
use core::fmt::{Display, Formatter}; use core::fmt::{Display, Formatter};

View File

@ -1,4 +1,4 @@
use crate::{ByteConversionError, SizeMissmatch}; use crate::ByteConversionError;
use core::fmt::{Debug, Display, Formatter}; use core::fmt::{Debug, Display, Formatter};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -133,10 +133,10 @@ impl UnsignedByteField {
pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> { pub fn new_from_be_bytes(width: usize, buf: &[u8]) -> Result<Self, UnsignedByteFieldError> {
if width > buf.len() { if width > buf.len() {
return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall {
expected: width, expected: width,
found: buf.len(), found: buf.len(),
}) }
.into()); .into());
} }
match width { match width {
@ -166,10 +166,10 @@ impl UnsignedEnum for UnsignedByteField {
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> { fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
if buf.len() < self.size() { if buf.len() < self.size() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
expected: self.size(), expected: self.size(),
found: buf.len(), found: buf.len(),
})); });
} }
match self.size() { match self.size() {
0 => Ok(0), 0 => Ok(0),
@ -216,10 +216,10 @@ impl<TYPE: ToBeBytes> UnsignedEnum for GenericUnsignedByteField<TYPE> {
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> { fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
if buf.len() < self.size() { if buf.len() < self.size() {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall {
found: buf.len(), found: buf.len(),
expected: self.size(), expected: self.size(),
})); });
} }
buf[0..self.size()].copy_from_slice(self.value.to_be_bytes().as_ref()); buf[0..self.size()].copy_from_slice(self.value.to_be_bytes().as_ref());
Ok(self.value.written_len()) Ok(self.value.written_len())
@ -582,9 +582,9 @@ pub mod tests {
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.found, 1); assert_eq!(found, 1);
assert_eq!(missmatch.expected, 2); assert_eq!(expected, 2);
} }
_ => { _ => {
panic!("invalid exception") panic!("invalid exception")
@ -600,9 +600,9 @@ pub mod tests {
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.found, 1); assert_eq!(found, 1);
assert_eq!(missmatch.expected, 2); assert_eq!(expected, 2);
} }
_ => { _ => {
panic!("invalid exception {}", err) panic!("invalid exception {}", err)
@ -612,11 +612,11 @@ pub mod tests {
assert!(u16.is_err()); assert!(u16.is_err());
let err = u16.unwrap_err(); let err = u16.unwrap_err();
if let UnsignedByteFieldError::ByteConversionError( if let UnsignedByteFieldError::ByteConversionError(
ByteConversionError::FromSliceTooSmall(missmatch), ByteConversionError::FromSliceTooSmall { found, expected },
) = err ) = err
{ {
assert_eq!(missmatch.expected, 2); assert_eq!(expected, 2);
assert_eq!(missmatch.found, 1); assert_eq!(found, 1);
} else { } else {
panic!("unexpected exception {}", err); panic!("unexpected exception {}", err);
} }
@ -630,9 +630,9 @@ pub mod tests {
assert!(res.is_err()); assert!(res.is_err());
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall { found, expected } => {
assert_eq!(missmatch.found, 3); assert_eq!(found, 3);
assert_eq!(missmatch.expected, 4); assert_eq!(expected, 4);
} }
_ => { _ => {
panic!("invalid exception") panic!("invalid exception")