diff --git a/satrs-core/CHANGELOG.md b/satrs-core/CHANGELOG.md
deleted file mode 100644
index 68e54a2..0000000
--- a/satrs-core/CHANGELOG.md
+++ /dev/null
@@ -1,9 +0,0 @@
-Change Log
-=======
-
-All notable changes to this project will be documented in this file.
-
-The format is based on [Keep a Changelog](http://keepachangelog.com/)
-and this project adheres to [Semantic Versioning](http://semver.org/).
-
-# [unreleased]
diff --git a/satrs-core/Cargo.toml b/satrs-core/Cargo.toml
deleted file mode 100644
index a7c5a73..0000000
--- a/satrs-core/Cargo.toml
+++ /dev/null
@@ -1,73 +0,0 @@
-[package]
-name = "satrs-core"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-delegate = "0.8"
-paste = "1.0"
-embed-doc-image = "0.1"
-
-[dependencies.dyn-clone]
-version = "1.0"
-optional = true
-
-[dependencies.hashbrown]
-version = "0.13"
-optional = true
-
-[dependencies.heapless]
-version = "0.7"
-optional = true
-
-[dependencies.num-traits]
-version = "0.2"
-default-features = false
-
-[dependencies.downcast-rs]
-version = "1.2"
-default-features = false
-optional = true
-
-[dependencies.bus]
-version = "2.2"
-optional = true
-
-[dependencies.crossbeam-channel]
-version= "0.5"
-default-features = false
-optional = true
-
-[dependencies.serde]
-version = "1.0"
-default-features = false
-optional = true
-
-[dependencies.spacepackets]
-# git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
-version = "0.4.0"
-default-features = false
-
-[dev-dependencies]
-serde = "1.0"
-zerocopy = "0.6"
-once_cell = "1.13"
-serde_json = "1"
-
-[dev-dependencies.postcard]
-version = "1.0"
-
-[features]
-default = ["std"]
-std = ["downcast-rs/std", "alloc", "bus", "postcard/use-std", "crossbeam-channel/std", "serde/std", "spacepackets/std"]
-alloc = ["serde/alloc", "spacepackets/alloc", "hashbrown", "dyn-clone", "downcast-rs"]
-serde = ["dep:serde", "spacepackets/serde"]
-crossbeam = ["crossbeam-channel"]
-heapless = ["dep:heapless"]
-doc-images = []
-
-[package.metadata.docs.rs]
-all-features = true
-rustdoc-args = ["--cfg", "doc_cfg"]
diff --git a/satrs-core/images/event_man_arch.graphml b/satrs-core/images/event_man_arch.graphml
deleted file mode 100644
index 1336793..0000000
--- a/satrs-core/images/event_man_arch.graphml
+++ /dev/null
@@ -1,259 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Example Event Flow
-
-
-
-
-
-
-
-
-
-
- Event Manager
-
-
-
-
-
-
-
-
-
-
- Event
-Creator 0
-
-
-
-
-
-
-
-
-
-
- Event
-Creator 2
-
-
-
-
-
-
-
-
-
-
- Event
-Creator 1
-
-
-
-
-
-
-
-
-
-
- Event
-Creator 3
-
-
-
-
-
-
-
-
-
-
- PUS Service 5
-Event Reporting
-
-
-
-
-
-
-
-
-
-
-
- PUS Service 19
-Event Action
-
-
-
-
-
-
-
-
-
-
- Telemetry
-Sink
-
-
-
-
-
-
-
-
-
-
- Subscriptions
-
-1. Event Creator 0 subscribes
- for event 0
-2. Event Creator 1 subscribes
- for event group 2
-3. PUS Service 5 handler
- subscribes for all events
-4. PUS Service 19 handler
- subscribes for all events
-
-
-
-
-
-
-
-
-
-
- event 1
-(group 1)
-
-
-
-
-
-
-
-
-
-
-
-
- event 0
-(group 0)
-
-
-
-
-
-
-
-
-
-
- event 2
-(group 3)
-
-
-
-
-
-
-
-
-
-
-
-
- event 3 (group 2)
-event 4 (group 2)
-
-
-
-
-
-
-
-
-
-
- <<all events>>
-
-
-
-
-
-
-
-
-
-
- <<all events>>
-
-
-
-
-
-
-
-
-
-
-
-
- event 1
-event 2
-
-
-
-
-
-
-
-
-
-
- group 2
-
-
-
-
-
-
-
-
-
-
- enabled Events
-as PUS 5 TM
-
-
-
-
-
-
-
-
-
diff --git a/satrs-core/images/event_man_arch.png b/satrs-core/images/event_man_arch.png
deleted file mode 100644
index 61c8d72..0000000
Binary files a/satrs-core/images/event_man_arch.png and /dev/null differ
diff --git a/satrs-core/src/error.rs b/satrs-core/src/error.rs
deleted file mode 100644
index 2144839..0000000
--- a/satrs-core/src/error.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-pub enum FsrcGroupIds {
- Tmtc = 0,
-}
-
-pub struct FsrcErrorRaw {
- pub group_id: u8,
- pub unique_id: u8,
- pub group_name: &'static str,
- pub info: &'static str,
-}
-
-pub trait FsrcErrorHandler {
- fn error(&mut self, e: FsrcErrorRaw);
- fn error_with_one_param(&mut self, e: FsrcErrorRaw, _p1: u32) {
- self.error(e);
- }
- fn error_with_two_params(&mut self, e: FsrcErrorRaw, _p1: u32, _p2: u32) {
- self.error(e);
- }
-}
-
-impl FsrcErrorRaw {
- pub const fn new(
- group_id: u8,
- unique_id: u8,
- group_name: &'static str,
- info: &'static str,
- ) -> Self {
- FsrcErrorRaw {
- group_id,
- unique_id,
- group_name,
- info,
- }
- }
-}
-
-#[derive(Clone, Copy, Default)]
-pub struct SimpleStdErrorHandler {}
-
-#[cfg(feature = "use_std")]
-impl FsrcErrorHandler for SimpleStdErrorHandler {
- fn error(&mut self, e: FsrcErrorRaw) {
- println!(
- "Received error from group {} with ID ({},{}): {}",
- e.group_name, e.group_id, e.unique_id, e.info
- );
- }
-}
diff --git a/satrs-core/src/event_man.rs b/satrs-core/src/event_man.rs
deleted file mode 100644
index 5d2db19..0000000
--- a/satrs-core/src/event_man.rs
+++ /dev/null
@@ -1,723 +0,0 @@
-//! Event management and forwarding
-//!
-//! This module provides components to perform event routing. The most important component for this
-//! task is the [EventManager]. It receives all events and then routes them to event subscribers
-//! where appropriate.
-#![cfg_attr(feature = "doc-images",
-cfg_attr(all(),
-doc = ::embed_doc_image::embed_image!("event_man_arch", "images/event_man_arch.png"
-)))]
-#![cfg_attr(
- not(feature = "doc-images"),
- doc = "**Doc images not enabled**. Compile with feature `doc-images` and Rust version >= 1.54 \
- to enable."
-)]
-//! One common use case for satellite systems is to offer a light-weight publish-subscribe mechanism
-//! and IPC mechanism for software and hardware events which are also packaged as telemetry (TM) or
-//! can trigger a system response.
-//!
-//! The following graph shows how the event flow for such a setup could look like:
-//!
-//! ![Event flow][event_man_arch]
-//!
-//! The event manager has a listener table abstracted by the [ListenerTable], which maps
-//! listener groups identified by [ListenerKey]s to a [sender ID][SenderId].
-//! It also contains a sender table abstracted by the [SenderTable] which maps these sender IDs
-//! to a concrete [SendEventProvider]s. A simple approach would be to use one send event provider
-//! for each OBSW thread and then subscribe for all interesting events for a particular thread
-//! using the send event provider ID.
-//!
-//! This can be done with the [EventManager] like this:
-//!
-//! 1. Provide a concrete [EventReceiver] implementation. This abstraction allow to use different
-//! message queue backends. A straightforward implementation where dynamic memory allocation is
-//! not a big concern could use [std::sync::mpsc::channel] to do this and is provided in
-//! form of the [MpscEventReceiver].
-//! 2. To set up event creators, create channel pairs using some message queue implementation.
-//! Each event creator gets a (cloned) sender component which allows it to send events to the
-//! manager.
-//! 3. The event manager receives the receiver component as part of a [EventReceiver]
-//! implementation so all events are routed to the manager.
-//! 4. Create the [send event providers][SendEventProvider]s which allow routing events to
-//! subscribers. You can now use their [sender IDs][SendEventProvider::id] to subscribe for
-//! event groups, for example by using the [EventManager::subscribe_single] method.
-//! 5. Add the send provider as well using the [EventManager::add_sender] call so the event
-//! manager can route listener groups to a the send provider.
-//!
-//! Some components like a PUS Event Service or PUS Event Action Service might require all
-//! events to package them as telemetry or start actions where applicable.
-//! 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.
-//!
-//! # Examples
-//!
-//! You can check [integration test](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-core/tests/pus_events.rs)
-//! for a concrete example using multi-threading where events are routed to
-//! different threads.
-use crate::events::{EventU16, EventU32, GenericEvent, LargestEventRaw, LargestGroupIdRaw};
-use crate::params::{Params, ParamsHeapless};
-#[cfg(feature = "alloc")]
-use alloc::boxed::Box;
-#[cfg(feature = "alloc")]
-use alloc::vec;
-#[cfg(feature = "alloc")]
-use alloc::vec::Vec;
-use core::slice::Iter;
-#[cfg(feature = "alloc")]
-use hashbrown::HashMap;
-
-#[cfg(feature = "std")]
-pub use stdmod::*;
-
-#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
-pub enum ListenerKey {
- Single(LargestEventRaw),
- Group(LargestGroupIdRaw),
- All,
-}
-
-pub type EventWithHeaplessAuxData = (Event, Option);
-pub type EventU32WithHeaplessAuxData = EventWithHeaplessAuxData;
-pub type EventU16WithHeaplessAuxData = EventWithHeaplessAuxData;
-
-pub type EventWithAuxData = (Event, Option);
-pub type EventU32WithAuxData = EventWithAuxData;
-pub type EventU16WithAuxData = EventWithAuxData;
-
-pub type SenderId = u32;
-
-pub trait SendEventProvider {
- type Error;
-
- fn id(&self) -> SenderId;
- fn send_no_data(&mut self, event: Provider) -> Result<(), Self::Error> {
- self.send(event, None)
- }
- fn send(
- &mut self,
- event: Provider,
- aux_data: Option,
- ) -> Result<(), Self::Error>;
-}
-
-/// Generic abstraction for an event receiver.
-pub trait EventReceiver {
- /// This function has to be provided by any event receiver. A receive call may or may not return
- /// an event.
- ///
- /// To allow returning arbitrary additional auxiliary data, a mutable slice is passed to the
- /// [Self::receive] call as well. Receivers can write data to this slice, but care must be taken
- /// to avoid panics due to size missmatches or out of bound writes.
- fn receive(&mut self) -> Option<(Event, Option)>;
-}
-
-pub trait ListenerTable {
- fn get_listeners(&self) -> Vec;
- fn contains_listener(&self, key: &ListenerKey) -> bool;
- fn get_listener_ids(&self, key: &ListenerKey) -> Option>;
- fn add_listener(&mut self, key: ListenerKey, sender_id: SenderId) -> bool;
- fn remove_duplicates(&mut self, key: &ListenerKey);
-}
-
-pub trait SenderTable {
- fn contains_send_event_provider(&self, id: &SenderId) -> bool;
- fn get_send_event_provider(
- &mut self,
- id: &SenderId,
- ) -> Option<&mut Box>>;
- fn add_send_event_provider(
- &mut self,
- send_provider: Box<
- dyn SendEventProvider,
- >,
- ) -> bool;
-}
-
-/// Generic event manager implementation.
-///
-/// # Generics
-///
-/// * `SendProviderError`: [SendEventProvider] error type
-/// * `Event`: Concrete event provider, currently either [EventU32] or [EventU16]
-/// * `AuxDataProvider`: Concrete auxiliary data provider, currently either [Params] or
-/// [ParamsHeapless]
-pub struct EventManager
-{
- listener_table: Box,
- sender_table: Box>,
- event_receiver: Box>,
-}
-
-/// Safety: It is safe to implement [Send] because all fields in the [EventManager] are [Send]
-/// as well
-#[cfg(feature = "std")]
-unsafe impl Send
- for EventManager
-{
-}
-
-#[cfg(feature = "std")]
-pub type EventManagerWithMpscQueue = EventManager<
- std::sync::mpsc::SendError<(Event, Option)>,
- Event,
- AuxDataProvider,
->;
-
-#[derive(Debug)]
-pub enum EventRoutingResult {
- /// No event was received
- Empty,
- /// An event was received and routed.
- /// The first tuple entry will contain the number of recipients.
- Handled(u32, Event, Option),
-}
-
-#[derive(Debug)]
-pub enum EventRoutingError {
- SendError(E),
- NoSendersForKey(ListenerKey),
- NoSenderForId(SenderId),
-}
-
-#[derive(Debug)]
-pub struct EventRoutingErrorsWithResult {
- pub result: EventRoutingResult,
- pub errors: [Option>; 3],
-}
-
-impl EventManager {
- pub fn remove_duplicates(&mut self, key: &ListenerKey) {
- self.listener_table.remove_duplicates(key)
- }
-
- /// Subscribe for a unique event.
- pub fn subscribe_single(&mut self, event: &Event, sender_id: SenderId) {
- self.update_listeners(ListenerKey::Single(event.raw_as_largest_type()), sender_id);
- }
-
- /// Subscribe for an event group.
- pub fn subscribe_group(&mut self, group_id: LargestGroupIdRaw, sender_id: SenderId) {
- self.update_listeners(ListenerKey::Group(group_id), sender_id);
- }
-
- /// Subscribe for all events received by the manager.
- ///
- /// For example, this can be useful for a handler component which sends every event as
- /// a telemetry packet.
- pub fn subscribe_all(&mut self, sender_id: SenderId) {
- self.update_listeners(ListenerKey::All, sender_id);
- }
-}
-
-impl
- EventManager
-{
- /// Create an event manager where the sender table will be the [DefaultSenderTableProvider]
- /// and the listener table will be the [DefaultListenerTableProvider].
- pub fn new(event_receiver: Box>) -> Self {
- let listener_table: Box = Box::default();
- let sender_table: Box> =
- Box::default();
- Self::new_custom_tables(listener_table, sender_table, event_receiver)
- }
-}
-
-impl
- EventManager
-{
- pub fn new_custom_tables(
- listener_table: Box,
- sender_table: Box>,
- event_receiver: Box>,
- ) -> Self {
- EventManager {
- listener_table,
- sender_table,
- event_receiver,
- }
- }
-
- pub fn add_sender(
- &mut self,
- send_provider: impl SendEventProvider + 'static,
- ) {
- if !self
- .sender_table
- .contains_send_event_provider(&send_provider.id())
- {
- self.sender_table
- .add_send_event_provider(Box::new(send_provider));
- }
- }
-
- fn update_listeners(&mut self, key: ListenerKey, sender_id: SenderId) {
- self.listener_table.add_listener(key, sender_id);
- }
-
- /// This function will use the cached event receiver and try to receive one event.
- /// If an event was received, it will try to route that event to all subscribed event listeners.
- /// If this works without any issues, the [EventRoutingResult] will contain context information
- /// about the routed event.
- ///
- /// This function will track up to 3 errors returned as part of the
- /// [EventRoutingErrorsWithResult] error struct.
- pub fn try_event_handling(
- &mut self,
- ) -> Result<
- EventRoutingResult,
- EventRoutingErrorsWithResult,
- > {
- let mut err_idx = 0;
- let mut err_slice = [None, None, None];
- let mut num_recipients = 0;
- let mut add_error = |error: EventRoutingError| {
- if err_idx < 3 {
- err_slice[err_idx] = Some(error);
- err_idx += 1;
- }
- };
- let mut send_handler =
- |key: &ListenerKey, event: Event, aux_data: &Option| {
- if self.listener_table.contains_listener(key) {
- if let Some(ids) = self.listener_table.get_listener_ids(key) {
- for id in ids {
- if let Some(sender) = self.sender_table.get_send_event_provider(id) {
- if let Err(e) = sender.send(event, aux_data.clone()) {
- add_error(EventRoutingError::SendError(e));
- } else {
- num_recipients += 1;
- }
- } else {
- add_error(EventRoutingError::NoSenderForId(*id));
- }
- }
- } else {
- add_error(EventRoutingError::NoSendersForKey(*key));
- }
- }
- };
- if let Some((event, aux_data)) = self.event_receiver.receive() {
- let single_key = ListenerKey::Single(event.raw_as_largest_type());
- send_handler(&single_key, event, &aux_data);
- let group_key = ListenerKey::Group(event.group_id_as_largest_type());
- send_handler(&group_key, event, &aux_data);
- send_handler(&ListenerKey::All, event, &aux_data);
- if err_idx > 0 {
- return Err(EventRoutingErrorsWithResult {
- result: EventRoutingResult::Handled(num_recipients, event, aux_data),
- errors: err_slice,
- });
- }
- return Ok(EventRoutingResult::Handled(num_recipients, event, aux_data));
- }
- Ok(EventRoutingResult::Empty)
- }
-}
-
-#[derive(Default)]
-pub struct DefaultListenerTableProvider {
- listeners: HashMap>,
-}
-
-pub struct DefaultSenderTableProvider<
- SendProviderError,
- Event: GenericEvent = EventU32,
- AuxDataProvider = Params,
-> {
- senders: HashMap<
- SenderId,
- Box>,
- >,
-}
-
-impl Default
- for DefaultSenderTableProvider
-{
- fn default() -> Self {
- Self {
- senders: HashMap::new(),
- }
- }
-}
-
-impl ListenerTable for DefaultListenerTableProvider {
- fn get_listeners(&self) -> Vec {
- let mut key_list = Vec::new();
- for key in self.listeners.keys() {
- key_list.push(*key);
- }
- key_list
- }
-
- fn contains_listener(&self, key: &ListenerKey) -> bool {
- self.listeners.contains_key(key)
- }
-
- fn get_listener_ids(&self, key: &ListenerKey) -> Option> {
- self.listeners.get(key).map(|vec| vec.iter())
- }
-
- fn add_listener(&mut self, key: ListenerKey, sender_id: SenderId) -> bool {
- if let Some(existing_list) = self.listeners.get_mut(&key) {
- existing_list.push(sender_id);
- } else {
- let new_list = vec![sender_id];
- self.listeners.insert(key, new_list);
- }
- true
- }
-
- fn remove_duplicates(&mut self, key: &ListenerKey) {
- if let Some(list) = self.listeners.get_mut(key) {
- list.sort_unstable();
- list.dedup();
- }
- }
-}
-
-impl
- SenderTable
- for DefaultSenderTableProvider
-{
- fn contains_send_event_provider(&self, id: &SenderId) -> bool {
- self.senders.contains_key(id)
- }
-
- fn get_send_event_provider(
- &mut self,
- id: &SenderId,
- ) -> Option<&mut Box>>
- {
- self.senders.get_mut(id).filter(|sender| sender.id() == *id)
- }
-
- fn add_send_event_provider(
- &mut self,
- send_provider: Box<
- dyn SendEventProvider,
- >,
- ) -> bool {
- let id = send_provider.id();
- if self.senders.contains_key(&id) {
- return false;
- }
- self.senders.insert(id, send_provider).is_none()
- }
-}
-
-#[cfg(feature = "std")]
-pub mod stdmod {
- use super::*;
- use crate::event_man::{EventReceiver, EventWithAuxData};
- use crate::events::{EventU16, EventU32, GenericEvent};
- use crate::params::Params;
- use std::sync::mpsc::{Receiver, SendError, Sender};
-
- pub struct MpscEventReceiver {
- mpsc_receiver: Receiver<(Event, Option)>,
- }
-
- impl MpscEventReceiver {
- pub fn new(receiver: Receiver<(Event, Option)>) -> Self {
- Self {
- mpsc_receiver: receiver,
- }
- }
- }
- impl EventReceiver for MpscEventReceiver {
- fn receive(&mut self) -> Option> {
- if let Ok(event_and_data) = self.mpsc_receiver.try_recv() {
- return Some(event_and_data);
- }
- None
- }
- }
-
- pub type MpscEventU32Receiver = MpscEventReceiver;
- pub type MpscEventU16Receiver = MpscEventReceiver;
-
- #[derive(Clone)]
- pub struct MpscEventSendProvider {
- id: u32,
- sender: Sender<(Event, Option)>,
- }
-
- impl MpscEventSendProvider {
- pub fn new(id: u32, sender: Sender<(Event, Option)>) -> Self {
- Self { id, sender }
- }
- }
-
- impl SendEventProvider for MpscEventSendProvider {
- type Error = SendError<(Event, Option)>;
-
- fn id(&self) -> u32 {
- self.id
- }
- fn send(&mut self, event: Event, aux_data: Option) -> Result<(), Self::Error> {
- self.sender.send((event, aux_data))
- }
- }
-
- pub type MpscEventU32SendProvider = MpscEventSendProvider;
- pub type MpscEventU16SendProvider = MpscEventSendProvider;
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::event_man::EventManager;
- use crate::events::{EventU32, GenericEvent, Severity};
- use crate::params::ParamsRaw;
- use alloc::boxed::Box;
- use std::format;
- use std::sync::mpsc::{channel, Receiver, SendError, Sender};
-
- #[derive(Clone)]
- struct MpscEventSenderQueue {
- id: u32,
- mpsc_sender: Sender,
- }
-
- impl MpscEventSenderQueue {
- fn new(id: u32, mpsc_sender: Sender) -> Self {
- Self { id, mpsc_sender }
- }
- }
-
- impl SendEventProvider for MpscEventSenderQueue {
- type Error = SendError;
-
- fn id(&self) -> u32 {
- self.id
- }
- fn send(&mut self, event: EventU32, aux_data: Option) -> Result<(), Self::Error> {
- self.mpsc_sender.send((event, aux_data))
- }
- }
-
- fn check_next_event(
- expected: EventU32,
- receiver: &Receiver,
- ) -> Option {
- if let Ok(event) = receiver.try_recv() {
- assert_eq!(event.0, expected);
- return event.1;
- }
- None
- }
-
- fn check_handled_event(
- res: EventRoutingResult,
- expected: EventU32,
- expected_num_sent: u32,
- ) {
- assert!(matches!(res, EventRoutingResult::Handled { .. }));
- if let EventRoutingResult::Handled(num_recipients, event, _aux_data) = res {
- assert_eq!(event, expected);
- assert_eq!(num_recipients, expected_num_sent);
- }
- }
-
- fn generic_event_man() -> (
- Sender,
- EventManager>,
- ) {
- let (event_sender, manager_queue) = channel();
- let event_man_receiver = MpscEventReceiver::new(manager_queue);
- (
- event_sender,
- EventManager::new(Box::new(event_man_receiver)),
- )
- }
-
- #[test]
- fn test_basic() {
- let (event_sender, mut event_man) = generic_event_man();
- let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap();
- let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
- let (single_event_sender, single_event_receiver) = channel();
- let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender);
- event_man.subscribe_single(&event_grp_0, single_event_listener.id());
- event_man.add_sender(single_event_listener);
- let (group_event_sender_0, group_event_receiver_0) = channel();
- let group_event_listener = MpscEventSenderQueue {
- id: 1,
- mpsc_sender: group_event_sender_0,
- };
- event_man.subscribe_group(event_grp_1_0.group_id(), group_event_listener.id());
- event_man.add_sender(group_event_listener);
-
- // Test event with one listener
- event_sender
- .send((event_grp_0, None))
- .expect("Sending single error failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_grp_0, 1);
- check_next_event(event_grp_0, &single_event_receiver);
-
- // Test event which is sent to all group listeners
- event_sender
- .send((event_grp_1_0, None))
- .expect("Sending group error failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_grp_1_0, 1);
- check_next_event(event_grp_1_0, &group_event_receiver_0);
- }
-
- #[test]
- fn test_with_basic_aux_data() {
- let (event_sender, mut event_man) = generic_event_man();
- let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap();
- let (single_event_sender, single_event_receiver) = channel();
- let single_event_listener = MpscEventSenderQueue::new(0, single_event_sender);
- event_man.subscribe_single(&event_grp_0, single_event_listener.id());
- event_man.add_sender(single_event_listener);
- event_sender
- .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());
- check_handled_event(res.unwrap(), event_grp_0, 1);
- let aux = check_next_event(event_grp_0, &single_event_receiver);
- assert!(aux.is_some());
- let aux = aux.unwrap();
- if let Params::Heapless(ParamsHeapless::Raw(ParamsRaw::U32Pair(pair))) = aux {
- assert_eq!(pair.0, 2);
- assert_eq!(pair.1, 3);
- } else {
- panic!("{}", format!("Unexpected auxiliary value type {:?}", aux));
- }
- }
-
- /// Test listening for multiple groups
- #[test]
- fn test_multi_group() {
- let (event_sender, mut event_man) = generic_event_man();
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- let hres = res.unwrap();
- assert!(matches!(hres, EventRoutingResult::Empty));
-
- let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap();
- let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
- let (event_grp_0_sender, event_grp_0_receiver) = channel();
- let event_grp_0_and_1_listener = MpscEventSenderQueue {
- id: 0,
- mpsc_sender: event_grp_0_sender,
- };
- event_man.subscribe_group(event_grp_0.group_id(), event_grp_0_and_1_listener.id());
- event_man.subscribe_group(event_grp_1_0.group_id(), event_grp_0_and_1_listener.id());
- event_man.add_sender(event_grp_0_and_1_listener);
-
- event_sender
- .send((event_grp_0, None))
- .expect("Sending Event Group 0 failed");
- event_sender
- .send((event_grp_1_0, None))
- .expect("Sendign Event Group 1 failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_grp_0, 1);
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_grp_1_0, 1);
-
- check_next_event(event_grp_0, &event_grp_0_receiver);
- check_next_event(event_grp_1_0, &event_grp_0_receiver);
- }
-
- /// Test listening to the same event from multiple listeners. Also test listening
- /// to both group and single events from one listener
- #[test]
- fn test_listening_to_same_event_and_multi_type() {
- let (event_sender, mut event_man) = generic_event_man();
- let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap();
- let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
- let (event_0_tx_0, event_0_rx_0) = channel();
- let (event_0_tx_1, event_0_rx_1) = channel();
- let event_listener_0 = MpscEventSenderQueue {
- id: 0,
- mpsc_sender: event_0_tx_0,
- };
- let event_listener_1 = MpscEventSenderQueue {
- id: 1,
- mpsc_sender: event_0_tx_1,
- };
- let event_listener_0_sender_id = event_listener_0.id();
- event_man.subscribe_single(&event_0, event_listener_0_sender_id);
- event_man.add_sender(event_listener_0);
- let event_listener_1_sender_id = event_listener_1.id();
- event_man.subscribe_single(&event_0, event_listener_1_sender_id);
- event_man.add_sender(event_listener_1);
- event_sender
- .send((event_0, None))
- .expect("Triggering Event 0 failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_0, 2);
- check_next_event(event_0, &event_0_rx_0);
- check_next_event(event_0, &event_0_rx_1);
- event_man.subscribe_group(event_1.group_id(), event_listener_0_sender_id);
- event_sender
- .send((event_0, None))
- .expect("Triggering Event 0 failed");
- event_sender
- .send((event_1, None))
- .expect("Triggering Event 1 failed");
-
- // 3 Events messages will be sent now
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_0, 2);
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_1, 1);
- // Both the single event and the group event should arrive now
- check_next_event(event_0, &event_0_rx_0);
- check_next_event(event_1, &event_0_rx_0);
-
- // Do double insertion and then remove duplicates
- event_man.subscribe_group(event_1.group_id(), event_listener_0_sender_id);
- event_man.remove_duplicates(&ListenerKey::Group(event_1.group_id()));
- event_sender
- .send((event_1, None))
- .expect("Triggering Event 1 failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_1, 1);
- }
-
- #[test]
- fn test_all_events_listener() {
- let (event_sender, manager_queue) = channel();
- let event_man_receiver = MpscEventReceiver::new(manager_queue);
- let mut event_man: EventManager> =
- EventManager::new(Box::new(event_man_receiver));
- let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap();
- let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap();
- let (event_0_tx_0, all_events_rx) = channel();
- let all_events_listener = MpscEventSenderQueue {
- id: 0,
- mpsc_sender: event_0_tx_0,
- };
- event_man.subscribe_all(all_events_listener.id());
- event_man.add_sender(all_events_listener);
- event_sender
- .send((event_0, None))
- .expect("Triggering event 0 failed");
- event_sender
- .send((event_1, None))
- .expect("Triggering event 1 failed");
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_0, 1);
- let res = event_man.try_event_handling();
- assert!(res.is_ok());
- check_handled_event(res.unwrap(), event_1, 1);
- check_next_event(event_0, &all_events_rx);
- check_next_event(event_1, &all_events_rx);
- }
-}
diff --git a/satrs-core/src/events.rs b/satrs-core/src/events.rs
deleted file mode 100644
index d5763a9..0000000
--- a/satrs-core/src/events.rs
+++ /dev/null
@@ -1,801 +0,0 @@
-//! Event support module
-//!
-//! This module includes the basic event structs [EventU32] and [EventU16] and versions with the
-//! ECSS severity levels as a type parameter. These structs are simple abstractions on top of the
-//! [u32] and [u16] types where the raw value is the unique identifier for a particular event.
-//! The abstraction also allows to group related events using a group ID, and the severity
-//! of an event is encoded inside the raw value itself with four possible [Severity] levels:
-//!
-//! - INFO
-//! - LOW
-//! - MEDIUM
-//! - HIGH
-//!
-//! All event structs implement the [EcssEnumeration] trait and can be created as constants.
-//! This allows to easily create a static list of constant events which can then be used to generate
-//! event telemetry using the PUS event manager modules.
-//!
-//! # Examples
-//!
-//! ```
-//! use satrs_core::events::{EventU16, EventU32, EventU32TypedSev, Severity, SeverityHigh, SeverityInfo};
-//!
-//! const MSG_RECVD: EventU32TypedSev = EventU32TypedSev::const_new(1, 0);
-//! const MSG_FAILED: EventU32 = EventU32::const_new(Severity::LOW, 1, 1);
-//!
-//! const TEMPERATURE_HIGH: EventU32TypedSev = EventU32TypedSev::const_new(2, 0);
-//!
-//! let small_event = EventU16::new(Severity::INFO, 3, 0);
-//! ```
-use core::fmt::Debug;
-use core::hash::Hash;
-use core::marker::PhantomData;
-use delegate::delegate;
-use spacepackets::ecss::{EcssEnumeration, ToBeBytes};
-use spacepackets::{ByteConversionError, SizeMissmatch};
-
-/// 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 {
- INFO = 0,
- LOW = 1,
- MEDIUM = 2,
- HIGH = 3,
-}
-
-pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone {
- const SEVERITY: Severity;
-}
-
-/// Type level support struct
-#[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, Copy, Clone)]
-pub struct SeverityLow {}
-impl HasSeverity for SeverityLow {
- const SEVERITY: Severity = Severity::LOW;
-}
-
-/// Type level support struct
-#[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, Copy, Clone)]
-pub struct SeverityHigh {}
-impl HasSeverity for SeverityHigh {
- const SEVERITY: Severity = Severity::HIGH;
-}
-
-pub trait GenericEvent: EcssEnumeration {
- 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_largest_type(&self) -> LargestEventRaw;
- fn group_id_as_largest_type(&self) -> LargestGroupIdRaw;
-}
-
-impl TryFrom for Severity {
- type Error = ();
-
- fn try_from(value: u8) -> Result {
- match value {
- x if x == Severity::INFO as u8 => Ok(Severity::INFO),
- x if x == Severity::LOW as u8 => Ok(Severity::LOW),
- x if x == Severity::MEDIUM as u8 => Ok(Severity::MEDIUM),
- x if x == Severity::HIGH as u8 => Ok(Severity::HIGH),
- _ => Err(()),
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-struct EventBase {
- severity: Severity,
- 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
- }
-}
-
-impl EventBase {
- #[inline]
- fn raw(&self) -> u16 {
- ((self.severity as u16) << 14) | ((self.group_id as u16) << 8) | self.unique_id 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()
- }
- };
-}
-
-macro_rules! impl_event_provider {
- ($BaseIdent: ident, $TypedIdent: ident, $raw: ty, $gid: ty, $uid: ty) => {
- impl GenericEvent for $BaseIdent {
- type Raw = $raw;
- type GroupId = $gid;
- type UniqueId = $uid;
-
- 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 GenericEvent for $TypedIdent {
- type Raw = $raw;
- type GroupId = $gid;
- type UniqueId = $uid;
-
- delegate!(to self.event {
- fn raw(&self) -> Self::Raw;
- fn severity(&self) -> Severity;
- fn group_id(&self) -> Self::GroupId;
- fn unique_id(&self) -> Self::UniqueId;
- fn raw_as_largest_type(&self) -> LargestEventRaw;
- fn group_id_as_largest_type(&self) -> LargestGroupIdRaw;
- });
- }
- }
-}
-
-macro_rules! try_from_impls {
- ($SevIdent: ident, $severity: path, $raw: ty, $TypedSevIdent: ident) => {
- impl TryFrom<$raw> for $TypedSevIdent<$SevIdent> {
- type Error = Severity;
-
- fn try_from(raw: $raw) -> Result {
- Self::try_from_generic($severity, raw)
- }
- }
- };
-}
-
-macro_rules! const_from_fn {
- ($from_fn_name: ident, $TypedIdent: ident, $SevIdent: ident) => {
- pub const fn $from_fn_name(event: $TypedIdent<$SevIdent>) -> Self {
- Self {
- base: event.event.base,
- }
- }
- };
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct EventU32 {
- base: EventBase,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct EventU32TypedSev {
- event: EventU32,
- phantom: PhantomData,
-}
-
-impl From> for EventU32 {
- fn from(e: EventU32TypedSev) -> Self {
- Self { base: e.event.base }
- }
-}
-
-impl AsRef for EventU32TypedSev {
- fn as_ref(&self) -> &EventU32 {
- &self.event
- }
-}
-
-impl AsMut for EventU32TypedSev {
- fn as_mut(&mut self) -> &mut EventU32 {
- &mut self.event
- }
-}
-
-impl_event_provider!(EventU32, EventU32TypedSev, u32, u16, u16);
-
-impl EventU32 {
- /// 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 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 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 {
- if group_id > (2u16.pow(14) - 1) {
- return None;
- }
- Some(Self {
- base: EventBase {
- severity,
- group_id,
- unique_id,
- phantom: PhantomData,
- },
- })
- }
- 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,
- },
- }
- }
-
- const_from_fn!(const_from_info, EventU32TypedSev, SeverityInfo);
- const_from_fn!(const_from_low, EventU32TypedSev, SeverityLow);
- const_from_fn!(const_from_medium, EventU32TypedSev, SeverityMedium);
- const_from_fn!(const_from_high, EventU32TypedSev, SeverityHigh);
-}
-
-impl EventU32TypedSev {
- /// This is similar to [EventU32::new] but the severity is a type generic, which allows to
- /// have distinct types for events with different severities
- pub fn new(
- group_id: ::GroupId,
- unique_id: ::UniqueId,
- ) -> Option {
- let event = EventU32::new(SEVERITY::SEVERITY, group_id, unique_id)?;
- Some(Self {
- event,
- phantom: PhantomData,
- })
- }
-
- /// Const version of [Self::new], but panics on invalid group ID input values.
- pub const fn const_new(
- group_id: ::GroupId,
- unique_id: ::UniqueId,
- ) -> Self {
- let event = EventU32::const_new(SEVERITY::SEVERITY, group_id, unique_id);
- Self {
- event,
- phantom: PhantomData,
- }
- }
-
- fn try_from_generic(expected: Severity, raw: u32) -> Result {
- let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
- if severity != expected {
- return Err(severity);
- }
- Ok(Self::const_new(
- ((raw >> 16) & 0x3FFF) as u16,
- (raw & 0xFFFF) as u16,
- ))
- }
-}
-
-impl From for EventU32 {
- 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;
- // Sanitized input, should never fail
- Self::const_new(severity, group_id, unique_id)
- }
-}
-
-try_from_impls!(SeverityInfo, Severity::INFO, u32, EventU32TypedSev);
-try_from_impls!(SeverityLow, Severity::LOW, u32, EventU32TypedSev);
-try_from_impls!(SeverityMedium, Severity::MEDIUM, u32, EventU32TypedSev);
-try_from_impls!(SeverityHigh, Severity::HIGH, u32, EventU32TypedSev);
-
-impl EcssEnumeration for EventU32 {
- fn pfc(&self) -> u8 {
- 32
- }
-
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
- self.base.write_to_bytes(self.raw(), buf, self.byte_width())
- }
-}
-
-//noinspection RsTraitImplementation
-impl EcssEnumeration for EventU32TypedSev {
- delegate!(to self.event {
- fn pfc(&self) -> u8;
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
- });
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct EventU16 {
- base: EventBase,
-}
-
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-pub struct EventU16TypedSev {
- event: EventU16,
- phantom: PhantomData,
-}
-
-impl AsRef for EventU16TypedSev {
- fn as_ref(&self) -> &EventU16 {
- &self.event
- }
-}
-
-impl AsMut for EventU16TypedSev {
- fn as_mut(&mut self) -> &mut EventU16 {
- &mut self.event
- }
-}
-
-impl EventU16 {
- /// 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 {
- base: EventBase {
- severity,
- group_id,
- unique_id,
- phantom: Default::default(),
- },
- })
- }
-
- /// Const version of [Self::new], but panics on invalid group ID input values.
- 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,
- },
- }
- }
- const_from_fn!(const_from_info, EventU16TypedSev, SeverityInfo);
- const_from_fn!(const_from_low, EventU16TypedSev, SeverityLow);
- const_from_fn!(const_from_medium, EventU16TypedSev, SeverityMedium);
- const_from_fn!(const_from_high, EventU16TypedSev, SeverityHigh);
-}
-
-impl EventU16TypedSev {
- /// This is similar to [EventU16::new] but the severity is a type generic, which allows to
- /// have distinct types for events with different severities
- pub fn new(
- group_id: ::GroupId,
- unique_id: ::UniqueId,
- ) -> Option {
- let event = EventU16::new(SEVERITY::SEVERITY, group_id, unique_id)?;
- Some(Self {
- event,
- phantom: PhantomData,
- })
- }
-
- /// Const version of [Self::new], but panics on invalid group ID input values.
- pub const fn const_new(
- group_id: ::GroupId,
- unique_id: ::UniqueId,
- ) -> Self {
- let event = EventU16::const_new(SEVERITY::SEVERITY, group_id, unique_id);
- Self {
- event,
- phantom: PhantomData,
- }
- }
-
- fn try_from_generic(expected: Severity, raw: u16) -> Result {
- let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
- if severity != expected {
- return Err(severity);
- }
- Ok(Self::const_new(
- ((raw >> 8) & 0x3F) as u8,
- (raw & 0xFF) as u8,
- ))
- }
-}
-
-impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
-
-impl EcssEnumeration for EventU16 {
- #[inline]
- fn pfc(&self) -> u8 {
- 16
- }
-
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError> {
- self.base.write_to_bytes(self.raw(), buf, self.byte_width())
- }
-}
-
-//noinspection RsTraitImplementation
-impl EcssEnumeration for EventU16TypedSev {
- delegate!(to self.event {
- fn pfc(&self) -> u8;
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<(), ByteConversionError>;
- });
-}
-
-impl From for EventU16 {
- 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)
- }
-}
-
-try_from_impls!(SeverityInfo, Severity::INFO, u16, EventU16TypedSev);
-try_from_impls!(SeverityLow, Severity::LOW, u16, EventU16TypedSev);
-try_from_impls!(SeverityMedium, Severity::MEDIUM, u16, EventU16TypedSev);
-try_from_impls!(SeverityHigh, Severity::HIGH, u16, EventU16TypedSev);
-
-impl PartialEq for EventU32TypedSev {
- #[inline]
- fn eq(&self, other: &EventU32) -> bool {
- self.raw() == other.raw()
- }
-}
-
-impl PartialEq> for EventU32 {
- #[inline]
- fn eq(&self, other: &EventU32TypedSev) -> bool {
- self.raw() == other.raw()
- }
-}
-
-impl PartialEq for EventU16TypedSev {
- #[inline]
- fn eq(&self, other: &EventU16) -> bool {
- self.raw() == other.raw()
- }
-}
-
-impl PartialEq> for EventU16 {
- #[inline]
- fn eq(&self, other: &EventU16TypedSev) -> bool {
- self.raw() == other.raw()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::EventU32TypedSev;
- use super::*;
- 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: EventU32TypedSev = EventU32TypedSev::const_new(0, 0);
- const INFO_EVENT_SMALL: EventU16TypedSev = EventU16TypedSev::const_new(0, 0);
- const HIGH_SEV_EVENT: EventU32TypedSev =
- EventU32TypedSev::const_new(0x3FFF, 0xFFFF);
- const HIGH_SEV_EVENT_SMALL: EventU16TypedSev =
- EventU16TypedSev::const_new(0x3F, 0xff);
-
- /// This working is a test in itself.
- const INFO_REDUCED: EventU32 = EventU32::const_from_info(INFO_EVENT);
-
- #[test]
- fn test_normal_from_raw_conversion() {
- let conv_from_raw = EventU32TypedSev::::try_from(INFO_EVENT.raw())
- .expect("Creating typed EventU32 failed");
- assert_eq!(conv_from_raw, INFO_EVENT);
- }
-
- #[test]
- fn test_small_from_raw_conversion() {
- let conv_from_raw = EventU16TypedSev::::try_from(INFO_EVENT_SMALL.raw())
- .expect("Creating typed EventU16 failed");
- 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);
- }
-
- #[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);
- }
-
- #[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!(EventU32TypedSev::::new(2_u16.pow(14), 0).is_none());
- }
-
- #[test]
- fn invalid_group_id_small() {
- assert!(EventU16TypedSev::::new(2_u8.pow(6), 0).is_none());
- }
-
- #[test]
- fn regular_new() {
- assert_eq!(
- EventU32TypedSev::::new(0, 0).expect("Creating regular event failed"),
- INFO_EVENT
- );
- }
-
- #[test]
- fn small_new() {
- assert_eq!(
- EventU16TypedSev::::new(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_be_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_be_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_be_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_be_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());
- }
-
- #[test]
- fn reduction() {
- let event = EventU32TypedSev::::const_new(1, 1);
- let raw = event.raw();
- let reduced: EventU32 = event.into();
- assert_eq!(reduced.group_id(), 1);
- assert_eq!(reduced.unique_id(), 1);
- assert_eq!(raw, reduced.raw());
- }
-
- #[test]
- fn const_reducation() {
- assert_eq!(INFO_REDUCED.raw(), INFO_EVENT.raw());
- }
-}
diff --git a/satrs-core/src/executable.rs b/satrs-core/src/executable.rs
deleted file mode 100644
index 440f8ee..0000000
--- a/satrs-core/src/executable.rs
+++ /dev/null
@@ -1,503 +0,0 @@
-//! Task scheduling module
-use bus::BusReader;
-use std::boxed::Box;
-use std::error::Error;
-use std::sync::mpsc::TryRecvError;
-use std::thread;
-use std::thread::JoinHandle;
-use std::time::Duration;
-use std::vec;
-use std::vec::Vec;
-
-#[derive(Debug, PartialEq, Eq)]
-pub enum OpResult {
- Ok,
- TerminationRequested,
-}
-
-pub enum ExecutionType {
- Infinite,
- Cycles(u32),
- OneShot,
-}
-
-pub trait Executable: Send {
- type Error;
-
- fn exec_type(&self) -> ExecutionType;
- fn task_name(&self) -> &'static str;
- fn periodic_op(&mut self, op_code: i32) -> Result;
-}
-
-/// This function allows executing one task which implements the [Executable][Executable] trait
-///
-/// # Arguments
-///
-/// * `executable`: Executable task
-/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks
-/// * `op_code`: Operation code which is passed to the executable task [operation call][Executable::periodic_op]
-/// * `termination`: Optional termination handler which can cancel threads with a broadcast
-pub fn exec_sched_single<
- T: Executable + Send + 'static + ?Sized,
- E: Error + Send + 'static,
->(
- mut executable: Box,
- task_freq: Option,
- op_code: i32,
- mut termination: Option>,
-) -> JoinHandle> {
- let mut cycle_count = 0;
- thread::spawn(move || loop {
- if let Some(ref mut terminator) = termination {
- match terminator.try_recv() {
- Ok(_) | Err(TryRecvError::Disconnected) => {
- return Ok(OpResult::Ok);
- }
- Err(TryRecvError::Empty) => (),
- }
- }
- match executable.exec_type() {
- ExecutionType::OneShot => {
- executable.periodic_op(op_code)?;
- return Ok(OpResult::Ok);
- }
- ExecutionType::Infinite => {
- executable.periodic_op(op_code)?;
- }
- ExecutionType::Cycles(cycles) => {
- executable.periodic_op(op_code)?;
- cycle_count += 1;
- if cycle_count == cycles {
- return Ok(OpResult::Ok);
- }
- }
- }
- let freq = task_freq.unwrap_or_else(|| panic!("No task frequency specified"));
- thread::sleep(freq);
- })
-}
-
-/// This function allows executing multiple tasks as long as the tasks implement the
-/// [Executable][Executable] trait
-///
-/// # Arguments
-///
-/// * `executable_vec`: Vector of executable objects
-/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks
-/// * `op_code`: Operation code which is passed to the executable task [operation call][Executable::periodic_op]
-/// * `termination`: Optional termination handler which can cancel threads with a broadcast
-pub fn exec_sched_multi<
- T: Executable + Send + 'static + ?Sized,
- E: Error + Send + 'static,
->(
- mut executable_vec: Vec>,
- task_freq: Option,
- op_code: i32,
- mut termination: Option>,
-) -> JoinHandle> {
- let mut cycle_counts = vec![0; executable_vec.len()];
- let mut removal_flags = vec![false; executable_vec.len()];
- thread::spawn(move || loop {
- if let Some(ref mut terminator) = termination {
- match terminator.try_recv() {
- Ok(_) | Err(TryRecvError::Disconnected) => {
- removal_flags.iter_mut().for_each(|x| *x = true);
- }
- Err(TryRecvError::Empty) => (),
- }
- }
- for (idx, executable) in executable_vec.iter_mut().enumerate() {
- match executable.exec_type() {
- ExecutionType::OneShot => {
- executable.periodic_op(op_code)?;
- removal_flags[idx] = true;
- }
- ExecutionType::Infinite => {
- executable.periodic_op(op_code)?;
- }
- ExecutionType::Cycles(cycles) => {
- executable.periodic_op(op_code)?;
- cycle_counts[idx] += 1;
- if cycle_counts[idx] == cycles {
- removal_flags[idx] = true;
- }
- }
- }
- }
- let mut removal_iter = removal_flags.iter();
- executable_vec.retain(|_| !*removal_iter.next().unwrap());
- removal_iter = removal_flags.iter();
- cycle_counts.retain(|_| !*removal_iter.next().unwrap());
- removal_flags.retain(|&i| !i);
- if executable_vec.is_empty() {
- return Ok(OpResult::Ok);
- }
- let freq = task_freq.unwrap_or_else(|| panic!("No task frequency specified"));
- thread::sleep(freq);
- })
-}
-
-#[cfg(test)]
-mod tests {
- use super::{exec_sched_multi, exec_sched_single, Executable, ExecutionType, OpResult};
- use bus::Bus;
- use std::boxed::Box;
- use std::error::Error;
- use std::string::{String, ToString};
- use std::sync::{Arc, Mutex};
- use std::time::Duration;
- use std::vec::Vec;
- use std::{fmt, thread, vec};
-
- struct TestInfo {
- exec_num: u32,
- op_code: i32,
- }
- struct OneShotTask {
- exec_num: Arc>,
- }
- struct FixedCyclesTask {
- cycles: u32,
- exec_num: Arc>,
- }
- struct PeriodicTask {
- exec_num: Arc>,
- }
-
- #[derive(Clone, Debug)]
- struct ExampleError {
- kind: ErrorKind,
- }
-
- /// The kind of an error that can occur.
- #[derive(Clone, Debug)]
- pub enum ErrorKind {
- Generic(String, i32),
- }
-
- impl ExampleError {
- fn new(msg: &str, code: i32) -> ExampleError {
- ExampleError {
- kind: ErrorKind::Generic(msg.to_string(), code),
- }
- }
-
- /// Return the kind of this error.
- pub fn kind(&self) -> &ErrorKind {
- &self.kind
- }
- }
-
- impl fmt::Display for ExampleError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self.kind() {
- ErrorKind::Generic(str, code) => {
- write!(f, "{str} with code {code}")
- }
- }
- }
- }
-
- impl Error for ExampleError {}
-
- const ONE_SHOT_TASK_NAME: &str = "One Shot Task";
-
- impl Executable for OneShotTask {
- type Error = ExampleError;
-
- fn exec_type(&self) -> ExecutionType {
- ExecutionType::OneShot
- }
-
- fn task_name(&self) -> &'static str {
- ONE_SHOT_TASK_NAME
- }
-
- fn periodic_op(&mut self, op_code: i32) -> Result {
- let mut data = self.exec_num.lock().expect("Locking Mutex failed");
- data.exec_num += 1;
- data.op_code = op_code;
- std::mem::drop(data);
- if op_code >= 0 {
- Ok(OpResult::Ok)
- } else {
- Err(ExampleError::new("One Shot Task Failure", op_code))
- }
- }
- }
-
- const CYCLE_TASK_NAME: &str = "Fixed Cycles Task";
-
- impl Executable for FixedCyclesTask {
- type Error = ExampleError;
-
- fn exec_type(&self) -> ExecutionType {
- ExecutionType::Cycles(self.cycles)
- }
-
- fn task_name(&self) -> &'static str {
- CYCLE_TASK_NAME
- }
-
- fn periodic_op(&mut self, op_code: i32) -> Result {
- let mut data = self.exec_num.lock().expect("Locking Mutex failed");
- data.exec_num += 1;
- data.op_code = op_code;
- std::mem::drop(data);
- if op_code >= 0 {
- Ok(OpResult::Ok)
- } else {
- Err(ExampleError::new("Fixed Cycle Task Failure", op_code))
- }
- }
- }
-
- const PERIODIC_TASK_NAME: &str = "Periodic Task";
-
- impl Executable for PeriodicTask {
- type Error = ExampleError;
-
- fn exec_type(&self) -> ExecutionType {
- ExecutionType::Infinite
- }
-
- fn task_name(&self) -> &'static str {
- PERIODIC_TASK_NAME
- }
-
- fn periodic_op(&mut self, op_code: i32) -> Result {
- let mut data = self.exec_num.lock().expect("Locking Mutex failed");
- data.exec_num += 1;
- data.op_code = op_code;
- std::mem::drop(data);
- if op_code >= 0 {
- Ok(OpResult::Ok)
- } else {
- Err(ExampleError::new("Example Task Failure", op_code))
- }
- }
- }
-
- #[test]
- fn test_simple_one_shot() {
- let expected_op_code = 42;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let exec_task = OneShotTask {
- exec_num: shared.clone(),
- };
- let task = Box::new(exec_task);
- let jhandle = exec_sched_single(
- task,
- Some(Duration::from_millis(100)),
- expected_op_code,
- None,
- );
- let thread_res = jhandle.join().expect("One Shot Task failed");
- assert!(thread_res.is_ok());
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(data.exec_num, 1);
- assert_eq!(data.op_code, expected_op_code);
- }
-
- #[test]
- fn test_failed_one_shot() {
- let op_code_inducing_failure = -1;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let exec_task = OneShotTask {
- exec_num: shared.clone(),
- };
- let task = Box::new(exec_task);
- let jhandle = exec_sched_single(
- task,
- Some(Duration::from_millis(100)),
- op_code_inducing_failure,
- None,
- );
- let thread_res = jhandle.join().expect("One Shot Task failed");
- assert!(thread_res.is_err());
- let error = thread_res.unwrap_err();
- let err = error.kind();
- assert!(matches!(err, &ErrorKind::Generic { .. }));
- match err {
- ErrorKind::Generic(str, op_code) => {
- assert_eq!(str, &String::from("One Shot Task Failure"));
- assert_eq!(op_code, &op_code_inducing_failure);
- }
- }
- let error_display = error.to_string();
- assert_eq!(error_display, "One Shot Task Failure with code -1");
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(data.exec_num, 1);
- assert_eq!(data.op_code, op_code_inducing_failure);
- }
-
- #[test]
- fn test_simple_multi_one_shot() {
- let expected_op_code = 43;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let exec_task_0 = OneShotTask {
- exec_num: shared.clone(),
- };
- let exec_task_1 = OneShotTask {
- exec_num: shared.clone(),
- };
- let task_vec = vec![Box::new(exec_task_0), Box::new(exec_task_1)];
- for task in task_vec.iter() {
- assert_eq!(task.task_name(), ONE_SHOT_TASK_NAME);
- }
- let jhandle = exec_sched_multi(
- task_vec,
- Some(Duration::from_millis(100)),
- expected_op_code,
- None,
- );
- let thread_res = jhandle.join().expect("One Shot Task failed");
- assert!(thread_res.is_ok());
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(data.exec_num, 2);
- assert_eq!(data.op_code, expected_op_code);
- }
-
- #[test]
- fn test_cycles_single() {
- let expected_op_code = 44;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let cycled_task = Box::new(FixedCyclesTask {
- exec_num: shared.clone(),
- cycles: 1,
- });
- assert_eq!(cycled_task.task_name(), CYCLE_TASK_NAME);
- let jh = exec_sched_single(
- cycled_task,
- Some(Duration::from_millis(100)),
- expected_op_code,
- None,
- );
- let thread_res = jh.join().expect("Cycles Task failed");
- assert!(thread_res.is_ok());
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- assert_eq!(data.exec_num, 1);
- assert_eq!(data.op_code, expected_op_code);
- }
-
- #[test]
- fn test_single_and_cycles() {
- let expected_op_code = 50;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let one_shot_task = Box::new(OneShotTask {
- exec_num: shared.clone(),
- });
- let cycled_task_0 = Box::new(FixedCyclesTask {
- exec_num: shared.clone(),
- cycles: 1,
- });
- let cycled_task_1 = Box::new(FixedCyclesTask {
- exec_num: shared.clone(),
- cycles: 1,
- });
- assert_eq!(cycled_task_0.task_name(), CYCLE_TASK_NAME);
- assert_eq!(one_shot_task.task_name(), ONE_SHOT_TASK_NAME);
- let task_vec: Vec>> =
- vec![one_shot_task, cycled_task_0, cycled_task_1];
- let jh = exec_sched_multi(
- task_vec,
- Some(Duration::from_millis(100)),
- expected_op_code,
- None,
- );
- let thread_res = jh.join().expect("Cycles Task failed");
- assert!(thread_res.is_ok());
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- assert_eq!(data.exec_num, 3);
- assert_eq!(data.op_code, expected_op_code);
- }
-
- #[test]
- #[ignore]
- fn test_periodic_single() {
- let mut terminator = Bus::new(5);
- let expected_op_code = 45;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let periodic_task = Box::new(PeriodicTask {
- exec_num: shared.clone(),
- });
- assert_eq!(periodic_task.task_name(), PERIODIC_TASK_NAME);
- let jh = exec_sched_single(
- periodic_task,
- Some(Duration::from_millis(20)),
- expected_op_code,
- Some(terminator.add_rx()),
- );
- thread::sleep(Duration::from_millis(40));
- terminator.broadcast(());
- let thread_res = jh.join().expect("Periodic Task failed");
- assert!(thread_res.is_ok());
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- let range = 2..4;
- assert!(range.contains(&data.exec_num));
- assert_eq!(data.op_code, expected_op_code);
- }
-
- #[test]
- #[ignore]
- fn test_periodic_multi() {
- let mut terminator = Bus::new(5);
- let expected_op_code = 46;
- let shared = Arc::new(Mutex::new(TestInfo {
- exec_num: 0,
- op_code: 0,
- }));
- let cycled_task = Box::new(FixedCyclesTask {
- exec_num: shared.clone(),
- cycles: 1,
- });
- let periodic_task_0 = Box::new(PeriodicTask {
- exec_num: shared.clone(),
- });
- let periodic_task_1 = Box::new(PeriodicTask {
- exec_num: shared.clone(),
- });
- assert_eq!(periodic_task_0.task_name(), PERIODIC_TASK_NAME);
- assert_eq!(periodic_task_1.task_name(), PERIODIC_TASK_NAME);
- let task_vec: Vec>> =
- vec![cycled_task, periodic_task_0, periodic_task_1];
- let jh = exec_sched_multi(
- task_vec,
- Some(Duration::from_millis(20)),
- expected_op_code,
- Some(terminator.add_rx()),
- );
- thread::sleep(Duration::from_millis(60));
- terminator.broadcast(());
- let thread_res = jh.join().expect("Periodic Task failed");
- assert!(thread_res.is_ok());
- let data = shared.lock().expect("Locking Mutex failed");
- assert_eq!(thread_res.unwrap(), OpResult::Ok);
- let range = 7..11;
- assert!(range.contains(&data.exec_num));
- assert_eq!(data.op_code, expected_op_code);
- }
-}
diff --git a/satrs-core/src/hal/host/mod.rs b/satrs-core/src/hal/host/mod.rs
deleted file mode 100644
index 8057db1..0000000
--- a/satrs-core/src/hal/host/mod.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-//! Helper modules intended to be used on hosts with a full [std] runtime
-pub mod udp_server;
diff --git a/satrs-core/src/hal/host/udp_server.rs b/satrs-core/src/hal/host/udp_server.rs
deleted file mode 100644
index ca0a26e..0000000
--- a/satrs-core/src/hal/host/udp_server.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-//! UDP server helper components
-use crate::tmtc::{ReceivesTc, ReceivesTcCore};
-use std::boxed::Box;
-use std::io::{Error, ErrorKind};
-use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
-use std::vec;
-use std::vec::Vec;
-
-/// This TC server helper can be used to receive raw PUS telecommands thorough a UDP interface.
-///
-/// It caches all received telecomands into a vector. The maximum expected telecommand size should
-/// be declared upfront. This avoids dynamic allocation during run-time. The user can specify a TC
-/// receiver in form of a special trait object which implements [ReceivesTc]. Please note that the
-/// receiver should copy out the received data if it the data is required past the
-/// [ReceivesTcCore::pass_tc] call.
-///
-/// # Examples
-///
-/// ```
-/// use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
-/// use satrs_core::hal::host::udp_server::UdpTcServer;
-/// use satrs_core::tmtc::{ReceivesTc, ReceivesTcCore};
-/// use spacepackets::SpHeader;
-/// use spacepackets::tc::PusTc;
-///
-/// #[derive (Default)]
-/// struct PingReceiver {}
-/// impl ReceivesTcCore for PingReceiver {
-/// type Error = ();
-/// fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
-/// assert_eq!(tc_raw.len(), 13);
-/// Ok(())
-/// }
-/// }
-///
-/// let mut buf = [0; 32];
-/// let dest_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7777);
-/// let ping_receiver = PingReceiver::default();
-/// let mut udp_tc_server = UdpTcServer::new(dest_addr, 2048, Box::new(ping_receiver))
-/// .expect("Creating UDP TMTC server failed");
-/// let mut sph = SpHeader::tc_unseg(0x02, 0, 0).unwrap();
-/// let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
-/// let len = pus_tc
-/// .write_to_bytes(&mut buf)
-/// .expect("Error writing PUS TC packet");
-/// assert_eq!(len, 13);
-/// let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed");
-/// client
-/// .send_to(&buf[0..len], dest_addr)
-/// .expect("Error sending PUS TC via UDP");
-/// ```
-///
-/// The [fsrc-example crate](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-example)
-/// server code also includes
-/// [example code](https://egit.irs.uni-stuttgart.de/rust/fsrc-launchpad/src/branch/main/fsrc-example/src/bin/obsw/tmtc.rs)
-/// on how to use this TC server. It uses the server to receive PUS telecommands on a specific port
-/// and then forwards them to a generic CCSDS packet receiver.
-pub struct UdpTcServer {
- pub socket: UdpSocket,
- recv_buf: Vec,
- sender_addr: Option,
- tc_receiver: Box>,
-}
-
-#[derive(Debug)]
-pub enum ReceiveResult {
- NothingReceived,
- IoError(Error),
- ReceiverError(E),
-}
-
-impl From for ReceiveResult {
- fn from(e: Error) -> Self {
- ReceiveResult::IoError(e)
- }
-}
-
-impl PartialEq for ReceiveResult {
- fn eq(&self, other: &Self) -> bool {
- use ReceiveResult::*;
- match (self, other) {
- (IoError(ref e), IoError(ref other_e)) => e.kind() == other_e.kind(),
- (NothingReceived, NothingReceived) => true,
- (ReceiverError(e), ReceiverError(other_e)) => e == other_e,
- _ => false,
- }
- }
-}
-
-impl Eq for ReceiveResult {}
-
-impl ReceivesTcCore for UdpTcServer {
- type Error = E;
-
- fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
- self.tc_receiver.pass_tc(tc_raw)
- }
-}
-
-impl UdpTcServer {
- pub fn new(
- addr: A,
- max_recv_size: usize,
- tc_receiver: Box>,
- ) -> Result {
- let server = Self {
- socket: UdpSocket::bind(addr)?,
- recv_buf: vec![0; max_recv_size],
- sender_addr: None,
- tc_receiver,
- };
- server.socket.set_nonblocking(true)?;
- Ok(server)
- }
-
- pub fn try_recv_tc(&mut self) -> Result<(usize, SocketAddr), ReceiveResult> {
- let res = match self.socket.recv_from(&mut self.recv_buf) {
- Ok(res) => res,
- Err(e) => {
- return if e.kind() == ErrorKind::WouldBlock || e.kind() == ErrorKind::TimedOut {
- Err(ReceiveResult::NothingReceived)
- } else {
- Err(e.into())
- }
- }
- };
- let (num_bytes, from) = res;
- self.sender_addr = Some(from);
- self.tc_receiver
- .pass_tc(&self.recv_buf[0..num_bytes])
- .map_err(|e| ReceiveResult::ReceiverError(e))?;
- Ok(res)
- }
-
- pub fn last_sender(&self) -> Option {
- self.sender_addr
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::hal::host::udp_server::{ReceiveResult, UdpTcServer};
- use crate::tmtc::ReceivesTcCore;
- use spacepackets::tc::PusTc;
- use spacepackets::SpHeader;
- use std::boxed::Box;
- use std::collections::VecDeque;
- use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
- use std::vec::Vec;
-
- fn is_send(_: &T) {}
-
- #[derive(Default)]
- struct PingReceiver {
- pub sent_cmds: VecDeque>,
- }
-
- impl ReceivesTcCore for PingReceiver {
- type Error = ();
-
- fn pass_tc(&mut self, tc_raw: &[u8]) -> Result<(), Self::Error> {
- let mut sent_data = Vec::new();
- sent_data.extend_from_slice(tc_raw);
- self.sent_cmds.push_back(sent_data);
- Ok(())
- }
- }
-
- #[test]
- fn basic_test() {
- let mut buf = [0; 32];
- let dest_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7777);
- let ping_receiver = PingReceiver::default();
- is_send(&ping_receiver);
- let mut udp_tc_server = UdpTcServer::new(dest_addr, 2048, Box::new(ping_receiver))
- .expect("Creating UDP TMTC server failed");
- is_send(&udp_tc_server);
- let mut sph = SpHeader::tc_unseg(0x02, 0, 0).unwrap();
- let pus_tc = PusTc::new_simple(&mut sph, 17, 1, None, true);
- let len = pus_tc
- .write_to_bytes(&mut buf)
- .expect("Error writing PUS TC packet");
- let client = UdpSocket::bind("127.0.0.1:7778").expect("Connecting to UDP server failed");
- client
- .send_to(&buf[0..len], dest_addr)
- .expect("Error sending PUS TC via UDP");
- let local_addr = client.local_addr().unwrap();
- udp_tc_server
- .try_recv_tc()
- .expect("Error receiving sent telecommand");
- assert_eq!(
- udp_tc_server.last_sender().expect("No sender set"),
- local_addr
- );
- let ping_receiver: &mut PingReceiver = udp_tc_server.tc_receiver.downcast_mut().unwrap();
- assert_eq!(ping_receiver.sent_cmds.len(), 1);
- let sent_cmd = ping_receiver.sent_cmds.pop_front().unwrap();
- assert_eq!(sent_cmd, buf[0..len]);
- }
-
- #[test]
- fn test_nothing_received() {
- let dest_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7779);
- let ping_receiver = PingReceiver::default();
- let mut udp_tc_server = UdpTcServer::new(dest_addr, 2048, Box::new(ping_receiver))
- .expect("Creating UDP TMTC server failed");
- let res = udp_tc_server.try_recv_tc();
- assert!(res.is_err());
- let err = res.unwrap_err();
- assert_eq!(err, ReceiveResult::NothingReceived);
- }
-}
diff --git a/satrs-core/src/hal/mod.rs b/satrs-core/src/hal/mod.rs
deleted file mode 100644
index c422a72..0000000
--- a/satrs-core/src/hal/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! # Hardware Abstraction Layer module
-#[cfg(feature = "std")]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
-pub mod host;
diff --git a/satrs-core/src/lib.rs b/satrs-core/src/lib.rs
deleted file mode 100644
index 51ee886..0000000
--- a/satrs-core/src/lib.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-//! # Core components of the Flight Software Rust Crate (FSRC) collection
-//!
-//! This is a collection of Rust crates which can be used to build On-Board Software for remote
-//! systems like satellites of rovers. It has special support for space tailored protocols
-//! like the ones provided by CCSDS and ECSS.
-//!
-//! The crates can generally be used in a `no_std` environment, but some crates expect that the
-//! [alloc](https://doc.rust-lang.org/alloc) crate is available to allow boxed trait objects.
-//! These are used to supply user code to the crates.
-#![no_std]
-#![cfg_attr(doc_cfg, feature(doc_cfg))]
-#[cfg(feature = "alloc")]
-extern crate alloc;
-#[cfg(feature = "alloc")]
-extern crate downcast_rs;
-#[cfg(any(feature = "std", test))]
-extern crate std;
-
-pub mod error;
-#[cfg(feature = "alloc")]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
-pub mod event_man;
-pub mod events;
-#[cfg(feature = "std")]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
-pub mod executable;
-pub mod hal;
-pub mod objects;
-pub mod params;
-#[cfg(feature = "alloc")]
-#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
-pub mod pool;
-pub mod pus;
-pub mod res_code;
-pub mod seq_count;
-pub mod tmtc;
-
-pub use spacepackets;
diff --git a/satrs-core/src/objects.rs b/satrs-core/src/objects.rs
deleted file mode 100644
index bc17696..0000000
--- a/satrs-core/src/objects.rs
+++ /dev/null
@@ -1,306 +0,0 @@
-//! # Module providing addressable object support and a manager for them
-//!
-//! Each addressable object can be identified using an [object ID][ObjectId].
-//! The [system object][ManagedSystemObject] trait also allows storing these objects into the
-//! [object manager][ObjectManager]. They can then be retrieved and casted back to a known type
-//! using the object ID.
-//!
-//! # Examples
-//!
-//! ```rust
-//! use std::any::Any;
-//! use std::error::Error;
-//! use satrs_core::objects::{ManagedSystemObject, ObjectId, ObjectManager, SystemObject};
-//!
-//! struct ExampleSysObj {
-//! id: ObjectId,
-//! dummy: u32,
-//! was_initialized: bool,
-//! }
-//!
-//! impl ExampleSysObj {
-//! fn new(id: ObjectId, dummy: u32) -> ExampleSysObj {
-//! ExampleSysObj {
-//! id,
-//! dummy,
-//! was_initialized: false,
-//! }
-//! }
-//! }
-//!
-//! impl SystemObject for ExampleSysObj {
-//! type Error = ();
-//! fn get_object_id(&self) -> &ObjectId {
-//! &self.id
-//! }
-//!
-//! fn initialize(&mut self) -> Result<(), Self::Error> {
-//! self.was_initialized = true;
-//! Ok(())
-//! }
-//! }
-//!
-//! impl ManagedSystemObject for ExampleSysObj {}
-//!
-//! let mut obj_manager = ObjectManager::default();
-//! let obj_id = ObjectId { id: 0, name: "Example 0"};
-//! let example_obj = ExampleSysObj::new(obj_id, 42);
-//! obj_manager.insert(Box::new(example_obj));
-//! let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get_ref(&obj_id);
-//! let example_obj = obj_back_casted.unwrap();
-//! assert_eq!(example_obj.id, obj_id);
-//! assert_eq!(example_obj.dummy, 42);
-//! ```
-#[cfg(feature = "alloc")]
-use alloc::boxed::Box;
-#[cfg(feature = "alloc")]
-pub use alloc_mod::*;
-#[cfg(feature = "alloc")]
-use downcast_rs::Downcast;
-#[cfg(feature = "alloc")]
-use hashbrown::HashMap;
-#[cfg(feature = "std")]
-use std::error::Error;
-
-#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
-pub struct ObjectId {
- pub id: u32,
- pub name: &'static str,
-}
-
-#[cfg(feature = "alloc")]
-pub mod alloc_mod {
- use super::*;
-
- /// Each object which is stored inside the [object manager][ObjectManager] needs to implemented
- /// this trait
- pub trait SystemObject: Downcast {
- type Error;
- fn get_object_id(&self) -> &ObjectId;
- fn initialize(&mut self) -> Result<(), Self::Error>;
- }
- downcast_rs::impl_downcast!(SystemObject assoc Error);
-
- pub trait ManagedSystemObject: SystemObject + Send {}
- downcast_rs::impl_downcast!(ManagedSystemObject assoc Error);
-
- /// Helper module to manage multiple [ManagedSystemObjects][ManagedSystemObject] by mapping them
- /// using an [object ID][ObjectId]
- #[cfg(feature = "alloc")]
- pub struct ObjectManager {
- obj_map: HashMap>>,
- }
-
- #[cfg(feature = "alloc")]
- impl Default for ObjectManager {
- fn default() -> Self {
- Self::new()
- }
- }
-
- #[cfg(feature = "alloc")]
- impl ObjectManager {
- pub fn new() -> Self {
- ObjectManager {
- obj_map: HashMap::new(),
- }
- }
- pub fn insert(&mut self, sys_obj: Box>) -> bool {
- let obj_id = sys_obj.get_object_id();
- if self.obj_map.contains_key(obj_id) {
- return false;
- }
- self.obj_map.insert(*obj_id, sys_obj).is_none()
- }
-
- /// Initializes all System Objects in the hash map and returns the number of successful
- /// initializations
- pub fn initialize(&mut self) -> Result> {
- let mut init_success = 0;
- for val in self.obj_map.values_mut() {
- if val.initialize().is_ok() {
- init_success += 1
- }
- }
- Ok(init_success)
- }
-
- /// Retrieve a reference to an object stored inside the manager. The type to retrieve needs to
- /// be explicitly passed as a generic parameter or specified on the left hand side of the
- /// expression.
- pub fn get_ref>(&self, key: &ObjectId) -> Option<&T> {
- self.obj_map.get(key).and_then(|o| o.downcast_ref::())
- }
-
- /// Retrieve a mutable reference to an object stored inside the manager. The type to retrieve
- /// needs to be explicitly passed as a generic parameter or specified on the left hand side
- /// of the expression.
- pub fn get_mut>(
- &mut self,
- key: &ObjectId,
- ) -> Option<&mut T> {
- self.obj_map
- .get_mut(key)
- .and_then(|o| o.downcast_mut::())
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::objects::{ManagedSystemObject, ObjectId, ObjectManager, SystemObject};
- use std::boxed::Box;
- use std::string::String;
- use std::sync::{Arc, Mutex};
- use std::thread;
-
- struct ExampleSysObj {
- id: ObjectId,
- dummy: u32,
- was_initialized: bool,
- }
-
- impl ExampleSysObj {
- fn new(id: ObjectId, dummy: u32) -> ExampleSysObj {
- ExampleSysObj {
- id,
- dummy,
- was_initialized: false,
- }
- }
- }
-
- impl SystemObject for ExampleSysObj {
- type Error = ();
- fn get_object_id(&self) -> &ObjectId {
- &self.id
- }
-
- fn initialize(&mut self) -> Result<(), Self::Error> {
- self.was_initialized = true;
- Ok(())
- }
- }
-
- impl ManagedSystemObject for ExampleSysObj {}
-
- struct OtherExampleObject {
- id: ObjectId,
- string: String,
- was_initialized: bool,
- }
-
- impl SystemObject for OtherExampleObject {
- type Error = ();
- fn get_object_id(&self) -> &ObjectId {
- &self.id
- }
-
- fn initialize(&mut self) -> Result<(), Self::Error> {
- self.was_initialized = true;
- Ok(())
- }
- }
-
- impl ManagedSystemObject for OtherExampleObject {}
-
- #[test]
- fn test_obj_manager_simple() {
- let mut obj_manager = ObjectManager::default();
- let expl_obj_id = ObjectId {
- id: 0,
- name: "Example 0",
- };
- let example_obj = ExampleSysObj::new(expl_obj_id, 42);
- assert!(obj_manager.insert(Box::new(example_obj)));
- let res = obj_manager.initialize();
- assert!(res.is_ok());
- assert_eq!(res.unwrap(), 1);
- let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get_ref(&expl_obj_id);
- assert!(obj_back_casted.is_some());
- let expl_obj_back_casted = obj_back_casted.unwrap();
- assert_eq!(expl_obj_back_casted.dummy, 42);
- assert!(expl_obj_back_casted.was_initialized);
-
- let second_obj_id = ObjectId {
- id: 12,
- name: "Example 1",
- };
- let second_example_obj = OtherExampleObject {
- id: second_obj_id,
- string: String::from("Hello Test"),
- was_initialized: false,
- };
-
- assert!(obj_manager.insert(Box::new(second_example_obj)));
- let res = obj_manager.initialize();
- assert!(res.is_ok());
- assert_eq!(res.unwrap(), 2);
- let obj_back_casted: Option<&OtherExampleObject> = obj_manager.get_ref(&second_obj_id);
- assert!(obj_back_casted.is_some());
- let expl_obj_back_casted = obj_back_casted.unwrap();
- assert_eq!(expl_obj_back_casted.string, String::from("Hello Test"));
- assert!(expl_obj_back_casted.was_initialized);
-
- let existing_obj_id = ObjectId {
- id: 12,
- name: "Example 1",
- };
- let invalid_obj = OtherExampleObject {
- id: existing_obj_id,
- string: String::from("Hello Test"),
- was_initialized: false,
- };
-
- assert!(!obj_manager.insert(Box::new(invalid_obj)));
- }
-
- #[test]
- fn object_man_threaded() {
- let obj_manager = Arc::new(Mutex::new(ObjectManager::new()));
- let expl_obj_id = ObjectId {
- id: 0,
- name: "Example 0",
- };
- let example_obj = ExampleSysObj::new(expl_obj_id, 42);
- let second_obj_id = ObjectId {
- id: 12,
- name: "Example 1",
- };
- let second_example_obj = OtherExampleObject {
- id: second_obj_id,
- string: String::from("Hello Test"),
- was_initialized: false,
- };
-
- let mut obj_man_handle = obj_manager.lock().expect("Mutex lock failed");
- assert!(obj_man_handle.insert(Box::new(example_obj)));
- assert!(obj_man_handle.insert(Box::new(second_example_obj)));
- let res = obj_man_handle.initialize();
- std::mem::drop(obj_man_handle);
- assert!(res.is_ok());
- assert_eq!(res.unwrap(), 2);
- let obj_man_0 = obj_manager.clone();
- let jh0 = thread::spawn(move || {
- let locked_man = obj_man_0.lock().expect("Mutex lock failed");
- let obj_back_casted: Option<&ExampleSysObj> = locked_man.get_ref(&expl_obj_id);
- assert!(obj_back_casted.is_some());
- let expl_obj_back_casted = obj_back_casted.unwrap();
- assert_eq!(expl_obj_back_casted.dummy, 42);
- assert!(expl_obj_back_casted.was_initialized);
- std::mem::drop(locked_man)
- });
-
- let jh1 = thread::spawn(move || {
- let locked_man = obj_manager.lock().expect("Mutex lock failed");
- let obj_back_casted: Option<&OtherExampleObject> = locked_man.get_ref(&second_obj_id);
- assert!(obj_back_casted.is_some());
- let expl_obj_back_casted = obj_back_casted.unwrap();
- assert_eq!(expl_obj_back_casted.string, String::from("Hello Test"));
- assert!(expl_obj_back_casted.was_initialized);
- std::mem::drop(locked_man)
- });
- jh0.join().expect("Joining thread 0 failed");
- jh1.join().expect("Joining thread 1 failed");
- }
-}
diff --git a/satrs-core/src/params.rs b/satrs-core/src/params.rs
deleted file mode 100644
index bd616bd..0000000
--- a/satrs-core/src/params.rs
+++ /dev/null
@@ -1,648 +0,0 @@
-//! Parameter types and enums.
-//!
-//! This module contains various helper types.
-//!
-//! # Primtive Parameter Wrappers and Enumeration
-//!
-//! This module includes wrapper for primitive rust types using the newtype pattern.
-//! This was also done for pairs and triplets of these primitive types.
-//! The [WritableToBeBytes] was implemented for all those types as well, which allows to easily
-//! convert them into a network friendly raw byte format. The [ParamsRaw] enumeration groups
-//! all newtypes and implements the [WritableToBeBytes] trait itself.
-//!
-//! ## Example for primitive type wrapper
-//!
-//! ```
-//! use satrs_core::params::{ParamsRaw, ToBeBytes, U32Pair, WritableToBeBytes};
-//!
-//! let u32_pair = U32Pair(0x1010, 25);
-//! assert_eq!(u32_pair.0, 0x1010);
-//! assert_eq!(u32_pair.1, 25);
-//! // Convert to raw stream
-//! let raw_buf = u32_pair.to_be_bytes();
-//! assert_eq!(raw_buf, [0, 0, 0x10, 0x10, 0, 0, 0, 25]);
-//!
-//! // Convert to enum variant
-//! let params_raw: ParamsRaw = u32_pair.into();
-//! assert_eq!(params_raw, (0x1010_u32, 25_u32).into());
-//!
-//! // Convert to stream using the enum variant
-//! let mut other_raw_buf: [u8; 8] = [0; 8];
-//! params_raw.write_to_be_bytes(&mut other_raw_buf).expect("Writing parameter to buffer failed");
-//! assert_eq!(other_raw_buf, [0, 0, 0x10, 0x10, 0, 0, 0, 25]);
-//!
-//! // Create a pair from a raw stream
-//! let u32_pair_from_stream: U32Pair = raw_buf.as_slice().try_into().unwrap();
-//! assert_eq!(u32_pair_from_stream.0, 0x1010);
-//! assert_eq!(u32_pair_from_stream.1, 25);
-//! ```
-//!
-//! # Generic Parameter Enumeration
-//!
-//! The module also contains generic parameter enumerations.
-//! This includes the [ParamsHeapless] enumeration for contained values which do not require heap
-//! allocation, and the [Params] which enumerates [ParamsHeapless] and some additional types which
-//! require [alloc] support but allow for more flexbility.
-#[cfg(feature = "alloc")]
-use crate::pool::StoreAddr;
-#[cfg(feature = "alloc")]
-use alloc::string::{String, ToString};
-#[cfg(feature = "alloc")]
-use alloc::vec::Vec;
-use core::fmt::Debug;
-use core::mem::size_of;
-use paste::paste;
-use spacepackets::ecss::{EcssEnumU16, EcssEnumU32, EcssEnumU64, EcssEnumU8, EcssEnumeration};
-use spacepackets::ByteConversionError;
-use spacepackets::SizeMissmatch;
-
-#[cfg(feature = "alloc")]
-pub use alloc_mod::*;
-pub use spacepackets::ecss::ToBeBytes;
-
-/// Generic trait which is used for objects which can be converted into a raw network (big) endian
-/// byte format.
-pub trait WritableToBeBytes {
- fn raw_len(&self) -> usize;
- /// Writes the object to a raw buffer in network endianness (big)
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result;
-}
-
-macro_rules! param_to_be_bytes_impl {
- ($Newtype: ident) => {
- impl WritableToBeBytes for $Newtype {
- #[inline]
- fn raw_len(&self) -> usize {
- size_of::<::ByteArray>()
- }
-
- fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result {
- let raw_len = self.raw_len();
- if buf.len() < raw_len {
- return Err(ByteConversionError::ToSliceTooSmall(SizeMissmatch {
- found: buf.len(),
- expected: raw_len,
- }));
- }
- buf[0..raw_len].copy_from_slice(&self.to_be_bytes());
- Ok(raw_len)
- }
- }
- };
-}
-
-macro_rules! primitive_newtypes_with_eq {
- ($($ty: ty,)+) => {
- $(
- paste! {
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub struct [<$ty:upper>](pub $ty);
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub struct [<$ty:upper Pair>](pub $ty, pub $ty);
- #[derive(Debug, Copy, Clone, PartialEq, Eq)]
- pub struct [<$ty:upper Triplet>](pub $ty, pub $ty, pub $ty);
-
- param_to_be_bytes_impl!([<$ty:upper>]);
- param_to_be_bytes_impl!([<$ty:upper Pair>]);
- param_to_be_bytes_impl!([<$ty:upper Triplet>]);
-
- 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)
- }
- }
- }
- )+
- }
-}
-
-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);
-
- param_to_be_bytes_impl!([<$ty:upper>]);
- param_to_be_bytes_impl!([<$ty:upper Pair>]);
- param_to_be_bytes_impl!([<$ty:upper Triplet>]);
-
- 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_byte_conversions_impl {
- ($($ty: ty,)+) => {
- $(
- paste! {
- impl ToBeBytes for [<$ty:upper>] {
- type ByteArray = [u8; size_of::<$ty>()];
- fn to_be_bytes(&self) -> Self::ByteArray {
- self.0.to_be_bytes()
- }
- }
-
- impl TryFrom<&[u8]> for [<$ty:upper>] {
- type Error = ByteConversionError;
-
- fn try_from(v: &[u8]) -> Result {
- if v.len() < size_of::<$ty>() {
- return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
- expected: size_of::<$ty>(),
- found: v.len()
- }));
- }
- Ok([<$ty:upper>]($ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap())))
- }
- }
- }
- )+
- }
-}
-
-macro_rules! pair_byte_conversions_impl {
- ($($ty: ty,)+) => {
- $(
- paste! {
- impl ToBeBytes for [<$ty:upper Pair>] {
- type ByteArray = [u8; size_of::<$ty>() * 2];
- fn to_be_bytes(&self) -> Self::ByteArray {
- let mut array = [0; size_of::<$ty>() * 2];
- array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
- array[
- size_of::<$ty>()..2 * size_of::<$ty>()
- ].copy_from_slice(&self.1.to_be_bytes());
- array
- }
- }
-
- impl TryFrom<&[u8]> for [<$ty:upper Pair>] {
- type Error = ByteConversionError;
-
- fn try_from(v: &[u8]) -> Result {
- if v.len() < 2 * size_of::<$ty>() {
- return Err(ByteConversionError::FromSliceTooSmall(SizeMissmatch {
- expected: 2 * size_of::<$ty>(),
- found: v.len()
- }));
- }
- Ok([<$ty:upper Pair>](
- $ty::from_be_bytes(v[0..size_of::<$ty>()].try_into().unwrap()),
- $ty::from_be_bytes(v[size_of::<$ty>()..2 * size_of::<$ty>()].try_into().unwrap())
- ))
- }
- }
- }
- )+
- }
-}
-
-macro_rules! triplet_to_be_bytes_impl {
- ($($ty: ty,)+) => {
- $(
- paste! {
- impl ToBeBytes for [<$ty:upper Triplet>] {
- type ByteArray = [u8; size_of::<$ty>() * 3];
- fn to_be_bytes(&self) -> Self::ByteArray {
- let mut array = [0; size_of::<$ty>() * 3];
- array[0..size_of::<$ty>()].copy_from_slice(&self.0.to_be_bytes());
- array[
- size_of::<$ty>()..2 * size_of::<$ty>()
- ].copy_from_slice(&self.1.to_be_bytes());
- array[
- 2 * size_of::<$ty>()..3 * size_of::<$ty>()
- ].copy_from_slice(&self.2.to_be_bytes());
- array
- }
- }
- impl TryFrom<&[u8]> for [<$ty:upper Triplet>] {
- type Error = ByteConversionError;
-
- fn try_from(v: &[u8]) -> Result