8 Commits

Author SHA1 Message Date
94489da003 return usize instead of u8 for byte width
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-09-06 10:14:23 +02:00
c72c5ad4aa extensions
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
- Add source_data getter for PusTm
- Add std time info updater for CDS short time stamp provider
2022-09-03 20:54:37 +02:00
bb83e67e54 bump changelog
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-09-03 18:50:21 +02:00
a4e297f0c0 Add new features
- Basic ECSS enumeration support for u8, u16, u32 and u64
- Better names for generic error enums
2022-09-03 18:47:59 +02:00
96d389a651 fix test
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-09-03 16:30:21 +02:00
cc680dba46 timestamp writer should return timestamp error too 2022-09-03 16:28:11 +02:00
42d3487c19 raw accessor function
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-28 00:25:22 +02:00
3970061ca1 only allow tests for std envs
All checks were successful
Rust/spacepackets/pipeline/head This commit looks good
2022-08-20 23:19:38 +02:00
6 changed files with 237 additions and 44 deletions

View File

@ -6,9 +6,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/) The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/). and this project adheres to [Semantic Versioning](http://semver.org/).
## [unreleased] # [unreleased]
## [v0.1.0] 16.08.2022 ## Added
- Basic support for ECSS enumeration types for u8, u16, u32 and u64
## Changed
- Better names for generic error enumerations: `PacketError` renamed to `ByteConversionError`
# [v0.1.0] 16.08.2022
Initial release with CCSDS Space Packet Primary Header implementation and basic PUS TC and TM Initial release with CCSDS Space Packet Primary Header implementation and basic PUS TC and TM
implementations. implementations.

View File

@ -1,6 +1,6 @@
//! Common definitions and helpers required to create PUS TMTC packets according to //! Common definitions and helpers required to create PUS TMTC packets according to
//! [ECSS-E-ST-70-41C](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/) //! [ECSS-E-ST-70-41C](https://ecss.nl/standard/ecss-e-st-70-41c-space-engineering-telemetry-and-telecommand-packet-utilization-15-april-2016/)
use crate::{CcsdsPacket, PacketError}; use crate::{ByteConversionError, CcsdsPacket, SizeMissmatch};
use core::mem::size_of; use core::mem::size_of;
use crc::{Crc, CRC_16_IBM_3740}; use crc::{Crc, CRC_16_IBM_3740};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -41,7 +41,7 @@ pub enum PusError {
NoRawData, NoRawData,
/// CRC16 needs to be calculated first /// CRC16 needs to be calculated first
CrcCalculationMissing, CrcCalculationMissing,
PacketError(PacketError), PacketError(ByteConversionError),
} }
pub trait PusPacket: CcsdsPacket { pub trait PusPacket: CcsdsPacket {
@ -135,3 +135,156 @@ macro_rules! sp_header_impls {
pub(crate) use ccsds_impl; pub(crate) use ccsds_impl;
pub(crate) use sp_header_impls; pub(crate) use sp_header_impls;
pub trait EcssEnumeration {
fn pfc(&self) -> u8;
fn byte_width(&self) -> usize {
(self.pfc() / 8) as usize
}
fn to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
}
trait ToBeBytes {
type ByteArray: AsRef<[u8]>;
fn to_be_bytes(&self) -> Self::ByteArray;
}
impl ToBeBytes for u8 {
type ByteArray = [u8; 1];
fn to_be_bytes(&self) -> Self::ByteArray {
u8::to_be_bytes(*self)
}
}
impl ToBeBytes for u16 {
type ByteArray = [u8; 2];
fn to_be_bytes(&self) -> Self::ByteArray {
u16::to_be_bytes(*self)
}
}
impl ToBeBytes for u32 {
type ByteArray = [u8; 4];
fn to_be_bytes(&self) -> Self::ByteArray {
u32::to_be_bytes(*self)
}
}
impl ToBeBytes for u64 {
type ByteArray = [u8; 8];
fn to_be_bytes(&self) -> Self::ByteArray {
u64::to_be_bytes(*self)
}
}
pub struct GenericEcssEnumWrapper<TYPE> {
val: TYPE,
}
impl<TYPE> GenericEcssEnumWrapper<TYPE> {
pub fn new(val: TYPE) -> Self {
Self { val }
}
}
impl<TYPE: ToBeBytes> EcssEnumeration for GenericEcssEnumWrapper<TYPE> {
fn pfc(&self) -> u8 {
size_of::<TYPE>() as u8 * 8_u8
}
fn to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
if buf.len() < self.byte_width() as usize {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(),
expected: self.byte_width() as usize,
}));
}
buf[0..self.byte_width() as usize].copy_from_slice(self.val.to_be_bytes().as_ref());
Ok(())
}
}
pub type EcssEnumU8 = GenericEcssEnumWrapper<u8>;
pub type EcssEnumU16 = GenericEcssEnumWrapper<u16>;
pub type EcssEnumU32 = GenericEcssEnumWrapper<u32>;
pub type EcssEnumU64 = GenericEcssEnumWrapper<u64>;
#[cfg(test)]
mod tests {
use crate::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU8, EcssEnumeration};
use crate::ByteConversionError;
#[test]
fn test_enum_u8() {
let mut buf = [0, 0, 0];
let my_enum = EcssEnumU8::new(1);
my_enum
.to_bytes(&mut buf[1..2])
.expect("To byte conversion of u8 failed");
assert_eq!(buf[1], 1);
}
#[test]
fn test_enum_u16() {
let mut buf = [0, 0, 0];
let my_enum = EcssEnumU16::new(0x1f2f);
my_enum
.to_bytes(&mut buf[1..3])
.expect("To byte conversion of u8 failed");
assert_eq!(buf[1], 0x1f);
assert_eq!(buf[2], 0x2f);
}
#[test]
fn test_slice_u16_too_small() {
let mut buf = [0];
let my_enum = EcssEnumU16::new(0x1f2f);
let res = my_enum.to_bytes(&mut buf[0..1]);
assert!(res.is_err());
let error = res.unwrap_err();
match error {
ByteConversionError::ToSliceTooSmall(missmatch) => {
assert_eq!(missmatch.expected, 2);
assert_eq!(missmatch.found, 1);
}
_ => {
panic!("Unexpected error {:?}", error);
}
}
}
#[test]
fn test_enum_u32() {
let mut buf = [0, 0, 0, 0, 0];
let my_enum = EcssEnumU32::new(0x1f2f3f4f);
my_enum
.to_bytes(&mut buf[1..5])
.expect("To byte conversion of u8 failed");
assert_eq!(buf[1], 0x1f);
assert_eq!(buf[2], 0x2f);
assert_eq!(buf[3], 0x3f);
assert_eq!(buf[4], 0x4f);
}
#[test]
fn test_slice_u32_too_small() {
let mut buf = [0, 0, 0, 0, 0];
let my_enum = EcssEnumU32::new(0x1f2f3f4f);
let res = my_enum.to_bytes(&mut buf[0..3]);
assert!(res.is_err());
let error = res.unwrap_err();
match error {
ByteConversionError::ToSliceTooSmall(missmatch) => {
assert_eq!(missmatch.expected, 4);
assert_eq!(missmatch.found, 3);
}
_ => {
panic!("Unexpected error {:?}", error);
}
}
}
}

