From deee70f40dab8acd1710429aa1411e43b2cdb276 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 31 Jul 2022 11:38:58 +0200 Subject: [PATCH] alloc support behind feature gate --- Cargo.toml | 2 +- src/lib.rs | 243 ++++++++++++++++++++++++++++++---------------------- src/tc.rs | 19 ++-- src/time.rs | 1 + src/tm.rs | 40 ++++++++- 5 files changed, 193 insertions(+), 112 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d9c919a..4268a7e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,6 @@ version = "0.7.3" features = ["use-std"] [features] -std = ["postcard/use-std"] default = ["heapless", "alloc"] +std = ["postcard/use-std"] alloc = ["serde/alloc"] diff --git a/src/lib.rs b/src/lib.rs index b490e79..1c35f69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ extern crate alloc; #[cfg(feature = "std")] extern crate std; +use delegate::delegate; use crate::ecss::CCSDS_HEADER_LEN; use serde::{Deserialize, Serialize}; @@ -259,102 +260,122 @@ pub trait CcsdsPrimaryHeader { ) -> Self; } -pub mod ser { - use crate::{ - CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, - }; - - /// Space Packet Primary Header according to CCSDS 133.0-B-2 - #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)] - pub struct SpHeader { - pub version: u8, - pub packet_id: PacketId, - pub psc: PacketSequenceCtrl, - pub data_len: u16, - } - impl Default for SpHeader { - fn default() -> Self { - SpHeader { - version: 0, - packet_id: PacketId { - ptype: PacketType::Tm, - apid: 0, - sec_header_flag: true, - }, - psc: PacketSequenceCtrl { - seq_flags: SequenceFlags::Unsegmented, - seq_count: 0, - }, - data_len: 0, - } - } - } - impl SpHeader { - pub fn new(apid: u16, ptype: PacketType, ssc: u16, data_len: u16) -> Option { - if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 { - return None; - } - let mut header = SpHeader::default(); - header.packet_id.apid = apid; - header.packet_id.ptype = ptype; - header.psc.seq_count = ssc; - header.data_len = data_len; - Some(header) - } - - pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option { - Self::new(apid, PacketType::Tm, seq_count, data_len) - } - - pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option { - Self::new(apid, PacketType::Tc, seq_count, data_len) - } - } - - impl CcsdsPacket for SpHeader { - #[inline] - fn ccsds_version(&self) -> u8 { - self.version - } - - #[inline] - fn packet_id(&self) -> PacketId { - self.packet_id - } - - #[inline] - fn psc(&self) -> PacketSequenceCtrl { - self.psc - } - - #[inline] - fn data_len(&self) -> u16 { - self.data_len - } - } - - impl CcsdsPrimaryHeader for SpHeader { - fn from_composite_fields( - packet_id: PacketId, - psc: PacketSequenceCtrl, - data_len: u16, - version: Option, - ) -> Self { - let mut version_to_set = 0b000; - if let Some(version) = version { - version_to_set = version; - } - SpHeader { - version: version_to_set, - packet_id, - psc, - data_len, - } - } - } - - sph_from_other!(SpHeader, crate::zc::SpHeader); +/// Space Packet Primary Header according to CCSDS 133.0-B-2 +#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)] +pub struct SpHeader { + pub version: u8, + pub packet_id: PacketId, + pub psc: PacketSequenceCtrl, + pub data_len: u16, } +impl Default for SpHeader { + fn default() -> Self { + SpHeader { + version: 0, + packet_id: PacketId { + ptype: PacketType::Tm, + apid: 0, + sec_header_flag: false, + }, + psc: PacketSequenceCtrl { + seq_flags: SequenceFlags::Unsegmented, + seq_count: 0, + }, + data_len: 0, + } + } +} +impl SpHeader { + pub fn new(ptype: PacketType, sec_header: bool, apid: u16, ssc: u16, data_len: u16) -> Option { + if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 { + return None; + } + let mut header = SpHeader::default(); + header.packet_id.sec_header_flag = sec_header; + header.packet_id.apid = apid; + header.packet_id.ptype = ptype; + header.psc.seq_count = ssc; + header.data_len = data_len; + Some(header) + } + + pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option { + Self::new(PacketType::Tm, false, apid, seq_count, data_len) + } + + pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option { + Self::new(PacketType::Tc, false, apid, seq_count, data_len) + } + + //noinspection RsTraitImplementation + delegate!(to self.packet_id { + pub fn set_apid(&mut self, apid: u16) -> bool; + }); + + delegate!(to self.psc { + pub fn set_seq_count(&mut self, seq_count: u16) -> bool; + }); + + pub fn set_seq_flags(&mut self, seq_flags: SequenceFlags) { + self.psc.seq_flags = seq_flags; + } + + pub fn set_sec_header_flag(&mut self) { + self.packet_id.sec_header_flag = true; + } + + pub fn clear_sec_header_flag(&mut self) { + self.packet_id.sec_header_flag = false; + } + + pub fn set_packet_type(&mut self, packet_type: PacketType) { + self.packet_id.ptype = packet_type; + } +} + +impl CcsdsPacket for SpHeader { + #[inline] + fn ccsds_version(&self) -> u8 { + self.version + } + + #[inline] + fn packet_id(&self) -> PacketId { + self.packet_id + } + + #[inline] + fn psc(&self) -> PacketSequenceCtrl { + self.psc + } + + #[inline] + fn data_len(&self) -> u16 { + self.data_len + } +} + +impl CcsdsPrimaryHeader for SpHeader { + fn from_composite_fields( + packet_id: PacketId, + psc: PacketSequenceCtrl, + data_len: u16, + version: Option, + ) -> Self { + let mut version_to_set = 0b000; + if let Some(version) = version { + version_to_set = version; + } + SpHeader { + version: version_to_set, + packet_id, + psc, + data_len, + } + } +} + +sph_from_other!(SpHeader, crate::zc::SpHeader); pub mod zc { use crate::{CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, VERSION_MASK}; @@ -434,12 +455,12 @@ pub mod zc { } } - sph_from_other!(SpHeader, crate::ser::SpHeader); + sph_from_other!(SpHeader, crate::SpHeader); } #[cfg(test)] mod tests { - use crate::ser::SpHeader; + use crate::SpHeader; use crate::{ packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, @@ -532,7 +553,7 @@ mod tests { let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header"); assert_eq!(sp_header.ccsds_version(), 0b000); assert!(sp_header.is_tc()); - assert!(sp_header.sec_header_flag()); + assert!(!sp_header.sec_header_flag()); assert_eq!(sp_header.ptype(), PacketType::Tc); assert_eq!(sp_header.seq_count(), 12); assert_eq!(sp_header.apid(), 0x42); @@ -541,12 +562,12 @@ mod tests { let output = to_stdvec(&sp_header).unwrap(); let sp_header: SpHeader = from_bytes(&output).unwrap(); assert_eq!(sp_header.version, 0b000); - assert!(sp_header.packet_id.sec_header_flag); + assert!(!sp_header.packet_id.sec_header_flag); assert_eq!(sp_header.ptype(), PacketType::Tc); assert_eq!(sp_header.seq_count(), 12); assert_eq!(sp_header.apid(), 0x42); assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); - assert_eq!(sp_header.packet_id_raw(), 0x1842); + assert_eq!(sp_header.packet_id_raw(), 0x1042); assert_eq!(sp_header.psc_raw(), 0xC00C); assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.data_len, 0); @@ -554,12 +575,12 @@ mod tests { let sp_header = SpHeader::tm(0x7, 22, 36).expect("Error creating SP header"); assert_eq!(sp_header.ccsds_version(), 0b000); assert!(sp_header.is_tm()); - assert!(sp_header.sec_header_flag()); + assert!(!sp_header.sec_header_flag()); assert_eq!(sp_header.ptype(), PacketType::Tm); assert_eq!(sp_header.seq_count(), 22); assert_eq!(sp_header.apid(), 0x07); assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); - assert_eq!(sp_header.packet_id_raw(), 0x0807); + assert_eq!(sp_header.packet_id_raw(), 0x0007); assert_eq!(sp_header.psc_raw(), 0xC016); assert_eq!(sp_header.data_len(), 36); assert_eq!(sp_header.ccsds_version(), 0b000); @@ -581,6 +602,24 @@ mod tests { assert_eq!(from_comp_fields.data_len(), 0); } + #[test] + fn test_sp_header_setters() { + let mut sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header"); + assert_eq!(sp_header.apid(), 0x42); + sp_header.set_apid(0x12); + assert_eq!(sp_header.apid(), 0x12); + + sp_header.set_sec_header_flag(); + assert!(sp_header.sec_header_flag()); + sp_header.clear_sec_header_flag(); + assert!(!sp_header.sec_header_flag()); + sp_header.set_seq_count(0x45); + assert_eq!(sp_header.seq_count(), 0x45); + assert_eq!(sp_header.ptype(), PacketType::Tc); + sp_header.set_packet_type(PacketType::Tm); + assert_eq!(sp_header.ptype(), PacketType::Tm); + } + #[test] fn test_zc_sph() { use zerocopy::AsBytes; diff --git a/src/tc.rs b/src/tc.rs index 38b7073..7cbfeb5 100644 --- a/src/tc.rs +++ b/src/tc.rs @@ -1,14 +1,16 @@ use crate::ecss::{ crc_from_raw_data, crc_procedure, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE, }; -use crate::ser::SpHeader; +use crate::SpHeader; use crate::{CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN}; -use alloc::vec::Vec; use core::mem::size_of; use delegate::delegate; use serde::{Deserialize, Serialize}; use zerocopy::AsBytes; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + /// PUS C secondary header length is fixed pub const PUC_TC_SECONDARY_HEADER_LEN: usize = size_of::(); pub const PUS_TC_MIN_LEN_WITHOUT_APP_DATA: usize = @@ -201,7 +203,8 @@ impl<'slice> PusTc<'slice> { app_data: Option<&'slice [u8]>, set_ccsds_len: bool, ) -> Self { - sp_header.packet_id.ptype = PacketType::Tc; + sp_header.set_packet_type(PacketType::Tc); + sp_header.set_sec_header_flag(); let mut pus_tc = PusTc { sp_header: *sp_header, raw_data: None, @@ -335,6 +338,7 @@ impl<'slice> PusTc<'slice> { Ok(curr_idx) } + #[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; @@ -366,7 +370,7 @@ impl<'slice> PusTc<'slice> { /// Create a PusTc instance from a raw slice. On success, it returns a tuple containing /// the instance and the found byte length of the packet pub fn new_from_raw_slice( - slice: &'slice (impl AsRef<[u8]> + ?Sized), + slice: &'slice [u8], ) -> Result<(Self, usize), PusError> { let slice_ref = slice.as_ref(); let raw_data_len = slice_ref.len(); @@ -465,7 +469,7 @@ impl PusTcSecondaryHeaderT for PusTc<'_> { mod tests { use crate::ecss::PusVersion::PusC; use crate::ecss::{PusError, PusPacket}; - use crate::ser::SpHeader; + use crate::SpHeader; use crate::tc::ACK_ALL; use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT}; use crate::{CcsdsPacket, SequenceFlags}; @@ -628,6 +632,7 @@ mod tests { fn verify_test_tc(tc: &PusTc, has_user_data: bool, exp_full_len: usize) { assert_eq!(PusPacket::service(tc), 17); assert_eq!(PusPacket::subservice(tc), 1); + assert!(tc.sec_header_flag()); assert_eq!(PusPacket::pus_version(tc), PusC); if !has_user_data { assert_eq!(tc.user_data(), None); @@ -637,9 +642,11 @@ mod tests { assert_eq!(tc.apid(), 0x02); assert_eq!(tc.ack_flags(), ACK_ALL); assert_eq!(tc.len_packed(), exp_full_len); + let mut comp_header = SpHeader::tc(0x02, 0x34, exp_full_len as u16 - 7).unwrap(); + comp_header.set_sec_header_flag(); assert_eq!( tc.sp_header, - SpHeader::tc(0x02, 0x34, exp_full_len as u16 - 7).unwrap() + comp_header ); } diff --git a/src/time.rs b/src/time.rs index cfd64a0..b8fb78b 100644 --- a/src/time.rs +++ b/src/time.rs @@ -308,6 +308,7 @@ mod tests { generic_dt_property_equality_check(dt.minute(), compare_stamp.minute(), 0, 59); } + #[cfg(feature = "std")] fn generic_dt_property_equality_check(first: u32, second: u32, start: u32, end: u32) { if second < first { assert_eq!(second, start); diff --git a/src/tm.rs b/src/tm.rs index 8788ce5..4008376 100644 --- a/src/tm.rs +++ b/src/tm.rs @@ -1,10 +1,12 @@ use crate::ecss::{crc_procedure, CrcType, PusError, PusVersion, CRC_CCITT_FALSE}; -use crate::ser::SpHeader; -use crate::{PacketError, PacketType, SizeMissmatch, CCSDS_HEADER_LEN}; +use crate::{PacketError, PacketType, SizeMissmatch, SpHeader, CCSDS_HEADER_LEN}; use core::mem::size_of; use serde::{Deserialize, Serialize}; use zerocopy::AsBytes; +#[cfg(feature = "alloc")] +use alloc::vec::Vec; + /// Length without timestamp pub const PUC_TM_MIN_SEC_HEADER_LEN: usize = 7; pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize = @@ -132,7 +134,8 @@ impl<'slice> PusTm<'slice> { source_data: Option<&'slice [u8]>, set_ccsds_len: bool, ) -> Self { - sp_header.packet_id.ptype = PacketType::Tm; + sp_header.set_packet_type(PacketType::Tm); + sp_header.set_sec_header_flag(); let mut pus_tm = PusTm { sp_header: *sp_header, raw_data: None, @@ -225,6 +228,37 @@ impl<'slice> PusTm<'slice> { curr_idx += 2; Ok(curr_idx) } + + #[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_TM_MIN_LEN_WITHOUT_SOURCE_DATA + self.sec_header.time_stamp.len(); + if let Some(src_data) = self.source_data { + appended_len += src_data.len(); + }; + let start_idx = vec.len(); + let mut curr_idx = vec.len(); + vec.extend_from_slice(sph_zc.as_bytes()); + curr_idx += sph_zc.as_bytes().len(); + // The PUS version is hardcoded to PUS C + let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap(); + vec.extend_from_slice(sec_header.as_bytes()); + curr_idx += sec_header.as_bytes().len(); + vec.extend_from_slice(self.sec_header.time_stamp); + curr_idx += self.sec_header.time_stamp.len(); + if let Some(src_data) = self.source_data { + vec.extend_from_slice(src_data); + curr_idx += src_data.len(); + } + let crc16 = crc_procedure( + self.calc_crc_on_serialization, + &self.crc16, + curr_idx, + &vec[start_idx..curr_idx], + )?; + vec.extend_from_slice(crc16.to_be_bytes().as_slice()); + Ok(appended_len) + } } #[cfg(test)]