diff --git a/src/lib.rs b/src/lib.rs index 74570b3..a622c50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,17 +88,10 @@ pub const CCSDS_HEADER_LEN: usize = core::mem::size_of::(); 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 { diff --git a/src/uslp/mod.rs b/src/uslp/mod.rs index d6f6555..ddae21f 100644 --- a/src/uslp/mod.rs +++ b/src/uslp/mod.rs @@ -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 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 { 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 { + #[inline] + pub const fn fhp_or_lvo(&self) -> Option { 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 { &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] diff --git a/src/util.rs b/src/util.rs index 46ac63c..5680808 100644 --- a/src/util.rs +++ b/src/util.rs @@ -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,50 +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, }, - ByteConversionError(ByteConversionError), + #[error("byte conversion error: {0}")] + ByteConversionError(#[from] ByteConversionError), } -impl From 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))]