alloc support behind feature gate

This commit is contained in:
Robin Müller 2022-07-31 11:38:58 +02:00
parent b7f3ec424c
commit deee70f40d
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
5 changed files with 193 additions and 112 deletions

View File

@ -30,6 +30,6 @@ version = "0.7.3"
features = ["use-std"] features = ["use-std"]
[features] [features]
std = ["postcard/use-std"]
default = ["heapless", "alloc"] default = ["heapless", "alloc"]
std = ["postcard/use-std"]
alloc = ["serde/alloc"] alloc = ["serde/alloc"]

View File

@ -5,6 +5,7 @@ extern crate alloc;
#[cfg(feature = "std")] #[cfg(feature = "std")]
extern crate std; extern crate std;
use delegate::delegate;
use crate::ecss::CCSDS_HEADER_LEN; use crate::ecss::CCSDS_HEADER_LEN;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -259,11 +260,6 @@ pub trait CcsdsPrimaryHeader {
) -> Self; ) -> Self;
} }
pub mod ser {
use crate::{
CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags,
};
/// Space Packet Primary Header according to CCSDS 133.0-B-2 /// Space Packet Primary Header according to CCSDS 133.0-B-2
#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)] #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq, Copy, Clone)]
pub struct SpHeader { pub struct SpHeader {
@ -279,7 +275,7 @@ pub mod ser {
packet_id: PacketId { packet_id: PacketId {
ptype: PacketType::Tm, ptype: PacketType::Tm,
apid: 0, apid: 0,
sec_header_flag: true, sec_header_flag: false,
}, },
psc: PacketSequenceCtrl { psc: PacketSequenceCtrl {
seq_flags: SequenceFlags::Unsegmented, seq_flags: SequenceFlags::Unsegmented,
@ -290,11 +286,12 @@ pub mod ser {
} }
} }
impl SpHeader { impl SpHeader {
pub fn new(apid: u16, ptype: PacketType, ssc: u16, data_len: u16) -> Option<Self> { pub fn new(ptype: PacketType, sec_header: bool, apid: u16, ssc: u16, data_len: u16) -> Option<Self> {
if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 { if ssc > num::pow(2, 14) - 1 || apid > num::pow(2, 11) - 1 {
return None; return None;
} }
let mut header = SpHeader::default(); let mut header = SpHeader::default();
header.packet_id.sec_header_flag = sec_header;
header.packet_id.apid = apid; header.packet_id.apid = apid;
header.packet_id.ptype = ptype; header.packet_id.ptype = ptype;
header.psc.seq_count = ssc; header.psc.seq_count = ssc;
@ -303,11 +300,36 @@ pub mod ser {
} }
pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> { pub fn tm(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
Self::new(apid, PacketType::Tm, seq_count, data_len) Self::new(PacketType::Tm, false, apid, seq_count, data_len)
} }
pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> { pub fn tc(apid: u16, seq_count: u16, data_len: u16) -> Option<Self> {
Self::new(apid, PacketType::Tc, seq_count, data_len) 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;
} }
} }
@ -354,7 +376,6 @@ pub mod ser {
} }
sph_from_other!(SpHeader, crate::zc::SpHeader); sph_from_other!(SpHeader, crate::zc::SpHeader);
}
pub mod zc { pub mod zc {
use crate::{CcsdsPacket, CcsdsPrimaryHeader, PacketId, PacketSequenceCtrl, VERSION_MASK}; 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)] #[cfg(test)]
mod tests { mod tests {
use crate::ser::SpHeader; use crate::SpHeader;
use crate::{ use crate::{
packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId, packet_type_in_raw_packet_id, zc, CcsdsPacket, CcsdsPrimaryHeader, PacketId,
PacketSequenceCtrl, PacketType, SequenceFlags, PacketSequenceCtrl, PacketType, SequenceFlags,
@ -532,7 +553,7 @@ mod tests {
let sp_header = SpHeader::tc(0x42, 12, 0).expect("Error creating SP header"); let sp_header = SpHeader::tc(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());
assert_eq!(sp_header.ptype(), PacketType::Tc); assert_eq!(sp_header.ptype(), PacketType::Tc);
assert_eq!(sp_header.seq_count(), 12); assert_eq!(sp_header.seq_count(), 12);
assert_eq!(sp_header.apid(), 0x42); assert_eq!(sp_header.apid(), 0x42);
@ -541,12 +562,12 @@ mod tests {
let output = to_stdvec(&sp_header).unwrap(); let output = to_stdvec(&sp_header).unwrap();
let sp_header: SpHeader = from_bytes(&output).unwrap(); let sp_header: SpHeader = from_bytes(&output).unwrap();
assert_eq!(sp_header.version, 0b000); 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.ptype(), PacketType::Tc);
assert_eq!(sp_header.seq_count(), 12); assert_eq!(sp_header.seq_count(), 12);
assert_eq!(sp_header.apid(), 0x42); assert_eq!(sp_header.apid(), 0x42);
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); 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.psc_raw(), 0xC00C);
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);
@ -554,12 +575,12 @@ mod tests {
let sp_header = SpHeader::tm(0x7, 22, 36).expect("Error creating SP header"); let sp_header = SpHeader::tm(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());
assert_eq!(sp_header.ptype(), PacketType::Tm); assert_eq!(sp_header.ptype(), PacketType::Tm);
assert_eq!(sp_header.seq_count(), 22); assert_eq!(sp_header.seq_count(), 22);
assert_eq!(sp_header.apid(), 0x07); assert_eq!(sp_header.apid(), 0x07);
assert_eq!(sp_header.sequence_flags(), SequenceFlags::Unsegmented); 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.psc_raw(), 0xC016);
assert_eq!(sp_header.data_len(), 36); assert_eq!(sp_header.data_len(), 36);
assert_eq!(sp_header.ccsds_version(), 0b000); assert_eq!(sp_header.ccsds_version(), 0b000);
@ -581,6 +602,24 @@ mod tests {
assert_eq!(from_comp_fields.data_len(), 0); 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] #[test]
fn test_zc_sph() { fn test_zc_sph() {
use zerocopy::AsBytes; use zerocopy::AsBytes;

View File

@ -1,14 +1,16 @@
use crate::ecss::{ use crate::ecss::{
crc_from_raw_data, crc_procedure, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE, 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 crate::{CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN};
use alloc::vec::Vec;
use core::mem::size_of; use core::mem::size_of;
use delegate::delegate; use delegate::delegate;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use zerocopy::AsBytes; use zerocopy::AsBytes;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// PUS C secondary header length is fixed /// PUS C secondary header length is fixed
pub const PUC_TC_SECONDARY_HEADER_LEN: usize = size_of::<zc::PusTcSecondaryHeader>(); pub const PUC_TC_SECONDARY_HEADER_LEN: usize = size_of::<zc::PusTcSecondaryHeader>();
pub const PUS_TC_MIN_LEN_WITHOUT_APP_DATA: usize = pub const PUS_TC_MIN_LEN_WITHOUT_APP_DATA: usize =
@ -201,7 +203,8 @@ impl<'slice> PusTc<'slice> {
app_data: Option<&'slice [u8]>, app_data: Option<&'slice [u8]>,
set_ccsds_len: bool, set_ccsds_len: bool,
) -> Self { ) -> 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 { let mut pus_tc = PusTc {
sp_header: *sp_header, sp_header: *sp_header,
raw_data: None, raw_data: None,
@ -335,6 +338,7 @@ impl<'slice> PusTc<'slice> {
Ok(curr_idx) Ok(curr_idx)
} }
#[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 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 /// 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 /// the instance and the found byte length of the packet
pub fn new_from_raw_slice( pub fn new_from_raw_slice(
slice: &'slice (impl AsRef<[u8]> + ?Sized), slice: &'slice [u8],
) -> Result<(Self, usize), PusError> { ) -> Result<(Self, usize), PusError> {
let slice_ref = slice.as_ref(); let slice_ref = slice.as_ref();
let raw_data_len = slice_ref.len(); let raw_data_len = slice_ref.len();
@ -465,7 +469,7 @@ impl PusTcSecondaryHeaderT for PusTc<'_> {
mod tests { mod tests {
use crate::ecss::PusVersion::PusC; use crate::ecss::PusVersion::PusC;
use crate::ecss::{PusError, PusPacket}; use crate::ecss::{PusError, PusPacket};
use crate::ser::SpHeader; use crate::SpHeader;
use crate::tc::ACK_ALL; use crate::tc::ACK_ALL;
use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT}; use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT};
use crate::{CcsdsPacket, SequenceFlags}; use crate::{CcsdsPacket, SequenceFlags};
@ -628,6 +632,7 @@ mod tests {
fn verify_test_tc(tc: &PusTc, has_user_data: bool, exp_full_len: usize) { fn verify_test_tc(tc: &PusTc, has_user_data: bool, exp_full_len: usize) {
assert_eq!(PusPacket::service(tc), 17); assert_eq!(PusPacket::service(tc), 17);
assert_eq!(PusPacket::subservice(tc), 1); assert_eq!(PusPacket::subservice(tc), 1);
assert!(tc.sec_header_flag());
assert_eq!(PusPacket::pus_version(tc), PusC); assert_eq!(PusPacket::pus_version(tc), PusC);
if !has_user_data { if !has_user_data {
assert_eq!(tc.user_data(), None); assert_eq!(tc.user_data(), None);
@ -637,9 +642,11 @@ mod tests {
assert_eq!(tc.apid(), 0x02); assert_eq!(tc.apid(), 0x02);
assert_eq!(tc.ack_flags(), ACK_ALL); assert_eq!(tc.ack_flags(), ACK_ALL);
assert_eq!(tc.len_packed(), exp_full_len); 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!( assert_eq!(
tc.sp_header, tc.sp_header,
SpHeader::tc(0x02, 0x34, exp_full_len as u16 - 7).unwrap() comp_header
); );
} }

View File

@ -308,6 +308,7 @@ mod tests {
generic_dt_property_equality_check(dt.minute(), compare_stamp.minute(), 0, 59); 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) { fn generic_dt_property_equality_check(first: u32, second: u32, start: u32, end: u32) {
if second < first { if second < first {
assert_eq!(second, start); assert_eq!(second, start);

View File

@ -1,10 +1,12 @@
use crate::ecss::{crc_procedure, CrcType, PusError, PusVersion, CRC_CCITT_FALSE}; use crate::ecss::{crc_procedure, CrcType, PusError, PusVersion, CRC_CCITT_FALSE};
use crate::ser::SpHeader; use crate::{PacketError, PacketType, SizeMissmatch, SpHeader, CCSDS_HEADER_LEN};
use crate::{PacketError, PacketType, SizeMissmatch, CCSDS_HEADER_LEN};
use core::mem::size_of; use core::mem::size_of;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use zerocopy::AsBytes; use zerocopy::AsBytes;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// Length without timestamp /// Length without timestamp
pub const PUC_TM_MIN_SEC_HEADER_LEN: usize = 7; pub const PUC_TM_MIN_SEC_HEADER_LEN: usize = 7;
pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize = pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize =
@ -132,7 +134,8 @@ impl<'slice> PusTm<'slice> {
source_data: Option<&'slice [u8]>, source_data: Option<&'slice [u8]>,
set_ccsds_len: bool, set_ccsds_len: bool,
) -> Self { ) -> 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 { let mut pus_tm = PusTm {
sp_header: *sp_header, sp_header: *sp_header,
raw_data: None, raw_data: None,
@ -225,6 +228,37 @@ impl<'slice> PusTm<'slice> {
curr_idx += 2; curr_idx += 2;
Ok(curr_idx) Ok(curr_idx)
} }
#[cfg(feature = "alloc")]
pub fn append_to_vec(&self, vec: &mut Vec<u8>) -> Result<usize, PusError> {
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)] #[cfg(test)]