Update #48

Merged
muellerr merged 4 commits from large-update into main 2023-07-06 00:51:08 +02:00
19 changed files with 326 additions and 231 deletions

View File

@ -57,11 +57,10 @@ default-features = false
optional = true optional = true
[dependencies.spacepackets] [dependencies.spacepackets]
version = "0.5.4" # version = "0.5.4"
# path = "../spacepackets" # path = "../spacepackets"
# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git" git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
# rev = "" rev = "ef4244c8cb5c"
default-features = false default-features = false
[dev-dependencies] [dev-dependencies]

View File

@ -31,7 +31,8 @@ use core::fmt::Debug;
use core::hash::Hash; use core::hash::Hash;
use core::marker::PhantomData; use core::marker::PhantomData;
use delegate::delegate; use delegate::delegate;
use spacepackets::ecss::{EcssEnumeration, ToBeBytes}; use spacepackets::ecss::EcssEnumeration;
use spacepackets::util::{ToBeBytes, UnsignedEnum};
use spacepackets::{ByteConversionError, SizeMissmatch}; use spacepackets::{ByteConversionError, SizeMissmatch};
/// Using a type definition allows to change this to u64 in the future more easily /// Using a type definition allows to change this to u64 in the future more easily
@ -121,7 +122,7 @@ impl<RAW: ToBeBytes, GID, UID> EventBase<RAW, GID, UID> {
raw: RAW, raw: RAW,
buf: &mut [u8], buf: &mut [u8],
width: usize, width: usize,
) -> Result<(), ByteConversionError> { ) -> Result<usize, ByteConversionError> {
if buf.len() < width { if buf.len() < width {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(), found: buf.len(),
@ -129,7 +130,7 @@ impl<RAW: ToBeBytes, GID, UID> EventBase<RAW, GID, UID> {
})); }));
} }
buf.copy_from_slice(raw.to_be_bytes().as_ref()); buf.copy_from_slice(raw.to_be_bytes().as_ref());
Ok(()) Ok(raw.written_len())
} }
} }
@ -403,21 +404,34 @@ try_from_impls!(SeverityLow, Severity::LOW, u32, EventU32TypedSev);
try_from_impls!(SeverityMedium, Severity::MEDIUM, u32, EventU32TypedSev); try_from_impls!(SeverityMedium, Severity::MEDIUM, u32, EventU32TypedSev);
try_from_impls!(SeverityHigh, Severity::HIGH, u32, EventU32TypedSev); try_from_impls!(SeverityHigh, Severity::HIGH, u32, EventU32TypedSev);
impl EcssEnumeration for EventU32 { impl UnsignedEnum for EventU32 {
fn pfc(&self) -> u8 { fn size(&self) -> usize {
32 core::mem::size_of::<u32>()
} }
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
self.base.write_to_bytes(self.raw(), buf, self.byte_width()) self.base.write_to_bytes(self.raw(), buf, self.size())
} }
} }
impl EcssEnumeration for EventU32 {
fn pfc(&self) -> u8 {
u32::BITS as u8
}
}
//noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> UnsignedEnum for EventU32TypedSev<SEVERITY> {
delegate!(to self.event {
fn size(&self) -> usize;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
});
}
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> EcssEnumeration for EventU32TypedSev<SEVERITY> { impl<SEVERITY: HasSeverity> EcssEnumeration for EventU32TypedSev<SEVERITY> {
delegate!(to self.event { delegate!(to self.event {
fn pfc(&self) -> u8; fn pfc(&self) -> u8;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
}); });
} }
@ -538,22 +552,34 @@ impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8); impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
impl UnsignedEnum for EventU16 {
fn size(&self) -> usize {
core::mem::size_of::<u16>()
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
self.base.write_to_bytes(self.raw(), buf, self.size())
}
}
impl EcssEnumeration for EventU16 { impl EcssEnumeration for EventU16 {
#[inline] #[inline]
fn pfc(&self) -> u8 { fn pfc(&self) -> u8 {
16 u16::BITS as u8
} }
}
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { //noinspection RsTraitImplementation
self.base.write_to_bytes(self.raw(), buf, self.byte_width()) impl<SEVERITY: HasSeverity> UnsignedEnum for EventU16TypedSev<SEVERITY> {
} delegate!(to self.event {
fn size(&self) -> usize;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError>;
});
} }
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> EcssEnumeration for EventU16TypedSev<SEVERITY> { impl<SEVERITY: HasSeverity> EcssEnumeration for EventU16TypedSev<SEVERITY> {
delegate!(to self.event { delegate!(to self.event {
fn pfc(&self) -> u8; fn pfc(&self) -> u8;
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
}); });
} }

View File

