Merge pull request 'unify CCSDS API as well' (#79) from unify-ccsds-api into main
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good

Reviewed-on: #79
This commit is contained in:
Robin Müller 2024-04-03 19:45:14 +02:00
commit ca90393d95
4 changed files with 171 additions and 88 deletions

View File

@ -8,6 +8,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
## Changed
- Renamed `PacketId` and `PacketSequenceCtrl` `new` method to `new_checked` and former
`new_const` method to `new`.
- Renamed `tc`, `tm`, `tc_unseg` and `tm_unseg` variants for `PacketId` and `SpHeader`
to `new_for_tc_checked`, `new_for_tm_checked`, `new_for_unseg_tc_checked` and
`new_for_unseg_tm_checked`.
# [v0.11.0-rc.1] 2024-04-03 # [v0.11.0-rc.1] 2024-04-03
Major API changes for the time API. If you are using the time API, it is strongly recommended Major API changes for the time API. If you are using the time API, it is strongly recommended

View File

@ -9,7 +9,7 @@
//! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; //! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
//! //!
//! // Create a ping telecommand with no user application data //! // Create a ping telecommand with no user application data
//! let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); //! let mut sph = SpHeader::new_for_unseg_tc_checked(0x02, 0x34, 0).unwrap();
//! let tc_header = PusTcSecondaryHeader::new_simple(17, 1); //! let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
//! let pus_tc = PusTcCreator::new_no_app_data(&mut sph, tc_header, true); //! let pus_tc = PusTcCreator::new_no_app_data(&mut sph, tc_header, true);
//! println!("{:?}", pus_tc); //! println!("{:?}", pus_tc);
@ -568,18 +568,18 @@ mod tests {
use postcard::{from_bytes, to_allocvec}; use postcard::{from_bytes, to_allocvec};
fn base_ping_tc_full_ctor() -> PusTcCreator<'static> { fn base_ping_tc_full_ctor() -> PusTcCreator<'static> {
let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tc_checked(0x02, 0x34, 0).unwrap();
let tc_header = PusTcSecondaryHeader::new_simple(17, 1); let tc_header = PusTcSecondaryHeader::new_simple(17, 1);
PusTcCreator::new_no_app_data(&mut sph, tc_header, true) PusTcCreator::new_no_app_data(&mut sph, tc_header, true)
} }
fn base_ping_tc_simple_ctor() -> PusTcCreator<'static> { fn base_ping_tc_simple_ctor() -> PusTcCreator<'static> {
let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tc_checked(0x02, 0x34, 0).unwrap();
PusTcCreator::new_simple(&mut sph, 17, 1, &[], true) PusTcCreator::new_simple(&mut sph, 17, 1, &[], true)
} }
fn base_ping_tc_simple_ctor_with_app_data(app_data: &'static [u8]) -> PusTcCreator<'static> { fn base_ping_tc_simple_ctor_with_app_data(app_data: &'static [u8]) -> PusTcCreator<'static> {
let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tc_checked(0x02, 0x34, 0).unwrap();
PusTcCreator::new_simple(&mut sph, 17, 1, app_data, true) PusTcCreator::new_simple(&mut sph, 17, 1, app_data, true)
} }
@ -636,7 +636,7 @@ mod tests {
#[test] #[test]
fn test_update_func() { fn test_update_func() {
let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tc_checked(0x02, 0x34, 0).unwrap();
let mut tc = PusTcCreator::new_simple(&mut sph, 17, 1, &[], false); let mut tc = PusTcCreator::new_simple(&mut sph, 17, 1, &[], false);
assert_eq!(tc.data_len(), 0); assert_eq!(tc.data_len(), 0);
tc.update_ccsds_data_len(); tc.update_ccsds_data_len();
@ -809,7 +809,8 @@ mod tests {
if !has_user_data { if !has_user_data {
assert!(tc.user_data().is_empty()); assert!(tc.user_data().is_empty());
} }
let mut comp_header = SpHeader::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap(); let mut comp_header =
SpHeader::new_for_unseg_tc_checked(0x02, 0x34, exp_full_len as u16 - 7).unwrap();
comp_header.set_sec_header_flag(); comp_header.set_sec_header_flag();
assert_eq!(*tc.sp_header(), comp_header); assert_eq!(*tc.sp_header(), comp_header);
} }
@ -820,7 +821,8 @@ mod tests {
assert!(tc.user_data().is_empty()); assert!(tc.user_data().is_empty());
} }
assert_eq!(tc.len_packed(), exp_full_len); assert_eq!(tc.len_packed(), exp_full_len);
let mut comp_header = SpHeader::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap(); let mut comp_header =
SpHeader::new_for_unseg_tc_checked(0x02, 0x34, exp_full_len as u16 - 7).unwrap();
comp_header.set_sec_header_flag(); comp_header.set_sec_header_flag();
assert_eq!(*tc.sp_header(), comp_header); assert_eq!(*tc.sp_header(), comp_header);
} }

View File

@ -788,18 +788,18 @@ mod tests {
const DUMMY_DATA: &[u8] = &[0, 1, 2]; const DUMMY_DATA: &[u8] = &[0, 1, 2];
fn base_ping_reply_full_ctor(timestamp: &[u8]) -> PusTmCreator { fn base_ping_reply_full_ctor(timestamp: &[u8]) -> PusTmCreator {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
PusTmCreator::new_no_source_data(&mut sph, tm_header, true) PusTmCreator::new_no_source_data(&mut sph, tm_header, true)
} }
fn ping_reply_with_data(timestamp: &[u8]) -> PusTmCreator { fn ping_reply_with_data(timestamp: &[u8]) -> PusTmCreator {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp);
PusTmCreator::new(&mut sph, tm_header, DUMMY_DATA, true) PusTmCreator::new(&mut sph, tm_header, DUMMY_DATA, true)
} }
fn base_hk_reply<'a, 'b>(timestamp: &'a [u8], src_data: &'b [u8]) -> PusTmCreator<'a, 'b> { fn base_hk_reply<'a, 'b>(timestamp: &'a [u8], src_data: &'b [u8]) -> PusTmCreator<'a, 'b> {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let tc_header = PusTmSecondaryHeader::new_simple(3, 5, timestamp); let tc_header = PusTmSecondaryHeader::new_simple(3, 5, timestamp);
PusTmCreator::new(&mut sph, tc_header, src_data, true) PusTmCreator::new(&mut sph, tc_header, src_data, true)
} }
@ -816,7 +816,7 @@ mod tests {
} }
#[test] #[test]
fn test_basic_simple_api() { fn test_basic_simple_api() {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let time_provider = CdsTime::new_with_u16_days(0, 0); let time_provider = CdsTime::new_with_u16_days(0, 0);
let mut stamp_buf: [u8; 8] = [0; 8]; let mut stamp_buf: [u8; 8] = [0; 8];
let pus_tm = let pus_tm =
@ -917,7 +917,7 @@ mod tests {
#[test] #[test]
fn test_manual_field_update() { fn test_manual_field_update() {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, dummy_timestamp()); let tc_header = PusTmSecondaryHeader::new_simple(17, 2, dummy_timestamp());
let mut tm = PusTmCreator::new_no_source_data(&mut sph, tc_header, false); let mut tm = PusTmCreator::new_no_source_data(&mut sph, tc_header, false);
tm.calc_crc_on_serialization = false; tm.calc_crc_on_serialization = false;
@ -1207,7 +1207,7 @@ mod tests {
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
fn test_serialization_creator_serde() { fn test_serialization_creator_serde() {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let time_provider = CdsTime::new_with_u16_days(0, 0); let time_provider = CdsTime::new_with_u16_days(0, 0);
let mut stamp_buf: [u8; 8] = [0; 8]; let mut stamp_buf: [u8; 8] = [0; 8];
let pus_tm = let pus_tm =
@ -1222,7 +1222,7 @@ mod tests {
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
fn test_serialization_reader_serde() { fn test_serialization_reader_serde() {
let mut sph = SpHeader::tm_unseg(0x123, 0x234, 0).unwrap(); let mut sph = SpHeader::new_for_unseg_tm_checked(0x123, 0x234, 0).unwrap();
let time_provider = CdsTime::new_with_u16_days(0, 0); let time_provider = CdsTime::new_with_u16_days(0, 0);
let mut stamp_buf: [u8; 8] = [0; 8]; let mut stamp_buf: [u8; 8] = [0; 8];
let pus_tm = let pus_tm =

View File

@ -52,7 +52,7 @@
//! //!
//! ```rust //! ```rust
//! use spacepackets::SpHeader; //! use spacepackets::SpHeader;
//! let sp_header = SpHeader::tc_unseg(0x42, 12, 1).expect("Error creating CCSDS TC header"); //! let sp_header = SpHeader::new_for_unseg_tc_checked(0x42, 12, 1).expect("error creating CCSDS TC header");
//! println!("{:?}", sp_header); //! println!("{:?}", sp_header);
//! let mut ccsds_buf: [u8; 32] = [0; 32]; //! let mut ccsds_buf: [u8; 32] = [0; 32];
//! sp_header.write_to_be_bytes(&mut ccsds_buf).expect("Writing CCSDS TC header failed"); //! sp_header.write_to_be_bytes(&mut ccsds_buf).expect("Writing CCSDS TC header failed");
@ -242,23 +242,29 @@ impl Default for PacketId {
} }
impl PacketId { impl PacketId {
pub const fn const_tc(sec_header: bool, apid: u16) -> Self { /// This constructor will panic if the passed APID exceeds [MAX_APID].
Self::const_new(PacketType::Tc, sec_header, apid) /// Use the checked constructor variants to avoid panics.
} pub const fn new_for_tc(sec_header: bool, apid: u16) -> Self {
pub const fn const_tm(sec_header: bool, apid: u16) -> Self {
Self::const_new(PacketType::Tm, sec_header, apid)
}
pub fn tc(sec_header: bool, apid: u16) -> Option<Self> {
Self::new(PacketType::Tc, sec_header, apid) Self::new(PacketType::Tc, sec_header, apid)
} }
pub fn tm(sec_header: bool, apid: u16) -> Option<Self> { /// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked constructor variants to avoid panics.
pub const fn new_for_tm(sec_header: bool, apid: u16) -> Self {
Self::new(PacketType::Tm, sec_header, apid) Self::new(PacketType::Tm, sec_header, apid)
} }
pub const fn const_new(ptype: PacketType, sec_header: bool, apid: u16) -> Self { pub fn new_for_tc_checked(sec_header: bool, apid: u16) -> Option<Self> {
Self::new_checked(PacketType::Tc, sec_header, apid)
}
pub fn new_for_tm_checked(sec_header: bool, apid: u16) -> Option<Self> {
Self::new_checked(PacketType::Tm, sec_header, apid)
}
/// This constructor will panic if the passed APID exceeds [MAX_APID].
/// Use the checked variants to avoid panics.
pub const fn new(ptype: PacketType, sec_header: bool, apid: u16) -> Self {
if apid > MAX_APID { if apid > MAX_APID {
panic!("APID too large"); panic!("APID too large");
} }
@ -269,11 +275,11 @@ impl PacketId {
} }
} }
pub fn new(ptype: PacketType, sec_header_flag: bool, apid: u16) -> Option<PacketId> { pub fn new_checked(ptype: PacketType, sec_header_flag: bool, apid: u16) -> Option<PacketId> {
if apid > MAX_APID { if apid > MAX_APID {
return None; return None;
} }
Some(PacketId::const_new(ptype, sec_header_flag, apid)) Some(PacketId::new(ptype, sec_header_flag, apid))
} }
/// Set a new Application Process ID (APID). If the passed number is invalid, the APID will /// Set a new Application Process ID (APID). If the passed number is invalid, the APID will
@ -318,9 +324,9 @@ pub struct PacketSequenceCtrl {
} }
impl PacketSequenceCtrl { impl PacketSequenceCtrl {
/// const variant of [PacketSequenceCtrl::new], but panics if the sequence count exceeds /// This constructor panics if the sequence count exceeds [MAX_SEQ_COUNT].
/// [MAX_SEQ_COUNT]. /// Use [Self::new_checked] to avoid panics.
pub const fn const_new(seq_flags: SequenceFlags, seq_count: u16) -> PacketSequenceCtrl { pub const fn new(seq_flags: SequenceFlags, seq_count: u16) -> PacketSequenceCtrl {
if seq_count > MAX_SEQ_COUNT { if seq_count > MAX_SEQ_COUNT {
panic!("Sequence count too large"); panic!("Sequence count too large");
} }
@ -331,11 +337,11 @@ impl PacketSequenceCtrl {
} }
/// Returns [None] if the passed sequence count exceeds [MAX_SEQ_COUNT]. /// Returns [None] if the passed sequence count exceeds [MAX_SEQ_COUNT].
pub fn new(seq_flags: SequenceFlags, seq_count: u16) -> Option<PacketSequenceCtrl> { pub fn new_checked(seq_flags: SequenceFlags, seq_count: u16) -> Option<PacketSequenceCtrl> {
if seq_count > MAX_SEQ_COUNT { if seq_count > MAX_SEQ_COUNT {
return None; return None;
} }
Some(PacketSequenceCtrl::const_new(seq_flags, seq_count)) Some(PacketSequenceCtrl::new(seq_flags, seq_count))
} }
pub fn raw(&self) -> u16 { pub fn raw(&self) -> u16 {
((self.seq_flags as u16) << 14) | self.seq_count ((self.seq_flags as u16) << 14) | self.seq_count
@ -506,9 +512,11 @@ impl SpHeader {
} }
} }
/// const variant of the [SpHeader::new_fron_single_fields] function. Panics if the passed /// This constructor panics if the passed APID exceeds [MAX_APID] or the passed packet sequence
/// APID exceeds [MAX_APID] or the passed packet sequence count exceeds [MAX_SEQ_COUNT]. /// count exceeds [MAX_SEQ_COUNT].
const fn const_new_from_single_fields( ///
/// The checked constructor variants can be used to avoid panics.
const fn new_from_fields(
ptype: PacketType, ptype: PacketType,
sec_header: bool, sec_header: bool,
apid: u16, apid: u16,
@ -523,17 +531,19 @@ impl SpHeader {
panic!("APID is too large"); panic!("APID is too large");
} }
Self { Self {
psc: PacketSequenceCtrl::const_new(seq_flags, seq_count), psc: PacketSequenceCtrl::new(seq_flags, seq_count),
packet_id: PacketId::const_new(ptype, sec_header, apid), packet_id: PacketId::new(ptype, sec_header, apid),
data_len, data_len,
version: 0, version: 0,
} }
} }
/// Create a new Space Packet Header instance which can be used to create generic /// Create a new Space Packet Header instance which can be used to create generic
/// Space Packets. This will return [None] if the APID or sequence count argument /// Space Packets.
///
/// This will return [None] if the APID or sequence count argument
/// exceed [MAX_APID] or [MAX_SEQ_COUNT] respectively. The version field is set to 0b000. /// exceed [MAX_APID] or [MAX_SEQ_COUNT] respectively. The version field is set to 0b000.
pub fn new_from_single_fields( pub fn new_from_fields_checked(
ptype: PacketType, ptype: PacketType,
sec_header: bool, sec_header: bool,
apid: u16, apid: u16,
@ -544,43 +554,90 @@ impl SpHeader {
if seq_count > MAX_SEQ_COUNT || apid > MAX_APID { if seq_count > MAX_SEQ_COUNT || apid > MAX_APID {
return None; return None;
} }
Some(SpHeader::const_new_from_single_fields( Some(SpHeader::new_from_fields(
ptype, sec_header, apid, seq_flags, seq_count, data_len, ptype, sec_header, apid, seq_flags, seq_count, data_len,
)) ))
} }
/// Helper function for telemetry space packet headers. The packet type field will be /// Helper function for telemetry space packet headers. The packet type field will be
/// set accordingly. The secondary header flag field is set to false. /// set accordingly. The secondary header flag field is set to false.
pub fn tm(apid: u16, seq_flags: SequenceFlags, seq_count: u16, data_len: u16) -> Option<Self> { pub fn new_for_tm_checked(
Self::new_from_single_fields(PacketType::Tm, false, apid, seq_flags, seq_count, data_len) apid: u16,
seq_flags: SequenceFlags,
seq_count: u16,
data_len: u16,
) -> Option<Self> {
Self::new_from_fields_checked(PacketType::Tm, false, apid, seq_flags, seq_count, data_len)
} }
/// Helper function for telemetry space packet headers. The packet type field will be /// Helper function for telemetry space packet headers. The packet type field will be
/// set accordingly. The secondary header flag field is set to false. /// set accordingly. The secondary header flag field is set to false.
pub fn tc(apid: u16, seq_flags: SequenceFlags, seq_count: u16, data_len: u16) -> Option<Self> { pub fn new_for_tc_checked(
Self::new_from_single_fields(PacketType::Tc, false, apid, seq_flags, seq_count, data_len) apid: u16,
seq_flags: SequenceFlags,
seq_count: u16,
data_len: u16,
) -> Option<Self> {
Self::new_from_fields_checked(PacketType::Tc, false, apid, seq_flags, seq_count, data_len)
} }
/// Variant of [SpHeader::tm] which sets the sequence flag field to [SequenceFlags::Unsegmented] /// This is an unchecked constructor which can panic on invalid input.
pub fn tm_unseg(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> { pub const fn new_for_tm(
Self::tm(apid, SequenceFlags::Unsegmented, seq_count, data_len) apid: u16,
seq_flags: SequenceFlags,
seq_count: u16,
data_len: u16,
) -> Self {
Self::new_from_fields(PacketType::Tm, false, apid, seq_flags, seq_count, data_len)
} }
/// Variant of [SpHeader::tc] which sets the sequence flag field to [SequenceFlags::Unsegmented] /// This is an unchecked constructor which can panic on invalid input.
pub fn tc_unseg(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> { pub const fn new_for_tc(
Self::tc(apid, SequenceFlags::Unsegmented, seq_count, data_len) apid: u16,
seq_flags: SequenceFlags,
seq_count: u16,
data_len: u16,
) -> Self {
Self::new_from_fields(PacketType::Tc, false, apid, seq_flags, seq_count, data_len)
} }
//noinspection RsTraitImplementation /// Variant of [SpHeader::new_for_tm_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
delegate!(to self.packet_id { pub fn new_for_unseg_tm_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
/// Returns [false] and fails if the APID exceeds [MAX_APID] Self::new_for_tm_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
pub fn set_apid(&mut self, apid: u16) -> bool; }
});
delegate!(to self.psc { /// Variant of [SpHeader::new_for_tc_checked] which sets the sequence flag field to [SequenceFlags::Unsegmented]
/// Returns [false] and fails if the sequence count exceeds [MAX_SEQ_COUNT] pub fn new_for_unseg_tc_checked(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
pub fn set_seq_count(&mut self, seq_count: u16) -> bool; Self::new_for_tc_checked(apid, SequenceFlags::Unsegmented, seq_count, data_len)
}); }
/// Variant of [SpHeader::new_for_tc] which sets the sequence flag field to [SequenceFlags::Unsegmented].
///
/// This is an unchecked constructor which can panic on invalid input.
pub const fn new_for_unseg_tc(apid: u16, seq_count: u16, data_len: u16) -> Self {
Self::new_for_tc(apid, SequenceFlags::Unsegmented, seq_count, data_len)
}
/// Variant of [SpHeader::new_for_tm] which sets the sequence flag field to [SequenceFlags::Unsegmented].
///
/// This is an unchecked constructor which can panic on invalid input.
pub const fn new_for_unseg_tm(apid: u16, seq_count: u16, data_len: u16) -> Self {
Self::new_for_tm(apid, SequenceFlags::Unsegmented, seq_count, data_len)
}
delegate! {
to self.packet_id {
/// Returns [false] and fails if the APID exceeds [MAX_APID]
pub fn set_apid(&mut self, apid: u16) -> bool;
}
}
delegate! {
to self.psc {
/// Returns [false] and fails if the sequence count exceeds [MAX_SEQ_COUNT]
pub fn set_seq_count(&mut self, seq_count: u16) -> bool;
}
}
pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) { pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) {
self.psc.seq_flags = seq_flags; self.psc.seq_flags = seq_flags;
@ -778,12 +835,12 @@ pub(crate) mod tests {
use serde::{de::DeserializeOwned, Serialize}; use serde::{de::DeserializeOwned, Serialize};
const CONST_SP: SpHeader = SpHeader::new( const CONST_SP: SpHeader = SpHeader::new(
PacketId::const_tc(true, 0x36), PacketId::new_for_tc(true, 0x36),
PacketSequenceCtrl::const_new(SequenceFlags::ContinuationSegment, 0x88), PacketSequenceCtrl::new(SequenceFlags::ContinuationSegment, 0x88),
0x90, 0x90,
); );
const PACKET_ID_TM: PacketId = PacketId::const_tm(true, 0x22); const PACKET_ID_TM: PacketId = PacketId::new_for_tm(true, 0x22);
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
pub(crate) fn generic_serde_test<T: Serialize + DeserializeOwned + PartialEq + Debug>( pub(crate) fn generic_serde_test<T: Serialize + DeserializeOwned + PartialEq + Debug>(
@ -795,11 +852,12 @@ pub(crate) mod tests {
} }
#[test] #[test]
#[allow(clippy::assertions_on_constants)]
fn verify_const_packet_id() { fn verify_const_packet_id() {
assert_eq!(PACKET_ID_TM.apid(), 0x22); assert_eq!(PACKET_ID_TM.apid(), 0x22);
assert!(PACKET_ID_TM.sec_header_flag); assert!(PACKET_ID_TM.sec_header_flag);
assert_eq!(PACKET_ID_TM.ptype, PacketType::Tm); assert_eq!(PACKET_ID_TM.ptype, PacketType::Tm);
let const_tc_id = PacketId::const_tc(true, 0x23); let const_tc_id = PacketId::new_for_tc(true, 0x23);
assert_eq!(const_tc_id.ptype, PacketType::Tc); assert_eq!(const_tc_id.ptype, PacketType::Tc);
} }
@ -813,27 +871,27 @@ pub(crate) mod tests {
#[test] #[test]
fn test_packet_id_ctors() { fn test_packet_id_ctors() {
let packet_id = PacketId::new(PacketType::Tc, true, 0x1ff); let packet_id = PacketId::new_checked(PacketType::Tc, true, 0x1ff);
assert!(packet_id.is_some()); assert!(packet_id.is_some());
let packet_id = packet_id.unwrap(); let packet_id = packet_id.unwrap();
assert_eq!(packet_id.apid(), 0x1ff); assert_eq!(packet_id.apid(), 0x1ff);
assert_eq!(packet_id.ptype, PacketType::Tc); assert_eq!(packet_id.ptype, PacketType::Tc);
assert!(packet_id.sec_header_flag); assert!(packet_id.sec_header_flag);
let packet_id_tc = PacketId::tc(true, 0x1ff); let packet_id_tc = PacketId::new_for_tc_checked(true, 0x1ff);
assert!(packet_id_tc.is_some()); assert!(packet_id_tc.is_some());
let packet_id_tc = packet_id_tc.unwrap(); let packet_id_tc = packet_id_tc.unwrap();
assert_eq!(packet_id_tc, packet_id); assert_eq!(packet_id_tc, packet_id);
let packet_id_tm = PacketId::tm(true, 0x2ff); let packet_id_tm = PacketId::new_for_tm_checked(true, 0x2ff);
assert!(packet_id_tm.is_some()); assert!(packet_id_tm.is_some());
let packet_id_tm = packet_id_tm.unwrap(); let packet_id_tm = packet_id_tm.unwrap();
assert_eq!(packet_id_tm.sec_header_flag, true); assert!(packet_id_tm.sec_header_flag);
assert_eq!(packet_id_tm.ptype, PacketType::Tm); assert_eq!(packet_id_tm.ptype, PacketType::Tm);
assert_eq!(packet_id_tm.apid, 0x2ff); assert_eq!(packet_id_tm.apid, 0x2ff);
} }
#[test] #[test]
fn verify_const_sp_header() { fn verify_const_sp_header() {
assert_eq!(CONST_SP.sec_header_flag(), true); assert!(CONST_SP.sec_header_flag());
assert_eq!(CONST_SP.apid(), 0x36); assert_eq!(CONST_SP.apid(), 0x36);
assert_eq!( assert_eq!(
CONST_SP.sequence_flags(), CONST_SP.sequence_flags(),
@ -874,7 +932,7 @@ pub(crate) mod tests {
#[test] #[test]
fn test_packet_id() { fn test_packet_id() {
let packet_id = let packet_id =
PacketId::new(PacketType::Tm, false, 0x42).expect("Packet ID creation failed"); PacketId::new_checked(PacketType::Tm, false, 0x42).expect("Packet ID creation failed");
assert_eq!(packet_id.raw(), 0x0042); assert_eq!(packet_id.raw(), 0x0042);
let packet_id_from_raw = PacketId::from(packet_id.raw()); let packet_id_from_raw = PacketId::from(packet_id.raw());
assert_eq!( assert_eq!(
@ -882,26 +940,26 @@ pub(crate) mod tests {
PacketType::Tm PacketType::Tm
); );
assert_eq!(packet_id_from_raw, packet_id); assert_eq!(packet_id_from_raw, packet_id);
let packet_id_from_new = PacketId::new(PacketType::Tm, false, 0x42).unwrap(); let packet_id_from_new = PacketId::new_checked(PacketType::Tm, false, 0x42).unwrap();
assert_eq!(packet_id_from_new, packet_id); assert_eq!(packet_id_from_new, packet_id);
} }
#[test] #[test]
fn test_invalid_packet_id() { fn test_invalid_packet_id() {
let packet_id_invalid = PacketId::new(PacketType::Tc, true, 0xFFFF); let packet_id_invalid = PacketId::new_checked(PacketType::Tc, true, 0xFFFF);
assert!(packet_id_invalid.is_none()); assert!(packet_id_invalid.is_none());
} }
#[test] #[test]
fn test_invalid_apid_setter() { fn test_invalid_apid_setter() {
let mut packet_id = let mut packet_id =
PacketId::new(PacketType::Tm, false, 0x42).expect("Packet ID creation failed"); PacketId::new_checked(PacketType::Tm, false, 0x42).expect("Packet ID creation failed");
assert!(!packet_id.set_apid(0xffff)); assert!(!packet_id.set_apid(0xffff));
} }
#[test] #[test]
fn test_invalid_seq_count() { fn test_invalid_seq_count() {
let mut psc = PacketSequenceCtrl::new(SequenceFlags::ContinuationSegment, 77) let mut psc = PacketSequenceCtrl::new_checked(SequenceFlags::ContinuationSegment, 77)
.expect("PSC creation failed"); .expect("PSC creation failed");
assert_eq!(psc.seq_count(), 77); assert_eq!(psc.seq_count(), 77);
assert!(!psc.set_seq_count(0xffff)); assert!(!psc.set_seq_count(0xffff));
@ -909,7 +967,7 @@ pub(crate) mod tests {
#[test] #[test]
fn test_packet_seq_ctrl() { fn test_packet_seq_ctrl() {
let mut psc = PacketSequenceCtrl::new(SequenceFlags::ContinuationSegment, 77) let mut psc = PacketSequenceCtrl::new_checked(SequenceFlags::ContinuationSegment, 77)
.expect("PSC creation failed"); .expect("PSC creation failed");
assert_eq!(psc.raw(), 77); assert_eq!(psc.raw(), 77);
let psc_from_raw = PacketSequenceCtrl::from(psc.raw()); let psc_from_raw = PacketSequenceCtrl::from(psc.raw());
@ -918,16 +976,18 @@ pub(crate) mod tests {
assert!(!psc.set_seq_count(2u16.pow(15))); assert!(!psc.set_seq_count(2u16.pow(15)));
assert_eq!(psc.raw(), 77); assert_eq!(psc.raw(), 77);
let psc_invalid = PacketSequenceCtrl::new(SequenceFlags::FirstSegment, 0xFFFF); let psc_invalid = PacketSequenceCtrl::new_checked(SequenceFlags::FirstSegment, 0xFFFF);
assert!(psc_invalid.is_none()); assert!(psc_invalid.is_none());
let psc_from_new = PacketSequenceCtrl::new(SequenceFlags::ContinuationSegment, 77).unwrap(); let psc_from_new =
PacketSequenceCtrl::new_checked(SequenceFlags::ContinuationSegment, 77).unwrap();
assert_eq!(psc_from_new, psc); assert_eq!(psc_from_new, psc);
} }
#[test] #[test]
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
fn test_serde_sph() { fn test_serde_sph() {
let sp_header = SpHeader::tc_unseg(0x42, 12, 0).expect("Error creating SP header"); let sp_header =
SpHeader::new_for_unseg_tc_checked(0x42, 12, 0).expect("Error creating SP header");
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert!(sp_header.is_tc()); assert!(sp_header.is_tc());
assert!(!sp_header.sec_header_flag()); assert!(!sp_header.sec_header_flag());
@ -949,7 +1009,8 @@ pub(crate) mod tests {
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert_eq!(sp_header.data_len, 0); assert_eq!(sp_header.data_len, 0);
let sp_header = SpHeader::tm_unseg(0x7, 22, 36).expect("Error creating SP header"); let sp_header =
SpHeader::new_for_unseg_tm_checked(0x7, 22, 36).expect("Error creating SP header");
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
assert!(sp_header.is_tm()); assert!(sp_header.is_tm());
assert!(!sp_header.sec_header_flag()); assert!(!sp_header.sec_header_flag());
@ -963,8 +1024,8 @@ pub(crate) mod tests {
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
let from_comp_fields = SpHeader::from_composite_fields( let from_comp_fields = SpHeader::from_composite_fields(
PacketId::new(PacketType::Tc, true, 0x42).unwrap(), PacketId::new(PacketType::Tc, true, 0x42),
PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 0x7).unwrap(), PacketSequenceCtrl::new(SequenceFlags::Unsegmented, 0x7),
0, 0,
None, None,
); );
@ -981,7 +1042,7 @@ pub(crate) mod tests {
#[test] #[test]
fn test_setters() { fn test_setters() {
let sp_header = SpHeader::tc(0x42, SequenceFlags::Unsegmented, 25, 0); let sp_header = SpHeader::new_for_tc_checked(0x42, SequenceFlags::Unsegmented, 25, 0);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let mut sp_header = sp_header.unwrap(); let mut sp_header = sp_header.unwrap();
sp_header.set_apid(0x12); sp_header.set_apid(0x12);
@ -999,7 +1060,7 @@ pub(crate) mod tests {
#[test] #[test]
fn test_tc_ctor() { fn test_tc_ctor() {
let sp_header = SpHeader::tc(0x42, SequenceFlags::Unsegmented, 25, 0); let sp_header = SpHeader::new_for_tc_checked(0x42, SequenceFlags::Unsegmented, 25, 0);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let sp_header = sp_header.unwrap(); let sp_header = sp_header.unwrap();
verify_sp_fields(PacketType::Tc, &sp_header); verify_sp_fields(PacketType::Tc, &sp_header);
@ -1007,23 +1068,35 @@ pub(crate) mod tests {
#[test] #[test]
fn test_tc_ctor_unseg() { fn test_tc_ctor_unseg() {
let sp_header = SpHeader::tc_unseg(0x42, 25, 0); let sp_header = SpHeader::new_for_unseg_tc_checked(0x42, 25, 0);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let sp_header = sp_header.unwrap(); let sp_header = sp_header.unwrap();
verify_sp_fields(PacketType::Tc, &sp_header); verify_sp_fields(PacketType::Tc, &sp_header);
} }
#[test]
fn test_tc_ctor_unseg_const() {
let sp_header = SpHeader::new_for_unseg_tc(0x42, 25, 0);
verify_sp_fields(PacketType::Tc, &sp_header);
}
#[test] #[test]
fn test_tm_ctor() { fn test_tm_ctor() {
let sp_header = SpHeader::tm(0x42, SequenceFlags::Unsegmented, 25, 0); let sp_header = SpHeader::new_for_tm_checked(0x42, SequenceFlags::Unsegmented, 25, 0);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let sp_header = sp_header.unwrap(); let sp_header = sp_header.unwrap();
verify_sp_fields(PacketType::Tm, &sp_header); verify_sp_fields(PacketType::Tm, &sp_header);
} }
#[test]
fn test_tm_ctor_const() {
let sp_header = SpHeader::new_for_tm(0x42, SequenceFlags::Unsegmented, 25, 0);
verify_sp_fields(PacketType::Tm, &sp_header);
}
#[test] #[test]
fn test_tm_ctor_unseg() { fn test_tm_ctor_unseg() {
let sp_header = SpHeader::tm_unseg(0x42, 25, 0); let sp_header = SpHeader::new_for_unseg_tm_checked(0x42, 25, 0);
assert!(sp_header.is_some()); assert!(sp_header.is_some());
let sp_header = sp_header.unwrap(); let sp_header = sp_header.unwrap();
verify_sp_fields(PacketType::Tm, &sp_header); verify_sp_fields(PacketType::Tm, &sp_header);
@ -1041,8 +1114,8 @@ pub(crate) mod tests {
fn test_zc_sph() { fn test_zc_sph() {
use zerocopy::AsBytes; use zerocopy::AsBytes;
let sp_header = let sp_header = SpHeader::new_for_unseg_tc_checked(0x7FF, pow(2, 14) - 1, 0)
SpHeader::tc_unseg(0x7FF, pow(2, 14) - 1, 0).expect("Error creating SP header"); .expect("Error creating SP header");
assert_eq!(sp_header.ptype(), PacketType::Tc); assert_eq!(sp_header.ptype(), PacketType::Tc);
assert_eq!(sp_header.apid(), 0x7FF); assert_eq!(sp_header.apid(), 0x7FF);
assert_eq!(sp_header.data_len(), 0); assert_eq!(sp_header.data_len(), 0);