add TM builder API
This commit is contained in:
6
justfile
6
justfile
@@ -1,4 +1,4 @@
|
|||||||
all: check clippy fmt build docs
|
all: check build test clippy fmt docs
|
||||||
|
|
||||||
clippy:
|
clippy:
|
||||||
cargo clippy -- -D warnings
|
cargo clippy -- -D warnings
|
||||||
@@ -9,6 +9,10 @@ fmt:
|
|||||||
check:
|
check:
|
||||||
cargo check --all-features
|
cargo check --all-features
|
||||||
|
|
||||||
|
test:
|
||||||
|
cargo nextest r --all-features
|
||||||
|
cargo test --doc
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cargo build --all-features
|
cargo build --all-features
|
||||||
|
|
||||||
|
|||||||
@@ -260,21 +260,6 @@ pub fn verify_crc16_ccitt_false_from_raw_no_table(raw_data: &[u8]) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! ccsds_impl {
|
|
||||||
() => {
|
|
||||||
delegate!(to self.sp_header {
|
|
||||||
#[inline]
|
|
||||||
fn ccsds_version(&self) -> u3;
|
|
||||||
#[inline]
|
|
||||||
fn packet_id(&self) -> crate::PacketId;
|
|
||||||
#[inline]
|
|
||||||
fn psc(&self) -> crate::PacketSequenceControl;
|
|
||||||
#[inline]
|
|
||||||
fn data_len(&self) -> u16;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! sp_header_impls {
|
macro_rules! sp_header_impls {
|
||||||
() => {
|
() => {
|
||||||
delegate!(to self.sp_header {
|
delegate!(to self.sp_header {
|
||||||
@@ -289,7 +274,6 @@ macro_rules! sp_header_impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::util::{GenericUnsignedByteField, ToBeBytes, UnsignedEnum};
|
use crate::util::{GenericUnsignedByteField, ToBeBytes, UnsignedEnum};
|
||||||
pub(crate) use ccsds_impl;
|
|
||||||
pub(crate) use sp_header_impls;
|
pub(crate) use sp_header_impls;
|
||||||
|
|
||||||
/// Generic trait for ECSS enumeration which consist of a PFC field denoting their bit length
|
/// Generic trait for ECSS enumeration which consist of a PFC field denoting their bit length
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use spacepackets::SpHeader;
|
//! use spacepackets::SpHeader;
|
||||||
//! use spacepackets::ecss::WritablePusPacket;
|
|
||||||
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader, CreatorConfig};
|
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader, CreatorConfig};
|
||||||
//! use arbitrary_int::u11;
|
//! use arbitrary_int::u11;
|
||||||
//!
|
//!
|
||||||
@@ -45,7 +44,7 @@
|
|||||||
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
||||||
pub use crate::ecss::CreatorConfig;
|
pub use crate::ecss::CreatorConfig;
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
ccsds_impl, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
||||||
WritablePusPacket,
|
WritablePusPacket,
|
||||||
};
|
};
|
||||||
@@ -497,7 +496,16 @@ impl WritablePusPacket for PusTcCreator<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTcCreator<'_> {
|
impl CcsdsPacket for PusTcCreator<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTcCreator<'_> {
|
impl PusPacket for PusTcCreator<'_> {
|
||||||
@@ -949,7 +957,16 @@ impl PartialEq for PusTcReader<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTcReader<'_> {
|
impl CcsdsPacket for PusTcReader<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTcReader<'_> {
|
impl PusPacket for PusTcReader<'_> {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
||||||
use crate::ecss::tc::{AckFlags, ACK_ALL};
|
use crate::ecss::tc::{AckFlags, ACK_ALL};
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
ccsds_impl, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
||||||
WritablePusPacket,
|
WritablePusPacket,
|
||||||
};
|
};
|
||||||
@@ -483,7 +483,16 @@ impl WritablePusPacket for PusTcCreator<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTcCreator<'_> {
|
impl CcsdsPacket for PusTcCreator<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTcCreator<'_> {
|
impl PusPacket for PusTcCreator<'_> {
|
||||||
@@ -770,7 +779,16 @@ impl PartialEq for PusTcReader<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTcReader<'_> {
|
impl CcsdsPacket for PusTcReader<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTcReader<'_> {
|
impl PusPacket for PusTcReader<'_> {
|
||||||
|
|||||||
@@ -4,10 +4,8 @@
|
|||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use spacepackets::time::TimeWriter;
|
|
||||||
//! use spacepackets::time::cds::CdsTime;
|
//! use spacepackets::time::cds::CdsTime;
|
||||||
//! use spacepackets::{CcsdsPacket, SpHeader};
|
//! use spacepackets::SpHeader;
|
||||||
//! use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
|
||||||
//! use spacepackets::ecss::tm::{PusTmCreator, PusTmReader, PusTmSecondaryHeader, CreatorConfig};
|
//! use spacepackets::ecss::tm::{PusTmCreator, PusTmReader, PusTmSecondaryHeader, CreatorConfig};
|
||||||
//! use arbitrary_int::u11;
|
//! use arbitrary_int::u11;
|
||||||
//!
|
//!
|
||||||
@@ -42,11 +40,20 @@
|
|||||||
//! assert_eq!(ping_tm_reader.subservice(), 2);
|
//! assert_eq!(ping_tm_reader.subservice(), 2);
|
||||||
//! assert_eq!(ping_tm_reader.apid().value(), 0x02);
|
//! assert_eq!(ping_tm_reader.apid().value(), 0x02);
|
||||||
//! assert_eq!(ping_tm_reader.timestamp(), &time_buf);
|
//! assert_eq!(ping_tm_reader.timestamp(), &time_buf);
|
||||||
|
//!
|
||||||
|
//! // Alternative builder API
|
||||||
|
//! let pus_tm_by_builder = PusTmCreator::builder()
|
||||||
|
//! .with_service(17)
|
||||||
|
//! .with_subservice(2)
|
||||||
|
//! .with_apid(u11::new(0x02))
|
||||||
|
//! .with_timestamp(&time_buf)
|
||||||
|
//! .build();
|
||||||
|
//! assert_eq!(pus_tm_by_builder, ping_tm);
|
||||||
//! ```
|
//! ```
|
||||||
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
||||||
pub use crate::ecss::CreatorConfig;
|
pub use crate::ecss::CreatorConfig;
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
calc_pus_crc16, ccsds_impl, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
calc_pus_crc16, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion,
|
||||||
WritablePusPacket,
|
WritablePusPacket,
|
||||||
};
|
};
|
||||||
@@ -535,7 +542,16 @@ impl PartialEq for PusTmCreator<'_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTmCreator<'_, '_> {
|
impl CcsdsPacket for PusTmCreator<'_, '_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTmCreator<'_, '_> {
|
impl PusPacket for PusTmCreator<'_, '_> {
|
||||||
@@ -1021,6 +1037,26 @@ impl<'raw_data> PusTmReader<'raw_data> {
|
|||||||
self.user_data()
|
self.user_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn service(&self) -> u8 {
|
||||||
|
self.sec_header.service
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn subservice(&self) -> u8 {
|
||||||
|
self.sec_header.subservice
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len(&self) -> usize {
|
||||||
|
self.sp_header.packet_len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn apid(&self) -> u11 {
|
||||||
|
self.sp_header.packet_id.apid
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn timestamp(&self) -> &[u8] {
|
pub fn timestamp(&self) -> &[u8] {
|
||||||
self.sec_header.timestamp
|
self.sec_header.timestamp
|
||||||
@@ -1048,7 +1084,16 @@ impl PartialEq for PusTmReader<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTmReader<'_> {
|
impl CcsdsPacket for PusTmReader<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTmReader<'_> {
|
impl PusPacket for PusTmReader<'_> {
|
||||||
@@ -1332,7 +1377,15 @@ mod tests {
|
|||||||
timestamp: &'a [u8],
|
timestamp: &'a [u8],
|
||||||
alt_api: bool,
|
alt_api: bool,
|
||||||
) -> PusTmCreator<'a, 'b> {
|
) -> PusTmCreator<'a, 'b> {
|
||||||
if alt_api {}
|
if alt_api {
|
||||||
|
return PusTmCreator::builder()
|
||||||
|
.with_apid(u11::new(0x123))
|
||||||
|
.with_sequence_count(u14::new(0x234))
|
||||||
|
.with_service(17)
|
||||||
|
.with_subservice(2)
|
||||||
|
.with_timestamp(timestamp)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
PusTmBuilder::new()
|
PusTmBuilder::new()
|
||||||
.with_apid(u11::new(0x123))
|
.with_apid(u11::new(0x123))
|
||||||
.with_sequence_count(u14::new(0x234))
|
.with_sequence_count(u14::new(0x234))
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
//! ```
|
//! ```
|
||||||
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE};
|
||||||
use crate::ecss::{
|
use crate::ecss::{
|
||||||
calc_pus_crc16, ccsds_impl, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
calc_pus_crc16, crc_from_raw_data, sp_header_impls, user_data_from_raw,
|
||||||
verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, PusError, PusPacket, PusVersion,
|
verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, PusError, PusPacket, PusVersion,
|
||||||
WritablePusPacket,
|
WritablePusPacket,
|
||||||
};
|
};
|
||||||
@@ -541,7 +541,16 @@ impl PartialEq for PusTmCreator<'_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTmCreator<'_, '_> {
|
impl CcsdsPacket for PusTmCreator<'_, '_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTmCreator<'_, '_> {
|
impl PusPacket for PusTmCreator<'_, '_> {
|
||||||
@@ -840,7 +849,16 @@ impl PartialEq for PusTmReader<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl CcsdsPacket for PusTmReader<'_> {
|
impl CcsdsPacket for PusTmReader<'_> {
|
||||||
ccsds_impl!();
|
delegate!(to self.sp_header {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> u3;
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> crate::PacketId;
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> crate::PacketSequenceControl;
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusPacket for PusTmReader<'_> {
|
impl PusPacket for PusTmReader<'_> {
|
||||||
|
|||||||
@@ -642,14 +642,12 @@ impl<ProvidesDaysLen: ProvidesDaysLength> CdsTime<ProvidesDaysLen> {
|
|||||||
self.unix_time = UnixTime::new(unix_days_seconds, subsec_nanos);
|
self.unix_time = UnixTime::new(unix_days_seconds, subsec_nanos);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), TimestampError> {
|
fn length_check(&self, buf: &[u8], len_as_bytes: usize) -> Result<(), ByteConversionError> {
|
||||||
if buf.len() < len_as_bytes {
|
if buf.len() < len_as_bytes {
|
||||||
return Err(TimestampError::ByteConversion(
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
ByteConversionError::ToSliceTooSmall {
|
expected: len_as_bytes,
|
||||||
expected: len_as_bytes,
|
found: buf.len(),
|
||||||
found: buf.len(),
|
});
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -957,6 +955,23 @@ impl CdsTime<DaysLen16Bits> {
|
|||||||
Self::from_now_generic_ps_prec(LengthOfDaySegment::Short16Bits)
|
Self::from_now_generic_ps_prec(LengthOfDaySegment::Short16Bits)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
|
self.length_check(buf, self.len_as_bytes())?;
|
||||||
|
buf[0] = self.pfield;
|
||||||
|
buf[1..3].copy_from_slice(self.ccsds_days.to_be_bytes().as_slice());
|
||||||
|
buf[3..7].copy_from_slice(self.ms_of_day.to_be_bytes().as_slice());
|
||||||
|
match self.submillis_precision() {
|
||||||
|
SubmillisPrecision::Microseconds => {
|
||||||
|
buf[7..9].copy_from_slice((self.submillis() as u16).to_be_bytes().as_slice());
|
||||||
|
}
|
||||||
|
SubmillisPrecision::Picoseconds => {
|
||||||
|
buf[7..11].copy_from_slice(self.submillis().to_be_bytes().as_slice());
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
Ok(self.len_as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_bytes_with_u16_days(buf: &[u8]) -> Result<Self, TimestampError> {
|
pub fn from_bytes_with_u16_days(buf: &[u8]) -> Result<Self, TimestampError> {
|
||||||
let submillis_precision =
|
let submillis_precision =
|
||||||
Self::generic_raw_read_checks(buf, LengthOfDaySegment::Short16Bits)?;
|
Self::generic_raw_read_checks(buf, LengthOfDaySegment::Short16Bits)?;
|
||||||
@@ -1212,20 +1227,7 @@ impl TimeReader for CdsTime<DaysLen24Bits> {
|
|||||||
|
|
||||||
impl TimeWriter for CdsTime<DaysLen16Bits> {
|
impl TimeWriter for CdsTime<DaysLen16Bits> {
|
||||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, TimestampError> {
|
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, TimestampError> {
|
||||||
self.length_check(buf, self.len_as_bytes())?;
|
self.write_to_bytes(buf).map_err(TimestampError::from)
|
||||||
buf[0] = self.pfield;
|
|
||||||
buf[1..3].copy_from_slice(self.ccsds_days.to_be_bytes().as_slice());
|
|
||||||
buf[3..7].copy_from_slice(self.ms_of_day.to_be_bytes().as_slice());
|
|
||||||
match self.submillis_precision() {
|
|
||||||
SubmillisPrecision::Microseconds => {
|
|
||||||
buf[7..9].copy_from_slice((self.submillis() as u16).to_be_bytes().as_slice());
|
|
||||||
}
|
|
||||||
SubmillisPrecision::Picoseconds => {
|
|
||||||
buf[7..11].copy_from_slice(self.submillis().to_be_bytes().as_slice());
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
Ok(self.len_as_bytes())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len_written(&self) -> usize {
|
fn len_written(&self) -> usize {
|
||||||
@@ -1233,8 +1235,8 @@ impl TimeWriter for CdsTime<DaysLen16Bits> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimeWriter for CdsTime<DaysLen24Bits> {
|
impl CdsTime<DaysLen24Bits> {
|
||||||
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, TimestampError> {
|
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
self.length_check(buf, self.len_as_bytes())?;
|
self.length_check(buf, self.len_as_bytes())?;
|
||||||
buf[0] = self.pfield;
|
buf[0] = self.pfield;
|
||||||
let be_days = self.ccsds_days.to_be_bytes();
|
let be_days = self.ccsds_days.to_be_bytes();
|
||||||
@@ -1251,6 +1253,12 @@ impl TimeWriter for CdsTime<DaysLen24Bits> {
|
|||||||
}
|
}
|
||||||
Ok(self.len_as_bytes())
|
Ok(self.len_as_bytes())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeWriter for CdsTime<DaysLen24Bits> {
|
||||||
|
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, TimestampError> {
|
||||||
|
self.write_to_bytes(buf).map_err(TimestampError::from)
|
||||||
|
}
|
||||||
|
|
||||||
fn len_written(&self) -> usize {
|
fn len_written(&self) -> usize {
|
||||||
self.len_as_bytes()
|
self.len_as_bytes()
|
||||||
@@ -1331,7 +1339,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::time::TimestampError::{ByteConversion, InvalidTimeCode};
|
use crate::time::TimestampError::{ByteConversion, InvalidTimeCode};
|
||||||
use crate::time::{UnixTime, DAYS_CCSDS_TO_UNIX, MS_PER_DAY};
|
use crate::time::{UnixTime, DAYS_CCSDS_TO_UNIX, MS_PER_DAY};
|
||||||
use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall};
|
use crate::ByteConversionError::FromSliceTooSmall;
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use chrono::{Datelike, NaiveDate, Timelike};
|
use chrono::{Datelike, NaiveDate, Timelike};
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
@@ -1486,12 +1494,14 @@ mod tests {
|
|||||||
assert!(res.is_err());
|
assert!(res.is_err());
|
||||||
let error = res.unwrap_err();
|
let error = res.unwrap_err();
|
||||||
match error {
|
match error {
|
||||||
ByteConversion(ToSliceTooSmall { found, expected }) => {
|
ByteConversionError::ToSliceTooSmall { found, expected } => {
|
||||||
assert_eq!(found, i);
|
assert_eq!(found, i);
|
||||||
assert_eq!(expected, 7);
|
assert_eq!(expected, 7);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
error.to_string(),
|
error.to_string(),
|
||||||
format!("time stamp: target slice with size {i} is too small, expected size of at least 7")
|
format!(
|
||||||
|
"target slice with size {i} is too small, expected size of at least 7"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
@@ -1537,10 +1547,7 @@ mod tests {
|
|||||||
if let InvalidTimeCode { expected, found } = err {
|
if let InvalidTimeCode { expected, found } = err {
|
||||||
assert_eq!(expected, CcsdsTimeCode::Cds);
|
assert_eq!(expected, CcsdsTimeCode::Cds);
|
||||||
assert_eq!(found, 0);
|
assert_eq!(found, 0);
|
||||||
assert_eq!(
|
assert_eq!(err.to_string(), "invalid time code, expected Cds, found 0");
|
||||||
err.to_string(),
|
|
||||||
"invalid raw time code value 0 for time code Cds"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2301,7 +2308,7 @@ mod tests {
|
|||||||
fn test_serialization() {
|
fn test_serialization() {
|
||||||
let stamp_now = CdsTime::now_with_u16_days().expect("Error retrieving time");
|
let stamp_now = CdsTime::now_with_u16_days().expect("Error retrieving time");
|
||||||
let val = to_allocvec(&stamp_now).expect("Serializing timestamp failed");
|
let val = to_allocvec(&stamp_now).expect("Serializing timestamp failed");
|
||||||
assert!(val.len() > 0);
|
assert!(!val.is_empty());
|
||||||
let stamp_deser: CdsTime = from_bytes(&val).expect("Stamp deserialization failed");
|
let stamp_deser: CdsTime = from_bytes(&val).expect("Stamp deserialization failed");
|
||||||
assert_eq!(stamp_deser, stamp_now);
|
assert_eq!(stamp_deser, stamp_now);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ use crate::ByteConversionError;
|
|||||||
#[cfg(feature = "chrono")]
|
#[cfg(feature = "chrono")]
|
||||||
use chrono::{TimeZone, Utc};
|
use chrono::{TimeZone, Utc};
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::fmt::{Display, Formatter};
|
|
||||||
use core::ops::{Add, AddAssign, Sub};
|
use core::ops::{Add, AddAssign, Sub};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
|
||||||
@@ -14,8 +13,6 @@ use num_traits::float::FloatCore;
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use std::error::Error;
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::time::{SystemTime, SystemTimeError};
|
use std::time::{SystemTime, SystemTimeError};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@@ -69,67 +66,23 @@ pub fn ccsds_time_code_from_p_field(pfield: u8) -> Result<CcsdsTimeCode, u8> {
|
|||||||
#[error("date before ccsds epoch: {0:?}")]
|
#[error("date before ccsds epoch: {0:?}")]
|
||||||
pub struct DateBeforeCcsdsEpochError(UnixTime);
|
pub struct DateBeforeCcsdsEpochError(UnixTime);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, 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))]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum TimestampError {
|
pub enum TimestampError {
|
||||||
|
#[error("invalid time code, expected {expected:?}, found {found}")]
|
||||||
InvalidTimeCode { expected: CcsdsTimeCode, found: u8 },
|
InvalidTimeCode { expected: CcsdsTimeCode, found: u8 },
|
||||||
ByteConversion(ByteConversionError),
|
#[error("time stamp: byte conversion error: {0}")]
|
||||||
Cds(cds::CdsError),
|
ByteConversion(#[from] ByteConversionError),
|
||||||
Cuc(cuc::CucError),
|
#[error("CDS error: {0}")]
|
||||||
|
Cds(#[from] cds::CdsError),
|
||||||
|
#[error("CUC error: {0}")]
|
||||||
|
Cuc(#[from] cuc::CucError),
|
||||||
|
#[error("custom epoch not supported")]
|
||||||
CustomEpochNotSupported,
|
CustomEpochNotSupported,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for TimestampError {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
|
||||||
match self {
|
|
||||||
TimestampError::InvalidTimeCode { expected, found } => {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"invalid raw time code value {found} for time code {expected:?}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TimestampError::Cds(e) => {
|
|
||||||
write!(f, "cds error: {e}")
|
|
||||||
}
|
|
||||||
TimestampError::Cuc(e) => {
|
|
||||||
write!(f, "cuc error: {e}")
|
|
||||||
}
|
|
||||||
TimestampError::ByteConversion(e) => {
|
|
||||||
write!(f, "time stamp: {e}")
|
|
||||||
}
|
|
||||||
TimestampError::CustomEpochNotSupported => {
|
|
||||||
write!(f, "custom epochs are not supported")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl Error for TimestampError {
|
|
||||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
|
||||||
match self {
|
|
||||||
TimestampError::ByteConversion(e) => Some(e),
|
|
||||||
TimestampError::Cds(e) => Some(e),
|
|
||||||
TimestampError::Cuc(e) => Some(e),
|
|
||||||
_ => 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(feature = "std")]
|
||||||
pub mod std_mod {
|
pub mod std_mod {
|
||||||
use crate::time::TimestampError;
|
use crate::time::TimestampError;
|
||||||
@@ -735,7 +688,7 @@ mod tests {
|
|||||||
fn test_cuc_error_printout() {
|
fn test_cuc_error_printout() {
|
||||||
let cuc_error = CucError::InvalidCounterWidth(12);
|
let cuc_error = CucError::InvalidCounterWidth(12);
|
||||||
let stamp_error = TimestampError::from(cuc_error);
|
let stamp_error = TimestampError::from(cuc_error);
|
||||||
assert_eq!(stamp_error.to_string(), format!("cuc error: {cuc_error}"));
|
assert_eq!(stamp_error.to_string(), format!("CUC error: {cuc_error}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user