more improvements
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good

This commit is contained in:
Robin Müller 2023-07-11 00:03:07 +02:00
parent 77be96e8de
commit 7db2190ec3
Signed by: muellerr
GPG Key ID: A649FB78196E3849
4 changed files with 69 additions and 102 deletions

View File

@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed ## 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 TC components from `tc` to `ecss.tc`.
- Moved ECSS TM components from `tm` to `ecss.tm`. - Moved ECSS TM components from `tm` to `ecss.tm`.
- Converted `PusTc` class to more specialized `PusTcCreator` and `PusTcReader` - Converted `PusTc` class to more specialized `PusTcCreator` and `PusTcReader`
@ -23,6 +25,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added ## 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 `IsPusTelemetry` implemented by `PusTmCreator` and `PusTmReader`.
- Added new marker trait `IsPusTelecommand` implemented by `PusTcCreator` and `PusTcReader`. - Added new marker trait `IsPusTelecommand` implemented by `PusTcCreator` and `PusTcReader`.

View File

@ -206,8 +206,7 @@ pub trait PusPacket: CcsdsPacket {
fn pus_version(&self) -> PusVersion; fn pus_version(&self) -> PusVersion;
fn service(&self) -> u8; fn service(&self) -> u8;
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
fn user_data(&self) -> &[u8];
fn user_data(&self) -> Option<&[u8]>;
fn crc16(&self) -> Option<u16>; fn crc16(&self) -> Option<u16>;
} }
@ -251,11 +250,10 @@ pub(crate) fn user_data_from_raw(
total_len: usize, total_len: usize,
raw_data_len: usize, raw_data_len: usize,
slice: &[u8], slice: &[u8],
) -> Result<Option<&[u8]>, PusError> { ) -> Result<&[u8], PusError> {
match current_idx { match current_idx {
_ if current_idx == total_len - 2 => Ok(None),
_ if current_idx > total_len - 2 => Err(PusError::RawDataTooShort(raw_data_len)), _ 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]),
} }
} }

View File