View File

@ -46,7 +46,7 @@
#![no_std] #![no_std]
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
extern crate alloc; extern crate alloc;
#[cfg(feature = "std")] #[cfg(any(feature = "std", test))]
extern crate std; extern crate std;
use crate::ecss::CCSDS_HEADER_LEN; use crate::ecss::CCSDS_HEADER_LEN;
@ -65,14 +65,14 @@ pub struct SizeMissmatch {
pub expected: usize, pub expected: usize,
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PacketError { pub enum ByteConversionError {
/// The passed slice is too small. Returns the found and expected minimum size /// The passed slice is too small. Returns the found and expected minimum size
ToBytesSliceTooSmall(SizeMissmatch), ToSliceTooSmall(SizeMissmatch),
/// The provider buffer it soo small. Returns the found and expected minimum size /// The provider buffer it soo small. Returns the found and expected minimum size
FromBytesSliceTooSmall(SizeMissmatch), FromSliceTooSmall(SizeMissmatch),
/// The [zerocopy] library failed to write to bytes /// The [zerocopy] library failed to write to bytes
ToBytesZeroCopyError, ZeroCopyToError,
FromBytesZeroCopyError, ZeroCopyFromError,
} }
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
@ -391,15 +391,15 @@ impl SpHeader {
self.packet_id.ptype = packet_type; self.packet_id.ptype = packet_type;
} }
pub fn from_raw_slice(buf: &[u8]) -> Result<Self, PacketError> { pub fn from_raw_slice(buf: &[u8]) -> Result<Self, ByteConversionError> {
if buf.len() < CCSDS_HEADER_LEN + 1 { if buf.len() < CCSDS_HEADER_LEN + 1 {
return Err(PacketError::FromBytesSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
found: buf.len(), found: buf.len(),
expected: CCSDS_HEADER_LEN + 1, expected: CCSDS_HEADER_LEN + 1,
})); }));
} }
let zc_header = zc::SpHeader::from_bytes(&buf[0..CCSDS_HEADER_LEN]) let zc_header = zc::SpHeader::from_bytes(&buf[0..CCSDS_HEADER_LEN])
.ok_or(PacketError::FromBytesZeroCopyError)?; .ok_or(ByteConversionError::ZeroCopyFromError)?;
Ok(Self::from(zc_header)) Ok(Self::from(zc_header))
} }
} }

