Merge remote-tracking branch 'origin/main' into refactoring-ecss-packet-mods

This commit is contained in:
Robin Müller 2023-07-10 00:38:07 +02:00
commit fd95c86294
Signed by: muellerr
GPG Key ID: A649FB78196E3849
7 changed files with 72 additions and 80 deletions

View File

@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Moved ECSS TM components from `tm` to `ecss.tm`. - Moved ECSS TM components from `tm` to `ecss.tm`.
- Converted `PusTc` class to specialized `PusTcCreator` and `PusTcReader` - Converted `PusTc` class to specialized `PusTcCreator` and `PusTcReader`
classes. The old `PusTc` is deprecated now. classes. The old `PusTc` is deprecated now.
- Implement `Display` and `Error` for `StdTimestampError` properly.
- Remove some redundant `Error` suffixes for enum error variants.
# [v0.6.0] 2023-07-06 # [v0.6.0] 2023-07-06

View File

@ -16,6 +16,7 @@ categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-sup
zerocopy = "0.6" zerocopy = "0.6"
crc = "3" crc = "3"
delegate = ">=0.8, <0.11" delegate = ">=0.8, <0.11"
thiserror = "1"
[dependencies.num_enum] [dependencies.num_enum]
version = "0.6" version = "0.6"

View File

