Merge pull request 'simplified CDS short impl' (#169) from simplify-cds-timestamp-impl into main
Reviewed-on: #169
This commit was merged in pull request #169.
This commit is contained in:
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- `CdsCommon` renamed to `CdsBase`
|
||||||
|
- Simplified CDS short timestamp, contains one less field which reduced serialization length.
|
||||||
|
|
||||||
# [v0.16.1] 2025-09-26
|
# [v0.16.1] 2025-09-26
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ pub trait ProvidesDaysLength: Sealed + Clone {
|
|||||||
+ Eq
|
+ Eq
|
||||||
+ TryFrom<i32>
|
+ TryFrom<i32>
|
||||||
+ TryFrom<u32>
|
+ TryFrom<u32>
|
||||||
|
+ TryFrom<i64>
|
||||||
+ From<u16>
|
+ From<u16>
|
||||||
+ Into<u32>
|
+ Into<u32>
|
||||||
+ Into<i64>;
|
+ Into<i64>;
|
||||||
@@ -173,15 +174,12 @@ pub struct CdsTime<DaysLen: ProvidesDaysLength = DaysLen16Bits> {
|
|||||||
ccsds_days: DaysLen::FieldType,
|
ccsds_days: DaysLen::FieldType,
|
||||||
ms_of_day: u32,
|
ms_of_day: u32,
|
||||||
submillis: u32,
|
submillis: u32,
|
||||||
/// This is not strictly necessary but still cached because it significantly simplifies the
|
|
||||||
/// calculation of [`DateTime<Utc>`].
|
|
||||||
unix_time: UnixTime,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common properties for all CDS time providers.
|
/// Base properties for all CDS time providers.
|
||||||
///
|
///
|
||||||
/// Also exists to encapsulate properties used by private converters.
|
/// Also exists to encapsulate properties used by private converters.
|
||||||
pub trait CdsCommon {
|
pub trait CdsBase {
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision;
|
fn submillis_precision(&self) -> SubmillisPrecision;
|
||||||
fn submillis(&self) -> u32;
|
fn submillis(&self) -> u32;
|
||||||
fn ms_of_day(&self) -> u32;
|
fn ms_of_day(&self) -> u32;
|
||||||
@@ -189,23 +187,18 @@ pub trait CdsCommon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic properties for all CDS time providers.
|
/// Generic properties for all CDS time providers.
|
||||||
pub trait CdsTimestamp: CdsCommon {
|
pub trait CdsTimestamp: CdsBase {
|
||||||
fn len_of_day_seg(&self) -> LengthOfDaySegment;
|
fn len_of_day_seg(&self) -> LengthOfDaySegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Private trait which serves as an abstraction for different converters.
|
/// Private trait which serves as an abstraction for different converters.
|
||||||
trait CdsConverter: CdsCommon {
|
trait CdsConverter: CdsBase {}
|
||||||
fn unix_days_seconds(&self) -> i64;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ConversionFromUnix {
|
struct ConversionFromUnix {
|
||||||
ccsds_days: u32,
|
ccsds_days: u32,
|
||||||
ms_of_day: u32,
|
ms_of_day: u32,
|
||||||
submilis_prec: SubmillisPrecision,
|
submilis_prec: SubmillisPrecision,
|
||||||
submillis: u32,
|
submillis: u32,
|
||||||
/// This is a side-product of the calculation of the CCSDS days. It is useful for
|
|
||||||
/// re-calculating the datetime at a later point and therefore supplied as well.
|
|
||||||
unix_days_seconds: i64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConversionFromUnix {
|
impl ConversionFromUnix {
|
||||||
@@ -232,14 +225,13 @@ impl ConversionFromUnix {
|
|||||||
Ok(Self {
|
Ok(Self {
|
||||||
ccsds_days: unix_to_ccsds_days(unix_days) as u32,
|
ccsds_days: unix_to_ccsds_days(unix_days) as u32,
|
||||||
ms_of_day,
|
ms_of_day,
|
||||||
unix_days_seconds: unix_days * SECONDS_PER_DAY as i64,
|
|
||||||
submilis_prec: precision,
|
submilis_prec: precision,
|
||||||
submillis,
|
submillis,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CdsCommon for ConversionFromUnix {
|
impl CdsBase for ConversionFromUnix {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
self.submilis_prec
|
self.submilis_prec
|
||||||
@@ -261,12 +253,7 @@ impl CdsCommon for ConversionFromUnix {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CdsConverter for ConversionFromUnix {
|
impl CdsConverter for ConversionFromUnix {}
|
||||||
#[inline]
|
|
||||||
fn unix_days_seconds(&self) -> i64 {
|
|
||||||
self.unix_days_seconds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper struct which generates fields for the CDS time provider from a datetime.
|
/// Helper struct which generates fields for the CDS time provider from a datetime.
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
@@ -277,7 +264,7 @@ struct ConversionFromChronoDatetime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
impl CdsCommon for ConversionFromChronoDatetime {
|
impl CdsBase for ConversionFromChronoDatetime {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
self.submillis_prec
|
self.submillis_prec
|
||||||
@@ -299,12 +286,7 @@ impl CdsCommon for ConversionFromChronoDatetime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
impl CdsConverter for ConversionFromChronoDatetime {
|
impl CdsConverter for ConversionFromChronoDatetime {}
|
||||||
delegate::delegate! {to self.unix_conversion {
|
|
||||||
#[inline]
|
|
||||||
fn unix_days_seconds(&self) -> i64;
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn calc_unix_days_and_secs_of_day(unix_seconds: i64) -> (i64, u32) {
|
fn calc_unix_days_and_secs_of_day(unix_seconds: i64) -> (i64, u32) {
|
||||||
@@ -414,7 +396,7 @@ impl ConversionFromNow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl CdsCommon for ConversionFromNow {
|
impl CdsBase for ConversionFromNow {
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
self.submillis_prec
|
self.submillis_prec
|
||||||
}
|
}
|
||||||
@@ -431,9 +413,7 @@ impl CdsCommon for ConversionFromNow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
impl CdsConverter for ConversionFromNow {
|
impl CdsConverter for ConversionFromNow {}
|
||||||
delegate::delegate! {to self.unix_conversion { fn unix_days_seconds(&self) -> i64; }}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
pub trait DynCdsTimeProvider: CcsdsTimeProvider + CdsTimestamp + TimeWriter + Any {}
|
pub trait DynCdsTimeProvider: CcsdsTimeProvider + CdsTimestamp + TimeWriter + Any {}
|
||||||
@@ -493,7 +473,7 @@ pub fn get_dyn_time_provider_from_bytes(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ProvidesDaysLen: ProvidesDaysLength> CdsCommon for CdsTime<ProvidesDaysLen> {
|
impl<ProvidesDaysLen: ProvidesDaysLength> CdsBase for CdsTime<ProvidesDaysLen> {
|
||||||
fn submillis_precision(&self) -> SubmillisPrecision {
|
fn submillis_precision(&self) -> SubmillisPrecision {
|
||||||
precision_from_pfield(self.pfield)
|
precision_from_pfield(self.pfield)
|
||||||
}
|
}
|
||||||
@@ -623,12 +603,14 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
init_len
|
init_len
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(&mut self, unix_days_seconds: i64, ms_of_day: u32) {
|
|
||||||
self.calc_unix_seconds(unix_days_seconds, ms_of_day);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn calc_unix_seconds(&mut self, mut unix_days_seconds: i64, ms_of_day: u32) {
|
fn calc_unix_seconds(&self) -> UnixTime {
|
||||||
|
let unix_days_seconds =
|
||||||
|
ccsds_to_unix_days(i64::try_from(self.ccsds_days()).unwrap()) * SECONDS_PER_DAY as i64;
|
||||||
|
self.calc_unix_seconds_internal(unix_days_seconds, self.ms_of_day())
|
||||||
|
}
|
||||||
|
#[inline]
|
||||||
|
fn calc_unix_seconds_internal(&self, mut unix_days_seconds: i64, ms_of_day: u32) -> UnixTime {
|
||||||
let seconds_of_day = (ms_of_day / 1000) as i64;
|
let seconds_of_day = (ms_of_day / 1000) as i64;
|
||||||
if unix_days_seconds < 0 {
|
if unix_days_seconds < 0 {
|
||||||
unix_days_seconds -= seconds_of_day;
|
unix_days_seconds -= seconds_of_day;
|
||||||
@@ -639,7 +621,7 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
if let Some(precision) = self.precision_as_ns() {
|
if let Some(precision) = self.precision_as_ns() {
|
||||||
subsec_nanos += precision;
|
subsec_nanos += precision;
|
||||||
}
|
}
|
||||||
self.unix_time = UnixTime::new(unix_days_seconds, subsec_nanos);
|
UnixTime::new(unix_days_seconds, subsec_nanos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), ByteConversionError> {
|
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), ByteConversionError> {
|
||||||
@@ -660,15 +642,12 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
where
|
where
|
||||||
i64: From<ProvidesDaysLen::FieldType>,
|
i64: From<ProvidesDaysLen::FieldType>,
|
||||||
{
|
{
|
||||||
let mut provider = Self {
|
let provider = Self {
|
||||||
pfield: Self::generate_p_field(days_len, SubmillisPrecision::Absent),
|
pfield: Self::generate_p_field(days_len, SubmillisPrecision::Absent),
|
||||||
ccsds_days,
|
ccsds_days,
|
||||||
ms_of_day,
|
ms_of_day,
|
||||||
unix_time: Default::default(),
|
|
||||||
submillis: 0,
|
submillis: 0,
|
||||||
};
|
};
|
||||||
let unix_days_seconds = ccsds_to_unix_days(i64::from(ccsds_days)) * SECONDS_PER_DAY as i64;
|
|
||||||
provider.setup(unix_days_seconds, ms_of_day);
|
|
||||||
Ok(provider)
|
Ok(provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -738,14 +717,12 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
.ccsds_days_as_u32()
|
.ccsds_days_as_u32()
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| CdsError::InvalidCcsdsDays(converter.ccsds_days_as_u32().into()))?;
|
.map_err(|_| CdsError::InvalidCcsdsDays(converter.ccsds_days_as_u32().into()))?;
|
||||||
let mut provider = Self {
|
let provider = Self {
|
||||||
pfield: Self::generate_p_field(days_len, converter.submillis_precision()),
|
pfield: Self::generate_p_field(days_len, converter.submillis_precision()),
|
||||||
ccsds_days,
|
ccsds_days,
|
||||||
ms_of_day: converter.ms_of_day(),
|
ms_of_day: converter.ms_of_day(),
|
||||||
unix_time: Default::default(),
|
|
||||||
submillis: converter.submillis(),
|
submillis: converter.submillis(),
|
||||||
};
|
};
|
||||||
provider.setup(converter.unix_days_seconds(), converter.ms_of_day());
|
|
||||||
Ok(provider)
|
Ok(provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -786,10 +763,6 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
})?;
|
})?;
|
||||||
self.ccsds_days = ccsds_days;
|
self.ccsds_days = ccsds_days;
|
||||||
self.ms_of_day = conversion_from_now.unix_conversion.ms_of_day;
|
self.ms_of_day = conversion_from_now.unix_conversion.ms_of_day;
|
||||||
self.setup(
|
|
||||||
conversion_from_now.unix_conversion.unix_days_seconds,
|
|
||||||
conversion_from_now.unix_conversion.ms_of_day,
|
|
||||||
);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1186,30 +1159,24 @@ impl TryFrom<chrono::DateTime<chrono::Utc>> for CdsTime<DaysLen24Bits> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ProvidesDaysLen: ProvidesDaysLength> CcsdsTimeProvider for CdsTime<ProvidesDaysLen> {
|
impl<ProvidesDaysLen: ProvidesDaysLength> CcsdsTimeProvider for CdsTime<ProvidesDaysLen> {
|
||||||
|
#[inline]
|
||||||
fn len_as_bytes(&self) -> usize {
|
fn len_as_bytes(&self) -> usize {
|
||||||
Self::calc_stamp_len(self.pfield)
|
Self::calc_stamp_len(self.pfield)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn p_field(&self) -> (usize, [u8; 2]) {
|
fn p_field(&self) -> (usize, [u8; 2]) {
|
||||||
(1, [self.pfield, 0])
|
(1, [self.pfield, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn ccdsd_time_code(&self) -> CcsdsTimeCode {
|
fn ccdsd_time_code(&self) -> CcsdsTimeCode {
|
||||||
CcsdsTimeCode::Cds
|
CcsdsTimeCode::Cds
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn unix_secs(&self) -> i64 {
|
|
||||||
self.unix_time.secs
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn subsec_nanos(&self) -> u32 {
|
|
||||||
self.unix_time.subsec_nanos
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn unix_time(&self) -> UnixTime {
|
fn unix_time(&self) -> UnixTime {
|
||||||
self.unix_time
|
self.calc_unix_seconds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,8 +183,13 @@ pub trait CcsdsTimeProvider {
|
|||||||
fn p_field(&self) -> (usize, [u8; 2]);
|
fn p_field(&self) -> (usize, [u8; 2]);
|
||||||
fn ccdsd_time_code(&self) -> CcsdsTimeCode;
|
fn ccdsd_time_code(&self) -> CcsdsTimeCode;
|
||||||
|
|
||||||
fn unix_secs(&self) -> i64;
|
fn unix_secs(&self) -> i64 {
|
||||||
fn subsec_nanos(&self) -> u32;
|
self.unix_time().secs
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subsec_nanos(&self) -> u32 {
|
||||||
|
self.unix_time().subsec_nanos
|
||||||
|
}
|
||||||
|
|
||||||
fn subsec_millis(&self) -> u16 {
|
fn subsec_millis(&self) -> u16 {
|
||||||
(self.subsec_nanos() / 1_000_000) as u16
|
(self.subsec_nanos() / 1_000_000) as u16
|
||||||
|
|||||||
Reference in New Issue
Block a user