From b7dbeb2dfd5bd229eb269e3342e4e8d5d46774a9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 22 Oct 2022 19:42:22 +0200 Subject: [PATCH 1/5] add small event impl --- fsrc-core/src/events.rs | 55 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 02bf7f6..cd7b62d 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -48,11 +48,11 @@ impl Event { /// next 13 bits after the severity. Therefore, the size is limited by dec 8191 hex 0x1FFF. /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the /// raw event ID - pub fn new(severity: Severity, group_id: GroupId, unique_id: UniqueId) -> Option { + pub fn new(severity: Severity, group_id: GroupId, unique_id: UniqueId) -> Option { if group_id > (2u16.pow(13) - 1) { return None; } - Some(Event { + Some(Self { severity, group_id, unique_id, @@ -94,6 +94,57 @@ impl TryFrom for Event { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct EventSmall { + severity: Severity, + group_id: u8, + unique_id: u8 +} + +impl EventSmall { + + /// Generate an event. The raw representation of an event has 32 bits. + /// If the passed group ID is invalid (too large), None wil be returned + /// + /// # Parameter + /// + /// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will + /// be stored inside the uppermost 3 bits of the raw event ID + /// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the + /// next 13 bits after the severity. Therefore, the size is limited by dec 8191 hex 0x1FFF. + /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the + /// raw event ID + pub fn new(severity: Severity, group_id: u8, unique_id: u8) -> Option { + if group_id > (2u8.pow(5) - 1) { + return None; + } + Some(Self { + severity, + group_id, + unique_id, + }) + } + + /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event + /// ID is invalid + pub fn severity(&self) -> Severity { + self.severity + } + + pub fn group_id(&self) -> u8 { + self.group_id + } + + pub fn unique_id(&self) -> u8 { + self.unique_id + } + + pub fn raw(&self) -> u16 { + (((self.severity as u16) << 12) as u16 + | ((self.group_id as u16) << 8) as u32 + | self.unique_id as u16) as u16 + } +} impl EcssEnumeration for Event { fn pfc(&self) -> u8 { 32 From 3ffbd3697e50bf8dd91a02f3e255f573f5d63e6f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 22 Oct 2022 19:42:47 +0200 Subject: [PATCH 2/5] cargo fmt --- fsrc-core/src/events.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index cd7b62d..089df83 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -98,11 +98,10 @@ impl TryFrom for Event { pub struct EventSmall { severity: Severity, group_id: u8, - unique_id: u8 + unique_id: u8, } impl EventSmall { - /// Generate an event. The raw representation of an event has 32 bits. /// If the passed group ID is invalid (too large), None wil be returned /// From b26703e0a95c1c6144ffcb9fba830928ad725073 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 23 Oct 2022 14:16:58 +0200 Subject: [PATCH 3/5] severity only uses two bits now --- fsrc-core/src/events.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 089df83..6a9250e 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -9,10 +9,10 @@ pub type EventRaw = u32; #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum Severity { - INFO = 1, - LOW = 2, - MEDIUM = 3, - HIGH = 4, + INFO = 0, + LOW = 1, + MEDIUM = 2, + HIGH = 3, } impl TryFrom for Severity { @@ -49,7 +49,7 @@ impl Event { /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the /// raw event ID pub fn new(severity: Severity, group_id: GroupId, unique_id: UniqueId) -> Option { - if group_id > (2u16.pow(13) - 1) { + if group_id > (2u16.pow(14) - 1) { return None; } Some(Self { @@ -74,7 +74,7 @@ impl Event { } pub fn raw(&self) -> EventRaw { - (((self.severity as u32) << 29) as u32 + (((self.severity as u32) << 30) as u32 | ((self.group_id as u32) << 16) as u32 | self.unique_id as u32) as EventRaw } @@ -84,11 +84,11 @@ impl TryFrom for Event { type Error = (); fn try_from(raw: u32) -> Result { - let severity: Option = (((raw >> 29) & 0b111) as u8).try_into().ok(); + let severity: Option = (((raw >> 30) & 0b11) as u8).try_into().ok(); if severity.is_none() { return Err(()); } - let group_id = ((raw >> 16) & 0x1FFF) as u16; + let group_id = ((raw >> 16) & 0x3FFF) as u16; let unique_id = (raw & 0xFFFF) as u16; Event::new(severity.unwrap(), group_id, unique_id).ok_or(()) } @@ -140,7 +140,7 @@ impl EventSmall { pub fn raw(&self) -> u16 { (((self.severity as u16) << 12) as u16 - | ((self.group_id as u16) << 8) as u32 + | ((self.group_id as u16) << 8) as u16 | self.unique_id as u16) as u16 } } @@ -174,7 +174,7 @@ mod tests { assert_eq!(event.group_id(), 0); let raw_event = event.raw(); - assert_eq!(raw_event, 0x20000000); + assert_eq!(raw_event, 0x00000000); let conv_from_raw = Event::try_from(raw_event); assert!(conv_from_raw.is_ok()); let opt_event = conv_from_raw.ok(); @@ -184,19 +184,19 @@ mod tests { assert_eq!(event.unique_id(), 0); assert_eq!(event.group_id(), 0); - let event = Event::new(Severity::HIGH, 0x1FFF, 0xFFFF).unwrap(); + let event = Event::new(Severity::HIGH, 0x3FFF, 0xFFFF).unwrap(); assert_eq!(event.severity(), Severity::HIGH); - assert_eq!(event.group_id(), 0x1FFF); + assert_eq!(event.group_id(), 0x3FFF); assert_eq!(event.unique_id(), 0xFFFF); let raw_event = event.raw(); - assert_eq!(raw_event, 0x9FFFFFFF); + assert_eq!(raw_event, 0xFFFFFFFF); let conv_from_raw = Event::try_from(raw_event); assert!(conv_from_raw.is_ok()); let opt_event = conv_from_raw.ok(); assert!(opt_event.is_some()); let event = opt_event.unwrap(); assert_eq!(event.severity(), Severity::HIGH); - assert_eq!(event.group_id(), 0x1FFF); + assert_eq!(event.group_id(), 0x3FFF); assert_eq!(event.unique_id(), 0xFFFF); } } From 2004155b7b1bdd9cedbb42a524e1d207c81c43c6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 23 Oct 2022 15:58:54 +0200 Subject: [PATCH 4/5] trying to make this generic --- fsrc-core/src/event_man.rs | 84 ++++++++----- fsrc-core/src/events.rs | 211 +++++++++++++++++++++------------ fsrc-core/src/pus/event_man.rs | 2 +- 3 files changed, 187 insertions(+), 110 deletions(-) diff --git a/fsrc-core/src/event_man.rs b/fsrc-core/src/event_man.rs index 83e4543..2fa71fd 100644 --- a/fsrc-core/src/event_man.rs +++ b/fsrc-core/src/event_man.rs @@ -1,5 +1,5 @@ //! [Event][crate::events::Event] management and forwarding -use crate::events::{Event, EventRaw, GroupId}; +use crate::events::{Event, EventProvider, EventSmall}; use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; @@ -7,63 +7,85 @@ use hashbrown::HashMap; #[derive(PartialEq, Eq, Hash, Copy, Clone)] enum ListenerType { - Single(EventRaw), - Group(GroupId), + Single(u32), + Group(u16), } -pub trait EventListener { +pub trait EventListener { type Error; fn id(&self) -> u32; - fn send_to(&mut self, event: Event) -> Result<(), Self::Error>; + fn send_to(&mut self, event: Provider) -> Result<(), Self::Error>; } -struct Listener { +struct Listener { ltype: ListenerType, - dest: Box>, + dest: Box>, } -pub trait ReceivesAllEvent { - fn receive(&mut self) -> Option; +pub trait ReceivesAllEvent { + fn receive(&mut self) -> Option; } -pub struct EventManager { - listeners: HashMap>>, - event_receiver: Box, +pub struct EventManager { + listeners: HashMap>>, + event_receiver: Box>, } -pub enum HandlerResult { +pub enum HandlerResult { Empty, - Handled(u32, Event), + Handled(u32, Provider), } -impl EventManager { - pub fn new(event_receiver: Box) -> Self { +impl EventManager { + pub fn new(event_receiver: Box>) -> Self { EventManager { listeners: HashMap::new(), event_receiver, } } +} + +impl EventManager { pub fn subscribe_single( &mut self, event: Event, - dest: impl EventListener + 'static, + dest: impl EventListener + 'static, ) { - self.update_listeners(ListenerType::Single(event.raw()), dest); + self.update_listeners(ListenerType::Single(event.raw_as_u32()), dest); } pub fn subscribe_group( &mut self, - group_id: GroupId, - dest: impl EventListener + 'static, + group_id: ::GroupId, + dest: impl EventListener + 'static, ) { self.update_listeners(ListenerType::Group(group_id), dest); } +} +impl EventManager { + pub fn subscribe_single( + &mut self, + event: EventSmall, + dest: impl EventListener + 'static, + ) { + self.update_listeners(ListenerType::Single(event.raw_as_u32()), dest); + } + + pub fn subscribe_group( + &mut self, + group_id: ::GroupId, + dest: impl EventListener + 'static, + ) { + self.update_listeners(ListenerType::Group(group_id.into()), dest); + } +} +impl EventManager { fn update_listeners( &mut self, key: ListenerType, - dest: impl EventListener + 'static, + dest: impl EventListener + 'static, ) { if !self.listeners.contains_key(&key) { self.listeners.insert( @@ -88,10 +110,10 @@ impl EventManager { } } - pub fn try_event_handling(&mut self) -> Result { + pub fn try_event_handling(&mut self) -> Result, E> { let mut err_status = None; let mut num_recipients = 0; - let mut send_handler = |event, llist: &mut Vec>| { + let mut send_handler = |event: Provider, llist: &mut Vec>| { for listener in llist.iter_mut() { if let Err(e) = listener.dest.send_to(event) { err_status = Some(Err(e)); @@ -101,11 +123,11 @@ impl EventManager { } }; if let Some(event) = self.event_receiver.receive() { - let single_key = ListenerType::Single(event.raw()); + let single_key = ListenerType::Single(event.raw_as_u32()); if self.listeners.contains_key(&single_key) { send_handler(event, self.listeners.get_mut(&single_key).unwrap()); } - let group_key = ListenerType::Group(event.group_id()); + let group_key = ListenerType::Group(event.group_id_as_u16()); if self.listeners.contains_key(&group_key) { send_handler(event, self.listeners.get_mut(&group_key).unwrap()); } @@ -122,7 +144,7 @@ impl EventManager { mod tests { use super::{EventListener, HandlerResult, ReceivesAllEvent}; use crate::event_man::EventManager; - use crate::events::{Event, Severity}; + use crate::events::{Event, EventProvider, Severity}; use alloc::boxed::Box; use std::sync::mpsc::{channel, Receiver, SendError, Sender}; use std::thread; @@ -131,7 +153,7 @@ mod tests { struct EventReceiver { mpsc_receiver: Receiver, } - impl ReceivesAllEvent for EventReceiver { + impl ReceivesAllEvent for EventReceiver { fn receive(&mut self) -> Option { self.mpsc_receiver.try_recv().ok() } @@ -143,7 +165,7 @@ mod tests { mpsc_sender: Sender, } - impl EventListener for MpscEventSenderQueue { + impl EventListener for MpscEventSenderQueue { type Error = SendError; fn id(&self) -> u32 { @@ -178,7 +200,7 @@ mod tests { let event_man_receiver = EventReceiver { mpsc_receiver: manager_queue, }; - let mut event_man: EventManager> = + let mut event_man: EventManager, Event> = EventManager::new(Box::new(event_man_receiver)); let event_grp_0 = Event::new(Severity::INFO, 0, 0).unwrap(); let event_grp_1_0 = Event::new(Severity::HIGH, 1, 0).unwrap(); @@ -221,7 +243,7 @@ mod tests { let event_man_receiver = EventReceiver { mpsc_receiver: manager_queue, }; - let mut event_man: EventManager> = + let mut event_man: EventManager, Event> = EventManager::new(Box::new(event_man_receiver)); let res = event_man.try_event_handling(); assert!(res.is_ok()); @@ -263,7 +285,7 @@ mod tests { let event_man_receiver = EventReceiver { mpsc_receiver: manager_queue, }; - let mut event_man: EventManager> = + let mut event_man: EventManager, Event> = EventManager::new(Box::new(event_man_receiver)); let event_0 = Event::new(Severity::INFO, 0, 5).unwrap(); let event_1 = Event::new(Severity::HIGH, 1, 0).unwrap(); diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 6a9250e..2265e67 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -3,9 +3,14 @@ use spacepackets::ecss::EcssEnumeration; use spacepackets::{ByteConversionError, SizeMissmatch}; +pub type EventRaw = u32; +pub type SmallEventRaw = u16; + pub type GroupId = u16; pub type UniqueId = u16; -pub type EventRaw = u32; + +pub type GroupIdSmall = u8; +pub type UniqueIdSmall = u8; #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum Severity { @@ -15,6 +20,20 @@ pub enum Severity { HIGH = 3, } +pub trait EventProvider: PartialEq + Eq + Copy + Clone { + type Raw; + type GroupId; + type UniqueId; + + fn raw(&self) -> Self::Raw; + fn severity(&self) -> Severity; + fn group_id(&self) -> Self::GroupId; + fn unique_id(&self) -> Self::UniqueId; + + fn raw_as_u32(&self) -> u32; + fn group_id_as_u16(&self) -> u16; +} + impl TryFrom for Severity { type Error = (); @@ -32,8 +51,42 @@ impl TryFrom for Severity { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct Event { severity: Severity, - group_id: GroupId, - unique_id: UniqueId, + group_id: u16, + unique_id: u16, +} + +impl EventProvider for Event { + type Raw = u32; + type GroupId = u16; + type UniqueId = u16; + + fn raw(&self) -> Self::Raw { + (((self.severity as Self::Raw) << 30) as Self::Raw + | ((self.group_id as Self::Raw) << 16) as Self::Raw + | self.unique_id as u32) as Self::Raw + } + + /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event + /// ID is invalid + fn severity(&self) -> Severity { + self.severity + } + + fn group_id(&self) -> Self::GroupId { + self.group_id + } + + fn unique_id(&self) -> Self::UniqueId { + self.unique_id + } + + fn raw_as_u32(&self) -> u32 { + self.raw() + } + + fn group_id_as_u16(&self) -> u16 { + self.group_id() + } } impl Event { @@ -43,12 +96,16 @@ impl Event { /// # Parameter /// /// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will - /// be stored inside the uppermost 3 bits of the raw event ID + /// be stored inside the uppermost 2 bits of the raw event ID /// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the - /// next 13 bits after the severity. Therefore, the size is limited by dec 8191 hex 0x1FFF. + /// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF. /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the /// raw event ID - pub fn new(severity: Severity, group_id: GroupId, unique_id: UniqueId) -> Option { + pub fn new( + severity: Severity, + group_id: ::GroupId, + unique_id: ::UniqueId, + ) -> Option { if group_id > (2u16.pow(14) - 1) { return None; } @@ -58,29 +115,9 @@ impl Event { unique_id, }) } - - /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event - /// ID is invalid - pub fn severity(&self) -> Severity { - self.severity - } - - pub fn group_id(&self) -> GroupId { - self.group_id - } - - pub fn unique_id(&self) -> UniqueId { - self.unique_id - } - - pub fn raw(&self) -> EventRaw { - (((self.severity as u32) << 30) as u32 - | ((self.group_id as u32) << 16) as u32 - | self.unique_id as u32) as EventRaw - } } -impl TryFrom for Event { +impl TryFrom for Event { type Error = (); fn try_from(raw: u32) -> Result { @@ -94,56 +131,6 @@ impl TryFrom for Event { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct EventSmall { - severity: Severity, - group_id: u8, - unique_id: u8, -} - -impl EventSmall { - /// Generate an event. The raw representation of an event has 32 bits. - /// If the passed group ID is invalid (too large), None wil be returned - /// - /// # Parameter - /// - /// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will - /// be stored inside the uppermost 3 bits of the raw event ID - /// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the - /// next 13 bits after the severity. Therefore, the size is limited by dec 8191 hex 0x1FFF. - /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the - /// raw event ID - pub fn new(severity: Severity, group_id: u8, unique_id: u8) -> Option { - if group_id > (2u8.pow(5) - 1) { - return None; - } - Some(Self { - severity, - group_id, - unique_id, - }) - } - - /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event - /// ID is invalid - pub fn severity(&self) -> Severity { - self.severity - } - - pub fn group_id(&self) -> u8 { - self.group_id - } - - pub fn unique_id(&self) -> u8 { - self.unique_id - } - - pub fn raw(&self) -> u16 { - (((self.severity as u16) << 12) as u16 - | ((self.group_id as u16) << 8) as u16 - | self.unique_id as u16) as u16 - } -} impl EcssEnumeration for Event { fn pfc(&self) -> u8 { 32 @@ -161,10 +148,78 @@ impl EcssEnumeration for Event { } } +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct EventSmall { + severity: Severity, + group_id: u8, + unique_id: u8, +} + +impl EventProvider for EventSmall { + type Raw = u16; + type GroupId = u8; + type UniqueId = u8; + + fn raw(&self) -> Self::Raw { + (((self.severity as Self::Raw) << 14) as Self::Raw + | ((self.group_id as Self::Raw) << 8) as Self::Raw + | self.unique_id as Self::Raw) as Self::Raw + } + + /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event + /// ID is invalid + fn severity(&self) -> Severity { + self.severity + } + + fn group_id(&self) -> Self::GroupId { + self.group_id.into() + } + + fn unique_id(&self) -> Self::UniqueId { + self.unique_id.into() + } + + fn raw_as_u32(&self) -> u32 { + self.raw().into() + } + + fn group_id_as_u16(&self) -> u16 { + self.group_id().into() + } +} + +impl EventSmall { + /// Generate a small event. The raw representation of a small event has 16 bits. + /// If the passed group ID is invalid (too large), [None] wil be returned + /// + /// # Parameter + /// + /// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will + /// be stored inside the uppermost 2 bits of the raw event ID + /// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the + /// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F. + /// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the + /// raw event ID + pub fn new( + severity: Severity, + group_id: ::GroupId, + unique_id: ::UniqueId, + ) -> Option { + if group_id > (2u8.pow(6) - 1) { + return None; + } + Some(Self { + severity, + group_id, + unique_id, + }) + } +} #[cfg(test)] mod tests { use super::Event; - use crate::events::Severity; + use crate::events::{EventProvider, Severity}; #[test] fn test_events() { diff --git a/fsrc-core/src/pus/event_man.rs b/fsrc-core/src/pus/event_man.rs index 0a006e1..6e1140d 100644 --- a/fsrc-core/src/pus/event_man.rs +++ b/fsrc-core/src/pus/event_man.rs @@ -50,7 +50,7 @@ impl PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider { #[cfg(feature = "heapless")] pub mod heapless_mod { use super::*; - use crate::events::EventRaw; + use crate::events::{EventProvider, EventRaw}; // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using // regular Event type again. From dd2929eb9887e1d874e6366baf1ee14247de883b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sun, 23 Oct 2022 18:36:33 +0200 Subject: [PATCH 5/5] small event support complete --- fsrc-core/src/event_man.rs | 11 +- fsrc-core/src/events.rs | 502 +++++++++++++++++++++++++-------- fsrc-core/src/pus/event_man.rs | 50 ++-- spacepackets | 2 +- 4 files changed, 414 insertions(+), 151 deletions(-) diff --git a/fsrc-core/src/event_man.rs b/fsrc-core/src/event_man.rs index 2fa71fd..4fe4092 100644 --- a/fsrc-core/src/event_man.rs +++ b/fsrc-core/src/event_man.rs @@ -52,7 +52,7 @@ impl EventManager { event: Event, dest: impl EventListener + 'static, ) { - self.update_listeners(ListenerType::Single(event.raw_as_u32()), dest); + self.update_listeners(ListenerType::Single(event.raw_as_largest_type()), dest); } pub fn subscribe_group( @@ -68,9 +68,9 @@ impl EventManager { pub fn subscribe_single( &mut self, event: EventSmall, - dest: impl EventListener + 'static, + dest: impl EventListener + 'static, ) { - self.update_listeners(ListenerType::Single(event.raw_as_u32()), dest); + self.update_listeners(ListenerType::Single(event.raw_as_largest_type()), dest); } pub fn subscribe_group( @@ -81,6 +81,7 @@ impl EventManager { self.update_listeners(ListenerType::Group(group_id.into()), dest); } } + impl EventManager { fn update_listeners( &mut self, @@ -123,11 +124,11 @@ impl EventManager { } }; if let Some(event) = self.event_receiver.receive() { - let single_key = ListenerType::Single(event.raw_as_u32()); + let single_key = ListenerType::Single(event.raw_as_largest_type()); if self.listeners.contains_key(&single_key) { send_handler(event, self.listeners.get_mut(&single_key).unwrap()); } - let group_key = ListenerType::Group(event.group_id_as_u16()); + let group_key = ListenerType::Group(event.group_id_as_largest_type()); if self.listeners.contains_key(&group_key) { send_handler(event, self.listeners.get_mut(&group_key).unwrap()); } diff --git a/fsrc-core/src/events.rs b/fsrc-core/src/events.rs index 2265e67..fc9c66f 100644 --- a/fsrc-core/src/events.rs +++ b/fsrc-core/src/events.rs @@ -1,16 +1,14 @@ //! Event support module -use spacepackets::ecss::EcssEnumeration; +use core::hash::Hash; +use spacepackets::ecss::{EcssEnumeration, ToBeBytes}; use spacepackets::{ByteConversionError, SizeMissmatch}; +use std::marker::PhantomData; -pub type EventRaw = u32; -pub type SmallEventRaw = u16; - -pub type GroupId = u16; -pub type UniqueId = u16; - -pub type GroupIdSmall = u8; -pub type UniqueIdSmall = u8; +/// Using a type definition allows to change this to u64 in the future more easily +pub type LargestEventRaw = u32; +/// Using a type definition allows to change this to u32 in the future more easily +pub type LargestGroupIdRaw = u16; #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] pub enum Severity { @@ -20,7 +18,7 @@ pub enum Severity { HIGH = 3, } -pub trait EventProvider: PartialEq + Eq + Copy + Clone { +pub trait EventProvider: PartialEq + Eq + Copy + Clone + Hash { type Raw; type GroupId; type UniqueId; @@ -30,8 +28,8 @@ pub trait EventProvider: PartialEq + Eq + Copy + Clone { fn group_id(&self) -> Self::GroupId; fn unique_id(&self) -> Self::UniqueId; - fn raw_as_u32(&self) -> u32; - fn group_id_as_u16(&self) -> u16; + fn raw_as_largest_type(&self) -> LargestEventRaw; + fn group_id_as_largest_type(&self) -> LargestGroupIdRaw; } impl TryFrom for Severity { @@ -49,10 +47,111 @@ impl TryFrom for Severity { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct Event { +pub struct EventBase { severity: Severity, - group_id: u16, - unique_id: u16, + group_id: GID, + unique_id: UID, + phantom: PhantomData, +} + +impl EventBase { + fn write_to_bytes( + &self, + raw: RAW, + buf: &mut [u8], + width: usize, + ) -> Result<(), ByteConversionError> { + if buf.len() < width { + return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { + found: buf.len(), + expected: width, + })); + } + buf.copy_from_slice(raw.to_be_bytes().as_ref()); + Ok(()) + } +} + +impl EventBase { + #[inline] + fn raw(&self) -> u32 { + (((self.severity as u32) << 30) | ((self.group_id as u32) << 16) | self.unique_id as u32) + as u32 + } +} + +impl EventBase { + #[inline] + fn raw(&self) -> u16 { + (((self.severity as u16) << 14) as u16 + | ((self.group_id as u16) << 8) as u16 + | self.unique_id as u16) as u16 + } +} + +impl EventBase { + #[inline] + pub fn severity(&self) -> Severity { + self.severity + } +} + +impl EventBase { + #[inline] + pub fn unique_id(&self) -> u16 { + self.unique_id + } +} + +impl EventBase { + #[inline] + pub fn unique_id(&self) -> u8 { + self.unique_id + } +} + +impl EventBase { + #[inline] + pub fn group_id(&self) -> u16 { + self.group_id + } +} + +impl EventBase { + #[inline] + pub fn group_id(&self) -> u8 { + self.group_id + } +} + +macro_rules! event_provider_impl { + () => { + #[inline] + fn raw(&self) -> Self::Raw { + self.base.raw() + } + + /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event + /// ID is invalid + #[inline] + fn severity(&self) -> Severity { + self.base.severity() + } + + #[inline] + fn group_id(&self) -> Self::GroupId { + self.base.group_id() + } + + #[inline] + fn unique_id(&self) -> Self::UniqueId { + self.base.unique_id() + } + }; +} +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub struct Event { + base: EventBase, } impl EventProvider for Event { @@ -60,31 +159,13 @@ impl EventProvider for Event { type GroupId = u16; type UniqueId = u16; - fn raw(&self) -> Self::Raw { - (((self.severity as Self::Raw) << 30) as Self::Raw - | ((self.group_id as Self::Raw) << 16) as Self::Raw - | self.unique_id as u32) as Self::Raw - } + event_provider_impl!(); - /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event - /// ID is invalid - fn severity(&self) -> Severity { - self.severity - } - - fn group_id(&self) -> Self::GroupId { - self.group_id - } - - fn unique_id(&self) -> Self::UniqueId { - self.unique_id - } - - fn raw_as_u32(&self) -> u32 { + fn raw_as_largest_type(&self) -> LargestEventRaw { self.raw() } - fn group_id_as_u16(&self) -> u16 { + fn group_id_as_largest_type(&self) -> LargestGroupIdRaw { self.group_id() } } @@ -110,24 +191,44 @@ impl Event { return None; } Some(Self { - severity, - group_id, - unique_id, + base: EventBase { + severity, + group_id, + unique_id, + phantom: PhantomData, + }, }) } + + /// Const version of [new], but panics on invalid input which is invalid group ID + /// values + pub const fn const_new( + severity: Severity, + group_id: ::GroupId, + unique_id: ::UniqueId, + ) -> Self { + if group_id > (2u16.pow(14) - 1) { + panic!("Group ID too large"); + } + Self { + base: EventBase { + severity, + group_id, + unique_id, + phantom: PhantomData, + }, + } + } } -impl TryFrom for Event { - type Error = (); - - fn try_from(raw: u32) -> Result { - let severity: Option = (((raw >> 30) & 0b11) as u8).try_into().ok(); - if severity.is_none() { - return Err(()); - } +impl From for Event { + fn from(raw: u32) -> Self { + // Severity conversion from u8 should never fail + let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap(); let group_id = ((raw >> 16) & 0x3FFF) as u16; let unique_id = (raw & 0xFFFF) as u16; - Event::new(severity.unwrap(), group_id, unique_id).ok_or(()) + // Sanitized input, should never fail + Self::const_new(severity, group_id, unique_id) } } @@ -137,56 +238,13 @@ impl EcssEnumeration for Event { } fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { - if buf.len() < self.byte_width() { - return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch { - found: buf.len(), - expected: self.byte_width(), - })); - } - buf.copy_from_slice(self.raw().to_be_bytes().as_slice()); - Ok(()) + self.base.write_to_bytes(self.raw(), buf, self.byte_width()) } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct EventSmall { - severity: Severity, - group_id: u8, - unique_id: u8, -} - -impl EventProvider for EventSmall { - type Raw = u16; - type GroupId = u8; - type UniqueId = u8; - - fn raw(&self) -> Self::Raw { - (((self.severity as Self::Raw) << 14) as Self::Raw - | ((self.group_id as Self::Raw) << 8) as Self::Raw - | self.unique_id as Self::Raw) as Self::Raw - } - - /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event - /// ID is invalid - fn severity(&self) -> Severity { - self.severity - } - - fn group_id(&self) -> Self::GroupId { - self.group_id.into() - } - - fn unique_id(&self) -> Self::UniqueId { - self.unique_id.into() - } - - fn raw_as_u32(&self) -> u32 { - self.raw().into() - } - - fn group_id_as_u16(&self) -> u16 { - self.group_id().into() - } + base: EventBase, } impl EventSmall { @@ -210,48 +268,244 @@ impl EventSmall { return None; } Some(Self { - severity, - group_id, - unique_id, + base: EventBase { + severity, + group_id, + unique_id, + phantom: Default::default(), + }, }) } + + pub const fn const_new( + severity: Severity, + group_id: ::GroupId, + unique_id: ::UniqueId, + ) -> Self { + if group_id > (2u8.pow(6) - 1) { + panic!("Group ID too large"); + } + Self { + base: EventBase { + severity, + group_id, + unique_id, + phantom: PhantomData, + }, + } + } } + +impl EventProvider for EventSmall { + type Raw = u16; + type GroupId = u8; + type UniqueId = u8; + + event_provider_impl!(); + + fn raw_as_largest_type(&self) -> LargestEventRaw { + self.raw().into() + } + + fn group_id_as_largest_type(&self) -> LargestGroupIdRaw { + self.group_id().into() + } +} + +impl EcssEnumeration for EventSmall { + fn pfc(&self) -> u8 { + 16 + } + + fn write_to_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> { + self.base.write_to_bytes(self.raw(), buf, self.byte_width()) + } +} + +impl From for EventSmall { + fn from(raw: ::Raw) -> Self { + let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap(); + let group_id = ((raw >> 8) & 0x3F) as u8; + let unique_id = (raw & 0xFF) as u8; + // Sanitized input, new call should never fail + Self::const_new(severity, group_id, unique_id) + } +} + #[cfg(test)] mod tests { use super::Event; - use crate::events::{EventProvider, Severity}; + use crate::events::{EventProvider, EventSmall, Severity}; + use spacepackets::ecss::EcssEnumeration; + use spacepackets::ByteConversionError; + use std::mem::size_of; + + fn assert_size(_: T, val: usize) { + assert_eq!(size_of::(), val); + } + + const INFO_EVENT: Event = Event::const_new(Severity::INFO, 0, 0); + const INFO_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::INFO, 0, 0); + const HIGH_SEV_EVENT: Event = Event::const_new(Severity::HIGH, 0x3FFF, 0xFFFF); + const HIGH_SEV_EVENT_SMALL: EventSmall = EventSmall::const_new(Severity::HIGH, 0x3F, 0xff); #[test] - fn test_events() { - let event = Event::new(Severity::INFO, 0, 0).unwrap(); - assert_eq!(event.severity(), Severity::INFO); - assert_eq!(event.unique_id(), 0); - assert_eq!(event.group_id(), 0); + fn test_normal_from_raw_conversion() { + let conv_from_raw = Event::from(INFO_EVENT.raw()); + assert_eq!(conv_from_raw, INFO_EVENT); + } - let raw_event = event.raw(); + #[test] + fn test_small_from_raw_conversion() { + let conv_from_raw = EventSmall::from(INFO_EVENT_SMALL.raw()); + assert_eq!(conv_from_raw, INFO_EVENT_SMALL); + } + + #[test] + fn verify_normal_size() { + assert_size(INFO_EVENT.raw(), 4) + } + + #[test] + fn verify_small_size() { + assert_size(INFO_EVENT_SMALL.raw(), 2) + } + + #[test] + fn test_normal_event_getters() { + assert_eq!(INFO_EVENT.severity(), Severity::INFO); + assert_eq!(INFO_EVENT.unique_id(), 0); + assert_eq!(INFO_EVENT.group_id(), 0); + let raw_event = INFO_EVENT.raw(); assert_eq!(raw_event, 0x00000000); - let conv_from_raw = Event::try_from(raw_event); - assert!(conv_from_raw.is_ok()); - let opt_event = conv_from_raw.ok(); - assert!(opt_event.is_some()); - let event = opt_event.unwrap(); - assert_eq!(event.severity(), Severity::INFO); - assert_eq!(event.unique_id(), 0); - assert_eq!(event.group_id(), 0); + } - let event = Event::new(Severity::HIGH, 0x3FFF, 0xFFFF).unwrap(); - assert_eq!(event.severity(), Severity::HIGH); - assert_eq!(event.group_id(), 0x3FFF); - assert_eq!(event.unique_id(), 0xFFFF); - let raw_event = event.raw(); + #[test] + fn test_small_event_getters() { + assert_eq!(INFO_EVENT_SMALL.severity(), Severity::INFO); + assert_eq!(INFO_EVENT_SMALL.unique_id(), 0); + assert_eq!(INFO_EVENT_SMALL.group_id(), 0); + let raw_event = INFO_EVENT_SMALL.raw(); + assert_eq!(raw_event, 0x00000000); + } + + #[test] + fn all_ones_event_regular() { + assert_eq!(HIGH_SEV_EVENT.severity(), Severity::HIGH); + assert_eq!(HIGH_SEV_EVENT.group_id(), 0x3FFF); + assert_eq!(HIGH_SEV_EVENT.unique_id(), 0xFFFF); + let raw_event = HIGH_SEV_EVENT.raw(); assert_eq!(raw_event, 0xFFFFFFFF); - let conv_from_raw = Event::try_from(raw_event); - assert!(conv_from_raw.is_ok()); - let opt_event = conv_from_raw.ok(); - assert!(opt_event.is_some()); - let event = opt_event.unwrap(); - assert_eq!(event.severity(), Severity::HIGH); - assert_eq!(event.group_id(), 0x3FFF); - assert_eq!(event.unique_id(), 0xFFFF); + } + + #[test] + fn all_ones_event_small() { + assert_eq!(HIGH_SEV_EVENT_SMALL.severity(), Severity::HIGH); + assert_eq!(HIGH_SEV_EVENT_SMALL.group_id(), 0x3F); + assert_eq!(HIGH_SEV_EVENT_SMALL.unique_id(), 0xFF); + let raw_event = HIGH_SEV_EVENT_SMALL.raw(); + assert_eq!(raw_event, 0xFFFF); + } + + #[test] + fn invalid_group_id_normal() { + assert!(Event::new(Severity::MEDIUM, 2_u16.pow(14), 0).is_none()); + } + + #[test] + fn invalid_group_id_small() { + assert!(EventSmall::new(Severity::MEDIUM, 2_u8.pow(6), 0).is_none()); + } + + #[test] + fn regular_new() { + assert_eq!( + Event::new(Severity::INFO, 0, 0).expect("Creating regular event failed"), + INFO_EVENT + ); + } + + #[test] + fn small_new() { + assert_eq!( + EventSmall::new(Severity::INFO, 0, 0).expect("Creating regular event failed"), + INFO_EVENT_SMALL + ); + } + + #[test] + fn as_largest_type() { + let event_raw = HIGH_SEV_EVENT.raw_as_largest_type(); + assert_size(event_raw, 4); + assert_eq!(event_raw, 0xFFFFFFFF); + } + + #[test] + fn as_largest_type_for_small_event() { + let event_raw = HIGH_SEV_EVENT_SMALL.raw_as_largest_type(); + assert_size(event_raw, 4); + assert_eq!(event_raw, 0xFFFF); + } + + #[test] + fn as_largest_group_id() { + let group_id = HIGH_SEV_EVENT.group_id_as_largest_type(); + assert_size(group_id, 2); + assert_eq!(group_id, 0x3FFF); + } + + #[test] + fn as_largest_group_id_small_event() { + let group_id = HIGH_SEV_EVENT_SMALL.group_id_as_largest_type(); + assert_size(group_id, 2); + assert_eq!(group_id, 0x3F); + } + + #[test] + fn write_to_buf() { + let mut buf: [u8; 4] = [0; 4]; + assert!(HIGH_SEV_EVENT.write_to_bytes(&mut buf).is_ok()); + let val_from_raw = u32::from_be_bytes(buf); + assert_eq!(val_from_raw, 0xFFFFFFFF); + } + + #[test] + fn write_to_buf_small() { + let mut buf: [u8; 2] = [0; 2]; + assert!(HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf).is_ok()); + let val_from_raw = u16::from_be_bytes(buf); + assert_eq!(val_from_raw, 0xFFFF); + } + + #[test] + fn write_to_buf_insufficient_buf() { + let mut buf: [u8; 3] = [0; 3]; + let err = HIGH_SEV_EVENT.write_to_bytes(&mut buf); + assert!(err.is_err()); + let err = err.unwrap_err(); + if let ByteConversionError::ToSliceTooSmall(missmatch) = err { + assert_eq!(missmatch.expected, 4); + assert_eq!(missmatch.found, 3); + } + } + + #[test] + fn write_to_buf_small_insufficient_buf() { + let mut buf: [u8; 1] = [0; 1]; + let err = HIGH_SEV_EVENT_SMALL.write_to_bytes(&mut buf); + assert!(err.is_err()); + let err = err.unwrap_err(); + if let ByteConversionError::ToSliceTooSmall(missmatch) = err { + assert_eq!(missmatch.expected, 2); + assert_eq!(missmatch.found, 1); + } + } + + #[test] + fn severity_from_invalid_raw_val() { + let invalid = 0xFF; + assert!(Severity::try_from(invalid).is_err()); + let invalid = Severity::HIGH as u8 + 1; + assert!(Severity::try_from(invalid).is_err()); } } diff --git a/fsrc-core/src/pus/event_man.rs b/fsrc-core/src/pus/event_man.rs index 6e1140d..2e33618 100644 --- a/fsrc-core/src/pus/event_man.rs +++ b/fsrc-core/src/pus/event_man.rs @@ -1,4 +1,4 @@ -use crate::events::Event; +use crate::events::EventProvider; use hashbrown::HashSet; #[cfg(feature = "heapless")] @@ -14,12 +14,12 @@ pub use heapless_mod::*; /// structure to track disabled events. A more primitive and embedded friendly /// solution could track this information in a static or pre-allocated list which contains /// the disabled events. -pub trait PusEventMgmtBackendProvider { +pub trait PusEventMgmtBackendProvider { type Error; - fn event_enabled(&self, event: &Event) -> bool; - fn enable_event_reporting(&mut self, event: &Event) -> Result; - fn disable_event_reporting(&mut self, event: &Event) -> Result; + fn event_enabled(&self, event: &Provider) -> bool; + fn enable_event_reporting(&mut self, event: &Provider) -> Result; + fn disable_event_reporting(&mut self, event: &Provider) -> Result; } /// Default backend provider which uses a hash set as the event reporting status container @@ -28,21 +28,23 @@ pub trait PusEventMgmtBackendProvider { /// This provider is a good option for host systems or larger embedded systems where /// the expected occasional memory allocation performed by the [HashSet] is not an issue. #[derive(Default)] -pub struct DefaultPusMgmtBackendProvider { - disabled: HashSet, +pub struct DefaultPusMgmtBackendProvider { + disabled: HashSet, } -impl PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider { +impl PusEventMgmtBackendProvider + for DefaultPusMgmtBackendProvider +{ type Error = (); - fn event_enabled(&self, event: &Event) -> bool { + fn event_enabled(&self, event: &Provider) -> bool { !self.disabled.contains(event) } - fn enable_event_reporting(&mut self, event: &Event) -> Result { + fn enable_event_reporting(&mut self, event: &Provider) -> Result { Ok(self.disabled.remove(event)) } - fn disable_event_reporting(&mut self, event: &Event) -> Result { + fn disable_event_reporting(&mut self, event: &Provider) -> Result { Ok(self.disabled.insert(*event)) } } @@ -50,28 +52,34 @@ impl PusEventMgmtBackendProvider for DefaultPusMgmtBackendProvider { #[cfg(feature = "heapless")] pub mod heapless_mod { use super::*; - use crate::events::{EventProvider, EventRaw}; + use crate::events::{EventProvider, LargestEventRaw}; + use std::marker::PhantomData; // TODO: After a new version of heapless is released which uses hash32 version 0.3, try using // regular Event type again. #[derive(Default)] - pub struct HeaplessPusMgmtBckendProvider { - disabled: heapless::FnvIndexSet, + pub struct HeaplessPusMgmtBckendProvider { + disabled: heapless::FnvIndexSet, + phantom: PhantomData, } - impl PusEventMgmtBackendProvider for HeaplessPusMgmtBckendProvider { + impl PusEventMgmtBackendProvider + for HeaplessPusMgmtBckendProvider + { type Error = (); - fn event_enabled(&self, event: &Event) -> bool { - self.disabled.contains(&event.raw()) + fn event_enabled(&self, event: &Provider) -> bool { + self.disabled.contains(&event.raw_as_largest_type()) } - fn enable_event_reporting(&mut self, event: &Event) -> Result { - self.disabled.insert(event.raw()).map_err(|_| ()) + fn enable_event_reporting(&mut self, event: &Provider) -> Result { + self.disabled + .insert(event.raw_as_largest_type()) + .map_err(|_| ()) } - fn disable_event_reporting(&mut self, event: &Event) -> Result { - Ok(self.disabled.remove(&event.raw())) + fn disable_event_reporting(&mut self, event: &Provider) -> Result { + Ok(self.disabled.remove(&event.raw_as_largest_type())) } } } diff --git a/spacepackets b/spacepackets index 603f688..a2673c9 160000 --- a/spacepackets +++ b/spacepackets @@ -1 +1 @@ -Subproject commit 603f688ac3e914de13037fd22ac544e125b6305b +Subproject commit a2673c98707ecbbabb9535bef607025c92b54724