View File

@ -36,7 +36,9 @@ use crate::ecss::{
verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE, verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
}; };
use crate::SpHeader; use crate::SpHeader;
use crate::{CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN}; use crate::{
ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, CCSDS_HEADER_LEN,
};
use core::mem::size_of; use core::mem::size_of;
use delegate::delegate; use delegate::delegate;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -334,7 +336,7 @@ impl<'slice> PusTc<'slice> {
let tc_header_len = size_of::<zc::PusTcSecondaryHeader>(); let tc_header_len = size_of::<zc::PusTcSecondaryHeader>();
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(PusError::PacketError(PacketError::ToBytesSliceTooSmall( return Err(PusError::PacketError(ByteConversionError::ToSliceTooSmall(
SizeMissmatch { SizeMissmatch {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
@ -343,13 +345,13 @@ impl<'slice> PusTc<'slice> {
} }
sph_zc sph_zc
.to_bytes(&mut slice[curr_idx..curr_idx + CCSDS_HEADER_LEN]) .to_bytes(&mut slice[curr_idx..curr_idx + CCSDS_HEADER_LEN])
.ok_or(PusError::PacketError(PacketError::ToBytesZeroCopyError))?; .ok_or(PusError::PacketError(ByteConversionError::ZeroCopyToError))?;
curr_idx += CCSDS_HEADER_LEN; curr_idx += CCSDS_HEADER_LEN;
let sec_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap(); let sec_header = zc::PusTcSecondaryHeader::try_from(self.sec_header).unwrap();
sec_header sec_header
.to_bytes(&mut slice[curr_idx..curr_idx + tc_header_len]) .to_bytes(&mut slice[curr_idx..curr_idx + tc_header_len])
.ok_or(PusError::PacketError(PacketError::ToBytesZeroCopyError))?; .ok_or(PusError::PacketError(ByteConversionError::ZeroCopyToError))?;
curr_idx += tc_header_len; curr_idx += tc_header_len;
if let Some(app_data) = self.app_data { if let Some(app_data) = self.app_data {
@ -408,16 +410,20 @@ impl<'slice> PusTc<'slice> {
let mut current_idx = 0; let mut current_idx = 0;
let sph = let sph =
crate::zc::SpHeader::from_bytes(&slice[current_idx..current_idx + CCSDS_HEADER_LEN]) crate::zc::SpHeader::from_bytes(&slice[current_idx..current_idx + CCSDS_HEADER_LEN])
.ok_or(PusError::PacketError(PacketError::FromBytesZeroCopyError))?; .ok_or(PusError::PacketError(
ByteConversionError::ZeroCopyFromError,
))?;
current_idx += CCSDS_HEADER_LEN; current_idx += CCSDS_HEADER_LEN;
let total_len = sph.total_len(); let total_len = sph.total_len();
if raw_data_len < total_len || total_len < PUS_TC_MIN_LEN_WITHOUT_APP_DATA { if raw_data_len < total_len || total_len < PUS_TC_MIN_LEN_WITHOUT_APP_DATA {
return Err(PusError::RawDataTooShort(raw_data_len)); return Err(PusError::RawDataTooShort(raw_data_len));
} }
let sec_header = crate::tc::zc::PusTcSecondaryHeader::from_bytes( let sec_header = zc::PusTcSecondaryHeader::from_bytes(
&slice[current_idx..current_idx + PUC_TC_SECONDARY_HEADER_LEN], &slice[current_idx..current_idx + PUC_TC_SECONDARY_HEADER_LEN],
) )
.ok_or(PusError::PacketError(PacketError::FromBytesZeroCopyError))?; .ok_or(PusError::PacketError(
ByteConversionError::ZeroCopyFromError,
))?;
current_idx += PUC_TC_SECONDARY_HEADER_LEN; current_idx += PUC_TC_SECONDARY_HEADER_LEN;
let raw_data = &slice[0..total_len]; let raw_data = &slice[0..total_len];
let pus_tc = PusTc { let pus_tc = PusTc {
@ -431,6 +437,10 @@ impl<'slice> PusTc<'slice> {
verify_crc16_from_raw(raw_data, pus_tc.crc16.expect("CRC16 invalid"))?; verify_crc16_from_raw(raw_data, pus_tc.crc16.expect("CRC16 invalid"))?;
Ok((pus_tc, total_len)) Ok((pus_tc, total_len))
} }
pub fn raw(&self) -> Option<&'slice [u8]> {
self.raw_data
}
} }
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
@ -472,8 +482,8 @@ mod tests {
use crate::ecss::{PusError, PusPacket}; use crate::ecss::{PusError, PusPacket};
use crate::tc::ACK_ALL; use crate::tc::ACK_ALL;
use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT}; use crate::tc::{PusTc, PusTcSecondaryHeader, PusTcSecondaryHeaderT};
use crate::{ByteConversionError, SpHeader};
use crate::{CcsdsPacket, SequenceFlags}; use crate::{CcsdsPacket, SequenceFlags};
use crate::{PacketError, SpHeader};
use alloc::vec::Vec; use alloc::vec::Vec;
fn base_ping_tc_full_ctor() -> PusTc<'static> { fn base_ping_tc_full_ctor() -> PusTc<'static> {
@ -627,7 +637,7 @@ mod tests {
let err = res.unwrap_err(); let err = res.unwrap_err();
match err { match err {
PusError::PacketError(err) => match err { PusError::PacketError(err) => match err {
PacketError::ToBytesSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall(missmatch) => {
assert_eq!(missmatch.expected, pus_tc.len_packed()); assert_eq!(missmatch.expected, pus_tc.len_packed());
assert_eq!(missmatch.found, 12); assert_eq!(missmatch.found, 12);
} }

View File

@ -1,5 +1,5 @@
//! CCSDS Time Code Formats according to [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf) //! CCSDS Time Code Formats according to [CCSDS 301.0-B-4](https://public.ccsds.org/Pubs/301x0b4e1.pdf)
use crate::{PacketError, SizeMissmatch}; use crate::{ByteConversionError, SizeMissmatch};
use chrono::{DateTime, TimeZone, Utc}; use chrono::{DateTime, TimeZone, Utc};
#[allow(unused_imports)] #[allow(unused_imports)]
@ -38,12 +38,12 @@ impl TryFrom<u8> for CcsdsTimeCodes {
} }
} }
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum TimestampError { pub enum TimestampError {
/// Contains tuple where first value is the expected time code and the second /// Contains tuple where first value is the expected time code and the second
/// value is the found raw value /// value is the found raw value
InvalidTimeCode(CcsdsTimeCodes, u8), InvalidTimeCode(CcsdsTimeCodes, u8),
OtherPacketError(PacketError), OtherPacketError(ByteConversionError),
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@ -71,7 +71,7 @@ pub const fn ccsds_to_unix_days(ccsds_days: i32) -> i32 {
} }
pub trait TimeWriter { pub trait TimeWriter {
fn write_to_bytes(&self, bytes: &mut [u8]) -> Result<(), PacketError>; fn write_to_bytes(&self, bytes: &mut [u8]) -> Result<(), TimestampError>;
} }
pub trait TimeReader { pub trait TimeReader {
@ -94,7 +94,7 @@ pub trait CcsdsTimeProvider {
fn date_time(&self) -> DateTime<Utc>; fn date_time(&self) -> DateTime<Utc>;
} }
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone, Default)]
pub struct CdsShortTimeProvider { pub struct CdsShortTimeProvider {
pfield: u8, pfield: u8,
ccsds_days: u16, ccsds_days: u16,
@ -125,7 +125,7 @@ impl CdsShortTimeProvider {
let unix_days_seconds = epoch - secs_of_day; let unix_days_seconds = epoch - secs_of_day;
let ms_of_day = secs_of_day * 1000 + now.subsec_millis() as u64; let ms_of_day = secs_of_day * 1000 + now.subsec_millis() as u64;
let provider = Self { let provider = Self {
pfield: (CcsdsTimeCodes::Cds as u8) << 4, pfield: (Cds as u8) << 4,
ccsds_days: unix_to_ccsds_days((unix_days_seconds / SECONDS_PER_DAY as u64) as i32) ccsds_days: unix_to_ccsds_days((unix_days_seconds / SECONDS_PER_DAY as u64) as i32)
as u16, as u16,
ms_of_day: ms_of_day as u32, ms_of_day: ms_of_day as u32,
@ -135,6 +135,17 @@ impl CdsShortTimeProvider {
Ok(provider.setup(unix_days_seconds as i64, ms_of_day)) Ok(provider.setup(unix_days_seconds as i64, ms_of_day))
} }
#[cfg(feature = "std")]
pub fn update_from_now(&mut self) -> Result<(), SystemTimeError> {
let now = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
let epoch = now.as_secs();
let secs_of_day = epoch % SECONDS_PER_DAY as u64;
let unix_days_seconds = epoch - secs_of_day;
let ms_of_day = secs_of_day * 1000 + now.subsec_millis() as u64;
self.setup(unix_days_seconds as i64, ms_of_day);
Ok(())
}
fn setup(mut self, unix_days_seconds: i64, ms_of_day: u64) -> Self { fn setup(mut self, unix_days_seconds: i64, ms_of_day: u64) -> Self {
self.calc_unix_seconds(unix_days_seconds, ms_of_day); self.calc_unix_seconds(unix_days_seconds, ms_of_day);
self.calc_date_time((ms_of_day % 1000) as u32); self.calc_date_time((ms_of_day % 1000) as u32);
@ -194,12 +205,14 @@ impl CcsdsTimeProvider for CdsShortTimeProvider {
} }
impl TimeWriter for CdsShortTimeProvider { impl TimeWriter for CdsShortTimeProvider {
fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), PacketError> { fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), TimestampError> {
if buf.len() < self.len_as_bytes() { if buf.len() < self.len_as_bytes() {
return Err(PacketError::ToBytesSliceTooSmall(SizeMissmatch { return Err(TimestampError::OtherPacketError(
expected: self.len_as_bytes(), ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(), expected: self.len_as_bytes(),
})); found: buf.len(),
}),
));
} }
buf[0] = self.pfield; buf[0] = self.pfield;
buf[1..3].copy_from_slice(self.ccsds_days.to_be_bytes().as_slice()); buf[1..3].copy_from_slice(self.ccsds_days.to_be_bytes().as_slice());
@ -212,7 +225,7 @@ impl TimeReader for CdsShortTimeProvider {
fn from_bytes(buf: &[u8]) -> Result<Self, TimestampError> { fn from_bytes(buf: &[u8]) -> Result<Self, TimestampError> {
if buf.len() < CDS_SHORT_LEN { if buf.len() < CDS_SHORT_LEN {
return Err(TimestampError::OtherPacketError( return Err(TimestampError::OtherPacketError(
PacketError::FromBytesSliceTooSmall(SizeMissmatch { ByteConversionError::FromSliceTooSmall(SizeMissmatch {
expected: CDS_SHORT_LEN, expected: CDS_SHORT_LEN,
found: buf.len(), found: buf.len(),
}), }),
@ -246,7 +259,7 @@ impl TimeReader for CdsShortTimeProvider {
mod tests { mod tests {
use super::*; use super::*;
use crate::time::TimestampError::{InvalidTimeCode, OtherPacketError}; use crate::time::TimestampError::{InvalidTimeCode, OtherPacketError};
use crate::PacketError::{FromBytesSliceTooSmall, ToBytesSliceTooSmall}; use crate::ByteConversionError::{FromSliceTooSmall, ToSliceTooSmall};
use alloc::format; use alloc::format;
use chrono::{Datelike, Timelike}; use chrono::{Datelike, Timelike};
@ -334,7 +347,7 @@ mod tests {
let res = time_stamper.write_to_bytes(&mut buf[0..i]); let res = time_stamper.write_to_bytes(&mut buf[0..i]);
assert!(res.is_err()); assert!(res.is_err());
match res.unwrap_err() { match res.unwrap_err() {
ToBytesSliceTooSmall(missmatch) => { OtherPacketError(ToSliceTooSmall(missmatch)) => {
assert_eq!(missmatch.found, i); assert_eq!(missmatch.found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(missmatch.expected, 7);
} }
@ -357,7 +370,7 @@ mod tests {
panic!("Unexpected error"); panic!("Unexpected error");
} }
OtherPacketError(e) => match e { OtherPacketError(e) => match e {
FromBytesSliceTooSmall(missmatch) => { FromSliceTooSmall(missmatch) => {
assert_eq!(missmatch.found, i); assert_eq!(missmatch.found, i);
assert_eq!(missmatch.expected, 7); assert_eq!(missmatch.expected, 7);
} }

View File

@ -5,7 +5,8 @@ use crate::ecss::{
verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE, verify_crc16_from_raw, CrcType, PusError, PusPacket, PusVersion, CRC_CCITT_FALSE,
}; };
use crate::{ use crate::{
CcsdsPacket, PacketError, PacketType, SequenceFlags, SizeMissmatch, SpHeader, CCSDS_HEADER_LEN, ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, SizeMissmatch, SpHeader,
CCSDS_HEADER_LEN,
}; };
use core::mem::size_of; use core::mem::size_of;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -258,6 +259,10 @@ impl<'slice> PusTm<'slice> {
self.sec_header.time_stamp self.sec_header.time_stamp
} }
pub fn source_data(&self) -> Option<&'slice [u8]> {
self.source_data
}
pub fn set_dest_id(&mut self, dest_id: u16) { pub fn set_dest_id(&mut self, dest_id: u16) {
self.sec_header.dest_id = dest_id; self.sec_header.dest_id = dest_id;
} }
@ -309,7 +314,7 @@ impl<'slice> PusTm<'slice> {
let sph_zc = crate::zc::SpHeader::from(self.sp_header); let sph_zc = crate::zc::SpHeader::from(self.sp_header);
let total_size = self.len_packed(); let total_size = self.len_packed();
if total_size > slice.len() { if total_size > slice.len() {
return Err(PusError::PacketError(PacketError::ToBytesSliceTooSmall( return Err(PusError::PacketError(ByteConversionError::ToSliceTooSmall(
SizeMissmatch { SizeMissmatch {
found: slice.len(), found: slice.len(),
expected: total_size, expected: total_size,
@ -318,14 +323,14 @@ impl<'slice> PusTm<'slice> {
} }
sph_zc sph_zc
.to_bytes(&mut slice[curr_idx..curr_idx + CCSDS_HEADER_LEN]) .to_bytes(&mut slice[curr_idx..curr_idx + CCSDS_HEADER_LEN])
.ok_or(PusError::PacketError(PacketError::ToBytesZeroCopyError))?; .ok_or(PusError::PacketError(ByteConversionError::ZeroCopyToError))?;
curr_idx += CCSDS_HEADER_LEN; curr_idx += CCSDS_HEADER_LEN;
let sec_header_len = size_of::<zc::PusTmSecHeaderWithoutTimestamp>(); let sec_header_len = size_of::<zc::PusTmSecHeaderWithoutTimestamp>();
let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap(); let sec_header = zc::PusTmSecHeaderWithoutTimestamp::try_from(self.sec_header).unwrap();
sec_header sec_header
.to_bytes(&mut slice[curr_idx..curr_idx + sec_header_len]) .to_bytes(&mut slice[curr_idx..curr_idx + sec_header_len])
.ok_or(PusError::PacketError(PacketError::ToBytesZeroCopyError))?; .ok_or(PusError::PacketError(ByteConversionError::ZeroCopyToError))?;
curr_idx += sec_header_len; curr_idx += sec_header_len;
let timestamp_len = self.sec_header.time_stamp.len(); let timestamp_len = self.sec_header.time_stamp.len();
slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(self.sec_header.time_stamp); slice[curr_idx..curr_idx + timestamp_len].copy_from_slice(self.sec_header.time_stamp);
@ -394,7 +399,9 @@ impl<'slice> PusTm<'slice> {
let mut current_idx = 0; let mut current_idx = 0;
let sph = let sph =
crate::zc::SpHeader::from_bytes(&slice[current_idx..current_idx + CCSDS_HEADER_LEN]) crate::zc::SpHeader::from_bytes(&slice[current_idx..current_idx + CCSDS_HEADER_LEN])
.ok_or(PusError::PacketError(PacketError::FromBytesZeroCopyError))?; .ok_or(PusError::PacketError(
ByteConversionError::ZeroCopyFromError,
))?;
current_idx += 6; current_idx += 6;
let total_len = sph.total_len(); let total_len = sph.total_len();
if raw_data_len < total_len || total_len < PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA { if raw_data_len < total_len || total_len < PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA {
@ -403,7 +410,9 @@ impl<'slice> PusTm<'slice> {
let sec_header_zc = zc::PusTmSecHeaderWithoutTimestamp::from_bytes( let sec_header_zc = zc::PusTmSecHeaderWithoutTimestamp::from_bytes(
&slice[current_idx..current_idx + PUC_TM_MIN_SEC_HEADER_LEN], &slice[current_idx..current_idx + PUC_TM_MIN_SEC_HEADER_LEN],
) )
.ok_or(PusError::PacketError(PacketError::FromBytesZeroCopyError))?; .ok_or(PusError::PacketError(
ByteConversionError::ZeroCopyFromError,
))?;
current_idx += PUC_TM_MIN_SEC_HEADER_LEN; current_idx += PUC_TM_MIN_SEC_HEADER_LEN;
let zc_sec_header_wrapper = zc::PusTmSecHeader { let zc_sec_header_wrapper = zc::PusTmSecHeader {
zc_header: sec_header_zc, zc_header: sec_header_zc,
@ -568,7 +577,7 @@ mod tests {
assert!(matches!(error, PusError::PacketError { .. })); assert!(matches!(error, PusError::PacketError { .. }));
match error { match error {
PusError::PacketError(err) => match err { PusError::PacketError(err) => match err {
PacketError::ToBytesSliceTooSmall(size_missmatch) => { ByteConversionError::ToSliceTooSmall(size_missmatch) => {
assert_eq!(size_missmatch.expected, 22); assert_eq!(size_missmatch.expected, 22);
assert_eq!(size_missmatch.found, 16); assert_eq!(size_missmatch.found, 16);
} }