From b5bea3e1c6032e03ac281b643d1e4caf04571262 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Jul 2023 16:43:45 +0200 Subject: [PATCH 1/6] implement thiserror::Error for StdTimestampError --- Cargo.toml | 1 + src/time/cds.rs | 3 +++ src/time/cuc.rs | 1 + src/time/mod.rs | 61 ++++++++++++++++++++++--------------------------- 4 files changed, 32 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fc3d1c1..cba3583 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup zerocopy = "0.6" crc = "3" delegate = ">=0.8, <0.11" +thiserror = "1" [dependencies.num_enum] version = "0.6" diff --git a/src/time/cds.rs b/src/time/cds.rs index a5426b7..883363c 100644 --- a/src/time/cds.rs +++ b/src/time/cds.rs @@ -17,6 +17,9 @@ use core::ops::{Add, AddAssign}; use core::time::Duration; use delegate::delegate; +#[cfg(feature = "std")] +use std_mod::*; + /// Base value for the preamble field for a time field parser to determine the time field type. pub const P_FIELD_BASE: u8 = (CcsdsTimeCodes::Cds as u8) << 4; pub const MIN_CDS_FIELD_LEN: usize = 7; diff --git a/src/time/cuc.rs b/src/time/cuc.rs index 95fd01e..bfd7da4 100644 --- a/src/time/cuc.rs +++ b/src/time/cuc.rs @@ -3,6 +3,7 @@ //! //! The core data structure to do this is the [TimeProviderCcsdsEpoch] struct. use super::*; +use crate::time::std_mod::StdTimestampError; use chrono::Datelike; use core::fmt::Debug; use core::ops::{Add, AddAssign}; diff --git a/src/time/mod.rs b/src/time/mod.rs index 2947d7c..f3116ce 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -71,40 +71,6 @@ pub enum TimestampError { CustomEpochNotSupported, } -impl From for TimestampError { - fn from(e: cds::CdsError) -> Self { - TimestampError::CdsError(e) - } -} - -impl From for TimestampError { - fn from(e: cuc::CucError) -> Self { - TimestampError::CucError(e) - } -} - -#[cfg(feature = "std")] -#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] -#[derive(Debug, Clone)] -pub enum StdTimestampError { - SystemTimeError(SystemTimeError), - TimestampError(TimestampError), -} - -#[cfg(feature = "std")] -impl From for StdTimestampError { - fn from(v: TimestampError) -> Self { - Self::TimestampError(v) - } -} - -#[cfg(feature = "std")] -impl From for StdTimestampError { - fn from(v: SystemTimeError) -> Self { - Self::SystemTimeError(v) - } -} - impl Display for TimestampError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { @@ -144,6 +110,33 @@ impl Error for TimestampError { } } } +impl From for TimestampError { + fn from(e: cds::CdsError) -> Self { + TimestampError::CdsError(e) + } +} + +impl From for TimestampError { + fn from(e: cuc::CucError) -> Self { + TimestampError::CucError(e) + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +pub mod std_mod { + use crate::time::TimestampError; + use std::time::SystemTimeError; + use thiserror::Error; + + #[derive(Debug, Clone, Error)] + pub enum StdTimestampError { + #[error("system time error: {0}")] + SystemTimeError(#[from] SystemTimeError), + #[error("timestamp error: {0}")] + TimestampError(#[from] TimestampError), + } +} #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] From 581b51c61ca0cf9c5fbf4de97e5ecf2ebaf1c295 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Jul 2023 16:46:25 +0200 Subject: [PATCH 2/6] improve std timestamp error further --- CHANGELOG.md | 5 +++++ src/time/cds.rs | 35 +++++++++++++++++------------------ src/time/cuc.rs | 20 +++++++------------- src/time/mod.rs | 26 +++++++++++++------------- 4 files changed, 42 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c59938..604d1bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] +## Changed + +- Implement `Display` and `Error` for `StdTimestampError` properly. +- Implement some redundant `Error` suffixes for enum error variants. + # [v0.6.0] 2023-07-06 ## Added diff --git a/src/time/cds.rs b/src/time/cds.rs index 883363c..7b1be71 100644 --- a/src/time/cds.rs +++ b/src/time/cds.rs @@ -514,7 +514,7 @@ impl TimeProvider { days_len: LengthOfDaySegment, ) -> Result { if buf.len() < MIN_CDS_FIELD_LEN { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::FromSliceTooSmall(SizeMissmatch { expected: MIN_CDS_FIELD_LEN, found: buf.len(), @@ -548,7 +548,7 @@ impl TimeProvider { } let stamp_len = Self::calc_stamp_len(pfield); if buf.len() < stamp_len { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::FromSliceTooSmall(SizeMissmatch { expected: stamp_len, found: buf.len(), @@ -605,7 +605,7 @@ impl TimeProvider { fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), TimestampError> { if buf.len() < len_as_bytes { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::ToSliceTooSmall(SizeMissmatch { expected: len_as_bytes, found: buf.len(), @@ -674,21 +674,21 @@ impl TimeProvider { fn from_now_generic(days_len: LengthOfDaySegment) -> Result { let conversion_from_now = ConversionFromNow::new()?; Self::generic_from_conversion(days_len, conversion_from_now) - .map_err(StdTimestampError::TimestampError) + .map_err(StdTimestampError::Timestamp) } #[cfg(feature = "std")] fn from_now_generic_us_prec(days_len: LengthOfDaySegment) -> Result { let conversion_from_now = ConversionFromNow::new_with_submillis_us_prec()?; Self::generic_from_conversion(days_len, conversion_from_now) - .map_err(StdTimestampError::TimestampError) + .map_err(StdTimestampError::Timestamp) } #[cfg(feature = "std")] fn from_now_generic_ps_prec(days_len: LengthOfDaySegment) -> Result { let conversion_from_now = ConversionFromNow::new_with_submillis_ps_prec()?; Self::generic_from_conversion(days_len, conversion_from_now) - .map_err(StdTimestampError::TimestampError) + .map_err(StdTimestampError::Timestamp) } fn generic_from_conversion( @@ -697,7 +697,7 @@ impl TimeProvider { ) -> Result { let ccsds_days: ProvidesDaysLen::FieldType = converter.ccsds_days_as_u32().try_into().map_err(|_| { - TimestampError::CdsError(CdsError::InvalidCcsdsDays( + TimestampError::Cds(CdsError::InvalidCcsdsDays( converter.ccsds_days_as_u32().into(), )) })?; @@ -753,7 +753,7 @@ impl TimeProvider { .ccsds_days .try_into() .map_err(|_| { - StdTimestampError::TimestampError( + StdTimestampError::Timestamp( CdsError::InvalidCcsdsDays( conversion_from_now.unix_conversion.ccsds_days as i64, ) @@ -791,7 +791,7 @@ impl TimeProvider { /// ## Errors /// /// This function will return [TimestampError::DateBeforeCcsdsEpoch] or - /// [TimestampError::CdsError] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) + /// [TimestampError::Cds] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) /// or the CCSDS days value exceeds the allowed bit width (24 bits). pub fn from_dt_with_u24_days(dt: &DateTime) -> Result { Self::from_dt_generic(dt, LengthOfDaySegment::Long24Bits) @@ -802,7 +802,7 @@ impl TimeProvider { /// ## Errors /// /// This function will return [TimestampError::DateBeforeCcsdsEpoch] or - /// [TimestampError::CdsError] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) + /// [TimestampError::Cds] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) /// or the CCSDS days value exceeds the allowed bit width (24 bits). pub fn from_unix_secs_with_u24_days( unix_stamp: &UnixTimestamp, @@ -867,7 +867,7 @@ impl TimeProvider { /// Create a provider from a [`DateTime`] struct. /// /// This function will return a [TimestampError::DateBeforeCcsdsEpoch] or a - /// [TimestampError::CdsError] if the time is before the CCSDS epoch (01-01-1958 00:00:00) or + /// [TimestampError::Cds] if the time is before the CCSDS epoch (01-01-1958 00:00:00) or /// the CCSDS days value exceeds the allowed bit width (16 bits). pub fn from_dt_with_u16_days(dt: &DateTime) -> Result { Self::from_dt_generic(dt, LengthOfDaySegment::Short16Bits) @@ -885,7 +885,7 @@ impl TimeProvider { /// ## Errors /// /// This function will return [TimestampError::DateBeforeCcsdsEpoch] or - /// [TimestampError::CdsError] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) + /// [TimestampError::Cds] if the time is before the CCSDS epoch (1958-01-01T00:00:00+00:00) /// or the CCSDS days value exceeds the allowed bit width (24 bits). pub fn from_unix_secs_with_u16_days( unix_stamp: &UnixTimestamp, @@ -1305,7 +1305,7 @@ impl TryFrom> for TimeProvider { #[cfg(test)] mod tests { use super::*; - use crate::time::TimestampError::{ByteConversionError, InvalidTimeCode}; + use crate::time::TimestampError::{ByteConversion, InvalidTimeCode}; use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall}; use chrono::{Datelike, NaiveDate, Timelike}; #[cfg(feature = "serde")] @@ -1403,8 +1403,7 @@ mod tests { let faulty_ctor = TimeProvider::::from_bytes(&buf); assert!(faulty_ctor.is_err()); let error = faulty_ctor.unwrap_err(); - if let TimestampError::CdsError(CdsError::InvalidCtorForDaysOfLenInPreamble(len_of_day)) = - error + if let TimestampError::Cds(CdsError::InvalidCtorForDaysOfLenInPreamble(len_of_day)) = error { assert_eq!(len_of_day, LengthOfDaySegment::Long24Bits); } else { @@ -1449,7 +1448,7 @@ mod tests { let res = time_stamper.write_to_bytes(&mut buf[0..i]); assert!(res.is_err()); match res.unwrap_err() { - ByteConversionError(ToSliceTooSmall(missmatch)) => { + ByteConversion(ToSliceTooSmall(missmatch)) => { assert_eq!(missmatch.found, i); assert_eq!(missmatch.expected, 7); } @@ -1469,7 +1468,7 @@ mod tests { assert!(res.is_err()); let err = res.unwrap_err(); match err { - ByteConversionError(e) => match e { + ByteConversion(e) => match e { FromSliceTooSmall(missmatch) => { assert_eq!(missmatch.found, i); assert_eq!(missmatch.expected, 7); @@ -1946,7 +1945,7 @@ mod tests { panic!("creation should not succeed") } Err(e) => { - if let TimestampError::CdsError(CdsError::InvalidCcsdsDays(days)) = e { + if let TimestampError::Cds(CdsError::InvalidCcsdsDays(days)) = e { assert_eq!( days, unix_to_ccsds_days(invalid_unix_secs / SECONDS_PER_DAY as i64) diff --git a/src/time/cuc.rs b/src/time/cuc.rs index bfd7da4..3f93080 100644 --- a/src/time/cuc.rs +++ b/src/time/cuc.rs @@ -245,7 +245,7 @@ impl TimeProviderCcsdsEpoch { let fractions = fractional_part_from_subsec_ns(fraction_resolution, now.subsec_nanos() as u64); Self::new_with_fractions(ccsds_epoch as u32, fractions.unwrap()) - .map_err(|e| StdTimestampError::TimestampError(e.into())) + .map_err(|e| StdTimestampError::Timestamp(e.into())) } /// Updates the current time stamp from the current time. The fractional field width remains @@ -454,7 +454,7 @@ impl TimeReader for TimeProviderCcsdsEpoch { Self: Sized, { if buf.len() < MIN_CUC_LEN { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::FromSliceTooSmall(SizeMissmatch { expected: MIN_CUC_LEN, found: buf.len(), @@ -480,7 +480,7 @@ impl TimeReader for TimeProviderCcsdsEpoch { let (cntr_len, fractions_len, total_len) = Self::len_components_and_total_from_pfield(buf[0]); if buf.len() < total_len { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::FromSliceTooSmall(SizeMissmatch { expected: total_len, found: buf.len(), @@ -536,7 +536,7 @@ impl TimeWriter for TimeProviderCcsdsEpoch { fn write_to_bytes(&self, bytes: &mut [u8]) -> Result { // Cross check the sizes of the counters against byte widths in the ctor if bytes.len() < self.len_as_bytes() { - return Err(TimestampError::ByteConversionError( + return Err(TimestampError::ByteConversion( ByteConversionError::ToSliceTooSmall(SizeMissmatch { found: bytes.len(), expected: self.len_as_bytes(), @@ -798,9 +798,7 @@ mod tests { let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]); assert!(res.is_err()); let err = res.unwrap_err(); - if let TimestampError::ByteConversionError(ByteConversionError::FromSliceTooSmall(e)) = - err - { + if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err { assert_eq!(e.found, i); assert_eq!(e.expected, 2); } @@ -811,9 +809,7 @@ mod tests { let res = TimeProviderCcsdsEpoch::from_bytes(&buf[0..i]); assert!(res.is_err()); let err = res.unwrap_err(); - if let TimestampError::ByteConversionError(ByteConversionError::FromSliceTooSmall(e)) = - err - { + if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err { assert_eq!(e.found, i); assert_eq!(e.expected, large_stamp.len_as_bytes()); } @@ -887,9 +883,7 @@ mod tests { let err = cuc.write_to_bytes(&mut buf[0..i]); assert!(err.is_err()); let err = err.unwrap_err(); - if let TimestampError::ByteConversionError(ByteConversionError::ToSliceTooSmall(e)) = - err - { + if let TimestampError::ByteConversion(ByteConversionError::ToSliceTooSmall(e)) = err { assert_eq!(e.expected, cuc.len_as_bytes()); assert_eq!(e.found, i); } else { diff --git a/src/time/mod.rs b/src/time/mod.rs index f3116ce..6b91199 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -64,9 +64,9 @@ pub enum TimestampError { /// Contains tuple where first value is the expected time code and the second /// value is the found raw value InvalidTimeCode(CcsdsTimeCodes, u8), - ByteConversionError(ByteConversionError), - CdsError(cds::CdsError), - CucError(cuc::CucError), + ByteConversion(ByteConversionError), + Cds(cds::CdsError), + Cuc(cuc::CucError), DateBeforeCcsdsEpoch(DateTime), CustomEpochNotSupported, } @@ -80,13 +80,13 @@ impl Display for TimestampError { "invalid raw time code value {raw_val} for time code {time_code:?}" ) } - TimestampError::CdsError(e) => { + TimestampError::Cds(e) => { write!(f, "cds error {e}") } - TimestampError::CucError(e) => { + TimestampError::Cuc(e) => { write!(f, "cuc error {e}") } - TimestampError::ByteConversionError(e) => { + TimestampError::ByteConversion(e) => { write!(f, "byte conversion error {e}") } TimestampError::DateBeforeCcsdsEpoch(e) => { @@ -103,22 +103,22 @@ impl Display for TimestampError { impl Error for TimestampError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { - TimestampError::ByteConversionError(e) => Some(e), - TimestampError::CdsError(e) => Some(e), - TimestampError::CucError(e) => Some(e), + TimestampError::ByteConversion(e) => Some(e), + TimestampError::Cds(e) => Some(e), + TimestampError::Cuc(e) => Some(e), _ => None, } } } impl From for TimestampError { fn from(e: cds::CdsError) -> Self { - TimestampError::CdsError(e) + TimestampError::Cds(e) } } impl From for TimestampError { fn from(e: cuc::CucError) -> Self { - TimestampError::CucError(e) + TimestampError::Cuc(e) } } @@ -132,9 +132,9 @@ pub mod std_mod { #[derive(Debug, Clone, Error)] pub enum StdTimestampError { #[error("system time error: {0}")] - SystemTimeError(#[from] SystemTimeError), + SystemTime(#[from] SystemTimeError), #[error("timestamp error: {0}")] - TimestampError(#[from] TimestampError), + Timestamp(#[from] TimestampError), } } From 4969d6c33c6d5f2aed0f72fb0cf2b8c9facb44cd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Jul 2023 16:48:53 +0200 Subject: [PATCH 3/6] moved re-export --- src/time/cds.rs | 3 --- src/time/mod.rs | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/time/cds.rs b/src/time/cds.rs index 7b1be71..3db55bd 100644 --- a/src/time/cds.rs +++ b/src/time/cds.rs @@ -17,9 +17,6 @@ use core::ops::{Add, AddAssign}; use core::time::Duration; use delegate::delegate; -#[cfg(feature = "std")] -use std_mod::*; - /// Base value for the preamble field for a time field parser to determine the time field type. pub const P_FIELD_BASE: u8 = (CcsdsTimeCodes::Cds as u8) << 4; pub const MIN_CDS_FIELD_LEN: usize = 7; diff --git a/src/time/mod.rs b/src/time/mod.rs index 6b91199..44d62a2 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -16,6 +16,8 @@ use serde::{Deserialize, Serialize}; use std::error::Error; #[cfg(feature = "std")] use std::time::{SystemTime, SystemTimeError}; +#[cfg(feature = "std")] +use std_mod::*; pub mod ascii; pub mod cds; From e3d2d885385ee323c1ce2faecb171fc1deba9451 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 9 Jul 2023 19:31:32 +0200 Subject: [PATCH 4/6] remove another error suffix --- src/ecss/mod.rs | 8 ++++---- src/tc.rs | 2 +- src/tm.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ecss/mod.rs b/src/ecss/mod.rs index add2d24..acf04b5 100644 --- a/src/ecss/mod.rs +++ b/src/ecss/mod.rs @@ -149,7 +149,7 @@ pub enum PusError { NoRawData, /// CRC16 needs to be calculated first CrcCalculationMissing, - ByteConversionError(ByteConversionError), + ByteConversion(ByteConversionError), } impl Display for PusError { @@ -173,7 +173,7 @@ impl Display for PusError { PusError::CrcCalculationMissing => { write!(f, "crc16 was not calculated") } - PusError::ByteConversionError(e) => { + PusError::ByteConversion(e) => { write!(f, "low level byte conversion error: {e}") } } @@ -183,7 +183,7 @@ impl Display for PusError { #[cfg(feature = "std")] impl Error for PusError { fn source(&self) -> Option<&(dyn Error + 'static)> { - if let PusError::ByteConversionError(e) = self { + if let PusError::ByteConversion(e) = self { return Some(e); } None @@ -192,7 +192,7 @@ impl Error for PusError { impl From for PusError { fn from(e: ByteConversionError) -> Self { - PusError::ByteConversionError(e) + PusError::ByteConversion(e) } } diff --git a/src/tc.rs b/src/tc.rs index 84e7f09..42a85fb 100644 --- a/src/tc.rs +++ b/src/tc.rs @@ -659,7 +659,7 @@ mod tests { assert!(res.is_err()); let err = res.unwrap_err(); match err { - PusError::ByteConversionError(err) => match err { + PusError::ByteConversion(err) => match err { ByteConversionError::ToSliceTooSmall(missmatch) => { assert_eq!(missmatch.expected, pus_tc.len_packed()); assert_eq!(missmatch.found, 12); diff --git a/src/tm.rs b/src/tm.rs index 5e1fc69..8a0d28d 100644 --- a/src/tm.rs +++ b/src/tm.rs @@ -686,9 +686,9 @@ mod tests { let res = pus_tm.write_to_bytes(&mut buf); assert!(res.is_err()); let error = res.unwrap_err(); - assert!(matches!(error, PusError::ByteConversionError { .. })); + assert!(matches!(error, PusError::ByteConversion { .. })); match error { - PusError::ByteConversionError(err) => match err { + PusError::ByteConversion(err) => match err { ByteConversionError::ToSliceTooSmall(size_missmatch) => { assert_eq!(size_missmatch.expected, 22); assert_eq!(size_missmatch.found, 16); From 784564a20ed831436f7c17e986fd3f0d94da48f0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 10 Jul 2023 00:00:20 +0200 Subject: [PATCH 5/6] now its a proper re-export --- src/time/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/time/mod.rs b/src/time/mod.rs index 44d62a2..dbfe995 100644 --- a/src/time/mod.rs +++ b/src/time/mod.rs @@ -17,7 +17,7 @@ use std::error::Error; #[cfg(feature = "std")] use std::time::{SystemTime, SystemTimeError}; #[cfg(feature = "std")] -use std_mod::*; +pub use std_mod::*; pub mod ascii; pub mod cds; From f117c8c4de9c968687c332e3dd1940ec1f5e74c4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 10 Jul 2023 00:37:16 +0200 Subject: [PATCH 6/6] changelog correction --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 604d1bc..ea761ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Changed - Implement `Display` and `Error` for `StdTimestampError` properly. -- Implement some redundant `Error` suffixes for enum error variants. +- Remove some redundant `Error` suffixes for enum error variants. # [v0.6.0] 2023-07-06