diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a2301..be8d509 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `GenericUnsignedByteField` and helper typedefs `UnsignedU8`, `UnsignedU16`, `UnsignedU32` and `UnsignedU64` as helper types implementing `UnsignedEnum` - `UnsignedByteField` as a type-erased helper. -- Initial CFDP support: Added PDU packet implementation. +- Added `SerializablePusPacket` as a generic abstraction for PUS packets which are + writable. ## Changed diff --git a/src/ecss/mod.rs b/src/ecss/mod.rs index 920632f..952ba9b 100644 --- a/src/ecss/mod.rs +++ b/src/ecss/mod.rs @@ -349,6 +349,10 @@ pub type EcssEnumU16 = GenericEcssEnumWrapper; pub type EcssEnumU32 = GenericEcssEnumWrapper; pub type EcssEnumU64 = GenericEcssEnumWrapper; +pub trait SerializablePusPacket { + fn write_to_bytes(&self, slice: &mut [u8]) -> Result; +} + #[cfg(test)] mod tests { use crate::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, UnsignedEnum}; diff --git a/src/tc.rs b/src/tc.rs index 8b75f1c..34707ba 100644 --- a/src/tc.rs +++ b/src/tc.rs @@ -34,6 +34,7 @@ use crate::ecss::{ ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw, verify_crc16_ccitt_false_from_raw, CrcType, PusError, PusPacket, PusVersion, + SerializablePusPacket, }; use crate::{ ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN, @@ -342,42 +343,6 @@ impl<'raw_data> PusTc<'raw_data> { self.calc_own_crc16(); } - /// Write the raw PUS byte representation to a provided buffer. - pub fn write_to_bytes(&self, slice: &mut [u8]) -> Result { - let mut curr_idx = 0; - let tc_header_len = size_of::(); - let total_size = self.len_packed(); - if total_size > slice.len() { - return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { - found: slice.len(), - expected: total_size, - }) - .into()); - } - self.sp_header.write_to_be_bytes(slice)?; - curr_idx += CCSDS_HEADER_LEN; - let sec_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); - sec_header - .write_to_bytes(&mut slice[curr_idx..curr_idx + tc_header_len]) - .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(); - } - let crc16 = crc_procedure( - self.calc_crc_on_serialization, - &self.crc16, - 0, - curr_idx, - slice, - )?; - slice[curr_idx..curr_idx + 2].copy_from_slice(crc16.to_be_bytes().as_slice()); - curr_idx += 2; - Ok(curr_idx) - } - #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub fn append_to_vec(&self, vec: &mut Vec) -> Result { @@ -453,6 +418,44 @@ impl<'raw_data> PusTc<'raw_data> { } } +impl SerializablePusPacket for PusTc<'_> { + /// Write the raw PUS byte representation to a provided buffer. + fn write_to_bytes(&self, slice: &mut [u8]) -> Result { + let mut curr_idx = 0; + let tc_header_len = size_of::(); + let total_size = self.len_packed(); + if total_size > slice.len() { + return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: slice.len(), + expected: total_size, + }) + .into()); + } + self.sp_header.write_to_be_bytes(slice)?; + curr_idx += CCSDS_HEADER_LEN; + let sec_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); + sec_header + .write_to_bytes(&mut slice[curr_idx..curr_idx + tc_header_len]) + .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(); + } + let crc16 = crc_procedure( + self.calc_crc_on_serialization, + &self.crc16, + 0, + curr_idx, + slice, + )?; + slice[curr_idx..curr_idx + 2].copy_from_slice(crc16.to_be_bytes().as_slice()); + curr_idx += 2; + Ok(curr_idx) + } +} + impl PartialEq for PusTc<'_> { fn eq(&self, other: &Self) -> bool { self.sp_header == other.sp_header diff --git a/src/tm.rs b/src/tm.rs index ed84a2e..856f34b 100644 --- a/src/tm.rs +++ b/src/tm.rs @@ -3,6 +3,7 @@ use crate::ecss::{ ccsds_impl, crc_from_raw_data, crc_procedure, sp_header_impls, user_data_from_raw, verify_crc16_ccitt_false_from_raw, CrcType, PusError, PusPacket, PusVersion, + SerializablePusPacket, }; use crate::{ ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, SpHeader, @@ -318,47 +319,6 @@ impl<'raw_data> PusTm<'raw_data> { self.calc_own_crc16(); } - /// Write the raw PUS byte representation to a provided buffer. - pub fn write_to_bytes(&self, slice: &mut [u8]) -> Result { - let mut curr_idx = 0; - let total_size = self.len_packed(); - if total_size > slice.len() { - return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { - found: slice.len(), - expected: total_size, - }) - .into()); - } - self.sp_header - .write_to_be_bytes(&mut slice[0..CCSDS_HEADER_LEN])?; - curr_idx += CCSDS_HEADER_LEN; - let sec_header_len = size_of::(); - let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap(); - sec_header - .write_to_bytes(&mut slice[curr_idx..curr_idx + sec_header_len]) - .ok_or(ByteConversionError::ZeroCopyToError)?; - curr_idx += sec_header_len; - if let Some(timestamp) = self.sec_header.timestamp { - let timestamp_len = timestamp.len(); - 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(); - } - let crc16 = crc_procedure( - self.calc_crc_on_serialization, - &self.crc16, - 0, - curr_idx, - slice, - )?; - slice[curr_idx..curr_idx + 2].copy_from_slice(crc16.to_be_bytes().as_slice()); - curr_idx += 2; - Ok(curr_idx) - } - /// Append the raw PUS byte representation to a provided [alloc::vec::Vec] #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] @@ -450,6 +410,49 @@ impl<'raw_data> PusTm<'raw_data> { } } +impl SerializablePusPacket for PusTm<'_> { + /// Write the raw PUS byte representation to a provided buffer. + fn write_to_bytes(&self, slice: &mut [u8]) -> Result { + let mut curr_idx = 0; + let total_size = self.len_packed(); + if total_size > slice.len() { + return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: slice.len(), + expected: total_size, + }) + .into()); + } + self.sp_header + .write_to_be_bytes(&mut slice[0..CCSDS_HEADER_LEN])?; + curr_idx += CCSDS_HEADER_LEN; + let sec_header_len = size_of::(); + let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap(); + sec_header + .write_to_bytes(&mut slice[curr_idx..curr_idx + sec_header_len]) + .ok_or(ByteConversionError::ZeroCopyToError)?; + curr_idx += sec_header_len; + if let Some(timestamp) = self.sec_header.timestamp { + let timestamp_len = timestamp.len(); + 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(); + } + let crc16 = crc_procedure( + self.calc_crc_on_serialization, + &self.crc16, + 0, + curr_idx, + slice, + )?; + slice[curr_idx..curr_idx + 2].copy_from_slice(crc16.to_be_bytes().as_slice()); + curr_idx += 2; + Ok(curr_idx) + } +} + impl PartialEq for PusTm<'_> { fn eq(&self, other: &Self) -> bool { self.sp_header == other.sp_header