add missing Error impls #150
25
src/lib.rs
25
src/lib.rs
@@ -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_APID: u11 = u11::MAX;
|
||||||
pub const MAX_SEQ_COUNT: u14 = u14::MAX;
|
pub const MAX_SEQ_COUNT: u14 = u14::MAX;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
#[inline]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
|
||||||
#[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);
|
|
||||||
|
|
||||||
/// Generic error type when converting to and from raw byte slices.
|
/// Generic error type when converting to and from raw byte slices.
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
||||||
@@ -136,10 +129,6 @@ pub enum PacketType {
|
|||||||
Tc = 1,
|
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)]
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@@ -203,22 +192,16 @@ impl Default for PacketId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PacketId {
|
impl PacketId {
|
||||||
/// This constructor will panic if the passed APID exceeds [MAX_APID].
|
|
||||||
/// Use the checked constructor variants to avoid panics.
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub const fn new_for_tc(sec_header: bool, apid: u11) -> Self {
|
pub const fn new_for_tc(sec_header: bool, apid: u11) -> Self {
|
||||||
Self::new(PacketType::Tc, sec_header, apid)
|
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]
|
#[inline]
|
||||||
pub const fn new_for_tm(sec_header: bool, apid: u11) -> Self {
|
pub const fn new_for_tm(sec_header: bool, apid: u11) -> Self {
|
||||||
Self::new(PacketType::Tm, sec_header, apid)
|
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]
|
#[inline]
|
||||||
pub const fn new(ptype: PacketType, sec_header: bool, apid: u11) -> Self {
|
pub const fn new(ptype: PacketType, sec_header: bool, apid: u11) -> Self {
|
||||||
PacketId {
|
PacketId {
|
||||||
|
|||||||
@@ -5,11 +5,10 @@ use crate::{crc::CRC_CCITT_FALSE, ByteConversionError};
|
|||||||
pub const USLP_VERSION_NUMBER: u8 = 0b1100;
|
pub const USLP_VERSION_NUMBER: u8 = 0b1100;
|
||||||
|
|
||||||
/// Identifies the association of the data contained in the transfer frame.
|
/// Identifies the association of the data contained in the transfer frame.
|
||||||
#[derive(
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
|
||||||
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum SourceOrDestField {
|
pub enum SourceOrDestField {
|
||||||
/// SCID refers to the source of the transfer frame.
|
/// SCID refers to the source of the transfer frame.
|
||||||
@@ -18,11 +17,10 @@ pub enum SourceOrDestField {
|
|||||||
Dest = 1,
|
Dest = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
|
||||||
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[bitbybit::bitenum(u1, exhaustive = true)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum BypassSequenceControlFlag {
|
pub enum BypassSequenceControlFlag {
|
||||||
/// Acceptance of this frame on the receiving end is subject to normal frame acceptance
|
/// Acceptance of this frame on the receiving end is subject to normal frame acceptance
|
||||||
@@ -43,24 +41,26 @@ pub enum ProtocolControlCommandFlag {
|
|||||||
TfdfContainsProtocolInfo = 1,
|
TfdfContainsProtocolInfo = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
|
||||||
pub enum UslpError {
|
pub enum UslpError {
|
||||||
ByteConversion(ByteConversionError),
|
#[error("byte conversion error: {0}")]
|
||||||
|
ByteConversion(#[from] ByteConversionError),
|
||||||
|
#[error("header is truncated, which is not supported")]
|
||||||
HeaderIsTruncated,
|
HeaderIsTruncated,
|
||||||
|
#[error("invalid protocol id: {0}")]
|
||||||
InvalidProtocolId(u8),
|
InvalidProtocolId(u8),
|
||||||
|
#[error("invalid construction rule: {0}")]
|
||||||
InvalidConstructionRule(u8),
|
InvalidConstructionRule(u8),
|
||||||
|
#[error("invalid version number: {0}")]
|
||||||
InvalidVersionNumber(u8),
|
InvalidVersionNumber(u8),
|
||||||
InvalidVcid(u8),
|
#[error("invalid virtual channel ID: {0}")]
|
||||||
|
InvalidVcId(u8),
|
||||||
|
#[error("invalid MAP ID: {0}")]
|
||||||
InvalidMapId(u8),
|
InvalidMapId(u8),
|
||||||
|
#[error("checksum failure")]
|
||||||
ChecksumFailure(u16),
|
ChecksumFailure(u16),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ByteConversionError> for UslpError {
|
|
||||||
fn from(value: ByteConversionError) -> Self {
|
|
||||||
Self::ByteConversion(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@@ -94,7 +94,7 @@ impl PrimaryHeader {
|
|||||||
frame_len: u16,
|
frame_len: u16,
|
||||||
) -> Result<Self, UslpError> {
|
) -> Result<Self, UslpError> {
|
||||||
if vc_id > 0b111111 {
|
if vc_id > 0b111111 {
|
||||||
return Err(UslpError::InvalidVcid(vc_id));
|
return Err(UslpError::InvalidVcId(vc_id));
|
||||||
}
|
}
|
||||||
if map_id > 0b1111 {
|
if map_id > 0b1111 {
|
||||||
return Err(UslpError::InvalidMapId(map_id));
|
return Err(UslpError::InvalidMapId(map_id));
|
||||||
@@ -271,11 +271,10 @@ impl PartialEq for PrimaryHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
|
||||||
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[bitbybit::bitenum(u5, exhaustive = false)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum UslpProtocolId {
|
pub enum UslpProtocolId {
|
||||||
@@ -293,11 +292,10 @@ pub enum UslpProtocolId {
|
|||||||
Idle = 0b11111,
|
Idle = 0b11111,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive)]
|
||||||
Debug, Copy, Clone, PartialEq, Eq, num_enum::TryFromPrimitive, num_enum::IntoPrimitive,
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[bitbybit::bitenum(u3, exhaustive = true)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum ConstructionRule {
|
pub enum ConstructionRule {
|
||||||
/// Indicated fixed-length TFDZ whose contents are CCSDS packets concatenated together, which
|
/// Indicated fixed-length TFDZ whose contents are CCSDS packets concatenated together, which
|
||||||
@@ -339,7 +337,8 @@ pub struct TransferFrameDataFieldHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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() {
|
if self.construction_rule.applicable_to_fixed_len_tfdz() {
|
||||||
3
|
3
|
||||||
} else {
|
} else {
|
||||||
@@ -347,15 +346,18 @@ impl TransferFrameDataFieldHeader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construction_rule(&self) -> ConstructionRule {
|
#[inline]
|
||||||
|
pub const fn construction_rule(&self) -> ConstructionRule {
|
||||||
self.construction_rule
|
self.construction_rule
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn uslp_protocol_id(&self) -> UslpProtocolId {
|
#[inline]
|
||||||
|
pub const fn uslp_protocol_id(&self) -> UslpProtocolId {
|
||||||
self.uslp_protocol_id
|
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
|
self.fhp_or_lvo
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,22 +451,27 @@ impl<'buf> TransferFrameReader<'buf> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn len_frame(&self) -> usize {
|
pub fn len_frame(&self) -> usize {
|
||||||
self.primary_header.len_frame()
|
self.primary_header.len_frame()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn primary_header(&self) -> &PrimaryHeader {
|
pub fn primary_header(&self) -> &PrimaryHeader {
|
||||||
&self.primary_header
|
&self.primary_header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn data_field_header(&self) -> &TransferFrameDataFieldHeader {
|
pub fn data_field_header(&self) -> &TransferFrameDataFieldHeader {
|
||||||
&self.data_field_header
|
&self.data_field_header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn data(&self) -> &'buf [u8] {
|
pub fn data(&self) -> &'buf [u8] {
|
||||||
self.data
|
self.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn operational_control_field(&self) -> &Option<u32> {
|
pub fn operational_control_field(&self) -> &Option<u32> {
|
||||||
&self.operational_control_field
|
&self.operational_control_field
|
||||||
}
|
}
|
||||||
@@ -669,7 +676,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(error.is_err());
|
assert!(error.is_err());
|
||||||
let error = error.unwrap_err();
|
let error = error.unwrap_err();
|
||||||
matches!(error, UslpError::InvalidVcid(0b1101011));
|
matches!(error, UslpError::InvalidVcId(0b1101011));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
42
src/util.rs
42
src/util.rs
@@ -1,9 +1,7 @@
|
|||||||
use crate::ByteConversionError;
|
use crate::ByteConversionError;
|
||||||
use core::fmt::{Debug, Display, Formatter};
|
use core::fmt::Debug;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use std::error::Error;
|
|
||||||
|
|
||||||
pub trait ToBeBytes {
|
pub trait ToBeBytes {
|
||||||
type ByteArray: AsRef<[u8]>;
|
type ByteArray: AsRef<[u8]>;
|
||||||
@@ -100,50 +98,24 @@ pub trait UnsignedEnum {
|
|||||||
|
|
||||||
pub trait UnsignedEnumExt: UnsignedEnum + Debug + Copy + Clone + PartialEq + Eq {}
|
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 = "serde", derive(Serialize, Deserialize))]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum UnsignedByteFieldError {
|
pub enum UnsignedByteFieldError {
|
||||||
/// Value is too large for specified width of byte field.
|
/// Value is too large for specified width of byte field.
|
||||||
ValueTooLargeForWidth {
|
#[error("value {value} too large for width {width}")]
|
||||||
width: usize,
|
ValueTooLargeForWidth { width: usize, value: u64 },
|
||||||
value: u64,
|
|
||||||
},
|
|
||||||
/// Only 1, 2, 4 and 8 are allow width values. Optionally contains the expected width if
|
/// Only 1, 2, 4 and 8 are allow width values. Optionally contains the expected width if
|
||||||
/// applicable, for example for conversions.
|
/// applicable, for example for conversions.
|
||||||
|
#[error("invalid width {found}, expected {expected:?}")]
|
||||||
InvalidWidth {
|
InvalidWidth {
|
||||||
found: usize,
|
found: usize,
|
||||||
expected: Option<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.
|
/// Type erased variant.
|
||||||
#[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))]
|
||||||
|
|||||||
Reference in New Issue
Block a user