diff --git a/fsrc-core/src/event_man.rs b/fsrc-core/src/event_man.rs index 381ccd7..98fe9a8 100644 --- a/fsrc-core/src/event_man.rs +++ b/fsrc-core/src/event_man.rs @@ -28,7 +28,7 @@ //! Other components might only be interested in certain events. For example, a thermal system //! handler might only be interested in temperature events generated by a thermal sensor component. use crate::events::{EventU16, EventU32, GenericEvent, LargestEventRaw, LargestGroupIdRaw}; -use crate::util::{AuxData, AuxDataHeapless}; +use crate::util::{Params, ParamsHeapless}; use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; @@ -44,15 +44,15 @@ enum ListenerType { All, } -pub type EventWithHeaplessAuxData = (Event, Option); +pub type EventWithHeaplessAuxData = (Event, Option); pub type EventU32WithHeaplessAuxData = EventWithHeaplessAuxData; pub type EventU16WithHeaplessAuxData = EventWithHeaplessAuxData; -pub type EventWithAuxData = (Event, Option); +pub type EventWithAuxData = (Event, Option); pub type EventU32WithAuxData = EventWithAuxData; pub type EventU16WithAuxData = EventWithAuxData; -pub trait SendEventProvider { +pub trait SendEventProvider { type Error; fn id(&self) -> u32; @@ -66,13 +66,13 @@ pub trait SendEventProvider { ) -> Result<(), Self::Error>; } -struct Listener { +struct Listener { ltype: ListenerType, send_provider: Box>, } /// Generic abstraction for an event receiver. -pub trait EventReceiver { +pub trait EventReceiver { /// This function has to be provided by any event receiver. A receive call may or may not return /// an event. /// @@ -88,13 +88,10 @@ pub trait EventReceiver { /// /// * `SendProviderError`: [SendEventProvider] error type /// * `Event`: Concrete event provider, currently either [EventU32] or [EventU16] -/// * `AuxDataProvider`: Concrete auxiliary data provder, currently either [AuxData] or -/// [AuxDataHeapless] -pub struct EventManager< - SendProviderError, - Event: GenericEvent = EventU32, - AuxDataProvider = AuxData, -> { +/// * `AuxDataProvider`: Concrete auxiliary data provder, currently either [Params] or +/// [ParamsHeapless] +pub struct EventManager +{ listeners: HashMap>>, event_receiver: Box>, } @@ -231,15 +228,15 @@ impl pub mod stdmod { use crate::event_man::{EventReceiver, EventWithAuxData}; use crate::events::{EventU16, EventU32, GenericEvent}; - use crate::util::AuxData; + use crate::util::Params; use std::sync::mpsc::Receiver; pub struct MpscEventReceiver { - mpsc_receiver: Receiver<(Event, Option)>, + mpsc_receiver: Receiver<(Event, Option)>, } impl MpscEventReceiver { - pub fn new(receiver: Receiver<(Event, Option)>) -> Self { + pub fn new(receiver: Receiver<(Event, Option)>) -> Self { Self { mpsc_receiver: receiver, } @@ -263,7 +260,7 @@ mod tests { use super::*; use crate::event_man::EventManager; use crate::events::{EventU32, GenericEvent, Severity}; - use crate::util::AuxDataRaw; + use crate::util::ParamsRaw; use alloc::boxed::Box; use std::format; use std::sync::mpsc::{channel, Receiver, SendError, Sender}; @@ -286,7 +283,7 @@ mod tests { fn id(&self) -> u32 { self.id } - fn send(&mut self, event: EventU32, aux_data: Option) -> Result<(), Self::Error> { + fn send(&mut self, event: EventU32, aux_data: Option) -> Result<(), Self::Error> { self.mpsc_sender.send((event, aux_data)) } } @@ -294,7 +291,7 @@ mod tests { fn check_next_event( expected: EventU32, receiver: &Receiver, - ) -> Option { + ) -> Option { if let Ok(event) = receiver.try_recv() { assert_eq!(event.0, expected); return event.1; @@ -303,7 +300,7 @@ mod tests { } fn check_handled_event( - res: HandlerResult, + res: HandlerResult, expected: EventU32, expected_num_sent: u32, ) { @@ -368,7 +365,7 @@ mod tests { let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender); event_man.subscribe_single(event_grp_0, single_event_listener); event_sender - .send((event_grp_0, Some(AuxData::Heapless((2_u32, 3_u32).into())))) + .send((event_grp_0, Some(Params::Heapless((2_u32, 3_u32).into())))) .expect("Sending group error failed"); let res = event_man.try_event_handling(); assert!(res.is_ok()); @@ -376,7 +373,7 @@ mod tests { let aux = check_next_event(event_grp_0, &single_event_receiver); assert!(aux.is_some()); let aux = aux.unwrap(); - if let AuxData::Heapless(AuxDataHeapless::Raw(AuxDataRaw::U32Pair(pair))) = aux { + if let Params::Heapless(ParamsHeapless::Raw(ParamsRaw::U32Pair(pair))) = aux { assert_eq!(pair.0, 2); assert_eq!(pair.1, 3); } else { diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 02f4dfd..8920a12 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -27,6 +27,7 @@ //! //! let small_event = EventU16::new(Severity::INFO, 3, 0); //! ``` +use core::fmt::Debug; use core::hash::Hash; use delegate::delegate; use spacepackets::ecss::{EcssEnumeration, ToBeBytes}; @@ -46,33 +47,33 @@ pub enum Severity { HIGH = 3, } -pub trait HasSeverity { +pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone { const SEVERITY: Severity; } /// Type level support struct -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct SeverityInfo {} impl HasSeverity for SeverityInfo { const SEVERITY: Severity = Severity::INFO; } /// Type level support struct -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct SeverityLow {} impl HasSeverity for SeverityLow { const SEVERITY: Severity = Severity::LOW; } /// Type level support struct -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct SeverityMedium {} impl HasSeverity for SeverityMedium { const SEVERITY: Severity = Severity::MEDIUM; } /// Type level support struct -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct SeverityHigh {} impl HasSeverity for SeverityHigh { const SEVERITY: Severity = Severity::HIGH; diff --git a/fsrc-core/src/util.rs b/fsrc-core/src/util.rs index bb9439e..5041306 100644 --- a/fsrc-core/src/util.rs +++ b/fsrc-core/src/util.rs @@ -1,6 +1,27 @@ //! Utility types and enums //! -//! This module contains helper types. +//! This module contains various helper types. This includes wrapper for primitive rust types +//! using the newtype pattern. This was also done for pairs and triplets of these primtive types. +//! +//! The [ToBeBytes] was implemented for those types as well, which allows to easily convert them +//! into a network friendly raw byte format. +//! +//! The module also contains generic parameter enumerations. +//! +//! # Example for primitive type wrapper +//! +//! ``` +//! use fsrc_core::util::{ParamsRaw, ToBeBytes, U32Pair}; +//! +//! let u32_pair = U32Pair(0x1010, 25); +//! assert_eq!(u32_pair.0, 0x1010); +//! assert_eq!(u32_pair.1, 25); +//! let raw_buf = u32_pair.to_be_bytes(); +//! assert_eq!(raw_buf, [0, 0, 0x10, 0x10, 0, 0, 0, 25]); +//! +//! let params_raw: ParamsRaw = u32_pair.into(); +//! assert_eq!(params_raw, (0x1010_u32, 25_u32).into()); +//! ``` use crate::pool::StoreAddr; #[cfg(feature = "alloc")] use alloc::string::String; @@ -8,19 +29,21 @@ use alloc::string::String; use alloc::string::ToString; #[cfg(feature = "alloc")] use alloc::vec::Vec; +use core::fmt::Debug; use core::mem::size_of; use paste::paste; -use spacepackets::ecss::ToBeBytes; +pub use spacepackets::ecss::ToBeBytes; +use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8}; -macro_rules! primitive_newtypes { +macro_rules! primitive_newtypes_with_eq { ($($ty: ty,)+) => { $( paste! { - #[derive(Debug, Copy, Clone)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct [<$ty:upper>](pub $ty); - #[derive(Debug, Copy, Clone)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct [<$ty:upper Pair>](pub $ty, pub $ty); - #[derive(Debug, Copy, Clone)] + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty); impl From<$ty> for [<$ty:upper>] { @@ -43,7 +66,39 @@ macro_rules! primitive_newtypes { } } -primitive_newtypes!(u8, u16, u32, u64, i8, i16, i32, i64, f32, f64,); +macro_rules! primitive_newtypes { + ($($ty: ty,)+) => { + $( + paste! { + #[derive(Debug, Copy, Clone, PartialEq)] + pub struct [<$ty:upper>](pub $ty); + #[derive(Debug, Copy, Clone, PartialEq)] + pub struct [<$ty:upper Pair>](pub $ty, pub $ty); + #[derive(Debug, Copy, Clone, PartialEq)] + pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty); + + impl From<$ty> for [<$ty:upper>] { + fn from(v: $ty) -> Self { + Self(v) + } + } + impl From<($ty, $ty)> for [<$ty:upper Pair>] { + fn from(v: ($ty, $ty)) -> Self { + Self(v.0, v.1) + } + } + impl From<($ty, $ty, $ty)> for [<$ty:upper Triplet>] { + fn from(v: ($ty, $ty, $ty)) -> Self { + Self(v.0, v.1, v.2) + } + } + } + )+ + } +} + +primitive_newtypes_with_eq!(u8, u16, u32, u64, i8, i16, i32, i64,); +primitive_newtypes!(f32, f64,); macro_rules! scalar_to_be_bytes_impl { ($($ty: ty,)+) => { @@ -154,8 +209,9 @@ impl ToBeBytes for I8Triplet { pair_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); triplet_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); -#[derive(Debug, Copy, Clone)] -pub enum AuxDataRaw { +/// Generic enumeration for additonal parameters only consisting of primitive data types. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ParamsRaw { U8(U8), U8Pair(U8Pair), U8Triplet(U8Triplet), @@ -178,16 +234,45 @@ pub enum AuxDataRaw { F32Pair(F32Pair), F32Triplet(F32Triplet), U64(U64), + I64(I64), F64(F64), } -#[derive(Debug, Copy, Clone)] -pub enum AuxDataHeapless { - Raw(AuxDataRaw), +macro_rules! params_raw_from_newtype { + ($($newtype: ident,)+) => { + $( + impl From<$newtype> for ParamsRaw { + fn from(v: $newtype) -> Self { + Self::$newtype(v) + } + } + )+ + } +} + +params_raw_from_newtype!( + U8, U8Pair, U8Triplet, U16, U16Pair, U16Triplet, U32, U32Pair, U32Triplet, I8, I8Pair, + I8Triplet, I16, I16Pair, I16Triplet, I32, I32Pair, I32Triplet, F32, F32Pair, F32Triplet, U64, + I64, F64, +); + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum EcssEnumParams { + U8(EcssEnumU8), + U16(EcssEnumU16), + U32(EcssEnumU32), + U64(EcssEnumU64), +} + +/// Generic enumeration for parameters which do not rely on heap allocations. +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum ParamsHeapless { + Raw(ParamsRaw), + EcssEnum(EcssEnumParams), Store(StoreAddr), } -impl From for AuxDataHeapless { +impl From for ParamsHeapless { fn from(x: StoreAddr) -> Self { Self::Store(x) } @@ -196,15 +281,15 @@ impl From for AuxDataHeapless { macro_rules! from_conversions_for_raw { ($(($raw_ty: ty, $TargetPath: path),)+) => { $( - impl From<$raw_ty> for AuxDataRaw { + impl From<$raw_ty> for ParamsRaw { fn from(val: $raw_ty) -> Self { $TargetPath(val.into()) } } - impl From<$raw_ty> for AuxDataHeapless { + impl From<$raw_ty> for ParamsHeapless { fn from(val: $raw_ty) -> Self { - AuxDataHeapless::Raw(val.into()) + ParamsHeapless::Raw(val.into()) } } )+ @@ -237,40 +322,42 @@ from_conversions_for_raw!( (f64, Self::F64), ); +/// Generic enumeration for additional parameters, including parameters which rely on heap +/// allocations. #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[derive(Debug, Clone)] -pub enum AuxData { - Heapless(AuxDataHeapless), +pub enum Params { + Heapless(ParamsHeapless), Vec(Vec), String(String), } -impl From for AuxData { - fn from(x: AuxDataHeapless) -> Self { +impl From for Params { + fn from(x: ParamsHeapless) -> Self { Self::Heapless(x) } } -impl From> for AuxData { +impl From> for Params { fn from(val: Vec) -> Self { Self::Vec(val) } } -impl From<&[u8]> for AuxData { +impl From<&[u8]> for Params { fn from(val: &[u8]) -> Self { Self::Vec(val.to_vec()) } } -impl From for AuxData { +impl From for Params { fn from(val: String) -> Self { Self::String(val) } } -impl From<&str> for AuxData { +impl From<&str> for Params { fn from(val: &str) -> Self { Self::String(val.to_string()) } @@ -318,4 +405,25 @@ mod tests { i8_conv_back = i8::from_be_bytes(raw[2..3].try_into().unwrap()); assert_eq!(i8_conv_back, -126); } + + #[test] + fn conversion_test_string() { + let param: Params = "Test String".into(); + if let Params::String(str) = param { + assert_eq!(str, String::from("Test String")); + } else { + panic!("Params type is not String") + } + } + + #[test] + fn conversion_from_slice() { + let test_slice: [u8; 5] = [0; 5]; + let vec_param: Params = test_slice.as_slice().into(); + if let Params::Vec(vec) = vec_param { + assert_eq!(vec, test_slice.to_vec()); + } else { + panic!("Params type is not a vector") + } + } } diff --git a/spacepackets b/spacepackets index 65e85f2..38b789c 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 65e85f20e03507f19a0d5086ee19360ff7596c27 +Subproject commit 38b789ca6d061239e6cecc76f0843d6ba8b9bd01