continued util module

This commit is contained in:
Robin Müller 2022-10-31 00:23:24 +01:00
parent 15ad96a843
commit 6d90da15c8
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
4 changed files with 158 additions and 52 deletions

View File

@ -28,7 +28,7 @@
//! Other components might only be interested in certain events. For example, a thermal system //! 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. //! handler might only be interested in temperature events generated by a thermal sensor component.
use crate::events::{EventU16, EventU32, GenericEvent, LargestEventRaw, LargestGroupIdRaw}; use crate::events::{EventU16, EventU32, GenericEvent, LargestEventRaw, LargestGroupIdRaw};
use crate::util::{AuxData, AuxDataHeapless}; use crate::util::{Params, ParamsHeapless};
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
@ -44,15 +44,15 @@ enum ListenerType {
All, All,
} }
pub type EventWithHeaplessAuxData<Event> = (Event, Option<AuxDataHeapless>); pub type EventWithHeaplessAuxData<Event> = (Event, Option<ParamsHeapless>);
pub type EventU32WithHeaplessAuxData = EventWithHeaplessAuxData<EventU32>; pub type EventU32WithHeaplessAuxData = EventWithHeaplessAuxData<EventU32>;
pub type EventU16WithHeaplessAuxData = EventWithHeaplessAuxData<EventU16>; pub type EventU16WithHeaplessAuxData = EventWithHeaplessAuxData<EventU16>;
pub type EventWithAuxData<Event> = (Event, Option<AuxData>); pub type EventWithAuxData<Event> = (Event, Option<Params>);
pub type EventU32WithAuxData = EventWithAuxData<EventU32>; pub type EventU32WithAuxData = EventWithAuxData<EventU32>;
pub type EventU16WithAuxData = EventWithAuxData<EventU16>; pub type EventU16WithAuxData = EventWithAuxData<EventU16>;
pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = AuxData> { pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = Params> {
type Error; type Error;
fn id(&self) -> u32; fn id(&self) -> u32;
@ -66,13 +66,13 @@ pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = AuxData> {
) -> Result<(), Self::Error>; ) -> Result<(), Self::Error>;
} }
struct Listener<E, Event: GenericEvent, AuxDataProvider = AuxData> { struct Listener<E, Event: GenericEvent, AuxDataProvider = Params> {
ltype: ListenerType, ltype: ListenerType,
send_provider: Box<dyn SendEventProvider<Event, AuxDataProvider, Error = E>>, send_provider: Box<dyn SendEventProvider<Event, AuxDataProvider, Error = E>>,
} }
/// Generic abstraction for an event receiver. /// Generic abstraction for an event receiver.
pub trait EventReceiver<Event: GenericEvent, AuxDataProvider = AuxData> { pub trait EventReceiver<Event: GenericEvent, AuxDataProvider = Params> {
/// This function has to be provided by any event receiver. A receive call may or may not return /// This function has to be provided by any event receiver. A receive call may or may not return
/// an event. /// an event.
/// ///
@ -88,13 +88,10 @@ pub trait EventReceiver<Event: GenericEvent, AuxDataProvider = AuxData> {
/// ///
/// * `SendProviderError`: [SendEventProvider] error type /// * `SendProviderError`: [SendEventProvider] error type
/// * `Event`: Concrete event provider, currently either [EventU32] or [EventU16] /// * `Event`: Concrete event provider, currently either [EventU32] or [EventU16]
/// * `AuxDataProvider`: Concrete auxiliary data provder, currently either [AuxData] or /// * `AuxDataProvider`: Concrete auxiliary data provder, currently either [Params] or
/// [AuxDataHeapless] /// [ParamsHeapless]
pub struct EventManager< pub struct EventManager<SendProviderError, Event: GenericEvent = EventU32, AuxDataProvider = Params>
SendProviderError, {
Event: GenericEvent = EventU32,
AuxDataProvider = AuxData,
> {
listeners: HashMap<ListenerType, Vec<Listener<SendProviderError, Event, AuxDataProvider>>>, listeners: HashMap<ListenerType, Vec<Listener<SendProviderError, Event, AuxDataProvider>>>,
event_receiver: Box<dyn EventReceiver<Event, AuxDataProvider>>, event_receiver: Box<dyn EventReceiver<Event, AuxDataProvider>>,
} }
@ -231,15 +228,15 @@ impl<E, Event: GenericEvent + Copy, AuxDataProvider: Clone>
pub mod stdmod { pub mod stdmod {
use crate::event_man::{EventReceiver, EventWithAuxData}; use crate::event_man::{EventReceiver, EventWithAuxData};
use crate::events::{EventU16, EventU32, GenericEvent}; use crate::events::{EventU16, EventU32, GenericEvent};
use crate::util::AuxData; use crate::util::Params;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
pub struct MpscEventReceiver<Event: GenericEvent = EventU32> { pub struct MpscEventReceiver<Event: GenericEvent = EventU32> {
mpsc_receiver: Receiver<(Event, Option<AuxData>)>, mpsc_receiver: Receiver<(Event, Option<Params>)>,
} }
impl<Event: GenericEvent> MpscEventReceiver<Event> { impl<Event: GenericEvent> MpscEventReceiver<Event> {
pub fn new(receiver: Receiver<(Event, Option<AuxData>)>) -> Self { pub fn new(receiver: Receiver<(Event, Option<Params>)>) -> Self {
Self { Self {
mpsc_receiver: receiver, mpsc_receiver: receiver,
} }
@ -263,7 +260,7 @@ mod tests {
use super::*; use super::*;
use crate::event_man::EventManager; use crate::event_man::EventManager;
use crate::events::{EventU32, GenericEvent, Severity}; use crate::events::{EventU32, GenericEvent, Severity};
use crate::util::AuxDataRaw; use crate::util::ParamsRaw;
use alloc::boxed::Box; use alloc::boxed::Box;
use std::format; use std::format;
use std::sync::mpsc::{channel, Receiver, SendError, Sender}; use std::sync::mpsc::{channel, Receiver, SendError, Sender};
@ -286,7 +283,7 @@ mod tests {
fn id(&self) -> u32 { fn id(&self) -> u32 {
self.id self.id
} }
fn send(&mut self, event: EventU32, aux_data: Option<AuxData>) -> Result<(), Self::Error> { fn send(&mut self, event: EventU32, aux_data: Option<Params>) -> Result<(), Self::Error> {
self.mpsc_sender.send((event, aux_data)) self.mpsc_sender.send((event, aux_data))
} }
} }
@ -294,7 +291,7 @@ mod tests {
fn check_next_event( fn check_next_event(
expected: EventU32, expected: EventU32,
receiver: &Receiver<EventU32WithAuxData>, receiver: &Receiver<EventU32WithAuxData>,
) -> Option<AuxData> { ) -> Option<Params> {
if let Ok(event) = receiver.try_recv() { if let Ok(event) = receiver.try_recv() {
assert_eq!(event.0, expected); assert_eq!(event.0, expected);
return event.1; return event.1;
@ -303,7 +300,7 @@ mod tests {
} }
fn check_handled_event( fn check_handled_event(
res: HandlerResult<EventU32, AuxData>, res: HandlerResult<EventU32, Params>,
expected: EventU32, expected: EventU32,
expected_num_sent: u32, expected_num_sent: u32,
) { ) {
@ -368,7 +365,7 @@ mod tests {
let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender); let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender);
event_man.subscribe_single(event_grp_0, single_event_listener); event_man.subscribe_single(event_grp_0, single_event_listener);
event_sender 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"); .expect("Sending group error failed");
let res = event_man.try_event_handling(); let res = event_man.try_event_handling();
assert!(res.is_ok()); assert!(res.is_ok());
@ -376,7 +373,7 @@ mod tests {
let aux = check_next_event(event_grp_0, &single_event_receiver); let aux = check_next_event(event_grp_0, &single_event_receiver);
assert!(aux.is_some()); assert!(aux.is_some());
let aux = aux.unwrap(); 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.0, 2);
assert_eq!(pair.1, 3); assert_eq!(pair.1, 3);
} else { } else {

View File

@ -27,6 +27,7 @@
//! //!
//! let small_event = EventU16::new(Severity::INFO, 3, 0); //! let small_event = EventU16::new(Severity::INFO, 3, 0);
//! ``` //! ```
use core::fmt::Debug;
use core::hash::Hash; use core::hash::Hash;
use delegate::delegate; use delegate::delegate;
use spacepackets::ecss::{EcssEnumeration, ToBeBytes}; use spacepackets::ecss::{EcssEnumeration, ToBeBytes};
@ -46,33 +47,33 @@ pub enum Severity {
HIGH = 3, HIGH = 3,
} }
pub trait HasSeverity { pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone {
const SEVERITY: Severity; const SEVERITY: Severity;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityInfo {} pub struct SeverityInfo {}
impl HasSeverity for SeverityInfo { impl HasSeverity for SeverityInfo {
const SEVERITY: Severity = Severity::INFO; const SEVERITY: Severity = Severity::INFO;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityLow {} pub struct SeverityLow {}
impl HasSeverity for SeverityLow { impl HasSeverity for SeverityLow {
const SEVERITY: Severity = Severity::LOW; const SEVERITY: Severity = Severity::LOW;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityMedium {} pub struct SeverityMedium {}
impl HasSeverity for SeverityMedium { impl HasSeverity for SeverityMedium {
const SEVERITY: Severity = Severity::MEDIUM; const SEVERITY: Severity = Severity::MEDIUM;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityHigh {} pub struct SeverityHigh {}
impl HasSeverity for SeverityHigh { impl HasSeverity for SeverityHigh {
const SEVERITY: Severity = Severity::HIGH; const SEVERITY: Severity = Severity::HIGH;

View File

@ -1,6 +1,27 @@
//! Utility types and enums //! 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; use crate::pool::StoreAddr;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::string::String; use alloc::string::String;
@ -8,19 +29,21 @@ use alloc::string::String;
use alloc::string::ToString; use alloc::string::ToString;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt::Debug;
use core::mem::size_of; use core::mem::size_of;
use paste::paste; 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,)+) => { ($($ty: ty,)+) => {
$( $(
paste! { paste! {
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct [<$ty:upper>](pub $ty); 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); 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); pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
impl From<$ty> for [<$ty:upper>] { 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 { macro_rules! scalar_to_be_bytes_impl {
($($ty: ty,)+) => { ($($ty: ty,)+) => {
@ -154,8 +209,9 @@ impl ToBeBytes for I8Triplet {
pair_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,); 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,); triplet_to_be_bytes_impl!(u16, u32, u64, i16, i32, i64, f32, f64,);
#[derive(Debug, Copy, Clone)] /// Generic enumeration for additonal parameters only consisting of primitive data types.
pub enum AuxDataRaw { #[derive(Debug, Copy, Clone, PartialEq)]
pub enum ParamsRaw {
U8(U8), U8(U8),
U8Pair(U8Pair), U8Pair(U8Pair),
U8Triplet(U8Triplet), U8Triplet(U8Triplet),
@ -178,16 +234,45 @@ pub enum AuxDataRaw {
F32Pair(F32Pair), F32Pair(F32Pair),
F32Triplet(F32Triplet), F32Triplet(F32Triplet),
U64(U64), U64(U64),
I64(I64),
F64(F64), F64(F64),
} }
#[derive(Debug, Copy, Clone)] macro_rules! params_raw_from_newtype {
pub enum AuxDataHeapless { ($($newtype: ident,)+) => {
Raw(AuxDataRaw), $(
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), Store(StoreAddr),
} }
impl From<StoreAddr> for AuxDataHeapless { impl From<StoreAddr> for ParamsHeapless {
fn from(x: StoreAddr) -> Self { fn from(x: StoreAddr) -> Self {
Self::Store(x) Self::Store(x)
} }
@ -196,15 +281,15 @@ impl From<StoreAddr> for AuxDataHeapless {
macro_rules! from_conversions_for_raw { macro_rules! from_conversions_for_raw {
($(($raw_ty: ty, $TargetPath: path),)+) => { ($(($raw_ty: ty, $TargetPath: path),)+) => {
$( $(
impl From<$raw_ty> for AuxDataRaw { impl From<$raw_ty> for ParamsRaw {
fn from(val: $raw_ty) -> Self { fn from(val: $raw_ty) -> Self {
$TargetPath(val.into()) $TargetPath(val.into())
} }
} }
impl From<$raw_ty> for AuxDataHeapless { impl From<$raw_ty> for ParamsHeapless {
fn from(val: $raw_ty) -> Self { 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), (f64, Self::F64),
); );
/// Generic enumeration for additional parameters, including parameters which rely on heap
/// allocations.
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AuxData { pub enum Params {
Heapless(AuxDataHeapless), Heapless(ParamsHeapless),
Vec(Vec<u8>), Vec(Vec<u8>),
String(String), String(String),
} }
impl From<AuxDataHeapless> for AuxData { impl From<ParamsHeapless> for Params {
fn from(x: AuxDataHeapless) -> Self { fn from(x: ParamsHeapless) -> Self {
Self::Heapless(x) Self::Heapless(x)
} }
} }
impl From<Vec<u8>> for AuxData { impl From<Vec<u8>> for Params {
fn from(val: Vec<u8>) -> Self { fn from(val: Vec<u8>) -> Self {
Self::Vec(val) Self::Vec(val)
} }
} }
impl From<&[u8]> for AuxData { impl From<&[u8]> for Params {
fn from(val: &[u8]) -> Self { fn from(val: &[u8]) -> Self {
Self::Vec(val.to_vec()) Self::Vec(val.to_vec())
} }
} }
impl From<String> for AuxData { impl From<String> for Params {
fn from(val: String) -> Self { fn from(val: String) -> Self {
Self::String(val) Self::String(val)
} }
} }
impl From<&str> for AuxData { impl From<&str> for Params {
fn from(val: &str) -> Self { fn from(val: &str) -> Self {
Self::String(val.to_string()) Self::String(val.to_string())
} }
@ -318,4 +405,25 @@ mod tests {
i8_conv_back = i8::from_be_bytes(raw[2..3].try_into().unwrap()); i8_conv_back = i8::from_be_bytes(raw[2..3].try_into().unwrap());
assert_eq!(i8_conv_back, -126); 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")
}
}
} }

@ -1 +1 @@
Subproject commit 65e85f20e03507f19a0d5086ee19360ff7596c27 Subproject commit 38b789ca6d061239e6cecc76f0843d6ba8b9bd01