@ -6,7 +6,7 @@
//! ```rust //! ```rust
//! use spacepackets::{CcsdsPacket, SpHeader}; //! use spacepackets::{CcsdsPacket, SpHeader};
//! use spacepackets::ecss::{PusPacket, SerializablePusPacket}; //! 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 //! // Create a ping telecommand with no user application data
//! let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap(); //! let mut sph = SpHeader::tc_unseg(0x02, 0x34, 0).unwrap();
@ -26,7 +26,7 @@
//! println!("{:?}", &test_buf[0..size]); //! println!("{:?}", &test_buf[0..size]);
//! //!
//! // Deserialize from the raw byte representation //! // 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.service(), 17);
//! assert_eq!(pus_tc.subservice(), 1); //! assert_eq!(pus_tc.subservice(), 1);
//! assert_eq!(pus_tc.apid(), 0x02); //! assert_eq!(pus_tc.apid(), 0x02);
@ -216,12 +216,12 @@ pub mod legacy_tc {
zc, GenericPusTcSecondaryHeader, PusTcSecondaryHeader, ACK_ALL, zc, GenericPusTcSecondaryHeader, PusTcSecondaryHeader, ACK_ALL,
PUC_TC_SECONDARY_HEADER_LEN, PUS_TC_MIN_LEN_WITHOUT_APP_DATA, PUC_TC_SECONDARY_HEADER_LEN, PUS_TC_MIN_LEN_WITHOUT_APP_DATA,
}; };
use crate::ecss::PusVersion;
use crate::ecss::{ 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, verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, SerializablePusPacket,
CCSDS_HEADER_LEN, CCSDS_HEADER_LEN,
}; };
use crate::ecss::{user_data_from_raw, PusVersion};
use crate::SequenceFlags; use crate::SequenceFlags;
use crate::{ use crate::{
ByteConversionError, CcsdsPacket, PacketType, SizeMissmatch, SpHeader, CRC_CCITT_FALSE, ByteConversionError, CcsdsPacket, PacketType, SizeMissmatch, SpHeader, CRC_CCITT_FALSE,
@ -260,7 +260,7 @@ pub mod legacy_tc {
pub calc_crc_on_serialization: bool, pub calc_crc_on_serialization: bool,
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
raw_data: Option<&'raw_data [u8]>, raw_data: Option<&'raw_data [u8]>,
app_data: Option<&'raw_data [u8]>, app_data: &'raw_data [u8],
crc16: Option<u16>, crc16: Option<u16>,
} }
@ -292,7 +292,7 @@ pub mod legacy_tc {
let mut pus_tc = Self { let mut pus_tc = Self {
sp_header: *sp_header, sp_header: *sp_header,
raw_data: None, raw_data: None,
app_data, app_data: app_data.unwrap_or(&[]),
sec_header, sec_header,
calc_crc_on_serialization: true, calc_crc_on_serialization: true,
crc16: None, crc16: None,
@ -362,8 +362,8 @@ pub mod legacy_tc {
digest.update(sph_zc.as_bytes()); digest.update(sph_zc.as_bytes());
let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap();
digest.update(pus_tc_header.as_bytes()); digest.update(pus_tc_header.as_bytes());
if let Some(app_data) = self.app_data { if !self.app_data.is_empty() {
digest.update(app_data); digest.update(self.app_data);
} }
self.crc16 = Some(digest.finalize()) self.crc16 = Some(digest.finalize())
} }
@ -378,10 +378,7 @@ pub mod legacy_tc {
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> { pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
let sph_zc = crate::zc::SpHeader::from(self.sp_header); let sph_zc = crate::zc::SpHeader::from(self.sp_header);
let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; let appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len();
if let Some(app_data) = self.app_data {
appended_len += app_data.len();
};
let start_idx = vec.len(); let start_idx = vec.len();
let mut ser_len = 0; let mut ser_len = 0;
vec.extend_from_slice(sph_zc.as_bytes()); 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(); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap();
vec.extend_from_slice(pus_tc_header.as_bytes()); vec.extend_from_slice(pus_tc_header.as_bytes());
ser_len += pus_tc_header.as_bytes().len(); ser_len += pus_tc_header.as_bytes().len();
if let Some(app_data) = self.app_data { vec.extend_from_slice(self.app_data);
vec.extend_from_slice(app_data); ser_len += self.app_data.len();
ser_len += app_data.len();
}
let crc16 = crc_procedure( let crc16 = crc_procedure(
self.calc_crc_on_serialization, self.calc_crc_on_serialization,
&self.crc16, &self.crc16,
@ -454,11 +449,7 @@ pub mod legacy_tc {
impl SerializablePusPacket for PusTc<'_> { impl SerializablePusPacket for PusTc<'_> {
fn len_packed(&self) -> usize { fn len_packed(&self) -> usize {
let mut length = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len()
if let Some(app_data) = self.app_data {
length += app_data.len();
}
length
} }
/// Write the raw PUS byte representation to a provided buffer. /// Write the raw PUS byte representation to a provided buffer.
@ -481,10 +472,8 @@ pub mod legacy_tc {
.ok_or(ByteConversionError::ZeroCopyToError)?; .ok_or(ByteConversionError::ZeroCopyToError)?;
curr_idx += tc_header_len; curr_idx += tc_header_len;
if let Some(app_data) = self.app_data { slice[curr_idx..curr_idx + self.app_data.len()].copy_from_slice(self.app_data);
slice[curr_idx..curr_idx + app_data.len()].copy_from_slice(app_data); curr_idx += self.app_data.len();
curr_idx += app_data.len();
}
let crc16 = crc_procedure( let crc16 = crc_procedure(
self.calc_crc_on_serialization, self.calc_crc_on_serialization,
&self.crc16, &self.crc16,
@ -517,7 +506,7 @@ pub mod legacy_tc {
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.app_data self.app_data
} }
@ -550,7 +539,7 @@ pub mod legacy_tc {
pub struct PusTcCreator<'raw_data> { pub struct PusTcCreator<'raw_data> {
sp_header: SpHeader, sp_header: SpHeader,
pub sec_header: PusTcSecondaryHeader, pub sec_header: PusTcSecondaryHeader,
app_data: Option<&'raw_data [u8]>, app_data: &'raw_data [u8],
} }
impl<'raw_data> PusTcCreator<'raw_data> { impl<'raw_data> PusTcCreator<'raw_data> {
@ -576,7 +565,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
sp_header.set_sec_header_flag(); sp_header.set_sec_header_flag();
let mut pus_tc = Self { let mut pus_tc = Self {
sp_header: *sp_header, sp_header: *sp_header,
app_data, app_data: app_data.unwrap_or(&[]),
sec_header, sec_header,
}; };
if set_ccsds_len { if set_ccsds_len {
@ -639,9 +628,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
digest.update(sph_zc.as_bytes()); digest.update(sph_zc.as_bytes());
let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap();
digest.update(pus_tc_header.as_bytes()); digest.update(pus_tc_header.as_bytes());
if let Some(app_data) = self.app_data { digest.update(self.app_data);
digest.update(app_data);
}
digest.finalize() digest.finalize()
} }
@ -650,17 +637,13 @@ impl<'raw_data> PusTcCreator<'raw_data> {
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> { pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
let sph_zc = crate::zc::SpHeader::from(self.sp_header); let sph_zc = crate::zc::SpHeader::from(self.sp_header);
let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; let mut appended_len = PUS_TC_MIN_LEN_WITHOUT_APP_DATA;
if let Some(app_data) = self.app_data { appended_len += self.app_data.len();
appended_len += app_data.len();
};
let start_idx = vec.len(); let start_idx = vec.len();
vec.extend_from_slice(sph_zc.as_bytes()); vec.extend_from_slice(sph_zc.as_bytes());
// The PUS version is hardcoded to PUS C // The PUS version is hardcoded to PUS C
let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); let pus_tc_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap();
vec.extend_from_slice(pus_tc_header.as_bytes()); vec.extend_from_slice(pus_tc_header.as_bytes());
if let Some(app_data) = self.app_data { vec.extend_from_slice(self.app_data);
vec.extend_from_slice(app_data);
}
let mut digest = CRC_CCITT_FALSE.digest(); let mut digest = CRC_CCITT_FALSE.digest();
digest.update(&vec[start_idx..start_idx + appended_len - 2]); digest.update(&vec[start_idx..start_idx + appended_len - 2]);
vec.extend_from_slice(&digest.finalize().to_be_bytes()); vec.extend_from_slice(&digest.finalize().to_be_bytes());
@ -670,11 +653,7 @@ impl<'raw_data> PusTcCreator<'raw_data> {
impl SerializablePusPacket for PusTcCreator<'_> { impl SerializablePusPacket for PusTcCreator<'_> {
fn len_packed(&self) -> usize { fn len_packed(&self) -> usize {
let mut length = PUS_TC_MIN_LEN_WITHOUT_APP_DATA; PUS_TC_MIN_LEN_WITHOUT_APP_DATA + self.app_data.len()
if let Some(app_data) = self.app_data {
length += app_data.len();
}
length
} }
/// Write the raw PUS byte representation to a provided buffer. /// Write the raw PUS byte representation to a provided buffer.
@ -697,10 +676,8 @@ impl SerializablePusPacket for PusTcCreator<'_> {
.ok_or(ByteConversionError::ZeroCopyToError)?; .ok_or(ByteConversionError::ZeroCopyToError)?;
curr_idx += tc_header_len; curr_idx += tc_header_len;
if let Some(app_data) = self.app_data { slice[curr_idx..curr_idx + self.app_data.len()].copy_from_slice(self.app_data);
slice[curr_idx..curr_idx + app_data.len()].copy_from_slice(app_data); curr_idx += self.app_data.len();
curr_idx += app_data.len();
}
let mut digest = CRC_CCITT_FALSE.digest(); let mut digest = CRC_CCITT_FALSE.digest();
digest.update(&slice[0..curr_idx]); digest.update(&slice[0..curr_idx]);
slice[curr_idx..curr_idx + 2].copy_from_slice(&digest.finalize().to_be_bytes()); 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 subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.app_data self.app_data
} }
@ -759,7 +736,7 @@ pub struct PusTcReader<'raw_data> {
raw_data: &'raw_data [u8], raw_data: &'raw_data [u8],
sp_header: SpHeader, sp_header: SpHeader,
sec_header: PusTcSecondaryHeader, sec_header: PusTcSecondaryHeader,
app_data: Option<&'raw_data [u8]>, app_data: &'raw_data [u8],
crc16: u16, crc16: u16,
} }
@ -795,6 +772,10 @@ impl<'raw_data> PusTcReader<'raw_data> {
Ok((pus_tc, total_len)) Ok((pus_tc, total_len))
} }
pub fn app_data(&self) -> &[u8] {
self.user_data()
}
pub fn raw_data(&self) -> &[u8] { pub fn raw_data(&self) -> &[u8] {
self.raw_data self.raw_data
} }
@ -825,7 +806,7 @@ impl PusPacket for PusTcReader<'_> {
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.app_data self.app_data
} }
@ -917,7 +898,7 @@ mod tests {
PusTcReader::new(&test_buf).expect("Creating PUS TC struct from raw buffer failed"); PusTcReader::new(&test_buf).expect("Creating PUS TC struct from raw buffer failed");
assert_eq!(size, 13); assert_eq!(size, 13);
verify_test_tc_with_reader(&tc_from_raw, false, 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_test_tc_raw(&test_buf);
verify_crc_no_app_data(&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"); PusTcReader::new(&test_buf).expect("Creating PUS TC struct from raw buffer failed");
assert_eq!(size, 16); assert_eq!(size, 16);
verify_test_tc_with_reader(&tc_from_raw, true, 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[0], 1);
assert_eq!(user_data[1], 2); assert_eq!(user_data[1], 2);
assert_eq!(user_data[2], 3); 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) { fn verify_test_tc(tc: &PusTcCreator, has_user_data: bool, exp_full_len: usize) {
verify_test_tc_generic(tc); verify_test_tc_generic(tc);
if !has_user_data { 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(); let mut comp_header = SpHeader::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap();
comp_header.set_sec_header_flag(); 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) { fn verify_test_tc_with_reader(tc: &PusTcReader, has_user_data: bool, exp_full_len: usize) {
verify_test_tc_generic(tc); verify_test_tc_generic(tc);
if !has_user_data { if !has_user_data {
assert_eq!(tc.user_data(), None); 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::tc_unseg(0x02, 0x34, exp_full_len as u16 - 7).unwrap();

View File

@ -243,7 +243,7 @@ pub mod legacy_tm {
pub calc_crc_on_serialization: bool, pub calc_crc_on_serialization: bool,
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
raw_data: Option<&'raw_data [u8]>, raw_data: Option<&'raw_data [u8]>,
source_data: Option<&'raw_data [u8]>, source_data: &'raw_data [u8],
crc16: Option<u16>, crc16: Option<u16>,
} }
@ -275,7 +275,7 @@ pub mod legacy_tm {
let mut pus_tm = PusTm { let mut pus_tm = PusTm {
sp_header: *sp_header, sp_header: *sp_header,
raw_data: None, raw_data: None,
source_data, source_data: source_data.unwrap_or(&[]),
sec_header, sec_header,
calc_crc_on_serialization: true, calc_crc_on_serialization: true,
crc16: None, crc16: None,
@ -290,7 +290,7 @@ pub mod legacy_tm {
self.sec_header.timestamp self.sec_header.timestamp
} }
pub fn source_data(&self) -> Option<&'raw_data [u8]> { pub fn source_data(&self) -> &'raw_data [u8] {
self.source_data self.source_data
} }
@ -330,9 +330,7 @@ pub mod legacy_tm {
if let Some(stamp) = self.sec_header.timestamp { if let Some(stamp) = self.sec_header.timestamp {
digest.update(stamp); digest.update(stamp);
} }
if let Some(src_data) = self.source_data { digest.update(self.source_data);
digest.update(src_data);
}
self.crc16 = Some(digest.finalize()) self.crc16 = Some(digest.finalize())
} }
@ -351,9 +349,7 @@ pub mod legacy_tm {
if let Some(timestamp) = self.sec_header.timestamp { if let Some(timestamp) = self.sec_header.timestamp {
appended_len += timestamp.len(); appended_len += timestamp.len();
} }
if let Some(src_data) = self.source_data { appended_len += self.source_data.len();
appended_len += src_data.len();
};
let start_idx = vec.len(); let start_idx = vec.len();
let mut ser_len = 0; let mut ser_len = 0;
vec.extend_from_slice(sph_zc.as_bytes()); vec.extend_from_slice(sph_zc.as_bytes());
@ -366,10 +362,8 @@ pub mod legacy_tm {
ser_len += timestamp.len(); ser_len += timestamp.len();
vec.extend_from_slice(timestamp); vec.extend_from_slice(timestamp);
} }
if let Some(src_data) = self.source_data { vec.extend_from_slice(self.source_data);
vec.extend_from_slice(src_data); ser_len += self.source_data.len();
ser_len += src_data.len();
}
let crc16 = crc_procedure( let crc16 = crc_procedure(
self.calc_crc_on_serialization, self.calc_crc_on_serialization,
&self.crc16, &self.crc16,
@ -442,9 +436,7 @@ pub mod legacy_tm {
if let Some(timestamp) = self.sec_header.timestamp { if let Some(timestamp) = self.sec_header.timestamp {
length += timestamp.len(); length += timestamp.len();
} }
if let Some(src_data) = self.source_data { length += self.source_data.len();
length += src_data.len();
}
length length
} }
/// Write the raw PUS byte representation to a provided buffer. /// 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); slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(timestamp);
curr_idx += timestamp_len; curr_idx += timestamp_len;
} }
if let Some(src_data) = self.source_data { slice[curr_idx..curr_idx + self.source_data.len()].copy_from_slice(self.source_data);
slice[curr_idx..curr_idx + src_data.len()].copy_from_slice(src_data); curr_idx += self.source_data.len();
curr_idx += src_data.len();
}
let crc16 = crc_procedure( let crc16 = crc_procedure(
self.calc_crc_on_serialization, self.calc_crc_on_serialization,
&self.crc16, &self.crc16,
@ -508,7 +498,7 @@ pub mod legacy_tm {
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.source_data self.source_data
} }
@ -546,7 +536,7 @@ pub mod legacy_tm {
pub struct PusTmCreator<'raw_data> { pub struct PusTmCreator<'raw_data> {
pub sp_header: SpHeader, pub sp_header: SpHeader,
pub sec_header: PusTmSecondaryHeader<'raw_data>, 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 /// 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. /// [PusTm::update_packet_fields] is necessary for the serialized or cached CRC16 to be valid.
pub calc_crc_on_serialization: bool, pub calc_crc_on_serialization: bool,
@ -575,7 +565,7 @@ impl<'raw_data> PusTmCreator<'raw_data> {
sp_header.set_sec_header_flag(); sp_header.set_sec_header_flag();
let mut pus_tm = Self { let mut pus_tm = Self {
sp_header: *sp_header, sp_header: *sp_header,
source_data, source_data: source_data.unwrap_or(&[]),
sec_header, sec_header,
calc_crc_on_serialization: true, calc_crc_on_serialization: true,
}; };
@ -589,7 +579,7 @@ impl<'raw_data> PusTmCreator<'raw_data> {
self.sec_header.timestamp self.sec_header.timestamp
} }
pub fn source_data(&self) -> Option<&'raw_data [u8]> { pub fn source_data(&self) -> &[u8] {
self.source_data self.source_data
} }
@ -628,9 +618,7 @@ impl<'raw_data> PusTmCreator<'raw_data> {
if let Some(stamp) = self.sec_header.timestamp { if let Some(stamp) = self.sec_header.timestamp {
digest.update(stamp); digest.update(stamp);
} }
if let Some(src_data) = self.source_data { digest.update(self.source_data);
digest.update(src_data);
}
digest.finalize() digest.finalize()
} }
@ -648,9 +636,7 @@ impl<'raw_data> PusTmCreator<'raw_data> {
if let Some(timestamp) = self.sec_header.timestamp { if let Some(timestamp) = self.sec_header.timestamp {
appended_len += timestamp.len(); appended_len += timestamp.len();
} }
if let Some(src_data) = self.source_data { appended_len += self.source_data.len();
appended_len += src_data.len();
};
let start_idx = vec.len(); let start_idx = vec.len();
vec.extend_from_slice(sph_zc.as_bytes()); vec.extend_from_slice(sph_zc.as_bytes());
// The PUS version is hardcoded to PUS C // 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 { if let Some(timestamp) = self.sec_header.timestamp {
vec.extend_from_slice(timestamp); vec.extend_from_slice(timestamp);
} }
if let Some(src_data) = self.source_data { vec.extend_from_slice(self.source_data);
vec.extend_from_slice(src_data);
}
let mut digest = CRC_CCITT_FALSE.digest(); let mut digest = CRC_CCITT_FALSE.digest();
digest.update(&vec[start_idx..start_idx + appended_len - 2]); digest.update(&vec[start_idx..start_idx + appended_len - 2]);
vec.extend_from_slice(&digest.finalize().to_be_bytes()); 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 { if let Some(timestamp) = self.sec_header.timestamp {
length += timestamp.len(); length += timestamp.len();
} }
if let Some(src_data) = self.source_data { length += self.source_data.len();
length += src_data.len();
}
length length
} }
/// Write the raw PUS byte representation to a provided buffer. /// 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); slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(timestamp);
curr_idx += timestamp_len; curr_idx += timestamp_len;
} }
if let Some(src_data) = self.source_data { slice[curr_idx..curr_idx + self.source_data.len()].copy_from_slice(self.source_data);
slice[curr_idx..curr_idx + src_data.len()].copy_from_slice(src_data); curr_idx += self.source_data.len();
curr_idx += src_data.len();
}
let mut digest = CRC_CCITT_FALSE.digest(); let mut digest = CRC_CCITT_FALSE.digest();
digest.update(&slice[0..curr_idx]); digest.update(&slice[0..curr_idx]);
slice[curr_idx..curr_idx + 2].copy_from_slice(&digest.finalize().to_be_bytes()); 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 subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.source_data self.source_data
} }
@ -777,7 +757,7 @@ pub struct PusTmReader<'raw_data> {
pub sec_header: PusTmSecondaryHeader<'raw_data>, pub sec_header: PusTmSecondaryHeader<'raw_data>,
#[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(skip))]
raw_data: &'raw_data [u8], raw_data: &'raw_data [u8],
source_data: Option<&'raw_data [u8]>, source_data: &'raw_data [u8],
crc16: u16, crc16: u16,
} }
@ -827,6 +807,10 @@ impl<'raw_data> PusTmReader<'raw_data> {
self.sp_header.total_len() self.sp_header.total_len()
} }
pub fn source_data(&self) -> &[u8] {
self.user_data()
}
pub fn timestamp(&self) -> Option<&'raw_data [u8]> { pub fn timestamp(&self) -> Option<&'raw_data [u8]> {
self.sec_header.timestamp self.sec_header.timestamp
} }
@ -855,7 +839,7 @@ impl PusPacket for PusTmReader<'_> {
fn subservice(&self) -> u8; fn subservice(&self) -> u8;
}); });
fn user_data(&self) -> Option<&[u8]> { fn user_data(&self) -> &[u8] {
self.source_data self.source_data
} }
@ -1179,7 +1163,7 @@ mod tests {
assert_eq!(PusPacket::subservice(tm), 2); assert_eq!(PusPacket::subservice(tm), 2);
assert!(tm.sec_header_flag()); assert!(tm.sec_header_flag());
if has_user_data { 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!(PusPacket::pus_version(tm), PusC);
assert_eq!(tm.apid(), 0x123); assert_eq!(tm.apid(), 0x123);