@ -52,13 +52,14 @@ use alloc::vec::Vec;
use core::fmt::Debug; use core::fmt::Debug;
use core::mem::size_of; use core::mem::size_of;
use paste::paste; use paste::paste;
use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8, EcssEnumeration}; use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8};
use spacepackets::util::UnsignedEnum;
use spacepackets::ByteConversionError; use spacepackets::ByteConversionError;
use spacepackets::SizeMissmatch; use spacepackets::SizeMissmatch;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub use alloc_mod::*; pub use alloc_mod::*;
pub use spacepackets::ecss::ToBeBytes; pub use spacepackets::util::ToBeBytes;
/// Generic trait which is used for objects which can be converted into a raw network (big) endian /// Generic trait which is used for objects which can be converted into a raw network (big) endian
/// byte format. /// byte format.
@ -170,6 +171,11 @@ macro_rules! scalar_byte_conversions_impl {
paste! { paste! {
impl ToBeBytes for [<$ty:upper>] { impl ToBeBytes for [<$ty:upper>] {
type ByteArray = [u8; size_of::<$ty>()]; type ByteArray = [u8; size_of::<$ty>()];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
self.0.to_be_bytes() self.0.to_be_bytes()
} }
@ -199,6 +205,11 @@ macro_rules! pair_byte_conversions_impl {
paste! { paste! {
impl ToBeBytes for [<$ty:upper Pair>] { impl ToBeBytes for [<$ty:upper Pair>] {
type ByteArray = [u8; size_of::<$ty>() * 2]; type ByteArray = [u8; size_of::<$ty>() * 2];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; size_of::<$ty>() * 2]; let mut array = [0; size_of::<$ty>() * 2];
array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes()); array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
@ -236,6 +247,11 @@ macro_rules! triplet_to_be_bytes_impl {
paste! { paste! {
impl ToBeBytes for [<$ty:upper Triplet>] { impl ToBeBytes for [<$ty:upper Triplet>] {
type ByteArray = [u8; size_of::<$ty>() * 3]; type ByteArray = [u8; size_of::<$ty>() * 3];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; size_of::<$ty>() * 3]; let mut array = [0; size_of::<$ty>() * 3];
array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes()); array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
@ -275,6 +291,10 @@ scalar_byte_conversions_impl!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,);
impl ToBeBytes for U8Pair { impl ToBeBytes for U8Pair {
type ByteArray = [u8; 2]; type ByteArray = [u8; 2];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; 2]; let mut array = [0; 2];
array[0] = self.0; array[0] = self.0;
@ -286,6 +306,10 @@ impl ToBeBytes for U8Pair {
impl ToBeBytes for I8Pair { impl ToBeBytes for I8Pair {
type ByteArray = [u8; 2]; type ByteArray = [u8; 2];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; 2]; let mut array = [0; 2];
array[0] = self.0 as u8; array[0] = self.0 as u8;
@ -297,6 +321,10 @@ impl ToBeBytes for I8Pair {
impl ToBeBytes for U8Triplet { impl ToBeBytes for U8Triplet {
type ByteArray = [u8; 3]; type ByteArray = [u8; 3];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; 3]; let mut array = [0; 3];
array[0] = self.0; array[0] = self.0;
@ -309,6 +337,10 @@ impl ToBeBytes for U8Triplet {
impl ToBeBytes for I8Triplet { impl ToBeBytes for I8Triplet {
type ByteArray = [u8; 3]; type ByteArray = [u8; 3];
fn written_len(&self) -> usize {
size_of::<Self::ByteArray>()
}
fn to_be_bytes(&self) -> Self::ByteArray { fn to_be_bytes(&self) -> Self::ByteArray {
let mut array = [0; 3]; let mut array = [0; 3];
array[0] = self.0 as u8; array[0] = self.0 as u8;
@ -443,11 +475,11 @@ macro_rules! writable_as_be_bytes_ecss_enum_impl {
($EnumIdent: ident) => { ($EnumIdent: ident) => {
impl WritableToBeBytes for $EnumIdent { impl WritableToBeBytes for $EnumIdent {
fn raw_len(&self) -> usize { fn raw_len(&self) -> usize {
self.byte_width() self.size()
} }
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> { fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
EcssEnumeration::write_to_be_bytes(self, buf).map(|_| self.byte_width()) <Self as UnsignedEnum>::write_to_be_bytes(self, buf).map(|_| self.raw_len())
} }
} }
}; };
@ -461,10 +493,10 @@ writable_as_be_bytes_ecss_enum_impl!(EcssEnumU64);
impl WritableToBeBytes for EcssEnumParams { impl WritableToBeBytes for EcssEnumParams {
fn raw_len(&self) -> usize { fn raw_len(&self) -> usize {
match self { match self {
EcssEnumParams::U8(e) => e.byte_width(), EcssEnumParams::U8(e) => e.raw_len(),
EcssEnumParams::U16(e) => e.byte_width(), EcssEnumParams::U16(e) => e.raw_len(),
EcssEnumParams::U32(e) => e.byte_width(), EcssEnumParams::U32(e) => e.raw_len(),
EcssEnumParams::U64(e) => e.byte_width(), EcssEnumParams::U64(e) => e.raw_len(),
} }
} }

View File

@ -1,4 +1,4 @@
use crate::pus::{source_buffer_large_enough, EcssTmError, EcssTmErrorWithSend}; use crate::pus::{source_buffer_large_enough, EcssTmtcError, EcssTmtcErrorWithSend};
use spacepackets::ecss::EcssEnumeration; use spacepackets::ecss::EcssEnumeration;
use spacepackets::tm::PusTm; use spacepackets::tm::PusTm;
use spacepackets::tm::PusTmSecondaryHeader; use spacepackets::tm::PusTmSecondaryHeader;
@ -34,7 +34,7 @@ impl EventReporterBase {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.generate_and_send_generic_tm( self.generate_and_send_generic_tm(
buf, buf,
Subservice::TmInfoReport, Subservice::TmInfoReport,
@ -52,7 +52,7 @@ impl EventReporterBase {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.generate_and_send_generic_tm( self.generate_and_send_generic_tm(
buf, buf,
Subservice::TmLowSeverityReport, Subservice::TmLowSeverityReport,
@ -70,7 +70,7 @@ impl EventReporterBase {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.generate_and_send_generic_tm( self.generate_and_send_generic_tm(
buf, buf,
Subservice::TmMediumSeverityReport, Subservice::TmMediumSeverityReport,
@ -88,7 +88,7 @@ impl EventReporterBase {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.generate_and_send_generic_tm( self.generate_and_send_generic_tm(
buf, buf,
Subservice::TmHighSeverityReport, Subservice::TmHighSeverityReport,
@ -107,11 +107,11 @@ impl EventReporterBase {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?; let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?;
sender sender
.send_tm(tm) .send_tm(tm)
.map_err(|e| EcssTmErrorWithSend::SendError(e))?; .map_err(|e| EcssTmtcErrorWithSend::SendError(e))?;
self.msg_count += 1; self.msg_count += 1;
Ok(()) Ok(())
} }
@ -123,8 +123,8 @@ impl EventReporterBase {
time_stamp: &'a [u8], time_stamp: &'a [u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<PusTm, EcssTmError> { ) -> Result<PusTm, EcssTmtcError> {
let mut src_data_len = event_id.byte_width(); let mut src_data_len = event_id.size();
if let Some(aux_data) = aux_data { if let Some(aux_data) = aux_data {
src_data_len += aux_data.len(); src_data_len += aux_data.len();
} }
@ -138,8 +138,8 @@ impl EventReporterBase {
Some(time_stamp), Some(time_stamp),
); );
let mut current_idx = 0; let mut current_idx = 0;
event_id.write_to_be_bytes(&mut buf[0..event_id.byte_width()])?; event_id.write_to_be_bytes(&mut buf[0..event_id.size()])?;
current_idx += event_id.byte_width(); current_idx += event_id.size();
if let Some(aux_data) = aux_data { if let Some(aux_data) = aux_data {
buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data); buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
current_idx += aux_data.len(); current_idx += aux_data.len();
@ -178,7 +178,7 @@ mod allocvec {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.reporter.event_info( self.reporter.event_info(
self.source_data_buf.as_mut_slice(), self.source_data_buf.as_mut_slice(),
sender, sender,
@ -194,7 +194,7 @@ mod allocvec {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.reporter.event_low_severity( self.reporter.event_low_severity(
self.source_data_buf.as_mut_slice(), self.source_data_buf.as_mut_slice(),
sender, sender,
@ -210,7 +210,7 @@ mod allocvec {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.reporter.event_medium_severity( self.reporter.event_medium_severity(
self.source_data_buf.as_mut_slice(), self.source_data_buf.as_mut_slice(),
sender, sender,
@ -226,7 +226,7 @@ mod allocvec {
time_stamp: &[u8], time_stamp: &[u8],
event_id: impl EcssEnumeration, event_id: impl EcssEnumeration,
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.reporter.event_high_severity( self.reporter.event_high_severity(
self.source_data_buf.as_mut_slice(), self.source_data_buf.as_mut_slice(),
sender, sender,
@ -413,7 +413,7 @@ mod tests {
let err = reporter.event_info(sender, &time_stamp_empty, event, None); let err = reporter.event_info(sender, &time_stamp_empty, event, None);
assert!(err.is_err()); assert!(err.is_err());
let err = err.unwrap_err(); let err = err.unwrap_err();
if let EcssTmErrorWithSend::EcssTmError(EcssTmError::ByteConversionError( if let EcssTmErrorWithSend::EcssTmError(EcssTmtcError::ByteConversionError(
ByteConversionError::ToSliceTooSmall(missmatch), ByteConversionError::ToSliceTooSmall(missmatch),
)) = err )) = err
{ {

View File

@ -11,9 +11,9 @@ use hashbrown::HashSet;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub use crate::pus::event::EventReporter; pub use crate::pus::event::EventReporter;
use crate::pus::verification::{TcStateStarted, VerificationToken}; use crate::pus::verification::{TcStateStarted, VerificationToken};
use crate::pus::EcssTmErrorWithSend;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use crate::pus::EcssTmSenderCore; use crate::pus::EcssTmSenderCore;
use crate::pus::EcssTmtcErrorWithSend;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub use alloc_mod::*; pub use alloc_mod::*;
@ -96,13 +96,13 @@ pub struct EventRequestWithToken<Event: GenericEvent = EventU32> {
#[derive(Debug)] #[derive(Debug)]
pub enum EventManError<SenderE> { pub enum EventManError<SenderE> {
EcssTmError(EcssTmErrorWithSend<SenderE>), EcssTmtcError(EcssTmtcErrorWithSend<SenderE>),
SeverityMissmatch(Severity, Severity), SeverityMissmatch(Severity, Severity),
} }
impl<SenderE> From<EcssTmErrorWithSend<SenderE>> for EventManError<SenderE> { impl<SenderE> From<EcssTmtcErrorWithSend<SenderE>> for EventManError<SenderE> {
fn from(v: EcssTmErrorWithSend<SenderE>) -> Self { fn from(v: EcssTmtcErrorWithSend<SenderE>) -> Self {
Self::EcssTmError(v) Self::EcssTmtcError(v)
} }
} }

View File

@ -4,6 +4,7 @@ use downcast_rs::{impl_downcast, Downcast};
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use dyn_clone::DynClone; use dyn_clone::DynClone;
use spacepackets::ecss::PusError; use spacepackets::ecss::PusError;
use spacepackets::tc::PusTc;
use spacepackets::time::TimestampError; use spacepackets::time::TimestampError;
use spacepackets::tm::PusTm; use spacepackets::tm::PusTm;
use spacepackets::{ByteConversionError, SizeMissmatch}; use spacepackets::{ByteConversionError, SizeMissmatch};
@ -24,21 +25,21 @@ use crate::SenderId;
pub use std_mod::*; pub use std_mod::*;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum EcssTmErrorWithSend<E> { pub enum EcssTmtcErrorWithSend<E> {
/// Errors related to sending the telemetry to a TM recipient /// Errors related to sending the telemetry to a TMTC recipient
SendError(E), SendError(E),
EcssTmError(EcssTmError), EcssTmtcError(EcssTmtcError),
} }
impl<E> From<EcssTmError> for EcssTmErrorWithSend<E> { impl<E> From<EcssTmtcError> for EcssTmtcErrorWithSend<E> {
fn from(value: EcssTmError) -> Self { fn from(value: EcssTmtcError) -> Self {
Self::EcssTmError(value) Self::EcssTmtcError(value)
} }
} }
/// Generic error type for PUS TM handling. /// Generic error type for PUS TM handling.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum EcssTmError { pub enum EcssTmtcError {
/// Errors related to the time stamp format of the telemetry /// Errors related to the time stamp format of the telemetry
TimestampError(TimestampError), TimestampError(TimestampError),
/// Errors related to byte conversion, for example insufficient buffer size for given data /// Errors related to byte conversion, for example insufficient buffer size for given data
@ -47,30 +48,41 @@ pub enum EcssTmError {
PusError(PusError), PusError(PusError),
} }
impl From<PusError> for EcssTmError { impl From<PusError> for EcssTmtcError {
fn from(e: PusError) -> Self { fn from(e: PusError) -> Self {
EcssTmError::PusError(e) EcssTmtcError::PusError(e)
} }
} }
impl From<ByteConversionError> for EcssTmError { impl From<ByteConversionError> for EcssTmtcError {
fn from(e: ByteConversionError) -> Self { fn from(e: ByteConversionError) -> Self {
EcssTmError::ByteConversionError(e) EcssTmtcError::ByteConversionError(e)
} }
} }
pub trait EcssSender: Send {
/// Each sender can have an ID associated with it
fn id(&self) -> SenderId;
fn name(&self) -> &'static str {
"unset"
}
}
/// Generic trait for a user supplied sender object.
///
/// This sender object is responsible for sending PUS telemetry to a TM sink.
pub trait EcssTmSenderCore: EcssSender {
type Error;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>;
}
/// Generic trait for a user supplied sender object. /// Generic trait for a user supplied sender object.
/// ///
/// This sender object is responsible for sending telemetry to a TM sink. /// This sender object is responsible for sending PUS telecommands to a TC recipient.
pub trait EcssTmSenderCore: Send { pub trait EcssTcSenderCore: EcssSender {
type Error; type Error;
/// Each sender can have an ID associated with it fn send_tc(&mut self, tc: PusTc) -> Result<(), Self::Error>;
fn id(&self) -> SenderId;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>;
fn name(&self) -> &'static str {
"unset"
}
} }
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@ -96,15 +108,36 @@ mod alloc_mod {
dyn_clone::clone_trait_object!(<T> EcssTmSender<Error=T>); dyn_clone::clone_trait_object!(<T> EcssTmSender<Error=T>);
impl_downcast!(EcssTmSender assoc Error); impl_downcast!(EcssTmSender assoc Error);
/// Extension trait for [EcssTcSenderCore].
///
/// It provides additional functionality, for example by implementing the [Downcast] trait
/// and the [DynClone] trait.
///
/// [Downcast] is implemented to allow passing the sender as a boxed trait object and still
/// retrieve the concrete type at a later point.
///
/// [DynClone] allows cloning the trait object as long as the boxed object implements
/// [Clone].
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub trait EcssTcSender: EcssTcSenderCore + Downcast + DynClone {}
/// Blanket implementation for all types which implement [EcssTcSenderCore] and are clonable.
impl<T> EcssTcSender for T where T: EcssTcSenderCore + Clone + 'static {}
dyn_clone::clone_trait_object!(<T> EcssTcSender<Error=T>);
impl_downcast!(EcssTcSender assoc Error);
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub mod std_mod { pub mod std_mod {
use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError}; use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr, StoreError};
use crate::pus::EcssTmSenderCore; use crate::pus::{EcssSender, EcssTcSenderCore, EcssTmSenderCore};
use crate::SenderId; use crate::SenderId;
use alloc::vec::Vec; use alloc::vec::Vec;
use spacepackets::ecss::PusError; use spacepackets::ecss::{PusError, SerializablePusPacket};
use spacepackets::tc::PusTc;
use spacepackets::tm::PusTm; use spacepackets::tm::PusTm;
use std::sync::mpsc::SendError; use std::sync::mpsc::SendError;
use std::sync::{mpsc, RwLockWriteGuard}; use std::sync::{mpsc, RwLockWriteGuard};
@ -135,7 +168,7 @@ pub mod std_mod {
} }
#[derive(Clone)] #[derive(Clone)]
pub struct MpscTmInStoreSender { pub struct MpscTmtcInStoreSender {
id: SenderId, id: SenderId,
name: &'static str, name: &'static str,
store_helper: SharedPool, store_helper: SharedPool,
@ -143,13 +176,19 @@ pub mod std_mod {
pub ignore_poison_errors: bool, pub ignore_poison_errors: bool,
} }
impl EcssTmSenderCore for MpscTmInStoreSender { impl EcssSender for MpscTmtcInStoreSender {
type Error = MpscPusInStoreSendError;
fn id(&self) -> SenderId { fn id(&self) -> SenderId {
self.id self.id
} }
fn name(&self) -> &'static str {
self.name
}
}
impl EcssTmSenderCore for MpscTmtcInStoreSender {
type Error = MpscPusInStoreSendError;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> { fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> {
let operation = |mut store: RwLockWriteGuard<ShareablePoolProvider>| { let operation = |mut store: RwLockWriteGuard<ShareablePoolProvider>| {
let (addr, slice) = store.free_element(tm.len_packed())?; let (addr, slice) = store.free_element(tm.len_packed())?;
@ -168,13 +207,32 @@ pub mod std_mod {
} }
} }
} }
}
fn name(&self) -> &'static str { impl EcssTcSenderCore for MpscTmtcInStoreSender {
self.name type Error = MpscPusInStoreSendError;
fn send_tc(&mut self, tc: PusTc) -> Result<(), Self::Error> {
let operation = |mut store: RwLockWriteGuard<ShareablePoolProvider>| {
let (addr, slice) = store.free_element(tc.len_packed())?;
tc.write_to_bytes(slice)?;
self.sender.send(addr)?;
Ok(())
};
match self.store_helper.write() {
Ok(pool) => operation(pool),
Err(e) => {
if self.ignore_poison_errors {
operation(e.into_inner())
} else {
Err(MpscPusInStoreSendError::LockError)
}
}
}
} }
} }
impl MpscTmInStoreSender { impl MpscTmtcInStoreSender {
pub fn new( pub fn new(
id: SenderId, id: SenderId,
name: &'static str, name: &'static str,
@ -209,11 +267,18 @@ pub mod std_mod {
Self { id, sender, name } Self { id, sender, name }
} }
} }
impl EcssTmSenderCore for MpscTmAsVecSender {
type Error = MpscAsVecSenderError; impl EcssSender for MpscTmAsVecSender {
fn id(&self) -> SenderId { fn id(&self) -> SenderId {
self.id self.id
} }
fn name(&self) -> &'static str {
self.name
}
}
impl EcssTmSenderCore for MpscTmAsVecSender {
type Error = MpscAsVecSenderError;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> { fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> {
let mut vec = Vec::new(); let mut vec = Vec::new();
@ -224,10 +289,6 @@ pub mod std_mod {
.map_err(MpscAsVecSenderError::SendError)?; .map_err(MpscAsVecSenderError::SendError)?;
Ok(()) Ok(())
} }
fn name(&self) -> &'static str {
self.name
}
} }
} }
@ -237,9 +298,9 @@ pub enum GenericTcCheckError {
InvalidSubservice, InvalidSubservice,
} }
pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmError> { pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> {
if len > cap { if len > cap {
return Err(EcssTmError::ByteConversionError( return Err(EcssTmtcError::ByteConversionError(
ByteConversionError::ToSliceTooSmall(SizeMissmatch { ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: cap, found: cap,
expected: len, expected: len,

View File

@ -73,7 +73,7 @@
//! for the verification module contains examples how this module could be used in a more complex //! for the verification module contains examples how this module could be used in a more complex
//! context involving multiple threads //! context involving multiple threads
use crate::pus::{ use crate::pus::{
source_buffer_large_enough, EcssTmError, EcssTmErrorWithSend, EcssTmSenderCore, source_buffer_large_enough, EcssTmSenderCore, EcssTmtcError, EcssTmtcErrorWithSend,
GenericTcCheckError, GenericTcCheckError,
}; };
use core::fmt::{Debug, Display, Formatter}; use core::fmt::{Debug, Display, Formatter};
@ -179,12 +179,12 @@ impl RequestId {
/// re-trying the operation at a later point. /// re-trying the operation at a later point.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VerificationOrSendErrorWithToken<E, T>( pub struct VerificationOrSendErrorWithToken<E, T>(
pub EcssTmErrorWithSend<E>, pub EcssTmtcErrorWithSend<E>,
pub VerificationToken<T>, pub VerificationToken<T>,
); );
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct VerificationErrorWithToken<T>(pub EcssTmError, pub VerificationToken<T>); pub struct VerificationErrorWithToken<T>(pub EcssTmtcError, pub VerificationToken<T>);
impl<E, T> From<VerificationErrorWithToken<T>> for VerificationOrSendErrorWithToken<E, T> { impl<E, T> From<VerificationErrorWithToken<T>> for VerificationOrSendErrorWithToken<E, T> {
fn from(value: VerificationErrorWithToken<T>) -> Self { fn from(value: VerificationErrorWithToken<T>) -> Self {
@ -543,7 +543,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -561,7 +561,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -630,7 +630,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -674,7 +674,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -693,7 +693,7 @@ impl VerificationReporterCore {
msg_counter: &(impl SequenceCountProviderCore<u16> + ?Sized), msg_counter: &(impl SequenceCountProviderCore<u16> + ?Sized),
time_stamp: Option<&'src_data [u8]>, time_stamp: Option<&'src_data [u8]>,
step: impl EcssEnumeration, step: impl EcssEnumeration,
) -> Result<VerificationSendable<'src_data, TcStateStarted, VerifSuccess>, EcssTmError> { ) -> Result<VerificationSendable<'src_data, TcStateStarted, VerifSuccess>, EcssTmtcError> {
Ok(VerificationSendable::new_no_token( Ok(VerificationSendable::new_no_token(
self.create_pus_verif_success_tm( self.create_pus_verif_success_tm(
src_data_buf, src_data_buf,
@ -799,7 +799,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -818,7 +818,7 @@ impl VerificationReporterCore {
.send_tm(sendable.pus_tm.take().unwrap()) .send_tm(sendable.pus_tm.take().unwrap())
.map_err(|e| { .map_err(|e| {
VerificationOrSendErrorWithToken( VerificationOrSendErrorWithToken(
EcssTmErrorWithSend::SendError(e), EcssTmtcErrorWithSend::SendError(e),
sendable.token.unwrap(), sendable.token.unwrap(),
) )
})?; })?;
@ -837,10 +837,10 @@ impl VerificationReporterCore {
req_id: &RequestId, req_id: &RequestId,
time_stamp: Option<&'src_data [u8]>, time_stamp: Option<&'src_data [u8]>,
step: Option<&(impl EcssEnumeration + ?Sized)>, step: Option<&(impl EcssEnumeration + ?Sized)>,
) -> Result<PusTm<'src_data>, EcssTmError> { ) -> Result<PusTm<'src_data>, EcssTmtcError> {
let mut source_data_len = size_of::<u32>(); let mut source_data_len = size_of::<u32>();
if let Some(step) = step { if let Some(step) = step {
source_data_len += step.byte_width(); source_data_len += step.size();
} }
source_buffer_large_enough(src_data_buf.len(), source_data_len)?; source_buffer_large_enough(src_data_buf.len(), source_data_len)?;
let mut idx = 0; let mut idx = 0;
@ -848,7 +848,7 @@ impl VerificationReporterCore {
idx += RequestId::SIZE_AS_BYTES; idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step { if let Some(step) = step {
// Size check was done beforehand // Size check was done beforehand
step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.byte_width()]) step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.size()])
.unwrap(); .unwrap();
} }
let mut sp_header = SpHeader::tm_unseg(self.apid(), seq_count, 0).unwrap(); let mut sp_header = SpHeader::tm_unseg(self.apid(), seq_count, 0).unwrap();
@ -873,11 +873,11 @@ impl VerificationReporterCore {
req_id: &RequestId, req_id: &RequestId,
step: Option<&(impl EcssEnumeration + ?Sized)>, step: Option<&(impl EcssEnumeration + ?Sized)>,
params: &FailParams<'src_data, '_>, params: &FailParams<'src_data, '_>,
) -> Result<PusTm<'src_data>, EcssTmError> { ) -> Result<PusTm<'src_data>, EcssTmtcError> {
let mut idx = 0; let mut idx = 0;
let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.byte_width(); let mut source_data_len = RequestId::SIZE_AS_BYTES + params.failure_code.size();
if let Some(step) = step { if let Some(step) = step {
source_data_len += step.byte_width(); source_data_len += step.size();
} }
if let Some(failure_data) = params.failure_data { if let Some(failure_data) = params.failure_data {
source_data_len += failure_data.len(); source_data_len += failure_data.len();
@ -887,14 +887,14 @@ impl VerificationReporterCore {
idx += RequestId::SIZE_AS_BYTES; idx += RequestId::SIZE_AS_BYTES;
if let Some(step) = step { if let Some(step) = step {
// Size check done beforehand // Size check done beforehand
step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.byte_width()]) step.write_to_be_bytes(&mut src_data_buf[idx..idx + step.size()])
.unwrap(); .unwrap();
idx += step.byte_width(); idx += step.size();
} }
params params
.failure_code .failure_code
.write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.byte_width()])?; .write_to_be_bytes(&mut src_data_buf[idx..idx + params.failure_code.size()])?;
idx += params.failure_code.byte_width(); idx += params.failure_code.size();
if let Some(failure_data) = params.failure_data { if let Some(failure_data) = params.failure_data {
src_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data); src_data_buf[idx..idx + failure_data.len()].copy_from_slice(failure_data);
} }
@ -1121,7 +1121,7 @@ mod alloc_mod {
sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized), sender: &mut (impl EcssTmSenderCore<Error = E> + ?Sized),
time_stamp: Option<&[u8]>, time_stamp: Option<&[u8]>,
step: impl EcssEnumeration, step: impl EcssEnumeration,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
let sendable = self.reporter.step_success( let sendable = self.reporter.step_success(
self.source_data_buf.as_mut_slice(), self.source_data_buf.as_mut_slice(),
token, token,
@ -1298,7 +1298,7 @@ mod alloc_mod {
token: &VerificationToken<TcStateStarted>, token: &VerificationToken<TcStateStarted>,
time_stamp: Option<&[u8]>, time_stamp: Option<&[u8]>,
step: impl EcssEnumeration, step: impl EcssEnumeration,
) -> Result<(), EcssTmErrorWithSend<E>> { ) -> Result<(), EcssTmtcErrorWithSend<E>> {
self.reporter self.reporter
.step_success(token, self.sender.as_mut(), time_stamp, step) .step_success(token, self.sender.as_mut(), time_stamp, step)
} }
@ -1337,9 +1337,10 @@ mod stdmod {
use super::alloc_mod::VerificationReporterWithSender; use super::alloc_mod::VerificationReporterWithSender;
use super::*; use super::*;
use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr}; use crate::pool::{ShareablePoolProvider, SharedPool, StoreAddr};
use crate::pus::MpscPusInStoreSendError; use crate::pus::{EcssSender, MpscPusInStoreSendError};
use crate::SenderId; use crate::SenderId;
use delegate::delegate; use delegate::delegate;
use spacepackets::ecss::SerializablePusPacket;
use spacepackets::tm::PusTm; use spacepackets::tm::PusTm;
use std::sync::{mpsc, Arc, Mutex, RwLockWriteGuard}; use std::sync::{mpsc, Arc, Mutex, RwLockWriteGuard};
@ -1400,14 +1401,22 @@ mod stdmod {
} }
} }
//noinspection RsTraitImplementation
impl EcssSender for MpscVerifSender {
delegate!(
to self.base {
fn id(&self) -> SenderId;
fn name(&self) -> &'static str;
}
);
}
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
impl EcssTmSenderCore for MpscVerifSender { impl EcssTmSenderCore for MpscVerifSender {
type Error = MpscPusInStoreSendError; type Error = MpscPusInStoreSendError;
delegate!( delegate!(
to self.base { to self.base {
fn id(&self) -> SenderId;
fn name(&self) -> &'static str;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>; fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>;
} }
); );
@ -1441,6 +1450,17 @@ mod stdmod {
} }
} }
//noinspection RsTraitImplementation
#[cfg(feature = "crossbeam")]
impl EcssSender for CrossbeamVerifSender {
delegate!(
to self.base {
fn id(&self) -> SenderId;
fn name(&self) -> &'static str;
}
);
}
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
#[cfg(feature = "crossbeam")] #[cfg(feature = "crossbeam")]
impl EcssTmSenderCore for CrossbeamVerifSender { impl EcssTmSenderCore for CrossbeamVerifSender {
@ -1448,19 +1468,21 @@ mod stdmod {
delegate!( delegate!(
to self.base { to self.base {
fn id(&self) -> SenderId;
fn name(&self) -> &'static str;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>; fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error>;
} }
); );
} }
impl<S: SendBackend + Clone + 'static> EcssTmSenderCore for StdSenderBase<S> { impl<S: SendBackend + Clone + 'static> EcssSender for StdSenderBase<S> {
type Error = MpscPusInStoreSendError;
fn id(&self) -> SenderId { fn id(&self) -> SenderId {
self.id self.id
} }
fn name(&self) -> &'static str {
self.name
}
}
impl<S: SendBackend + Clone + 'static> EcssTmSenderCore for StdSenderBase<S> {
type Error = MpscPusInStoreSendError;
fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> { fn send_tm(&mut self, tm: PusTm) -> Result<(), Self::Error> {
let operation = |mut mg: RwLockWriteGuard<ShareablePoolProvider>| { let operation = |mut mg: RwLockWriteGuard<ShareablePoolProvider>| {
@ -1484,10 +1506,6 @@ mod stdmod {
} }
} }
} }
fn name(&self) -> &'static str {
self.name
}
} }
} }
@ -1799,7 +1817,7 @@ mod tests {
let err_with_token = res.unwrap_err(); let err_with_token = res.unwrap_err();
assert_eq!(err_with_token.1, tok); assert_eq!(err_with_token.1, tok);
match err_with_token.0 { match err_with_token.0 {
EcssTmErrorWithSend::EcssTmError(EcssTmError::ByteConversionError(e)) => match e { EcssTmErrorWithSend::EcssTmError(EcssTmtcError::ByteConversionError(e)) => match e {
ByteConversionError::ToSliceTooSmall(missmatch) => { ByteConversionError::ToSliceTooSmall(missmatch) => {
assert_eq!( assert_eq!(
missmatch.expected, missmatch.expected,

View File

@ -1,6 +1,7 @@
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use spacepackets::ecss::{EcssEnumU16, EcssEnumeration}; use spacepackets::ecss::{EcssEnumU16, EcssEnumeration};
use spacepackets::util::UnsignedEnum;
use spacepackets::{ByteConversionError, SizeMissmatch}; use spacepackets::{ByteConversionError, SizeMissmatch};
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -34,12 +35,12 @@ impl From<ResultU16> for EcssEnumU16 {
} }
} }
impl EcssEnumeration for ResultU16 { impl UnsignedEnum for ResultU16 {
fn pfc(&self) -> u8 { fn size(&self) -> usize {
16 core::mem::size_of::<u16>()
} }
fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
if buf.len() < 2 { if buf.len() < 2 {
return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
found: buf.len(), found: buf.len(),
@ -48,6 +49,12 @@ impl EcssEnumeration for ResultU16 {
} }
buf[0] = self.group_id; buf[0] = self.group_id;
buf[1] = self.unique_id; buf[1] = self.unique_id;
Ok(()) Ok(self.size())
}
}
impl EcssEnumeration for ResultU16 {
fn pfc(&self) -> u8 {
16
} }
} }

View File

@ -10,10 +10,10 @@ fern = "0.6"
chrono = "0.4" chrono = "0.4"
log = "0.4" log = "0.4"
crossbeam-channel = "0.5" crossbeam-channel = "0.5"
delegate = "0.9" delegate = "0.10"
zerocopy = "0.6" zerocopy = "0.6"
csv = "1" csv = "1"
num_enum = "0.5" num_enum = "0.6"
[dependencies.satrs-core] [dependencies.satrs-core]
path = "../satrs-core" path = "../satrs-core"

View File

@ -1,6 +1,8 @@
use satrs_core::pus::verification::RequestId; use satrs_core::pus::verification::RequestId;
use satrs_core::{ use satrs_core::{
spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::tm::PusTm, spacepackets::ecss::{PusPacket, SerializablePusPacket},
spacepackets::tc::PusTc,
spacepackets::tm::PusTm,
spacepackets::SpHeader, spacepackets::SpHeader,
}; };
use satrs_example::{OBSW_SERVER_ADDR, SERVER_PORT}; use satrs_example::{OBSW_SERVER_ADDR, SERVER_PORT};

View File

@ -27,7 +27,7 @@ use satrs_core::pus::hk::Subservice as HkSubservice;
use satrs_core::pus::verification::{ use satrs_core::pus::verification::{
MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender, MpscVerifSender, VerificationReporterCfg, VerificationReporterWithSender,
}; };
use satrs_core::pus::MpscTmInStoreSender; use satrs_core::pus::MpscTmtcInStoreSender;
use satrs_core::seq_count::{SeqCountProviderSimple, SeqCountProviderSyncClonable}; use satrs_core::seq_count::{SeqCountProviderSimple, SeqCountProviderSyncClonable};
use satrs_core::spacepackets::{ use satrs_core::spacepackets::{
time::cds::TimeProvider, time::cds::TimeProvider,
@ -185,7 +185,7 @@ fn main() {
.spawn(move || { .spawn(move || {
let mut timestamp: [u8; 7] = [0; 7]; let mut timestamp: [u8; 7] = [0; 7];
let mut sender = let mut sender =
MpscTmInStoreSender::new(1, "event_sender", tm_store.pool, tm_funnel_tx); MpscTmtcInStoreSender::new(1, "event_sender", tm_store.pool, tm_funnel_tx);
let mut time_provider = TimeProvider::new_with_u16_days(0, 0); let mut time_provider = TimeProvider::new_with_u16_days(0, 0);
let mut report_completion = |event_req: EventRequestWithToken, timestamp: &[u8]| { let mut report_completion = |event_req: EventRequestWithToken, timestamp: &[u8]| {
reporter_event_handler reporter_event_handler

View File

@ -7,7 +7,6 @@ use satrs_core::mode::{ModeAndSubmode, ModeRequest};
use satrs_core::params::Params; use satrs_core::params::Params;
use satrs_core::pool::{PoolProvider, StoreAddr}; use satrs_core::pool::{PoolProvider, StoreAddr};
use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken};
use satrs_core::pus::hk;
use satrs_core::pus::mode; use satrs_core::pus::mode;
use satrs_core::pus::mode::Subservice; use satrs_core::pus::mode::Subservice;
use satrs_core::pus::scheduling::PusScheduler; use satrs_core::pus::scheduling::PusScheduler;
@ -16,6 +15,7 @@ use satrs_core::pus::verification::{
VerificationToken, VerificationToken,
}; };
use satrs_core::pus::{event, GenericTcCheckError}; use satrs_core::pus::{event, GenericTcCheckError};
use satrs_core::pus::{hk, EcssTmSender, EcssTmSenderCore};
use satrs_core::res_code::ResultU16; use satrs_core::res_code::ResultU16;
use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore}; use satrs_core::seq_count::{SeqCountProviderSyncClonable, SequenceCountProviderCore};
use satrs_core::spacepackets::ecss::{scheduling, PusServiceId}; use satrs_core::spacepackets::ecss::{scheduling, PusServiceId};
@ -33,6 +33,9 @@ use std::convert::TryFrom;
use std::rc::Rc; use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender}; use std::sync::mpsc::{Receiver, Sender};
pub trait PusTcMultiplexer {
fn route_pus_tc(tc: &PusTc, apid: u16, service: u8, subservice: u8);
}
pub struct PusReceiver { pub struct PusReceiver {
pub tm_helper: PusTmWithCdsShortHelper, pub tm_helper: PusTmWithCdsShortHelper,
pub tm_args: PusTmArgs, pub tm_args: PusTmArgs,

View File

@ -20,6 +20,7 @@ use satrs_core::pus::event_man::EventRequestWithToken;
use satrs_core::pus::scheduling::{PusScheduler, TcInfo}; use satrs_core::pus::scheduling::{PusScheduler, TcInfo};
use satrs_core::pus::verification::StdVerifReporterWithSender; use satrs_core::pus::verification::StdVerifReporterWithSender;
use satrs_core::seq_count::SeqCountProviderSyncClonable; use satrs_core::seq_count::SeqCountProviderSyncClonable;
use satrs_core::spacepackets::ecss::SerializablePusPacket;
use satrs_core::spacepackets::{ecss::PusPacket, tc::PusTc, tm::PusTm, SpHeader}; use satrs_core::spacepackets::{ecss::PusPacket, tc::PusTc, tm::PusTm, SpHeader};
use satrs_core::tmtc::{ use satrs_core::tmtc::{
CcsdsDistributor, CcsdsError, PusServiceProvider, ReceivesCcsdsTc, ReceivesEcssPusTc, CcsdsDistributor, CcsdsError, PusServiceProvider, ReceivesCcsdsTc, ReceivesEcssPusTc,

View File

@ -19,7 +19,7 @@ path = "../satrs-core"
path = "codegen" path = "codegen"
[dependencies.serde] [dependencies.serde]
version = "1.0" version = "1"
default-features = false default-features = false
[features] [features]

View File

@ -12,18 +12,18 @@ name = "tests"
path = "tests/tests.rs" path = "tests/tests.rs"
[dependencies] [dependencies]
quote = "1.0" quote = "1"
proc-macro2 = "1.0" proc-macro2 = "1"
[dependencies.satrs-core] [dependencies.satrs-core]
path = "../../satrs-core" path = "../../satrs-core"
[dev-dependencies] [dev-dependencies]
trybuild = { version = "1.0", features = ["diff"] } trybuild = { version = "1", features = ["diff"] }
[dev-dependencies.satrs-mib] [dev-dependencies.satrs-mib]
path = ".." path = ".."
[dependencies.syn] [dependencies.syn]
version = "1.0" version = "2"
features = ["extra-traits"] features = ["full"]

View File

@ -1,105 +1,42 @@
use proc_macro2::{Ident, TokenStream};
use quote::{format_ident, quote, ToTokens}; use quote::{format_ident, quote, ToTokens};
use syn::spanned::Spanned; use syn::{parse_macro_input, ItemConst, LitStr};
use syn::{parse_macro_input, AttributeArgs, Item, Lit, LitStr, Meta, NestedMeta, Type};
#[derive(Default)]
struct ResultExtGenerator {
name_str: Option<Ident>,
info_str: Option<LitStr>,
}
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn resultcode( pub fn resultcode(
args: proc_macro::TokenStream, args: proc_macro::TokenStream,
item: proc_macro::TokenStream, item: proc_macro::TokenStream,
) -> proc_macro::TokenStream { ) -> proc_macro::TokenStream {
let args = parse_macro_input!(args as AttributeArgs); // Handle attributes first.
let input = parse_macro_input!(item as Item); let mut info_str: Option<LitStr> = None;
let mut result_ext_generator = ResultExtGenerator::default(); let res_code_parser = syn::meta::parser(|meta| {
result_ext_generator.parse(args, input).into() if meta.path.is_ident("info") {
} info_str = Some(meta.value()?.parse()?);
Ok(())
impl ResultExtGenerator {
pub fn parse(&mut self, args: AttributeArgs, input: Item) -> TokenStream {
let mut output = input.to_token_stream();
if let Err(e) = self.parse_args(args) {
output.extend(e.into_compile_error());
return output;
}
match self.gen_ext_struct(input) {
Ok(ts) => output.extend(ts),
Err(e) => output.extend(e.into_compile_error()),
}
output
}
pub fn parse_args(&mut self, args: AttributeArgs) -> syn::Result<()> {
for arg in args {
if let NestedMeta::Meta(Meta::NameValue(nvm)) = arg {
if let Some(path) = nvm.path.segments.first() {
if path.ident == "info" {
if let Lit::Str(str) = nvm.lit {
self.info_str = Some(str);
} else {
return Err(syn::Error::new(
nvm.lit.span(),
"Only literal strings are allowed as information",
));
}
} else {
return Err(syn::Error::new(
path.span(),
format!("Unknown attribute argument name {}", path.ident),
));
}
}
}
}
Ok(())
}
pub fn gen_ext_struct(&mut self, input: Item) -> syn::Result<TokenStream> {
if let Item::Const(const_item) = &input {
self.name_str = Some(const_item.ident.clone());
if let Type::Path(p) = &const_item.ty.as_ref() {
let mut valid_type_found = false;
for seg in &p.path.segments {
if seg.ident == "ResultU16" {
valid_type_found = true;
}
}
if !valid_type_found {
return Err(syn::Error::new(
p.span(),
"Can only be applied on items of type ResultU16",
));
}
}
} else { } else {
return Err(syn::Error::new( Err(meta.error("unsupported property for resultcode attribute"))
input.span(),
"Only const items are allowed to be use with this attribute",
));
} }
let result_code_name = self.name_str.to_owned().unwrap(); });
let name_as_str = result_code_name.to_string(); parse_macro_input!(args with res_code_parser);
let gen_struct_name = format_ident!("{}_EXT", result_code_name); let item = parse_macro_input!(item as ItemConst);
let info_str = if let Some(info_str) = &self.info_str {
info_str.value() // Generate additional generated info struct used for introspection.
} else { let result_code_name = item.ident.clone();
String::from("") let name_as_str = result_code_name.to_string();
}; let gen_struct_name = format_ident!("{}_EXT", result_code_name);
// TODO: Group string let info_str = info_str.map_or(String::from(""), |v| v.value());
let gen_struct = quote! { // TODO: Group string
const #gen_struct_name: satrs_mib::res_code::ResultU16Info = let generated_struct = quote! {
satrs_mib::res_code::ResultU16Info::const_new( const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
#name_as_str, satrs_mib::res_code::ResultU16Info::const_new(
&#result_code_name, #name_as_str,
"", &#result_code_name,
#info_str "",
); #info_str
}; );
Ok(gen_struct) };
}
// The input constant returncode is written to the output in any case.
let mut output = item.to_token_stream();
output.extend(generated_struct);
output.into()
} }

View File

@ -2,7 +2,7 @@
use satrs_core::res_code::ResultU16; use satrs_core::res_code::ResultU16;
use satrs_mib::resultcode; use satrs_mib::resultcode;
#[resultcode(info = "This is a test result where the first parameter is foo")] #[resultcode]
const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1); const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1);
fn main() {} fn main() {}

View File

@ -0,0 +1,8 @@
//! Basic check which just verifies that everything compiles
use satrs_core::res_code::ResultU16;
use satrs_mib::resultcode;
#[resultcode(info = "This is a test result where the first parameter is foo")]
const _TEST_RESULT: ResultU16 = ResultU16::const_new(0, 1);
fn main() {}

View File

@ -2,6 +2,7 @@
fn tests() { fn tests() {
let t = trybuild::TestCases::new(); let t = trybuild::TestCases::new();
t.pass("tests/basic.rs"); t.pass("tests/basic.rs");
t.pass("tests/basic_with_info.rs");
t.pass("tests/verify_gen_struct.rs"); t.pass("tests/verify_gen_struct.rs");
//t.pass("tests/group_in_enum.rs"); //t.pass("tests/group_in_enum.rs");
} }