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
//! 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> = (Event, Option<AuxDataHeapless>);
pub type EventWithHeaplessAuxData<Event> = (Event, Option<ParamsHeapless>);
pub type EventU32WithHeaplessAuxData = EventWithHeaplessAuxData<EventU32>;
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 EventU16WithAuxData = EventWithAuxData<EventU16>;
pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = AuxData> {
pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = Params> {
type Error;
fn id(&self) -> u32;
@ -66,13 +66,13 @@ pub trait SendEventProvider<Provider: GenericEvent, AuxDataProvider = AuxData> {
) -> Result<(), Self::Error>;
}
struct Listener<E, Event: GenericEvent, AuxDataProvider = AuxData> {
struct Listener<E, Event: GenericEvent, AuxDataProvider = Params> {
ltype: ListenerType,
send_provider: Box<dyn SendEventProvider<Event, AuxDataProvider, Error = E>>,
}
/// 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
/// an event.
///
@ -88,13 +88,10 @@ pub trait EventReceiver<Event: GenericEvent, AuxDataProvider = AuxData> {
///
/// * `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<SendProviderError, Event: GenericEvent = EventU32, AuxDataProvider = Params>
{
listeners: HashMap<ListenerType, Vec<Listener<SendProviderError, Event, AuxDataProvider>>>,
event_receiver: Box<dyn EventReceiver<Event, AuxDataProvider>>,
}
@ -231,15 +228,15 @@ impl<E, Event: GenericEvent + Copy, AuxDataProvider: Clone>
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<Event: GenericEvent = EventU32> {
mpsc_receiver: Receiver<(Event, Option<AuxData>)>,
mpsc_receiver: Receiver<(Event, Option<Params>)>,
}
impl<Event: GenericEvent> MpscEventReceiver<Event> {
pub fn new(receiver: Receiver<(Event, Option<AuxData>)>) -> Self {
pub fn new(receiver: Receiver<(Event, Option<Params>)>) -> 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<AuxData>) -> Result<(), Self::Error> {
fn send(&mut self, event: EventU32, aux_data: Option<Params>) -> Result<(), Self::Error> {
self.mpsc_sender.send((event, aux_data))
}
}
@ -294,7 +291,7 @@ mod tests {
fn check_next_event(
expected: EventU32,
receiver: &Receiver<EventU32WithAuxData>,
) -> Option<AuxData> {
) -> Option<Params> {
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<EventU32, AuxData>,
res: HandlerResult<EventU32, Params>,
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 {

View File

@ -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;

View File

@ -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<StoreAddr> for AuxDataHeapless {
impl From<StoreAddr> for ParamsHeapless {
fn from(x: StoreAddr) -> Self {
Self::Store(x)
}
@ -196,15 +281,15 @@ impl From<StoreAddr> 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<u8>),
String(String),
}
impl From<AuxDataHeapless> for AuxData {
fn from(x: AuxDataHeapless) -> Self {
impl From<ParamsHeapless> for Params {
fn from(x: ParamsHeapless) -> Self {
Self::Heapless(x)
}
}
impl From<Vec<u8>> for AuxData {
impl From<Vec<u8>> for Params {
fn from(val: Vec<u8>) -> 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<String> for AuxData {
impl From<String> 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")
}
}
}

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