@ -151,7 +151,7 @@ pub enum PusError {
NoRawData, NoRawData,
/// CRC16 needs to be calculated first /// CRC16 needs to be calculated first
CrcCalculationMissing, CrcCalculationMissing,
ByteConversionError(ByteConversionError), ByteConversion(ByteConversionError),
} }
impl Display for PusError { impl Display for PusError {
@ -175,7 +175,7 @@ impl Display for PusError {
PusError::CrcCalculationMissing => { PusError::CrcCalculationMissing => {
write!(f, "crc16 was not calculated") write!(f, "crc16 was not calculated")
} }
PusError::ByteConversionError(e) => { PusError::ByteConversion(e) => {
write!(f, "low level byte conversion error: {e}") write!(f, "low level byte conversion error: {e}")
} }
} }
@ -185,7 +185,7 @@ impl Display for PusError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl Error for PusError { impl Error for PusError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
if let PusError::ByteConversionError(e) = self { if let PusError::ByteConversion(e) = self {
return Some(e); return Some(e);
} }
None None
@ -194,7 +194,7 @@ impl Error for PusError {
impl From<ByteConversionError> for PusError { impl From<ByteConversionError> for PusError {
fn from(e: ByteConversionError) -> Self { fn from(e: ByteConversionError) -> Self {
PusError::ByteConversionError(e) PusError::ByteConversion(e)
} }
} }

View File

@ -686,9 +686,9 @@ mod tests {
let res = pus_tm.write_to_bytes(&mut buf); let res = pus_tm.write_to_bytes(&mut buf);
assert!(res.is_err()); assert!(res.is_err());
let error = res.unwrap_err(); let error = res.unwrap_err();
assert!(matches!(error, PusError::ByteConversionError { .. })); assert!(matches!(error, PusError::ByteConversion { .. }));
match error { match error {
PusError::ByteConversionError(err) => match err { PusError::ByteConversion(err) => match err {
ByteConversionError::ToSliceTooSmall(size_missmatch) => { ByteConversionError::ToSliceTooSmall(size_missmatch) => {
assert_eq!(size_missmatch.expected, 22); assert_eq!(size_missmatch.expected, 22);
assert_eq!(size_missmatch.found, 16); assert_eq!(size_missmatch.found, 16);

View File

@ -511,7 +511,7 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
days_len: LengthOfDaySegment, days_len: LengthOfDaySegment,
) -> Result<SubmillisPrecision, TimestampError> { ) -> Result<SubmillisPrecision, TimestampError> {
if buf.len() < MIN_CDS_FIELD_LEN { if buf.len() < MIN_CDS_FIELD_LEN {
return Err(TimestampError::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: MIN_CDS_FIELD_LEN, expected: MIN_CDS_FIELD_LEN,
found: buf.len(), found: buf.len(),
@ -545,7 +545,7 @@ 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::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: stamp_len, expected: stamp_len,
found: buf.len(), found: buf.len(),
@ -602,7 +602,7 @@ 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::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::ToSliceTooSmall(SizeMissmatch { ByteConversionError::ToSliceTooSmall(SizeMissmatch {
expected: len_as_bytes, expected: len_as_bytes,
found: buf.len(), found: buf.len(),
@ -671,21 +671,21 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
fn from_now_generic(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> { fn from_now_generic(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> {
let conversion_from_now = ConversionFromNow::new()?; let conversion_from_now = ConversionFromNow::new()?;
Self::generic_from_conversion(days_len, conversion_from_now) Self::generic_from_conversion(days_len, conversion_from_now)
.map_err(StdTimestampError::TimestampError) .map_err(StdTimestampError::Timestamp)
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
fn from_now_generic_us_prec(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> { fn from_now_generic_us_prec(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> {
let conversion_from_now = ConversionFromNow::new_with_submillis_us_prec()?; let conversion_from_now = ConversionFromNow::new_with_submillis_us_prec()?;
Self::generic_from_conversion(days_len, conversion_from_now) Self::generic_from_conversion(days_len, conversion_from_now)
.map_err(StdTimestampError::TimestampError) .map_err(StdTimestampError::Timestamp)
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
fn from_now_generic_ps_prec(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> { fn from_now_generic_ps_prec(days_len: LengthOfDaySegment) -> Result<Self, StdTimestampError> {
let conversion_from_now = ConversionFromNow::new_with_submillis_ps_prec()?; let conversion_from_now = ConversionFromNow::new_with_submillis_ps_prec()?;
Self::generic_from_conversion(days_len, conversion_from_now) Self::generic_from_conversion(days_len, conversion_from_now)
.map_err(StdTimestampError::TimestampError) .map_err(StdTimestampError::Timestamp)
} }
fn generic_from_conversion<C: CdsConverter>( fn generic_from_conversion<C: CdsConverter>(
@ -694,7 +694,7 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
) -> Result<Self, TimestampError> { ) -> Result<Self, TimestampError> {
let ccsds_days: ProvidesDaysLen::FieldType = let ccsds_days: ProvidesDaysLen::FieldType =
converter.ccsds_days_as_u32().try_into().map_err(|_| { converter.ccsds_days_as_u32().try_into().map_err(|_| {
TimestampError::CdsError(CdsError::InvalidCcsdsDays( TimestampError::Cds(CdsError::InvalidCcsdsDays(
converter.ccsds_days_as_u32().into(), converter.ccsds_days_as_u32().into(),
)) ))
})?; })?;
@ -750,7 +750,7 @@ impl<ProvidesDaysLen: ProvidesDaysLength> TimeProvider<ProvidesDaysLen> {
.ccsds_days .ccsds_days
.try_into() .try_into()
.map_err(|_| { .map_err(|_| {
StdTimestampError::TimestampError( StdTimestampError::Timestamp(
CdsError::InvalidCcsdsDays( CdsError::InvalidCcsdsDays(
conversion_from_now.unix_conversion.ccsds_days as i64, conversion_from_now.unix_conversion.ccsds_days as i64,
) )
@ -788,7 +788,7 @@ impl TimeProvider<DaysLen24Bits> {
/// ## Errors /// ## Errors
/// ///
/// This function will return [TimestampError::DateBeforeCcsdsEpoch] or /// 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). /// or the CCSDS days value exceeds the allowed bit width (24 bits).
pub fn from_dt_with_u24_days(dt: &DateTime<Utc>) -> Result<Self, TimestampError> { pub fn from_dt_with_u24_days(dt: &DateTime<Utc>) -> Result<Self, TimestampError> {
Self::from_dt_generic(dt, LengthOfDaySegment::Long24Bits) Self::from_dt_generic(dt, LengthOfDaySegment::Long24Bits)
@ -799,7 +799,7 @@ impl TimeProvider<DaysLen24Bits> {
/// ## Errors /// ## Errors
/// ///
/// This function will return [TimestampError::DateBeforeCcsdsEpoch] or /// 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). /// or the CCSDS days value exceeds the allowed bit width (24 bits).
pub fn from_unix_secs_with_u24_days( pub fn from_unix_secs_with_u24_days(
unix_stamp: &UnixTimestamp, unix_stamp: &UnixTimestamp,
@ -864,7 +864,7 @@ impl TimeProvider<DaysLen16Bits> {
/// Create a provider from a [`DateTime<Utc>`] struct. /// Create a provider from a [`DateTime<Utc>`] struct.
/// ///
/// This function will return a [TimestampError::DateBeforeCcsdsEpoch] or a /// 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). /// the CCSDS days value exceeds the allowed bit width (16 bits).
pub fn from_dt_with_u16_days(dt: &DateTime<Utc>) -> Result<Self, TimestampError> { pub fn from_dt_with_u16_days(dt: &DateTime<Utc>) -> Result<Self, TimestampError> {
Self::from_dt_generic(dt, LengthOfDaySegment::Short16Bits) Self::from_dt_generic(dt, LengthOfDaySegment::Short16Bits)
@ -882,7 +882,7 @@ impl TimeProvider<DaysLen16Bits> {
/// ## Errors /// ## Errors
/// ///
/// This function will return [TimestampError::DateBeforeCcsdsEpoch] or /// 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). /// or the CCSDS days value exceeds the allowed bit width (24 bits).
pub fn from_unix_secs_with_u16_days( pub fn from_unix_secs_with_u16_days(
unix_stamp: &UnixTimestamp, unix_stamp: &UnixTimestamp,
@ -1302,7 +1302,7 @@ impl TryFrom<TimeProvider<DaysLen24Bits>> for TimeProvider<DaysLen16Bits> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::time::TimestampError::{ByteConversionError, InvalidTimeCode}; use crate::time::TimestampError::{ByteConversion, InvalidTimeCode};
use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall}; use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall};
use chrono::{Datelike, NaiveDate, Timelike}; use chrono::{Datelike, NaiveDate, Timelike};
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
@ -1400,8 +1400,7 @@ mod tests {
let faulty_ctor = TimeProvider::<DaysLen16Bits>::from_bytes(&buf); let faulty_ctor = TimeProvider::<DaysLen16Bits>::from_bytes(&buf);
assert!(faulty_ctor.is_err()); assert!(faulty_ctor.is_err());
let error = faulty_ctor.unwrap_err(); let error = faulty_ctor.unwrap_err();
if let TimestampError::CdsError(CdsError::InvalidCtorForDaysOfLenInPreamble(len_of_day)) = if let TimestampError::Cds(CdsError::InvalidCtorForDaysOfLenInPreamble(len_of_day)) = error
error
{ {
assert_eq!(len_of_day, LengthOfDaySegment::Long24Bits); assert_eq!(len_of_day, LengthOfDaySegment::Long24Bits);
} else { } else {
@ -1446,7 +1445,7 @@ 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() {
ByteConversionError(ToSliceTooSmall(missmatch)) => { ByteConversion(ToSliceTooSmall(missmatch)) => {
assert_eq!(missmatch.found, i); assert_eq!(missmatch.found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(missmatch.expected, 7);
} }
@ -1466,7 +1465,7 @@ 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(e) => match e { ByteConversion(e) => match e {
FromSliceTooSmall(missmatch) => { FromSliceTooSmall(missmatch) => {
assert_eq!(missmatch.found, i); assert_eq!(missmatch.found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(missmatch.expected, 7);
@ -1943,7 +1942,7 @@ mod tests {
panic!("creation should not succeed") panic!("creation should not succeed")
} }
Err(e) => { Err(e) => {
if let TimestampError::CdsError(CdsError::InvalidCcsdsDays(days)) = e { if let TimestampError::Cds(CdsError::InvalidCcsdsDays(days)) = e {
assert_eq!( assert_eq!(
days, days,
unix_to_ccsds_days(invalid_unix_secs / SECONDS_PER_DAY as i64) unix_to_ccsds_days(invalid_unix_secs / SECONDS_PER_DAY as i64)

View File

@ -3,6 +3,7 @@
//! //!
//! The core data structure to do this is the [TimeProviderCcsdsEpoch] struct. //! The core data structure to do this is the [TimeProviderCcsdsEpoch] struct.
use super::*; use super::*;
use crate::time::std_mod::StdTimestampError;
use chrono::Datelike; use chrono::Datelike;
use core::fmt::Debug; use core::fmt::Debug;
use core::ops::{Add, AddAssign}; use core::ops::{Add, AddAssign};
@ -244,7 +245,7 @@ impl TimeProviderCcsdsEpoch {
let fractions = let fractions =
fractional_part_from_subsec_ns(fraction_resolution, now.subsec_nanos() as u64); fractional_part_from_subsec_ns(fraction_resolution, now.subsec_nanos() as u64);
Self::new_with_fractions(ccsds_epoch as u32, fractions.unwrap()) 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 /// Updates the current time stamp from the current time. The fractional field width remains
@ -453,7 +454,7 @@ impl TimeReader for TimeProviderCcsdsEpoch {
Self: Sized, Self: Sized,
{ {
if buf.len() < MIN_CUC_LEN { if buf.len() < MIN_CUC_LEN {
return Err(TimestampError::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: MIN_CUC_LEN, expected: MIN_CUC_LEN,
found: buf.len(), found: buf.len(),
@ -479,7 +480,7 @@ impl TimeReader for TimeProviderCcsdsEpoch {
let (cntr_len, fractions_len, total_len) = let (cntr_len, fractions_len, total_len) =
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::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::FromSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: total_len, expected: total_len,
found: buf.len(), found: buf.len(),
@ -535,7 +536,7 @@ impl TimeWriter for TimeProviderCcsdsEpoch {
fn write_to_bytes(&self, bytes: &mut [u8]) -> Result<usize, TimestampError> { fn write_to_bytes(&self, bytes: &mut [u8]) -> Result<usize, TimestampError> {
// 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::ByteConversionError( return Err(TimestampError::ByteConversion(
ByteConversionError::ToSliceTooSmall(SizeMissmatch { ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: bytes.len(), found: bytes.len(),
expected: self.len_as_bytes(), expected: self.len_as_bytes(),
@ -797,9 +798,7 @@ 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::ByteConversionError(ByteConversionError::FromSliceTooSmall(e)) = if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err {
err
{
assert_eq!(e.found, i); assert_eq!(e.found, i);
assert_eq!(e.expected, 2); assert_eq!(e.expected, 2);
} }
@ -810,9 +809,7 @@ 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::ByteConversionError(ByteConversionError::FromSliceTooSmall(e)) = if let TimestampError::ByteConversion(ByteConversionError::FromSliceTooSmall(e)) = err {
err
{
assert_eq!(e.found, i); assert_eq!(e.found, i);
assert_eq!(e.expected, large_stamp.len_as_bytes()); assert_eq!(e.expected, large_stamp.len_as_bytes());
} }
@ -886,9 +883,7 @@ 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::ByteConversionError(ByteConversionError::ToSliceTooSmall(e)) = if let TimestampError::ByteConversion(ByteConversionError::ToSliceTooSmall(e)) = err {
err
{
assert_eq!(e.expected, cuc.len_as_bytes()); assert_eq!(e.expected, cuc.len_as_bytes());
assert_eq!(e.found, i); assert_eq!(e.found, i);
} else { } else {

View File

@ -16,6 +16,8 @@ use serde::{Deserialize, Serialize};
use std::error::Error; use std::error::Error;
#[cfg(feature = "std")] #[cfg(feature = "std")]
use std::time::{SystemTime, SystemTimeError}; use std::time::{SystemTime, SystemTimeError};
#[cfg(feature = "std")]
pub use std_mod::*;
pub mod ascii; pub mod ascii;
pub mod cds; pub mod cds;
@ -64,47 +66,13 @@ pub enum TimestampError {
/// Contains tuple where first value is the expected time code and the second /// Contains tuple where first value is the expected time code and the second
/// value is the found raw value /// value is the found raw value
InvalidTimeCode(CcsdsTimeCodes, u8), InvalidTimeCode(CcsdsTimeCodes, u8),
ByteConversionError(ByteConversionError), ByteConversion(ByteConversionError),
CdsError(cds::CdsError), Cds(cds::CdsError),
CucError(cuc::CucError), Cuc(cuc::CucError),
DateBeforeCcsdsEpoch(DateTime<Utc>), DateBeforeCcsdsEpoch(DateTime<Utc>),
CustomEpochNotSupported, CustomEpochNotSupported,
} }
impl From<cds::CdsError> for TimestampError {
fn from(e: cds::CdsError) -> Self {
TimestampError::CdsError(e)
}
}
impl From<cuc::CucError> 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<TimestampError> for StdTimestampError {
fn from(v: TimestampError) -> Self {
Self::TimestampError(v)
}
}
#[cfg(feature = "std")]
impl From<SystemTimeError> for StdTimestampError {
fn from(v: SystemTimeError) -> Self {
Self::SystemTimeError(v)
}
}
impl Display for TimestampError { impl Display for TimestampError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self { match self {
@ -114,13 +82,13 @@ impl Display for TimestampError {
"invalid raw time code value {raw_val} for time code {time_code:?}" "invalid raw time code value {raw_val} for time code {time_code:?}"
) )
} }
TimestampError::CdsError(e) => { TimestampError::Cds(e) => {
write!(f, "cds error {e}") write!(f, "cds error {e}")
} }
TimestampError::CucError(e) => { TimestampError::Cuc(e) => {
write!(f, "cuc error {e}") write!(f, "cuc error {e}")
} }
TimestampError::ByteConversionError(e) => { TimestampError::ByteConversion(e) => {
write!(f, "byte conversion error {e}") write!(f, "byte conversion error {e}")
} }
TimestampError::DateBeforeCcsdsEpoch(e) => { TimestampError::DateBeforeCcsdsEpoch(e) => {
@ -137,13 +105,40 @@ impl Display for TimestampError {
impl Error for TimestampError { impl Error for TimestampError {
fn source(&self) -> Option<&(dyn Error + 'static)> { fn source(&self) -> Option<&(dyn Error + 'static)> {
match self { match self {
TimestampError::ByteConversionError(e) => Some(e), TimestampError::ByteConversion(e) => Some(e),
TimestampError::CdsError(e) => Some(e), TimestampError::Cds(e) => Some(e),
TimestampError::CucError(e) => Some(e), TimestampError::Cuc(e) => Some(e),
_ => None, _ => None,
} }
} }
} }
impl From<cds::CdsError> for TimestampError {
fn from(e: cds::CdsError) -> Self {
TimestampError::Cds(e)
}
}
impl From<cuc::CucError> for TimestampError {
fn from(e: cuc::CucError) -> Self {
TimestampError::Cuc(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}")]
SystemTime(#[from] SystemTimeError),
#[error("timestamp error: {0}")]
Timestamp(#[from] TimestampError),
}
}
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]