Update #48
@ -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]
|
||||||
|
@ -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>;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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};
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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]
|
||||||
|
@ -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"]
|
||||||
|
@ -1,97 +1,31 @@
|
|||||||
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()?);
|
||||||
|
|
||||||
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(())
|
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();
|
});
|
||||||
|
parse_macro_input!(args with res_code_parser);
|
||||||
|
let item = parse_macro_input!(item as ItemConst);
|
||||||
|
|
||||||
|
// Generate additional generated info struct used for introspection.
|
||||||
|
let result_code_name = item.ident.clone();
|
||||||
let name_as_str = result_code_name.to_string();
|
let name_as_str = result_code_name.to_string();
|
||||||
let gen_struct_name = format_ident!("{}_EXT", result_code_name);
|
let gen_struct_name = format_ident!("{}_EXT", result_code_name);
|
||||||
let info_str = if let Some(info_str) = &self.info_str {
|
let info_str = info_str.map_or(String::from(""), |v| v.value());
|
||||||
info_str.value()
|
|
||||||
} else {
|
|
||||||
String::from("")
|
|
||||||
};
|
|
||||||
// TODO: Group string
|
// TODO: Group string
|
||||||
let gen_struct = quote! {
|
let generated_struct = quote! {
|
||||||
const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
|
const #gen_struct_name: satrs_mib::res_code::ResultU16Info =
|
||||||
satrs_mib::res_code::ResultU16Info::const_new(
|
satrs_mib::res_code::ResultU16Info::const_new(
|
||||||
#name_as_str,
|
#name_as_str,
|
||||||
@ -100,6 +34,9 @@ impl ResultExtGenerator {
|
|||||||
#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()
|
||||||
}
|
}
|
||||||
|
@ -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() {}
|
||||||
|
8
satrs-mib/codegen/tests/basic_with_info.rs
Normal file
8
satrs-mib/codegen/tests/basic_with_info.rs
Normal 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() {}
|
@ -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");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user