From 7db2190ec3e47cc388e389b9e10f133c1f64f2e4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 11 Jul 2023 00:03:07 +0200 Subject: [PATCH] more improvements --- CHANGELOG.md | 4 +++ src/ecss/mod.rs | 8 ++--- src/ecss/tc.rs | 87 +++++++++++++++++++------------------------------ src/ecss/tm.rs | 72 ++++++++++++++++------------------------ 4 files changed, 69 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3f341..646a7db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Changed +- `PusPacket` trait: `user_data` now returns `&[u8]` instead of `Option<&[u8]>`. Empty user data + can simply be an empty slice. - Moved ECSS TC components from `tc` to `ecss.tc`. - Moved ECSS TM components from `tm` to `ecss.tm`. - Converted `PusTc` class to more specialized `PusTcCreator` and `PusTcReader` @@ -23,6 +25,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Added +- `source_data` and `app_data` API provided for PUS TM and PUS TC reader classes. These simply + call `user_data` but are also in line with the PUS packet standard names for those fields. - Added new marker trait `IsPusTelemetry` implemented by `PusTmCreator` and `PusTmReader`. - Added new marker trait `IsPusTelecommand` implemented by `PusTcCreator` and `PusTcReader`. diff --git a/src/ecss/mod.rs b/src/ecss/mod.rs index 08943cc..a223b32 100644 --- a/src/ecss/mod.rs +++ b/src/ecss/mod.rs @@ -206,8 +206,7 @@ pub trait PusPacket: CcsdsPacket { fn pus_version(&self) -> PusVersion; fn service(&self) -> u8; fn subservice(&self) -> u8; - - fn user_data(&self) -> Option<&[u8]>; + fn user_data(&self) -> &[u8]; fn crc16(&self) -> Option; } @@ -251,11 +250,10 @@ pub(crate) fn user_data_from_raw( total_len: usize, raw_data_len: usize, slice: &[u8], -) -> Result, PusError> { +) -> Result<&[u8], PusError> { match current_idx { - _ if current_idx == total_len - 2 => Ok(None), _ if current_idx > total_len - 2 => Err(PusError::RawDataTooShort(raw_data_len)), - _ => Ok(Some(&slice[current_idx..total_len - 2])), + _ => Ok(&slice[current_idx..total_len - 2]), } } diff --git a/src/ecss/tc.rs b/src/ecss/tc.rs index b472bc0..a537151 100644 --- a/src/ecss/tc.rs +++ b/src/ecss/tc.rs @@ -6,7 +6,7 @@ //! ```rust //! use spacepackets::{CcsdsPacket, SpHeader}; //! use spacepackets::ecss::{PusPacket, SerializablePusPacket}; -//! use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader}; +//! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader}; //! //! // Create a ping telecommand with no user application data //! let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); @@ -26,7 +26,7 @@ //! println!("{:?}", &test_buf[0..size]); //! //! // Deserialize from the raw byte representation -//! let pus_tc_deserialized = PusTcCreator::from_bytes(&test_buf).expect("Deserialization failed"); +//! let pus_tc_deserialized = PusTcReader::new(&test_buf).expect("Deserialization failed"); //! assert_eq!(pus_tc.service(), 17); //! assert_eq!(pus_tc.subservice(), 1); //! assert_eq!(pus_tc.apid(), 0x02); @@ -216,12 +216,12 @@ pub mod legacy_tc { zc, GenericPusTcSecondaryHeader, PusTcSecondaryHeader, ACK_ALL, PUC_TC_SECONDARY_HEADER_LEN, PUS_TC_MIN_LEN_WITHOUT_APP_DATA, }; - use crate::ecss::PusVersion; use crate::ecss::{ - ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw, + ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, SerializablePusPacket, CCSDS_HEADER_LEN, }; + use crate::ecss::{user_data_from_raw, PusVersion}; use crate::SequenceFlags; use crate::{ ByteConversionError, CcsdsPacket, PacketType, SizeMissmatch, SpHeader, CRC_CCITT_FALSE, @@ -260,7 +260,7 @@ pub mod legacy_tc { pub calc_crc_on_serialization: bool, #[cfg_attr(feature = "serde", serde(skip))] raw_data: Option<&'raw_data [u8]>, - app_data: Option<&'raw_data [u8]>, + app_data: &'raw_data [u8], crc16: Option, } @@ -292,7 +292,7 @@ pub mod legacy_tc { let mut pus_tc = Self { sp_header: *sp_header, raw_data: None, - app_data, + app_data: app_data.unwrap_or(&[]), sec_header, calc_crc_on_serialization: true, crc16: None, @@ -362,8 +362,8 @@ pub mod legacy_tc { digest.update(sph_zc.as_bytes()); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); digest.update(pus_tc_header.as_bytes()); - if let Some(app_data) = self.app_data { - digest.update(app_data); + if !self.app_data.is_empty() { + digest.update(self.app_data); } self.crc16 = Some(digest.finalize()) } @@ -378,10 +378,7 @@ pub mod legacy_tc { #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub fn append_to_vec(&self, vec: &mut Vec) -> Result { let sph_zc = crate::zc::SpHeader::from(self.sp_header); - let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; - if let Some(app_data) = self.app_data { - appended_len += app_data.len(); - }; + let appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len(); let start_idx = vec.len(); let mut ser_len = 0; vec.extend_from_slice(sph_zc.as_bytes()); @@ -390,10 +387,8 @@ pub mod legacy_tc { let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); vec.extend_from_slice(pus_tc_header.as_bytes()); ser_len += pus_tc_header.as_bytes().len(); - if let Some(app_data) = self.app_data { - vec.extend_from_slice(app_data); - ser_len += app_data.len(); - } + vec.extend_from_slice(self.app_data); + ser_len += self.app_data.len(); let crc16 = crc_procedure( self.calc_crc_on_serialization, &self.crc16, @@ -454,11 +449,7 @@ pub mod legacy_tc { impl SerializablePusPacket for PusTc<'_> { fn len_packed(&self) -> usize { - let mut length = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; - if let Some(app_data) = self.app_data { - length += app_data.len(); - } - length + PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len() } /// Write the raw PUS byte representation to a provided buffer. @@ -481,10 +472,8 @@ pub mod legacy_tc { .ok_or(ByteConversionError::ZeroCopyToError)?; curr_idx += tc_header_len; - if let Some(app_data) = self.app_data { - slice[curr_idx..curr_idx + app_data.len()].copy_from_slice(app_data); - curr_idx += app_data.len(); - } + slice[curr_idx..curr_idx + self.app_data.len()].copy_from_slice(self.app_data); + curr_idx += self.app_data.len(); let crc16 = crc_procedure( self.calc_crc_on_serialization, &self.crc16, @@ -517,7 +506,7 @@ pub mod legacy_tc { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.app_data } @@ -550,7 +539,7 @@ pub mod legacy_tc { pub struct PusTcCreator<'raw_data> { sp_header: SpHeader, pub sec_header: PusTcSecondaryHeader, - app_data: Option<&'raw_data [u8]>, + app_data: &'raw_data [u8], } impl<'raw_data> PusTcCreator<'raw_data> { @@ -576,7 +565,7 @@ impl<'raw_data> PusTcCreator<'raw_data> { sp_header.set_sec_header_flag(); let mut pus_tc = Self { sp_header: *sp_header, - app_data, + app_data: app_data.unwrap_or(&[]), sec_header, }; if set_ccsds_len { @@ -639,9 +628,7 @@ impl<'raw_data> PusTcCreator<'raw_data> { digest.update(sph_zc.as_bytes()); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); digest.update(pus_tc_header.as_bytes()); - if let Some(app_data) = self.app_data { - digest.update(app_data); - } + digest.update(self.app_data); digest.finalize() } @@ -650,17 +637,13 @@ impl<'raw_data> PusTcCreator<'raw_data> { pub fn append_to_vec(&self, vec: &mut Vec) -> Result { let sph_zc = crate::zc::SpHeader::from(self.sp_header); let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; - if let Some(app_data) = self.app_data { - appended_len += app_data.len(); - }; + appended_len += self.app_data.len(); let start_idx = vec.len(); vec.extend_from_slice(sph_zc.as_bytes()); // The PUS version is hardcoded to PUS C let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); vec.extend_from_slice(pus_tc_header.as_bytes()); - if let Some(app_data) = self.app_data { - vec.extend_from_slice(app_data); - } + vec.extend_from_slice(self.app_data); let mut digest = CRC_CCITT_FALSE.digest(); digest.update(&vec[start_idx..start_idx + appended_len - 2]); vec.extend_from_slice(&digest.finalize().to_be_bytes()); @@ -670,11 +653,7 @@ impl<'raw_data> PusTcCreator<'raw_data> { impl SerializablePusPacket for PusTcCreator<'_> { fn len_packed(&self) -> usize { - let mut length = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; - if let Some(app_data) = self.app_data { - length += app_data.len(); - } - length + PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len() } /// Write the raw PUS byte representation to a provided buffer. @@ -697,10 +676,8 @@ impl SerializablePusPacket for PusTcCreator<'_> { .ok_or(ByteConversionError::ZeroCopyToError)?; curr_idx += tc_header_len; - if let Some(app_data) = self.app_data { - slice[curr_idx..curr_idx + app_data.len()].copy_from_slice(app_data); - curr_idx += app_data.len(); - } + slice[curr_idx..curr_idx + self.app_data.len()].copy_from_slice(self.app_data); + curr_idx += self.app_data.len(); let mut digest = CRC_CCITT_FALSE.digest(); digest.update(&slice[0..curr_idx]); slice[curr_idx..curr_idx + 2].copy_from_slice(&digest.finalize().to_be_bytes()); @@ -720,7 +697,7 @@ impl PusPacket for PusTcCreator<'_> { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.app_data } @@ -759,7 +736,7 @@ pub struct PusTcReader<'raw_data> { raw_data: &'raw_data [u8], sp_header: SpHeader, sec_header: PusTcSecondaryHeader, - app_data: Option<&'raw_data [u8]>, + app_data: &'raw_data [u8], crc16: u16, } @@ -795,6 +772,10 @@ impl<'raw_data> PusTcReader<'raw_data> { Ok((pus_tc, total_len)) } + pub fn app_data(&self) -> &[u8] { + self.user_data() + } + pub fn raw_data(&self) -> &[u8] { self.raw_data } @@ -825,7 +806,7 @@ impl PusPacket for PusTcReader<'_> { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.app_data } @@ -917,7 +898,7 @@ mod tests { PusTcReader::new(&test_buf).expect("Creating PUS TC struct from raw buffer failed"); assert_eq!(size, 13); verify_test_tc_with_reader(&tc_from_raw, false, 13); - assert!(tc_from_raw.user_data().is_none()); + assert!(tc_from_raw.user_data().is_empty()); verify_test_tc_raw(&test_buf); verify_crc_no_app_data(&test_buf); } @@ -942,7 +923,7 @@ mod tests { PusTcReader::new(&test_buf).expect("Creating PUS TC struct from raw buffer failed"); assert_eq!(size, 16); verify_test_tc_with_reader(&tc_from_raw, true, 16); - let user_data = tc_from_raw.user_data().unwrap(); + let user_data = tc_from_raw.user_data(); assert_eq!(user_data[0], 1); assert_eq!(user_data[1], 2); assert_eq!(user_data[2], 3); @@ -1064,7 +1045,7 @@ mod tests { fn verify_test_tc(tc: &PusTcCreator, has_user_data: bool, exp_full_len: usize) { verify_test_tc_generic(tc); if !has_user_data { - assert_eq!(tc.user_data(), None); + assert!(tc.user_data().is_empty()); } let mut comp_header = SpHeader::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap(); comp_header.set_sec_header_flag(); @@ -1074,7 +1055,7 @@ mod tests { fn verify_test_tc_with_reader(tc: &PusTcReader, has_user_data: bool, exp_full_len: usize) { verify_test_tc_generic(tc); if !has_user_data { - assert_eq!(tc.user_data(), None); + assert!(tc.user_data().is_empty()); } assert_eq!(tc.len_packed(), exp_full_len); let mut comp_header = SpHeader::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap(); diff --git a/src/ecss/tm.rs b/src/ecss/tm.rs index b45506f..78b41f7 100644 --- a/src/ecss/tm.rs +++ b/src/ecss/tm.rs @@ -243,7 +243,7 @@ pub mod legacy_tm { pub calc_crc_on_serialization: bool, #[cfg_attr(feature = "serde", serde(skip))] raw_data: Option<&'raw_data [u8]>, - source_data: Option<&'raw_data [u8]>, + source_data: &'raw_data [u8], crc16: Option, } @@ -275,7 +275,7 @@ pub mod legacy_tm { let mut pus_tm = PusTm { sp_header: *sp_header, raw_data: None, - source_data, + source_data: source_data.unwrap_or(&[]), sec_header, calc_crc_on_serialization: true, crc16: None, @@ -290,7 +290,7 @@ pub mod legacy_tm { self.sec_header.timestamp } - pub fn source_data(&self) -> Option<&'raw_data [u8]> { + pub fn source_data(&self) -> &'raw_data [u8] { self.source_data } @@ -330,9 +330,7 @@ pub mod legacy_tm { if let Some(stamp) = self.sec_header.timestamp { digest.update(stamp); } - if let Some(src_data) = self.source_data { - digest.update(src_data); - } + digest.update(self.source_data); self.crc16 = Some(digest.finalize()) } @@ -351,9 +349,7 @@ pub mod legacy_tm { if let Some(timestamp) = self.sec_header.timestamp { appended_len += timestamp.len(); } - if let Some(src_data) = self.source_data { - appended_len += src_data.len(); - }; + appended_len += self.source_data.len(); let start_idx = vec.len(); let mut ser_len = 0; vec.extend_from_slice(sph_zc.as_bytes()); @@ -366,10 +362,8 @@ pub mod legacy_tm { ser_len += timestamp.len(); vec.extend_from_slice(timestamp); } - if let Some(src_data) = self.source_data { - vec.extend_from_slice(src_data); - ser_len += src_data.len(); - } + vec.extend_from_slice(self.source_data); + ser_len += self.source_data.len(); let crc16 = crc_procedure( self.calc_crc_on_serialization, &self.crc16, @@ -442,9 +436,7 @@ pub mod legacy_tm { if let Some(timestamp) = self.sec_header.timestamp { length += timestamp.len(); } - if let Some(src_data) = self.source_data { - length += src_data.len(); - } + length += self.source_data.len(); length } /// Write the raw PUS byte representation to a provided buffer. @@ -472,10 +464,8 @@ pub mod legacy_tm { slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(timestamp); curr_idx += timestamp_len; } - if let Some(src_data) = self.source_data { - slice[curr_idx..curr_idx + src_data.len()].copy_from_slice(src_data); - curr_idx += src_data.len(); - } + slice[curr_idx..curr_idx + self.source_data.len()].copy_from_slice(self.source_data); + curr_idx += self.source_data.len(); let crc16 = crc_procedure( self.calc_crc_on_serialization, &self.crc16, @@ -508,7 +498,7 @@ pub mod legacy_tm { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.source_data } @@ -546,7 +536,7 @@ pub mod legacy_tm { pub struct PusTmCreator<'raw_data> { pub sp_header: SpHeader, pub sec_header: PusTmSecondaryHeader<'raw_data>, - source_data: Option<&'raw_data [u8]>, + source_data: &'raw_data [u8], /// If this is set to false, a manual call to [PusTm::calc_own_crc16] or /// [PusTm::update_packet_fields] is necessary for the serialized or cached CRC16 to be valid. pub calc_crc_on_serialization: bool, @@ -575,7 +565,7 @@ impl<'raw_data> PusTmCreator<'raw_data> { sp_header.set_sec_header_flag(); let mut pus_tm = Self { sp_header: *sp_header, - source_data, + source_data: source_data.unwrap_or(&[]), sec_header, calc_crc_on_serialization: true, }; @@ -589,7 +579,7 @@ impl<'raw_data> PusTmCreator<'raw_data> { self.sec_header.timestamp } - pub fn source_data(&self) -> Option<&'raw_data [u8]> { + pub fn source_data(&self) -> &[u8] { self.source_data } @@ -628,9 +618,7 @@ impl<'raw_data> PusTmCreator<'raw_data> { if let Some(stamp) = self.sec_header.timestamp { digest.update(stamp); } - if let Some(src_data) = self.source_data { - digest.update(src_data); - } + digest.update(self.source_data); digest.finalize() } @@ -648,9 +636,7 @@ impl<'raw_data> PusTmCreator<'raw_data> { if let Some(timestamp) = self.sec_header.timestamp { appended_len += timestamp.len(); } - if let Some(src_data) = self.source_data { - appended_len += src_data.len(); - }; + appended_len += self.source_data.len(); let start_idx = vec.len(); vec.extend_from_slice(sph_zc.as_bytes()); // The PUS version is hardcoded to PUS C @@ -659,9 +645,7 @@ impl<'raw_data> PusTmCreator<'raw_data> { if let Some(timestamp) = self.sec_header.timestamp { vec.extend_from_slice(timestamp); } - if let Some(src_data) = self.source_data { - vec.extend_from_slice(src_data); - } + vec.extend_from_slice(self.source_data); let mut digest = CRC_CCITT_FALSE.digest(); digest.update(&vec[start_idx..start_idx + appended_len - 2]); vec.extend_from_slice(&digest.finalize().to_be_bytes()); @@ -675,9 +659,7 @@ impl SerializablePusPacket for PusTmCreator<'_> { if let Some(timestamp) = self.sec_header.timestamp { length += timestamp.len(); } - if let Some(src_data) = self.source_data { - length += src_data.len(); - } + length += self.source_data.len(); length } /// Write the raw PUS byte representation to a provided buffer. @@ -705,10 +687,8 @@ impl SerializablePusPacket for PusTmCreator<'_> { slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(timestamp); curr_idx += timestamp_len; } - if let Some(src_data) = self.source_data { - slice[curr_idx..curr_idx + src_data.len()].copy_from_slice(src_data); - curr_idx += src_data.len(); - } + slice[curr_idx..curr_idx + self.source_data.len()].copy_from_slice(self.source_data); + curr_idx += self.source_data.len(); let mut digest = CRC_CCITT_FALSE.digest(); digest.update(&slice[0..curr_idx]); slice[curr_idx..curr_idx + 2].copy_from_slice(&digest.finalize().to_be_bytes()); @@ -736,7 +716,7 @@ impl PusPacket for PusTmCreator<'_> { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.source_data } @@ -777,7 +757,7 @@ pub struct PusTmReader<'raw_data> { pub sec_header: PusTmSecondaryHeader<'raw_data>, #[cfg_attr(feature = "serde", serde(skip))] raw_data: &'raw_data [u8], - source_data: Option<&'raw_data [u8]>, + source_data: &'raw_data [u8], crc16: u16, } @@ -827,6 +807,10 @@ impl<'raw_data> PusTmReader<'raw_data> { self.sp_header.total_len() } + pub fn source_data(&self) -> &[u8] { + self.user_data() + } + pub fn timestamp(&self) -> Option<&'raw_data [u8]> { self.sec_header.timestamp } @@ -855,7 +839,7 @@ impl PusPacket for PusTmReader<'_> { fn subservice(&self) -> u8; }); - fn user_data(&self) -> Option<&[u8]> { + fn user_data(&self) -> &[u8] { self.source_data } @@ -1179,7 +1163,7 @@ mod tests { assert_eq!(PusPacket::subservice(tm), 2); assert!(tm.sec_header_flag()); if has_user_data { - assert!(!tm.user_data().is_none()); + assert!(!tm.user_data().is_empty()); } assert_eq!(PusPacket::pus_version(tm), PusC); assert_eq!(tm.apid(), 0x123);