start adding improved CCSDS packet support
This commit is contained in:
432
src/lib.rs
432
src/lib.rs
@@ -71,6 +71,8 @@ use zerocopy::{FromBytes, IntoBytes};
|
|||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::crc::CRC_CCITT_FALSE;
|
||||||
|
|
||||||
pub mod cfdp;
|
pub mod cfdp;
|
||||||
pub mod crc;
|
pub mod crc;
|
||||||
pub mod ecss;
|
pub mod ecss;
|
||||||
@@ -83,14 +85,21 @@ mod private {
|
|||||||
pub trait Sealed {}
|
pub trait Sealed {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Length of the CCSDS header.
|
||||||
pub const CCSDS_HEADER_LEN: usize = core::mem::size_of::<crate::zc::SpHeader>();
|
pub const CCSDS_HEADER_LEN: usize = core::mem::size_of::<crate::zc::SpHeader>();
|
||||||
|
|
||||||
|
/// Maximum allowed value for the 11-bit APID.
|
||||||
pub const MAX_APID: u11 = u11::MAX;
|
pub const MAX_APID: u11 = u11::MAX;
|
||||||
|
/// Maximum allowed value for the 14-bit APID.
|
||||||
pub const MAX_SEQ_COUNT: u14 = u14::MAX;
|
pub const MAX_SEQ_COUNT: u14 = u14::MAX;
|
||||||
|
|
||||||
#[inline]
|
/// Checksum types currently provided by the CCSDS packet support.
|
||||||
pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum ChecksumType {
|
||||||
|
Crc16CcittFalse,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic error type when converting to and from raw byte slices.
|
/// Generic error type when converting to and from raw byte slices.
|
||||||
@@ -118,6 +127,22 @@ pub enum ZeroCopyError {
|
|||||||
ZeroCopyFromError,
|
ZeroCopyFromError,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
#[error("invalid payload length: {0}")]
|
||||||
|
pub struct InvalidPayloadLengthError(usize);
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub enum CcsdsPacketCreationError {
|
||||||
|
#[error("byte conversion: {0}")]
|
||||||
|
ByteConversion(#[from] ByteConversionError),
|
||||||
|
#[error("invalid payload length: {0}")]
|
||||||
|
InvalidPayloadLength(#[from] InvalidPayloadLengthError),
|
||||||
|
}
|
||||||
|
|
||||||
/// CCSDS packet type enumeration.
|
/// CCSDS packet type enumeration.
|
||||||
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
|
#[derive(Debug, PartialEq, Eq, num_enum::TryFromPrimitive)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
@@ -141,6 +166,29 @@ pub enum SequenceFlags {
|
|||||||
Unsegmented = 0b11,
|
Unsegmented = 0b11,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_type_in_raw_packet_id(packet_id: u16) -> PacketType {
|
||||||
|
PacketType::try_from((packet_id >> 12) as u8 & 0b1).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn ccsds_packet_len_for_user_data_len(
|
||||||
|
data_len: usize,
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
) -> usize {
|
||||||
|
data_len
|
||||||
|
+ CCSDS_HEADER_LEN
|
||||||
|
+ match checksum {
|
||||||
|
Some(ChecksumType::Crc16CcittFalse) => 2,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len_for_user_data_len_with_checksum(data_len: usize) -> usize {
|
||||||
|
ccsds_packet_len_for_user_data_len(data_len, Some(ChecksumType::Crc16CcittFalse))
|
||||||
|
}
|
||||||
|
|
||||||
/// Abstraction for the CCSDS Packet ID, which forms the last thirteen bits
|
/// Abstraction for the CCSDS Packet ID, which forms the last thirteen bits
|
||||||
/// of the first two bytes in the CCSDS primary header.
|
/// of the first two bytes in the CCSDS primary header.
|
||||||
#[derive(Debug, Eq, Copy, Clone)]
|
#[derive(Debug, Eq, Copy, Clone)]
|
||||||
@@ -372,6 +420,11 @@ pub trait CcsdsPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait CcsdsTc: CcsdsPacket {
|
||||||
|
/// Shared access to the packet data field.
|
||||||
|
fn data(&self) -> &[u8];
|
||||||
|
}
|
||||||
|
|
||||||
pub trait CcsdsPrimaryHeader {
|
pub trait CcsdsPrimaryHeader {
|
||||||
fn from_composite_fields(
|
fn from_composite_fields(
|
||||||
packet_id: PacketId,
|
packet_id: PacketId,
|
||||||
@@ -708,6 +761,376 @@ pub mod zc {
|
|||||||
sph_from_other!(SpHeader, crate::SpHeader);
|
sph_from_other!(SpHeader, crate::SpHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CCSDS packet creator with optional support for a CRC16 CCITT checksum appended to the
|
||||||
|
/// end of the packet and support for copying into the user buffer directly.
|
||||||
|
///
|
||||||
|
/// This packet creator variant reserves memory based on the required user data length specified
|
||||||
|
/// by the user and then provides mutable or shared access to that memory. This is useful
|
||||||
|
/// to avoid an additional slice for the user data and allow copying data directly
|
||||||
|
/// into the packet.
|
||||||
|
pub struct CcsdsPacketCreatorWithReservedData<'buf> {
|
||||||
|
sp_header: SpHeader,
|
||||||
|
buf: &'buf mut [u8],
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'buf> CcsdsPacketCreatorWithReservedData<'buf> {
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len_for_user_data_with_checksum(user_data_len: usize) -> usize {
|
||||||
|
ccsds_packet_len_for_user_data_len(user_data_len, Some(ChecksumType::Crc16CcittFalse))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
mut sp_header: SpHeader,
|
||||||
|
packet_type: PacketType,
|
||||||
|
payload_len: usize,
|
||||||
|
buf: &'buf mut [u8],
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
let full_packet_len = match checksum {
|
||||||
|
Some(crc_type) => match crc_type {
|
||||||
|
ChecksumType::Crc16CcittFalse => CCSDS_HEADER_LEN + payload_len + 2,
|
||||||
|
},
|
||||||
|
None => CCSDS_HEADER_LEN + payload_len,
|
||||||
|
};
|
||||||
|
if full_packet_len > buf.len() {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: full_packet_len,
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
if full_packet_len - CCSDS_HEADER_LEN - 1 > u16::MAX as usize {
|
||||||
|
return Err(InvalidPayloadLengthError(payload_len).into());
|
||||||
|
}
|
||||||
|
sp_header.data_len = (full_packet_len - CCSDS_HEADER_LEN - 1) as u16;
|
||||||
|
sp_header.packet_id.packet_type = packet_type;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
sp_header,
|
||||||
|
buf: buf[0..full_packet_len].as_mut(),
|
||||||
|
checksum,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_checksum(
|
||||||
|
sp_header: SpHeader,
|
||||||
|
packet_type: PacketType,
|
||||||
|
payload_len: usize,
|
||||||
|
buf: &'buf mut [u8],
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
Self::new(
|
||||||
|
sp_header,
|
||||||
|
packet_type,
|
||||||
|
payload_len,
|
||||||
|
buf,
|
||||||
|
Some(ChecksumType::Crc16CcittFalse),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_tm_with_checksum(
|
||||||
|
sp_header: SpHeader,
|
||||||
|
payload_len: usize,
|
||||||
|
buf: &'buf mut [u8],
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
Self::new(
|
||||||
|
sp_header,
|
||||||
|
PacketType::Tm,
|
||||||
|
payload_len,
|
||||||
|
buf,
|
||||||
|
Some(ChecksumType::Crc16CcittFalse),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_tc_with_checksum(
|
||||||
|
sp_header: SpHeader,
|
||||||
|
payload_len: usize,
|
||||||
|
buf: &'buf mut [u8],
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
Self::new(
|
||||||
|
sp_header,
|
||||||
|
PacketType::Tc,
|
||||||
|
payload_len,
|
||||||
|
buf,
|
||||||
|
Some(ChecksumType::Crc16CcittFalse),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacketCreatorWithReservedData<'_> {
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len(&self) -> usize {
|
||||||
|
<Self as CcsdsPacket>::packet_len(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn sp_header(&self) -> &SpHeader {
|
||||||
|
&self.sp_header
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_data_mut(&mut self) -> &mut [u8] {
|
||||||
|
let len = self.buf.len();
|
||||||
|
&mut self.buf[CCSDS_HEADER_LEN..len - 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_data(&mut self) -> &[u8] {
|
||||||
|
let len = self.buf.len();
|
||||||
|
&self.buf[CCSDS_HEADER_LEN..len - 2]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(self) -> usize {
|
||||||
|
self.sp_header
|
||||||
|
.write_to_be_bytes(&mut self.buf[0..CCSDS_HEADER_LEN])
|
||||||
|
.unwrap();
|
||||||
|
let len = self.buf.len();
|
||||||
|
match self.checksum {
|
||||||
|
Some(ChecksumType::Crc16CcittFalse) => {
|
||||||
|
let crc16 = CRC_CCITT_FALSE.checksum(&self.buf[0..len - 2]);
|
||||||
|
self.buf[len - 2..len].copy_from_slice(&crc16.to_be_bytes());
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacket for CcsdsPacketCreatorWithReservedData<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> arbitrary_int::u3 {
|
||||||
|
self.sp_header.ccsds_version()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> PacketId {
|
||||||
|
self.sp_header.packet_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> PacketSequenceControl {
|
||||||
|
self.sp_header.psc()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16 {
|
||||||
|
self.sp_header.data_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CCSDS packet creator with optional support for a CRC16 CCITT checksum appended to the
|
||||||
|
/// end of the packet.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub struct CcsdsPacketCreator<'app_data> {
|
||||||
|
sp_header: SpHeader,
|
||||||
|
packet_data: &'app_data [u8],
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'app_data> CcsdsPacketCreator<'app_data> {
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len_for_user_data_with_checksum(user_data_len: usize) -> usize {
|
||||||
|
ccsds_packet_len_for_user_data_len(user_data_len, Some(ChecksumType::Crc16CcittFalse))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
mut sp_header: SpHeader,
|
||||||
|
packet_type: PacketType,
|
||||||
|
packet_data: &'app_data [u8],
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
sp_header.data_len = (packet_data.len()
|
||||||
|
+ match checksum {
|
||||||
|
Some(ChecksumType::Crc16CcittFalse) => 2,
|
||||||
|
None => 0,
|
||||||
|
}
|
||||||
|
- 1) as u16;
|
||||||
|
|
||||||
|
let full_packet_len = match checksum {
|
||||||
|
Some(crc_type) => match crc_type {
|
||||||
|
ChecksumType::Crc16CcittFalse => CCSDS_HEADER_LEN + packet_data.len() + 2,
|
||||||
|
},
|
||||||
|
None => CCSDS_HEADER_LEN + packet_data.len(),
|
||||||
|
};
|
||||||
|
if full_packet_len - CCSDS_HEADER_LEN - 1 > u16::MAX as usize {
|
||||||
|
return Err(InvalidPayloadLengthError(packet_data.len()).into());
|
||||||
|
}
|
||||||
|
sp_header.data_len = (full_packet_len - CCSDS_HEADER_LEN - 1) as u16;
|
||||||
|
sp_header.packet_id.packet_type = packet_type;
|
||||||
|
Ok(Self {
|
||||||
|
sp_header,
|
||||||
|
packet_data,
|
||||||
|
checksum,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_checksum(
|
||||||
|
sp_header: SpHeader,
|
||||||
|
packet_type: PacketType,
|
||||||
|
app_data: &'app_data [u8],
|
||||||
|
) -> Result<Self, CcsdsPacketCreationError> {
|
||||||
|
Self::new(
|
||||||
|
sp_header,
|
||||||
|
packet_type,
|
||||||
|
app_data,
|
||||||
|
Some(ChecksumType::Crc16CcittFalse),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacketCreator<'_> {
|
||||||
|
pub fn len_written(&self) -> usize {
|
||||||
|
ccsds_packet_len_for_user_data_len(self.packet_data.len(), self.checksum)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_to_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
|
let len_written = self.len_written();
|
||||||
|
if len_written > buf.len() {
|
||||||
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
|
found: buf.len(),
|
||||||
|
expected: len_written,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.sp_header
|
||||||
|
.write_to_be_bytes(&mut buf[0..CCSDS_HEADER_LEN])?;
|
||||||
|
buf[CCSDS_HEADER_LEN..CCSDS_HEADER_LEN + self.packet_data.len()]
|
||||||
|
.copy_from_slice(self.packet_data);
|
||||||
|
match self.checksum {
|
||||||
|
Some(ChecksumType::Crc16CcittFalse) => {
|
||||||
|
let crc16 = CRC_CCITT_FALSE.checksum(&buf[0..len_written - 2]);
|
||||||
|
buf[len_written - 2..len_written].copy_from_slice(&crc16.to_be_bytes());
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
};
|
||||||
|
Ok(len_written)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "alloc")]
|
||||||
|
pub fn to_vec(&self) -> alloc::vec::Vec<u8> {
|
||||||
|
let mut vec = alloc::vec![0u8; self.len_written()];
|
||||||
|
// Can not fail, unless we messed up the len_written method..
|
||||||
|
self.write_to_bytes(&mut vec).unwrap();
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub enum CcsdsPacketReadError {
|
||||||
|
#[error("byte conversion: {0}")]
|
||||||
|
ByteConversion(#[from] ByteConversionError),
|
||||||
|
#[error("CRC error")]
|
||||||
|
CrcError,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CCSDS packet reader structure.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
|
pub struct CcsdsPacketReader<'buf> {
|
||||||
|
sp_header: SpHeader,
|
||||||
|
packet_data: &'buf [u8],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'buf> CcsdsPacketReader<'buf> {
|
||||||
|
pub fn new_with_checksum(
|
||||||
|
buf: &'buf [u8],
|
||||||
|
) -> Result<CcsdsPacketReader<'buf>, CcsdsPacketReadError> {
|
||||||
|
Self::new(buf, Some(ChecksumType::Crc16CcittFalse))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(
|
||||||
|
buf: &'buf [u8],
|
||||||
|
checksum: Option<ChecksumType>,
|
||||||
|
) -> Result<Self, CcsdsPacketReadError> {
|
||||||
|
let sp_header = SpHeader::from_be_bytes(&buf[0..CCSDS_HEADER_LEN])
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
if sp_header.packet_len() > buf.len() {
|
||||||
|
return Err(ByteConversionError::FromSliceTooSmall {
|
||||||
|
found: sp_header.packet_len(),
|
||||||
|
expected: buf.len(),
|
||||||
|
}
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
let user_data = match checksum {
|
||||||
|
Some(ChecksumType::Crc16CcittFalse) => {
|
||||||
|
if CRC_CCITT_FALSE.checksum(&buf[0..sp_header.packet_len()]) != 0 {
|
||||||
|
return Err(CcsdsPacketReadError::CrcError);
|
||||||
|
}
|
||||||
|
&buf[CCSDS_HEADER_LEN..sp_header.packet_len() - 2]
|
||||||
|
}
|
||||||
|
None => &buf[CCSDS_HEADER_LEN..sp_header.packet_len()],
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
sp_header,
|
||||||
|
packet_data: user_data,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacketReader<'_> {
|
||||||
|
#[inline]
|
||||||
|
pub fn sp_header(&self) -> &SpHeader {
|
||||||
|
&self.sp_header
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_data(&self) -> &[u8] {
|
||||||
|
self.packet_data
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn apid(&self) -> u11 {
|
||||||
|
self.sp_header.apid()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_id(&self) -> PacketId {
|
||||||
|
self.sp_header.packet_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn psc(&self) -> PacketSequenceControl {
|
||||||
|
self.sp_header.psc()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn packet_len(&self) -> usize {
|
||||||
|
<Self as CcsdsPacket>::packet_len(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn data_len(&self) -> u16 {
|
||||||
|
self.sp_header.data_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CcsdsPacket for CcsdsPacketReader<'_> {
|
||||||
|
#[inline]
|
||||||
|
fn ccsds_version(&self) -> arbitrary_int::u3 {
|
||||||
|
self.sp_header.ccsds_version()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn packet_id(&self) -> PacketId {
|
||||||
|
self.packet_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn psc(&self) -> PacketSequenceControl {
|
||||||
|
self.psc()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn data_len(&self) -> u16 {
|
||||||
|
self.data_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(all(test, feature = "std"))]
|
#[cfg(all(test, feature = "std"))]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
@@ -1058,4 +1481,7 @@ pub(crate) mod tests {
|
|||||||
.0;
|
.0;
|
||||||
assert_eq!(sp_header, sp_header_read_back);
|
assert_eq!(sp_header, sp_header_read_back);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_ccsds_size_function() {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user