add missing Error impls

This commit is contained in:
Robin Mueller
2025-09-10 17:48:10 +02:00
parent 4e153e0b68
commit a5dcba7d63
3 changed files with 46 additions and 83 deletions

View File

@@ -88,17 +88,10 @@ pub const CCSDS_HEADER_LEN: usize = core::mem::size_of::<crate::zc::SpHeader>();
pub const MAX_APID: u11 = u11::MAX;
pub const MAX_SEQ_COUNT: u14 = u14::MAX;
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[error("apid is out of range, maximum value is {MAX_APID}")]
pub struct ApidOutOfRangeError(u16);
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[error("apid is out of range, maximum value is {MAX_SEQ_COUNT}")]
pub struct SequenceCountOutOfRangeError(u16);
#[inline]
pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
}
/// Generic error type when converting to and from raw byte slices.
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
@@ -136,10 +129,6 @@ pub enum PacketType {
Tc = 1,
}
pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
}
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -203,22 +192,16 @@ impl Default for PacketId {
}
impl PacketId {
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked constructor variants to avoid panics.
#[inline]
pub const fn new_for_tc(sec_header: bool, apid: u11) -> Self {
Self::new(PacketType::Tc, sec_header, apid)
}
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked constructor variants to avoid panics.
#[inline]
pub const fn new_for_tm(sec_header: bool, apid: u11) -> Self {
Self::new(PacketType::Tm, sec_header, apid)
}
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked variants to avoid panics.
#[inline]
pub const fn new(ptype: PacketType, sec_header: bool, apid: u11) -> Self {
PacketId {

View File

@@ -5,11 +5,10 @@ use crate::{crc::CRC_CCITT_FALSE, ByteConversionError};
pub const USLP_VERSION_NUMBER: u8 = 0b1100;
/// Identifies the association of the data contained in the transfer frame.
#[derive(
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
)]
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitbybit::bitenum(u1, exhaustive = true)]
#[repr(u8)]
pub enum SourceOrDestField {
/// SCID refers to the source of the transfer frame.
@@ -18,11 +17,10 @@ pub enum SourceOrDestField {
Dest = 1,
}
#[derive(
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
)]
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitbybit::bitenum(u1, exhaustive = true)]
#[repr(u8)]
pub enum BypassSequenceControlFlag {
/// Acceptance of this frame on the receiving end is subject to normal frame acceptance
@@ -43,24 +41,26 @@ pub enum ProtocolControlCommandFlag {
TfdfContainsProtocolInfo = 1,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
pub enum UslpError {
ByteConversion(ByteConversionError),
#[error("byte conversion error: {0}")]
ByteConversion(#[from] ByteConversionError),
#[error("header is truncated, which is not supported")]
HeaderIsTruncated,
#[error("invalid protocol id: {0}")]
InvalidProtocolId(u8),
#[error("invalid construction rule: {0}")]
InvalidConstructionRule(u8),
#[error("invalid version number: {0}")]
InvalidVersionNumber(u8),
InvalidVcid(u8),
#[error("invalid virtual channel ID: {0}")]
InvalidVcId(u8),
#[error("invalid MAP ID: {0}")]
InvalidMapId(u8),
#[error("checksum failure")]
ChecksumFailure(u16),
}
impl From<ByteConversionError> for UslpError {
fn from(value: ByteConversionError) -> Self {
Self::ByteConversion(value)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -94,7 +94,7 @@ impl PrimaryHeader {
frame_len: u16,
) -> Result<Self, UslpError> {
if vc_id > 0b111111 {
return Err(UslpError::InvalidVcid(vc_id));
return Err(UslpError::InvalidVcId(vc_id));
}
if map_id > 0b1111 {
return Err(UslpError::InvalidMapId(map_id));
@@ -271,11 +271,10 @@ impl PartialEq for PrimaryHeader {
}
}
#[derive(
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
)]
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitbybit::bitenum(u5, exhaustive = false)]
#[repr(u8)]
#[non_exhaustive]
pub enum UslpProtocolId {
@@ -293,11 +292,10 @@ pub enum UslpProtocolId {
Idle = 0b11111,
}
#[derive(
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
)]
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitbybit::bitenum(u3, exhaustive = true)]
#[repr(u8)]
pub enum ConstructionRule {
/// Indicated fixed-length TFDZ whose contents are CCSDS packets concatenated together, which
@@ -339,7 +337,8 @@ pub struct TransferFrameDataFieldHeader {
}
impl TransferFrameDataFieldHeader {
pub fn len_header(&self) -> usize {
#[inline]
pub const fn len_header(&self) -> usize {
if self.construction_rule.applicable_to_fixed_len_tfdz() {
3
} else {
@@ -347,15 +346,18 @@ impl TransferFrameDataFieldHeader {
}
}
pub fn construction_rule(&self) -> ConstructionRule {
#[inline]
pub const fn construction_rule(&self) -> ConstructionRule {
self.construction_rule
}
pub fn uslp_protocol_id(&self) -> UslpProtocolId {
#[inline]
pub const fn uslp_protocol_id(&self) -> UslpProtocolId {
self.uslp_protocol_id
}
pub fn fhp_or_lvo(&self) -> Option<u16> {
#[inline]
pub const fn fhp_or_lvo(&self) -> Option<u16> {
self.fhp_or_lvo
}
@@ -449,22 +451,27 @@ impl<'buf> TransferFrameReader<'buf> {
})
}
#[inline]
pub fn len_frame(&self) -> usize {
self.primary_header.len_frame()
}
#[inline]
pub fn primary_header(&self) -> &PrimaryHeader {
&self.primary_header
}
#[inline]
pub fn data_field_header(&self) -> &TransferFrameDataFieldHeader {
&self.data_field_header
}
#[inline]
pub fn data(&self) -> &'buf [u8] {
self.data
}
#[inline]
pub fn operational_control_field(&self) -> &Option<u32> {
&self.operational_control_field
}
@@ -669,7 +676,7 @@ mod tests {
);
assert!(error.is_err());
let error = error.unwrap_err();
matches!(error, UslpError::InvalidVcid(0b1101011));
matches!(error, UslpError::InvalidVcId(0b1101011));
}
#[test]

View File

@@ -1,9 +1,7 @@
use crate::ByteConversionError;
use core::fmt::{Debug, Display, Formatter};
use core::fmt::Debug;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "std")]
use std::error::Error;
pub trait ToBeBytes {
type ByteArray: AsRef<[u8]>;
@@ -100,49 +98,24 @@ pub trait UnsignedEnum {
pub trait UnsignedEnumExt: UnsignedEnum + Debug + Copy + Clone + PartialEq + Eq {}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum UnsignedByteFieldError {
/// Value is too large for specified width of byte field.
ValueTooLargeForWidth {
width: usize,
value: u64,
},
#[error("value {value} too large for width {width}")]
ValueTooLargeForWidth { width: usize, value: u64 },
/// Only 1, 2, 4 and 8 are allow width values. Optionally contains the expected width if
/// applicable, for example for conversions.
#[error("invalid width {found}, expected {expected:?}")]
InvalidWidth {
found: usize,
expected: Option<usize>,
},
ByteConversionError(ByteConversionError),
#[error("byte conversion error: {0}")]
ByteConversionError(#[from] ByteConversionError),
}
impl From<ByteConversionError> for UnsignedByteFieldError {
#[inline]
fn from(value: ByteConversionError) -> Self {
Self::ByteConversionError(value)
}
}
impl Display for UnsignedByteFieldError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::ByteConversionError(e) => {
write!(f, "low level byte conversion error: {e}")
}
Self::InvalidWidth { found, .. } => {
write!(f, "invalid width {found}, only 1, 2, 4 and 8 are allowed.")
}
Self::ValueTooLargeForWidth { width, value } => {
write!(f, "value {value} too large for width {width}")
}
}
}
}
#[cfg(feature = "std")]
impl Error for UnsignedByteFieldError {}
/// Type erased variant.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]