More improvements for Event API #173

Merged
muellerr merged 3 commits from improve-event-api into main 2024-04-24 19:34:34 +02:00
15 changed files with 345 additions and 201 deletions

View File

@ -38,8 +38,7 @@ pub enum GroupId {
pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED; pub const OBSW_SERVER_ADDR: Ipv4Addr = Ipv4Addr::UNSPECIFIED;
pub const SERVER_PORT: u16 = 7301; pub const SERVER_PORT: u16 = 7301;
pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> = pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityInfo>::new(0, 0);
EventU32TypedSev::<SeverityInfo>::const_new(0, 0);
lazy_static! { lazy_static! {
pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = { pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = {

View File

@ -210,4 +210,82 @@ impl<TmSender: EcssTmSender> EventHandler<TmSender> {
} }
#[cfg(test)] #[cfg(test)]
mod tests {} mod tests {
use satrs::{
events::EventU32,
pus::verification::VerificationReporterCfg,
spacepackets::{
ecss::{tm::PusTmReader, PusPacket},
CcsdsPacket,
},
tmtc::PacketAsVec,
};
use super::*;
const TEST_CREATOR_ID: UniqueApidTargetId = UniqueApidTargetId::new(1, 2);
const TEST_EVENT: EventU32 = EventU32::new(satrs::events::Severity::Info, 1, 1);
pub struct EventManagementTestbench {
pub event_tx: mpsc::SyncSender<EventMessageU32>,
pub event_manager: EventManagerWithBoundedMpsc,
pub tm_receiver: mpsc::Receiver<PacketAsVec>,
pub pus_event_handler: PusEventHandler<mpsc::Sender<PacketAsVec>>,
}
impl EventManagementTestbench {
pub fn new() -> Self {
let (event_tx, event_rx) = mpsc::sync_channel(10);
let (_event_req_tx, event_req_rx) = mpsc::sync_channel(10);
let (tm_sender, tm_receiver) = mpsc::channel();
let verif_reporter_cfg = VerificationReporterCfg::new(0x05, 2, 2, 128).unwrap();
let verif_reporter =
VerificationReporter::new(PUS_EVENT_MANAGEMENT.id(), &verif_reporter_cfg);
let mut event_manager = EventManagerWithBoundedMpsc::new(event_rx);
let pus_event_handler = PusEventHandler::<mpsc::Sender<PacketAsVec>>::new(
tm_sender,
verif_reporter,
&mut event_manager,
event_req_rx,
);
Self {
event_tx,
tm_receiver,
event_manager,
pus_event_handler,
}
}
}
#[test]
fn test_basic_event_generation() {
let mut testbench = EventManagementTestbench::new();
testbench
.event_tx
.send(EventMessageU32::new(
TEST_CREATOR_ID.id(),
EventU32::new(satrs::events::Severity::Info, 1, 1),
))
.expect("failed to send event");
testbench.pus_event_handler.handle_event_requests();
testbench.event_manager.try_event_handling(|_, _| {});
testbench.pus_event_handler.generate_pus_event_tm();
let tm_packet = testbench
.tm_receiver
.try_recv()
.expect("failed to receive TM packet");
assert_eq!(tm_packet.sender_id, PUS_EVENT_MANAGEMENT.id());
let tm_reader = PusTmReader::new(&tm_packet.packet, 7)
.expect("failed to create TM reader")
.0;
assert_eq!(tm_reader.apid(), TEST_CREATOR_ID.apid);
assert_eq!(tm_reader.user_data().len(), 4);
let event_read_back = EventU32::from_be_bytes(tm_reader.user_data().try_into().unwrap());
assert_eq!(event_read_back, TEST_EVENT);
}
#[test]
fn test_basic_event_disabled() {
// TODO: Add test.
}
}

View File

@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v0.1.4] 2024-04-24
## Added
- `ResultU16::from_be_bytes`
- `From<u16>` impl for `ResultU16`.
- Optional `defmt` support: `defmt::Format` impl on `ResultU16` if the `defmt` feature is
activated.
# [v0.1.3] 2024-04-16 # [v0.1.3] 2024-04-16
Allow `spacepackets` range starting with v0.10 and v0.11. Allow `spacepackets` range starting with v0.10 and v0.11.

View File

@ -1,7 +1,7 @@
[package] [package]
name = "satrs-shared" name = "satrs-shared"
description = "Components shared by multiple sat-rs crates" description = "Components shared by multiple sat-rs crates"
version = "0.1.3" version = "0.1.4"
edition = "2021" edition = "2021"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"] authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/" homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
@ -17,12 +17,17 @@ version = "1"
default-features = false default-features = false
optional = true optional = true
[dependencies.defmt]
version = "0.3"
optional = true
[dependencies.spacepackets] [dependencies.spacepackets]
version = ">0.9, <=0.11" version = ">0.9, <=0.11"
default-features = false default-features = false
[features] [features]
serde = ["dep:serde", "spacepackets/serde"] serde = ["dep:serde", "spacepackets/serde"]
spacepackets = ["dep:defmt", "spacepackets/defmt"]
[package.metadata.docs.rs] [package.metadata.docs.rs]
rustdoc-args = ["--cfg", "doc_cfg", "--generate-link-to-definition"] rustdoc-args = ["--cfg", "docs_rs", "--generate-link-to-definition"]

View File

@ -1,3 +1,4 @@
//! This crates contains modules shared among other sat-rs framework crates. //! This crates contains modules shared among other sat-rs framework crates.
#![no_std] #![no_std]
#![cfg_attr(docs_rs, feature(doc_auto_cfg))]
pub mod res_code; pub mod res_code;

View File

@ -7,6 +7,7 @@ use spacepackets::ByteConversionError;
/// Simple [u16] based result code type which also allows to group related resultcodes. /// Simple [u16] based result code type which also allows to group related resultcodes.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ResultU16 { pub struct ResultU16 {
group_id: u8, group_id: u8,
unique_id: u8, unique_id: u8,
@ -19,15 +20,28 @@ impl ResultU16 {
unique_id, unique_id,
} }
} }
pub fn raw(&self) -> u16 { pub fn raw(&self) -> u16 {
((self.group_id as u16) << 8) | self.unique_id as u16 ((self.group_id as u16) << 8) | self.unique_id as u16
} }
pub fn group_id(&self) -> u8 { pub fn group_id(&self) -> u8 {
self.group_id self.group_id
} }
pub fn unique_id(&self) -> u8 { pub fn unique_id(&self) -> u8 {
self.unique_id self.unique_id
} }
pub fn from_be_bytes(bytes: [u8; 2]) -> Self {
Self::from(u16::from_be_bytes(bytes))
}
}
impl From<u16> for ResultU16 {
fn from(value: u16) -> Self {
Self::new(((value >> 8) & 0xff) as u8, (value & 0xff) as u8)
}
} }
impl From<ResultU16> for EcssEnumU16 { impl From<ResultU16> for EcssEnumU16 {
@ -84,5 +98,14 @@ mod tests {
assert_eq!(written, 2); assert_eq!(written, 2);
assert_eq!(buf[0], 1); assert_eq!(buf[0], 1);
assert_eq!(buf[1], 1); assert_eq!(buf[1], 1);
let read_back = ResultU16::from_be_bytes(buf);
assert_eq!(read_back, result_code);
}
#[test]
fn test_from_u16() {
let result_code = ResultU16::new(1, 1);
let result_code_2 = ResultU16::from(result_code.raw());
assert_eq!(result_code, result_code_2);
} }
} }

View File

@ -8,7 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v0.2.0-rc.5] 2024-04-23 # [v0.2.0-rc.5] 2024-04-24
## Added
- Optional `defmt::Format` support for the event types, if the `defmt` feature is activated.
## Changed ## Changed
@ -17,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Renamed `PusEventDispatcher` to `PusEventTmCreatorWithMap`. - Renamed `PusEventDispatcher` to `PusEventTmCreatorWithMap`.
- Renamed `DefaultPusEventU32Dispatcher` to `DefaultPusEventU32EventCreator`. - Renamed `DefaultPusEventU32Dispatcher` to `DefaultPusEventU32EventCreator`.
- Renamed `PusEventMgmtBackendProvider` renamed to `PusEventReportingMap`. - Renamed `PusEventMgmtBackendProvider` renamed to `PusEventReportingMap`.
- Reanmed Event `const_new` methods to `new` and the former `new` methods to `new_checked`
# [v0.2.0-rc.4] 2024-04-23 # [v0.2.0-rc.4] 2024-04-23

View File

@ -1,6 +1,6 @@
[package] [package]
name = "satrs" name = "satrs"
version = "0.2.0-rc.4" version = "0.2.0-rc.5"
edition = "2021" edition = "2021"
rust-version = "1.71.1" rust-version = "1.71.1"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"] authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
@ -84,10 +84,14 @@ version = "0.8"
features = ["os-poll", "net"] features = ["os-poll", "net"]
optional = true optional = true
[dependencies.defmt]
version = "0.3"
optional = true
[dev-dependencies] [dev-dependencies]
serde = "1" serde = "1"
zerocopy = "0.7" zerocopy = "0.7"
once_cell = "1.13" once_cell = "1"
serde_json = "1" serde_json = "1"
rand = "0.8" rand = "0.8"
tempfile = "3" tempfile = "3"
@ -120,7 +124,7 @@ alloc = [
serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"] serde = ["dep:serde", "spacepackets/serde", "satrs-shared/serde"]
crossbeam = ["crossbeam-channel"] crossbeam = ["crossbeam-channel"]
heapless = ["dep:heapless"] heapless = ["dep:heapless"]
defmt = ["spacepackets/defmt"] defmt = ["dep:defmt", "spacepackets/defmt"]
test_util = [] test_util = []
doc-images = [] doc-images = []

View File

@ -295,7 +295,7 @@ impl<
for id in ids { for id in ids {
if let Some(sender) = self.sender_map.get_send_event_provider(id) { if let Some(sender) = self.sender_map.get_send_event_provider(id) {
if let Err(e) = sender.send(EventMessage::new_generic( if let Err(e) = sender.send(EventMessage::new_generic(
*id, event_msg.sender_id,
event_msg.event, event_msg.event,
event_msg.params.as_ref(), event_msg.params.as_ref(),
)) { )) {
@ -597,7 +597,7 @@ mod tests {
use std::format; use std::format;
use std::sync::mpsc::{self}; use std::sync::mpsc::{self};
const TEST_EVENT: EventU32 = EventU32::const_new(Severity::INFO, 0, 5); const TEST_EVENT: EventU32 = EventU32::new(Severity::Info, 0, 5);
fn check_next_event( fn check_next_event(
expected: EventU32, expected: EventU32,
@ -614,6 +614,7 @@ mod tests {
res: EventRoutingResult<EventU32, Params>, res: EventRoutingResult<EventU32, Params>,
expected: EventU32, expected: EventU32,
expected_num_sent: u32, expected_num_sent: u32,
expected_sender_id: ComponentId,
) { ) {
assert!(matches!(res, EventRoutingResult::Handled { .. })); assert!(matches!(res, EventRoutingResult::Handled { .. }));
if let EventRoutingResult::Handled { if let EventRoutingResult::Handled {
@ -622,6 +623,7 @@ mod tests {
} = res } = res
{ {
assert_eq!(event_msg.event, expected); assert_eq!(event_msg.event, expected);
assert_eq!(event_msg.sender_id, expected_sender_id);
assert_eq!(num_recipients, expected_num_sent); assert_eq!(num_recipients, expected_num_sent);
} }
} }
@ -634,8 +636,8 @@ mod tests {
#[test] #[test]
fn test_basic() { fn test_basic() {
let (event_sender, mut event_man) = generic_event_man(); let (event_sender, mut event_man) = generic_event_man();
let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let event_grp_0 = EventU32::new(Severity::Info, 0, 0);
let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let event_grp_1_0 = EventU32::new(Severity::High, 1, 0);
let (single_event_sender, single_event_receiver) = mpsc::channel(); let (single_event_sender, single_event_receiver) = mpsc::channel();
let single_event_listener = EventSenderMpsc::new(0, single_event_sender); let single_event_listener = EventSenderMpsc::new(0, single_event_sender);
event_man.subscribe_single(&event_grp_0, single_event_listener.target_id()); event_man.subscribe_single(&event_grp_0, single_event_listener.target_id());
@ -653,8 +655,7 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_grp_0)) .send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_grp_0))
.expect("Sending single error failed"); .expect("Sending single error failed");
let res = event_man.try_event_handling(&error_handler); let res = event_man.try_event_handling(&error_handler);
// assert!(res.is_ok()); check_handled_event(res, event_grp_0, 1, TEST_COMPONENT_ID_0.id());
check_handled_event(res, event_grp_0, 1);
check_next_event(event_grp_0, &single_event_receiver); check_next_event(event_grp_0, &single_event_receiver);
// Test event which is sent to all group listeners // Test event which is sent to all group listeners
@ -662,7 +663,7 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_grp_1_0)) .send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_grp_1_0))
.expect("Sending group error failed"); .expect("Sending group error failed");
let res = event_man.try_event_handling(&error_handler); let res = event_man.try_event_handling(&error_handler);
check_handled_event(res, event_grp_1_0, 1); check_handled_event(res, event_grp_1_0, 1, TEST_COMPONENT_ID_1.id());
check_next_event(event_grp_1_0, &group_event_receiver_0); check_next_event(event_grp_1_0, &group_event_receiver_0);
} }
@ -672,7 +673,7 @@ mod tests {
panic!("routing error occurred for event {:?}: {:?}", event_msg, e); panic!("routing error occurred for event {:?}: {:?}", event_msg, e);
}; };
let (event_sender, mut event_man) = generic_event_man(); let (event_sender, mut event_man) = generic_event_man();
let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let event_grp_0 = EventU32::new(Severity::Info, 0, 0);
let (single_event_sender, single_event_receiver) = mpsc::channel(); let (single_event_sender, single_event_receiver) = mpsc::channel();
let single_event_listener = EventSenderMpsc::new(0, single_event_sender); let single_event_listener = EventSenderMpsc::new(0, single_event_sender);
event_man.subscribe_single(&event_grp_0, single_event_listener.target_id()); event_man.subscribe_single(&event_grp_0, single_event_listener.target_id());
@ -685,7 +686,7 @@ mod tests {
)) ))
.expect("Sending group error failed"); .expect("Sending group error failed");
let res = event_man.try_event_handling(&error_handler); let res = event_man.try_event_handling(&error_handler);
check_handled_event(res, event_grp_0, 1); check_handled_event(res, event_grp_0, 1, TEST_COMPONENT_ID_0.id());
let aux = check_next_event(event_grp_0, &single_event_receiver); let aux = check_next_event(event_grp_0, &single_event_receiver);
assert!(aux.is_some()); assert!(aux.is_some());
let aux = aux.unwrap(); let aux = aux.unwrap();
@ -707,8 +708,8 @@ mod tests {
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
assert!(matches!(res, EventRoutingResult::Empty)); assert!(matches!(res, EventRoutingResult::Empty));
let event_grp_0 = EventU32::new(Severity::INFO, 0, 0).unwrap(); let event_grp_0 = EventU32::new(Severity::Info, 0, 0);
let event_grp_1_0 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let event_grp_1_0 = EventU32::new(Severity::High, 1, 0);
let (event_grp_0_sender, event_grp_0_receiver) = mpsc::channel(); let (event_grp_0_sender, event_grp_0_receiver) = mpsc::channel();
let event_grp_0_and_1_listener = EventU32SenderMpsc::new(0, event_grp_0_sender); let event_grp_0_and_1_listener = EventU32SenderMpsc::new(0, event_grp_0_sender);
event_man.subscribe_group( event_man.subscribe_group(
@ -728,9 +729,9 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_grp_1_0)) .send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_grp_1_0))
.expect("Sendign Event Group 1 failed"); .expect("Sendign Event Group 1 failed");
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_grp_0, 1); check_handled_event(res, event_grp_0, 1, TEST_COMPONENT_ID_0.id());
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_grp_1_0, 1); check_handled_event(res, event_grp_1_0, 1, TEST_COMPONENT_ID_1.id());
check_next_event(event_grp_0, &event_grp_0_receiver); check_next_event(event_grp_0, &event_grp_0_receiver);
check_next_event(event_grp_1_0, &event_grp_0_receiver); check_next_event(event_grp_1_0, &event_grp_0_receiver);
@ -744,8 +745,8 @@ mod tests {
panic!("routing error occurred for event {:?}: {:?}", event_msg, e); panic!("routing error occurred for event {:?}: {:?}", event_msg, e);
}; };
let (event_sender, mut event_man) = generic_event_man(); let (event_sender, mut event_man) = generic_event_man();
let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap(); let event_0 = EventU32::new(Severity::Info, 0, 5);
let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let event_1 = EventU32::new(Severity::High, 1, 0);
let (event_0_tx_0, event_0_rx_0) = mpsc::channel(); let (event_0_tx_0, event_0_rx_0) = mpsc::channel();
let (event_0_tx_1, event_0_rx_1) = mpsc::channel(); let (event_0_tx_1, event_0_rx_1) = mpsc::channel();
let event_listener_0 = EventU32SenderMpsc::new(0, event_0_tx_0); let event_listener_0 = EventU32SenderMpsc::new(0, event_0_tx_0);
@ -760,7 +761,7 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_0)) .send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_0))
.expect("Triggering Event 0 failed"); .expect("Triggering Event 0 failed");
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_0, 2); check_handled_event(res, event_0, 2, TEST_COMPONENT_ID_0.id());
check_next_event(event_0, &event_0_rx_0); check_next_event(event_0, &event_0_rx_0);
check_next_event(event_0, &event_0_rx_1); check_next_event(event_0, &event_0_rx_1);
event_man.subscribe_group(event_1.group_id(), event_listener_0_sender_id); event_man.subscribe_group(event_1.group_id(), event_listener_0_sender_id);
@ -773,9 +774,9 @@ mod tests {
// 3 Events messages will be sent now // 3 Events messages will be sent now
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_0, 2); check_handled_event(res, event_0, 2, TEST_COMPONENT_ID_0.id());
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_1, 1); check_handled_event(res, event_1, 1, TEST_COMPONENT_ID_1.id());
// Both the single event and the group event should arrive now // Both the single event and the group event should arrive now
check_next_event(event_0, &event_0_rx_0); check_next_event(event_0, &event_0_rx_0);
check_next_event(event_1, &event_0_rx_0); check_next_event(event_1, &event_0_rx_0);
@ -787,7 +788,7 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_1)) .send(EventMessage::new(TEST_COMPONENT_ID_0.id(), event_1))
.expect("Triggering Event 1 failed"); .expect("Triggering Event 1 failed");
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_1, 1); check_handled_event(res, event_1, 1, TEST_COMPONENT_ID_0.id());
} }
#[test] #[test]
@ -797,8 +798,8 @@ mod tests {
}; };
let (event_sender, event_receiver) = mpsc::channel(); let (event_sender, event_receiver) = mpsc::channel();
let mut event_man = EventManagerWithMpsc::new(event_receiver); let mut event_man = EventManagerWithMpsc::new(event_receiver);
let event_0 = EventU32::new(Severity::INFO, 0, 5).unwrap(); let event_0 = EventU32::new(Severity::Info, 0, 5);
let event_1 = EventU32::new(Severity::HIGH, 1, 0).unwrap(); let event_1 = EventU32::new(Severity::High, 1, 0);
let (event_0_tx_0, all_events_rx) = mpsc::channel(); let (event_0_tx_0, all_events_rx) = mpsc::channel();
let all_events_listener = EventU32SenderMpsc::new(0, event_0_tx_0); let all_events_listener = EventU32SenderMpsc::new(0, event_0_tx_0);
event_man.subscribe_all(all_events_listener.target_id()); event_man.subscribe_all(all_events_listener.target_id());
@ -810,9 +811,9 @@ mod tests {
.send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_1)) .send(EventMessage::new(TEST_COMPONENT_ID_1.id(), event_1))
.expect("Triggering event 1 failed"); .expect("Triggering event 1 failed");
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_0, 1); check_handled_event(res, event_0, 1, TEST_COMPONENT_ID_0.id());
let res = event_man.try_event_handling(error_handler); let res = event_man.try_event_handling(error_handler);
check_handled_event(res, event_1, 1); check_handled_event(res, event_1, 1, TEST_COMPONENT_ID_1.id());
check_next_event(event_0, &all_events_rx); check_next_event(event_0, &all_events_rx);
check_next_event(event_1, &all_events_rx); check_next_event(event_1, &all_events_rx);
} }

View File

@ -20,10 +20,10 @@
//! ``` //! ```
//! use satrs::events::{EventU16, EventU32, EventU32TypedSev, Severity, SeverityHigh, SeverityInfo}; //! use satrs::events::{EventU16, EventU32, EventU32TypedSev, Severity, SeverityHigh, SeverityInfo};
//! //!
//! const MSG_RECVD: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(1, 0); //! const MSG_RECVD: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::new(1, 0);
//! const MSG_FAILED: EventU32 = EventU32::const_new(Severity::LOW, 1, 1); //! const MSG_FAILED: EventU32 = EventU32::new(Severity::LOW, 1, 1);
//! //!
//! const TEMPERATURE_HIGH: EventU32TypedSev<SeverityHigh> = EventU32TypedSev::const_new(2, 0); //! const TEMPERATURE_HIGH: EventU32TypedSev<SeverityHigh> = EventU32TypedSev::new(2, 0);
//! //!
//! let small_event = EventU16::new(Severity::INFO, 3, 0); //! let small_event = EventU16::new(Severity::INFO, 3, 0);
//! ``` //! ```
@ -40,12 +40,17 @@ pub type LargestEventRaw = u32;
/// Using a type definition allows to change this to u32 in the future more easily /// Using a type definition allows to change this to u32 in the future more easily
pub type LargestGroupIdRaw = u16; pub type LargestGroupIdRaw = u16;
pub const MAX_GROUP_ID_U32_EVENT: u16 = 2_u16.pow(14) - 1;
pub const MAX_GROUP_ID_U16_EVENT: u16 = 2_u16.pow(6) - 1;
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Severity { pub enum Severity {
INFO = 0, Info = 0,
LOW = 1, Low = 1,
MEDIUM = 2, Medium = 2,
HIGH = 3, High = 3,
} }
pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone { pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone {
@ -56,28 +61,28 @@ pub trait HasSeverity: Debug + PartialEq + Eq + Copy + Clone {
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityInfo {} pub struct SeverityInfo {}
impl HasSeverity for SeverityInfo { impl HasSeverity for SeverityInfo {
const SEVERITY: Severity = Severity::INFO; const SEVERITY: Severity = Severity::Info;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityLow {} pub struct SeverityLow {}
impl HasSeverity for SeverityLow { impl HasSeverity for SeverityLow {
const SEVERITY: Severity = Severity::LOW; const SEVERITY: Severity = Severity::Low;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityMedium {} pub struct SeverityMedium {}
impl HasSeverity for SeverityMedium { impl HasSeverity for SeverityMedium {
const SEVERITY: Severity = Severity::MEDIUM; const SEVERITY: Severity = Severity::Medium;
} }
/// Type level support struct /// Type level support struct
#[derive(Debug, PartialEq, Eq, Copy, Clone)] #[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct SeverityHigh {} pub struct SeverityHigh {}
impl HasSeverity for SeverityHigh { impl HasSeverity for SeverityHigh {
const SEVERITY: Severity = Severity::HIGH; const SEVERITY: Severity = Severity::High;
} }
pub trait GenericEvent: EcssEnumeration + Copy + Clone { pub trait GenericEvent: EcssEnumeration + Copy + Clone {
@ -99,27 +104,29 @@ impl TryFrom<u8> for Severity {
fn try_from(value: u8) -> Result<Self, Self::Error> { fn try_from(value: u8) -> Result<Self, Self::Error> {
match value { match value {
x if x == Severity::INFO as u8 => Ok(Severity::INFO), x if x == Severity::Info as u8 => Ok(Severity::Info),
x if x == Severity::LOW as u8 => Ok(Severity::LOW), x if x == Severity::Low as u8 => Ok(Severity::Low),
x if x == Severity::MEDIUM as u8 => Ok(Severity::MEDIUM), x if x == Severity::Medium as u8 => Ok(Severity::Medium),
x if x == Severity::HIGH as u8 => Ok(Severity::HIGH), x if x == Severity::High as u8 => Ok(Severity::High),
_ => Err(()), _ => Err(()),
} }
} }
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
struct EventBase<RAW, GID, UID> { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct EventBase<Raw, GroupId, UniqueId> {
severity: Severity, severity: Severity,
group_id: GID, group_id: GroupId,
unique_id: UID, unique_id: UniqueId,
phantom: PhantomData<RAW>, phantom: PhantomData<Raw>,
} }
impl<RAW: ToBeBytes, GID, UID> EventBase<RAW, GID, UID> { impl<Raw: ToBeBytes, GroupId, UniqueId> EventBase<Raw, GroupId, UniqueId> {
fn write_to_bytes( fn write_to_bytes(
&self, &self,
raw: RAW, raw: Raw,
buf: &mut [u8], buf: &mut [u8],
width: usize, width: usize,
) -> Result<usize, ByteConversionError> { ) -> Result<usize, ByteConversionError> {
@ -267,6 +274,7 @@ macro_rules! const_from_fn {
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EventU32 { pub struct EventU32 {
base: EventBase<u32, u16, u16>, base: EventBase<u32, u16, u16>,
} }
@ -309,12 +317,12 @@ impl EventU32 {
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF. /// 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 /// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
/// raw event ID /// raw event ID
pub fn new( pub fn new_checked(
severity: Severity, severity: Severity,
group_id: <Self as GenericEvent>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> { ) -> Option<Self> {
if group_id > (2u16.pow(14) - 1) { if group_id > MAX_GROUP_ID_U32_EVENT {
return None; return None;
} }
Some(Self { Some(Self {
@ -326,12 +334,14 @@ impl EventU32 {
}, },
}) })
} }
pub const fn const_new(
/// This constructor will panic if the passed group is is larger than [MAX_GROUP_ID_U32_EVENT].
pub const fn new(
severity: Severity, severity: Severity,
group_id: <Self as GenericEvent>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
) -> Self { ) -> Self {
if group_id > (2u16.pow(14) - 1) { if group_id > MAX_GROUP_ID_U32_EVENT {
panic!("Group ID too large"); panic!("Group ID too large");
} }
Self { Self {
@ -344,50 +354,16 @@ impl EventU32 {
} }
} }
pub fn from_be_bytes(bytes: [u8; 4]) -> Self {
Self::from(u32::from_be_bytes(bytes))
}
const_from_fn!(const_from_info, EventU32TypedSev, SeverityInfo); const_from_fn!(const_from_info, EventU32TypedSev, SeverityInfo);
const_from_fn!(const_from_low, EventU32TypedSev, SeverityLow); const_from_fn!(const_from_low, EventU32TypedSev, SeverityLow);
const_from_fn!(const_from_medium, EventU32TypedSev, SeverityMedium); const_from_fn!(const_from_medium, EventU32TypedSev, SeverityMedium);
const_from_fn!(const_from_high, EventU32TypedSev, SeverityHigh); const_from_fn!(const_from_high, EventU32TypedSev, SeverityHigh);
} }
impl<SEVERITY: HasSeverity> EventU32TypedSev<SEVERITY> {
/// 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: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
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: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::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<Self, Severity> {
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<u32> for EventU32 { impl From<u32> for EventU32 {
fn from(raw: u32) -> Self { fn from(raw: u32) -> Self {
// Severity conversion from u8 should never fail // Severity conversion from u8 should never fail
@ -395,15 +371,10 @@ impl From<u32> for EventU32 {
let group_id = ((raw >> 16) & 0x3FFF) as u16; let group_id = ((raw >> 16) & 0x3FFF) as u16;
let unique_id = (raw & 0xFFFF) as u16; let unique_id = (raw & 0xFFFF) as u16;
// Sanitized input, should never fail // Sanitized input, should never fail
Self::const_new(severity, group_id, unique_id) Self::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 UnsignedEnum for EventU32 { impl UnsignedEnum for EventU32 {
fn size(&self) -> usize { fn size(&self) -> usize {
core::mem::size_of::<u32>() core::mem::size_of::<u32>()
@ -424,6 +395,49 @@ impl EcssEnumeration for EventU32 {
} }
} }
impl<SEVERITY: HasSeverity> EventU32TypedSev<SEVERITY> {
/// 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_checked(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
let event = EventU32::new_checked(SEVERITY::SEVERITY, group_id, unique_id)?;
Some(Self {
event,
phantom: PhantomData,
})
}
/// This constructor will panic if the `group_id` is larger than [MAX_GROUP_ID_U32_EVENT].
pub const fn new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
let event = EventU32::new(SEVERITY::SEVERITY, group_id, unique_id);
Self {
event,
phantom: PhantomData,
}
}
fn try_from_generic(expected: Severity, raw: u32) -> Result<Self, Severity> {
let severity = Severity::try_from(((raw >> 30) & 0b11) as u8).unwrap();
if severity != expected {
return Err(severity);
}
Ok(Self::new(
((raw >> 16) & 0x3FFF) as u16,
(raw & 0xFFFF) as u16,
))
}
}
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);
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> UnsignedEnum for EventU32TypedSev<SEVERITY> { impl<SEVERITY: HasSeverity> UnsignedEnum for EventU32TypedSev<SEVERITY> {
delegate!(to self.event { delegate!(to self.event {
@ -441,6 +455,8 @@ impl<SEVERITY: HasSeverity> EcssEnumeration for EventU32TypedSev<SEVERITY> {
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct EventU16 { pub struct EventU16 {
base: EventBase<u16, u8, u8>, base: EventBase<u16, u8, u8>,
} }
@ -475,7 +491,7 @@ impl EventU16 {
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F. /// 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 /// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the
/// raw event ID /// raw event ID
pub fn new( pub fn new_checked(
severity: Severity, severity: Severity,
group_id: <Self as GenericEvent>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
@ -493,8 +509,8 @@ impl EventU16 {
}) })
} }
/// Const version of [Self::new], but panics on invalid group ID input values. /// This constructor will panic if the `group_id` is larger than [MAX_GROUP_ID_U16_EVENT].
pub const fn const_new( pub const fn new(
severity: Severity, severity: Severity,
group_id: <Self as GenericEvent>::GroupId, group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId, unique_id: <Self as GenericEvent>::UniqueId,
@ -511,52 +527,26 @@ impl EventU16 {
}, },
} }
} }
pub fn from_be_bytes(bytes: [u8; 2]) -> Self {
Self::from(u16::from_be_bytes(bytes))
}
const_from_fn!(const_from_info, EventU16TypedSev, SeverityInfo); const_from_fn!(const_from_info, EventU16TypedSev, SeverityInfo);
const_from_fn!(const_from_low, EventU16TypedSev, SeverityLow); const_from_fn!(const_from_low, EventU16TypedSev, SeverityLow);
const_from_fn!(const_from_medium, EventU16TypedSev, SeverityMedium); const_from_fn!(const_from_medium, EventU16TypedSev, SeverityMedium);
const_from_fn!(const_from_high, EventU16TypedSev, SeverityHigh); const_from_fn!(const_from_high, EventU16TypedSev, SeverityHigh);
} }
impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> { impl From<u16> for EventU16 {
/// This is similar to [EventU16::new] but the severity is a type generic, which allows to fn from(raw: <Self as GenericEvent>::Raw) -> Self {
/// have distinct types for events with different severities
pub fn new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
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: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::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<Self, Severity> {
let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap(); let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
if severity != expected { let group_id = ((raw >> 8) & 0x3F) as u8;
return Err(severity); let unique_id = (raw & 0xFF) as u8;
} // Sanitized input, new call should never fail
Ok(Self::const_new( Self::new(severity, group_id, unique_id)
((raw >> 8) & 0x3F) as u8,
(raw & 0xFF) as u8,
))
} }
} }
impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
impl UnsignedEnum for EventU16 { impl UnsignedEnum for EventU16 {
fn size(&self) -> usize { fn size(&self) -> usize {
core::mem::size_of::<u16>() core::mem::size_of::<u16>()
@ -577,6 +567,43 @@ impl EcssEnumeration for EventU16 {
} }
} }
impl<SEVERITY: HasSeverity> EventU16TypedSev<SEVERITY> {
/// 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_checked(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Option<Self> {
let event = EventU16::new_checked(SEVERITY::SEVERITY, group_id, unique_id)?;
Some(Self {
event,
phantom: PhantomData,
})
}
/// This constructor will panic if the `group_id` is larger than [MAX_GROUP_ID_U16_EVENT].
pub const fn new(
group_id: <Self as GenericEvent>::GroupId,
unique_id: <Self as GenericEvent>::UniqueId,
) -> Self {
let event = EventU16::new(SEVERITY::SEVERITY, group_id, unique_id);
Self {
event,
phantom: PhantomData,
}
}
fn try_from_generic(expected: Severity, raw: u16) -> Result<Self, Severity> {
let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap();
if severity != expected {
return Err(severity);
}
Ok(Self::new(((raw >> 8) & 0x3F) as u8, (raw & 0xFF) as u8))
}
}
impl_event_provider!(EventU16, EventU16TypedSev, u16, u8, u8);
//noinspection RsTraitImplementation //noinspection RsTraitImplementation
impl<SEVERITY: HasSeverity> UnsignedEnum for EventU16TypedSev<SEVERITY> { impl<SEVERITY: HasSeverity> UnsignedEnum for EventU16TypedSev<SEVERITY> {
delegate!(to self.event { delegate!(to self.event {
@ -593,20 +620,10 @@ impl<SEVERITY: HasSeverity> EcssEnumeration for EventU16TypedSev<SEVERITY> {
}); });
} }
impl From<u16> for EventU16 { try_from_impls!(SeverityInfo, Severity::Info, u16, EventU16TypedSev);
fn from(raw: <Self as GenericEvent>::Raw) -> Self { try_from_impls!(SeverityLow, Severity::Low, u16, EventU16TypedSev);
let severity = Severity::try_from(((raw >> 14) & 0b11) as u8).unwrap(); try_from_impls!(SeverityMedium, Severity::Medium, u16, EventU16TypedSev);
let group_id = ((raw >> 8) & 0x3F) as u8; try_from_impls!(SeverityHigh, Severity::High, u16, EventU16TypedSev);
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<Severity: HasSeverity> PartialEq<EventU32> for EventU32TypedSev<Severity> { impl<Severity: HasSeverity> PartialEq<EventU32> for EventU32TypedSev<Severity> {
#[inline] #[inline]
@ -647,12 +664,10 @@ mod tests {
assert_eq!(size_of::<T>(), val); assert_eq!(size_of::<T>(), val);
} }
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0); const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::new(0, 0);
const INFO_EVENT_SMALL: EventU16TypedSev<SeverityInfo> = EventU16TypedSev::const_new(0, 0); const INFO_EVENT_SMALL: EventU16TypedSev<SeverityInfo> = EventU16TypedSev::new(0, 0);
const HIGH_SEV_EVENT: EventU32TypedSev<SeverityHigh> = const HIGH_SEV_EVENT: EventU32TypedSev<SeverityHigh> = EventU32TypedSev::new(0x3FFF, 0xFFFF);
EventU32TypedSev::const_new(0x3FFF, 0xFFFF); const HIGH_SEV_EVENT_SMALL: EventU16TypedSev<SeverityHigh> = EventU16TypedSev::new(0x3F, 0xff);
const HIGH_SEV_EVENT_SMALL: EventU16TypedSev<SeverityHigh> =
EventU16TypedSev::const_new(0x3F, 0xff);
/// This working is a test in itself. /// This working is a test in itself.
const INFO_REDUCED: EventU32 = EventU32::const_from_info(INFO_EVENT); const INFO_REDUCED: EventU32 = EventU32::const_from_info(INFO_EVENT);
@ -683,7 +698,7 @@ mod tests {
#[test] #[test]
fn test_normal_event_getters() { fn test_normal_event_getters() {
assert_eq!(INFO_EVENT.severity(), Severity::INFO); assert_eq!(INFO_EVENT.severity(), Severity::Info);
assert_eq!(INFO_EVENT.unique_id(), 0); assert_eq!(INFO_EVENT.unique_id(), 0);
assert_eq!(INFO_EVENT.group_id(), 0); assert_eq!(INFO_EVENT.group_id(), 0);
let raw_event = INFO_EVENT.raw(); let raw_event = INFO_EVENT.raw();
@ -692,7 +707,7 @@ mod tests {
#[test] #[test]
fn test_small_event_getters() { fn test_small_event_getters() {
assert_eq!(INFO_EVENT_SMALL.severity(), Severity::INFO); assert_eq!(INFO_EVENT_SMALL.severity(), Severity::Info);
assert_eq!(INFO_EVENT_SMALL.unique_id(), 0); assert_eq!(INFO_EVENT_SMALL.unique_id(), 0);
assert_eq!(INFO_EVENT_SMALL.group_id(), 0); assert_eq!(INFO_EVENT_SMALL.group_id(), 0);
let raw_event = INFO_EVENT_SMALL.raw(); let raw_event = INFO_EVENT_SMALL.raw();
@ -701,7 +716,7 @@ mod tests {
#[test] #[test]
fn all_ones_event_regular() { fn all_ones_event_regular() {
assert_eq!(HIGH_SEV_EVENT.severity(), Severity::HIGH); assert_eq!(HIGH_SEV_EVENT.severity(), Severity::High);
assert_eq!(HIGH_SEV_EVENT.group_id(), 0x3FFF); assert_eq!(HIGH_SEV_EVENT.group_id(), 0x3FFF);
assert_eq!(HIGH_SEV_EVENT.unique_id(), 0xFFFF); assert_eq!(HIGH_SEV_EVENT.unique_id(), 0xFFFF);
let raw_event = HIGH_SEV_EVENT.raw(); let raw_event = HIGH_SEV_EVENT.raw();
@ -710,7 +725,7 @@ mod tests {
#[test] #[test]
fn all_ones_event_small() { fn all_ones_event_small() {
assert_eq!(HIGH_SEV_EVENT_SMALL.severity(), Severity::HIGH); assert_eq!(HIGH_SEV_EVENT_SMALL.severity(), Severity::High);
assert_eq!(HIGH_SEV_EVENT_SMALL.group_id(), 0x3F); assert_eq!(HIGH_SEV_EVENT_SMALL.group_id(), 0x3F);
assert_eq!(HIGH_SEV_EVENT_SMALL.unique_id(), 0xFF); assert_eq!(HIGH_SEV_EVENT_SMALL.unique_id(), 0xFF);
let raw_event = HIGH_SEV_EVENT_SMALL.raw(); let raw_event = HIGH_SEV_EVENT_SMALL.raw();
@ -719,18 +734,19 @@ mod tests {
#[test] #[test]
fn invalid_group_id_normal() { fn invalid_group_id_normal() {
assert!(EventU32TypedSev::<SeverityMedium>::new(2_u16.pow(14), 0).is_none()); assert!(EventU32TypedSev::<SeverityMedium>::new_checked(2_u16.pow(14), 0).is_none());
} }
#[test] #[test]
fn invalid_group_id_small() { fn invalid_group_id_small() {
assert!(EventU16TypedSev::<SeverityMedium>::new(2_u8.pow(6), 0).is_none()); assert!(EventU16TypedSev::<SeverityMedium>::new_checked(2_u8.pow(6), 0).is_none());
} }
#[test] #[test]
fn regular_new() { fn regular_new() {
assert_eq!( assert_eq!(
EventU32TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"), EventU32TypedSev::<SeverityInfo>::new_checked(0, 0)
.expect("Creating regular event failed"),
INFO_EVENT INFO_EVENT
); );
} }
@ -738,7 +754,8 @@ mod tests {
#[test] #[test]
fn small_new() { fn small_new() {
assert_eq!( assert_eq!(
EventU16TypedSev::<SeverityInfo>::new(0, 0).expect("Creating regular event failed"), EventU16TypedSev::<SeverityInfo>::new_checked(0, 0)
.expect("Creating regular event failed"),
INFO_EVENT_SMALL INFO_EVENT_SMALL
); );
} }
@ -777,6 +794,8 @@ mod tests {
assert!(HIGH_SEV_EVENT.write_to_be_bytes(&mut buf).is_ok()); assert!(HIGH_SEV_EVENT.write_to_be_bytes(&mut buf).is_ok());
let val_from_raw = u32::from_be_bytes(buf); let val_from_raw = u32::from_be_bytes(buf);
assert_eq!(val_from_raw, 0xFFFFFFFF); assert_eq!(val_from_raw, 0xFFFFFFFF);
let event_read_back = EventU32::from_be_bytes(buf);
assert_eq!(event_read_back, HIGH_SEV_EVENT);
} }
#[test] #[test]
@ -785,6 +804,8 @@ mod tests {
assert!(HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf).is_ok()); assert!(HIGH_SEV_EVENT_SMALL.write_to_be_bytes(&mut buf).is_ok());
let val_from_raw = u16::from_be_bytes(buf); let val_from_raw = u16::from_be_bytes(buf);
assert_eq!(val_from_raw, 0xFFFF); assert_eq!(val_from_raw, 0xFFFF);
let event_read_back = EventU16::from_be_bytes(buf);
assert_eq!(event_read_back, HIGH_SEV_EVENT_SMALL);
} }
#[test] #[test]
@ -815,13 +836,13 @@ mod tests {
fn severity_from_invalid_raw_val() { fn severity_from_invalid_raw_val() {
let invalid = 0xFF; let invalid = 0xFF;
assert!(Severity::try_from(invalid).is_err()); assert!(Severity::try_from(invalid).is_err());
let invalid = Severity::HIGH as u8 + 1; let invalid = Severity::High as u8 + 1;
assert!(Severity::try_from(invalid).is_err()); assert!(Severity::try_from(invalid).is_err());
} }
#[test] #[test]
fn reduction() { fn reduction() {
let event = EventU32TypedSev::<SeverityInfo>::const_new(1, 1); let event = EventU32TypedSev::<SeverityInfo>::new(1, 1);
let raw = event.raw(); let raw = event.raw();
let reduced: EventU32 = event.into(); let reduced: EventU32 = event.into();
assert_eq!(reduced.group_id(), 1); assert_eq!(reduced.group_id(), 1);

View File

@ -331,10 +331,10 @@ mod tests {
fn severity_to_subservice(severity: Severity) -> Subservice { fn severity_to_subservice(severity: Severity) -> Subservice {
match severity { match severity {
Severity::INFO => Subservice::TmInfoReport, Severity::Info => Subservice::TmInfoReport,
Severity::LOW => Subservice::TmLowSeverityReport, Severity::Low => Subservice::TmLowSeverityReport,
Severity::MEDIUM => Subservice::TmMediumSeverityReport, Severity::Medium => Subservice::TmMediumSeverityReport,
Severity::HIGH => Subservice::TmHighSeverityReport, Severity::High => Subservice::TmHighSeverityReport,
} }
} }
@ -347,22 +347,22 @@ mod tests {
aux_data: Option<&[u8]>, aux_data: Option<&[u8]>,
) { ) {
match severity { match severity {
Severity::INFO => { Severity::Info => {
reporter reporter
.event_info(sender, time_stamp, event, aux_data) .event_info(sender, time_stamp, event, aux_data)
.expect("Error reporting info event"); .expect("Error reporting info event");
} }
Severity::LOW => { Severity::Low => {
reporter reporter
.event_low_severity(sender, time_stamp, event, aux_data) .event_low_severity(sender, time_stamp, event, aux_data)
.expect("Error reporting low event"); .expect("Error reporting low event");
} }
Severity::MEDIUM => { Severity::Medium => {
reporter reporter
.event_medium_severity(sender, time_stamp, event, aux_data) .event_medium_severity(sender, time_stamp, event, aux_data)
.expect("Error reporting medium event"); .expect("Error reporting medium event");
} }
Severity::HIGH => { Severity::High => {
reporter reporter
.event_high_severity(sender, time_stamp, event, aux_data) .event_high_severity(sender, time_stamp, event, aux_data)
.expect("Error reporting high event"); .expect("Error reporting high event");
@ -389,7 +389,7 @@ mod tests {
if let Some(err_data) = error_data { if let Some(err_data) = error_data {
error_copy.extend_from_slice(err_data); error_copy.extend_from_slice(err_data);
} }
let event = EventU32::new(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) let event = EventU32::new_checked(severity, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0)
.expect("Error creating example event"); .expect("Error creating example event");
report_basic_event( report_basic_event(
&mut reporter, &mut reporter,
@ -417,35 +417,35 @@ mod tests {
#[test] #[test]
fn basic_info_event_generation() { fn basic_info_event_generation() {
basic_event_test(4, Severity::INFO, None); basic_event_test(4, Severity::Info, None);
} }
#[test] #[test]
fn basic_low_severity_event() { fn basic_low_severity_event() {
basic_event_test(4, Severity::LOW, None); basic_event_test(4, Severity::Low, None);
} }
#[test] #[test]
fn basic_medium_severity_event() { fn basic_medium_severity_event() {
basic_event_test(4, Severity::MEDIUM, None); basic_event_test(4, Severity::Medium, None);
} }
#[test] #[test]
fn basic_high_severity_event() { fn basic_high_severity_event() {
basic_event_test(4, Severity::HIGH, None); basic_event_test(4, Severity::High, None);
} }
#[test] #[test]
fn event_with_info_string() { fn event_with_info_string() {
let info_string = "Test Information"; let info_string = "Test Information";
basic_event_test(32, Severity::INFO, Some(info_string.as_bytes())); basic_event_test(32, Severity::Info, Some(info_string.as_bytes()));
} }
#[test] #[test]
fn low_severity_with_raw_err_data() { fn low_severity_with_raw_err_data() {
let raw_err_param: i32 = -1; let raw_err_param: i32 = -1;
let raw_err = raw_err_param.to_be_bytes(); let raw_err = raw_err_param.to_be_bytes();
basic_event_test(8, Severity::LOW, Some(&raw_err)) basic_event_test(8, Severity::Low, Some(&raw_err))
} }
fn check_buf_too_small( fn check_buf_too_small(
@ -454,7 +454,7 @@ mod tests {
expected_found_len: usize, expected_found_len: usize,
) { ) {
let time_stamp_empty: [u8; 7] = [0; 7]; let time_stamp_empty: [u8; 7] = [0; 7];
let event = EventU32::new(Severity::INFO, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0) let event = EventU32::new_checked(Severity::Info, EXAMPLE_GROUP_ID, EXAMPLE_EVENT_ID_0)
.expect("Error creating example event"); .expect("Error creating example event");
let err = reporter.event_info(sender, &time_stamp_empty, event, None); let err = reporter.event_info(sender, &time_stamp_empty, event, None);
assert!(err.is_err()); assert!(err.is_err());

View File

@ -190,22 +190,22 @@ pub mod alloc_mod {
return Ok(false); return Ok(false);
} }
match event.severity() { match event.severity() {
Severity::INFO => self Severity::Info => self
.reporter .reporter
.event_info(sender, time_stamp, event, params) .event_info(sender, time_stamp, event, params)
.map(|_| true) .map(|_| true)
.map_err(|e| e.into()), .map_err(|e| e.into()),
Severity::LOW => self Severity::Low => self
.reporter .reporter
.event_low_severity(sender, time_stamp, event, params) .event_low_severity(sender, time_stamp, event, params)
.map(|_| true) .map(|_| true)
.map_err(|e| e.into()), .map_err(|e| e.into()),
Severity::MEDIUM => self Severity::Medium => self
.reporter .reporter
.event_medium_severity(sender, time_stamp, event, params) .event_medium_severity(sender, time_stamp, event, params)
.map(|_| true) .map(|_| true)
.map_err(|e| e.into()), .map_err(|e| e.into()),
Severity::HIGH => self Severity::High => self
.reporter .reporter
.event_high_severity(sender, time_stamp, event, params) .event_high_severity(sender, time_stamp, event, params)
.map(|_| true) .map(|_| true)
@ -266,9 +266,8 @@ mod tests {
use crate::{events::SeverityInfo, tmtc::PacketAsVec}; use crate::{events::SeverityInfo, tmtc::PacketAsVec};
use std::sync::mpsc::{self, TryRecvError}; use std::sync::mpsc::{self, TryRecvError};
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityInfo>::new(1, 0);
EventU32TypedSev::<SeverityInfo>::const_new(1, 0); const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
const EMPTY_STAMP: [u8; 7] = [0; 7]; const EMPTY_STAMP: [u8; 7] = [0; 7];
const TEST_APID: u16 = 0x02; const TEST_APID: u16 = 0x02;
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05); const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);

View File

@ -181,7 +181,7 @@ mod tests {
use super::PusEventServiceHandler; use super::PusEventServiceHandler;
const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25); const TEST_EVENT_0: EventU32 = EventU32::new(crate::events::Severity::Info, 5, 25);
struct Pus5HandlerWithStoreTester { struct Pus5HandlerWithStoreTester {
common: PusServiceHandlerWithSharedStoreCommon, common: PusServiceHandlerWithSharedStoreCommon,

View File

@ -21,7 +21,7 @@ struct EventIntrospection {
} }
//#[event(descr="This is some info event")] //#[event(descr="This is some info event")]
const INFO_EVENT_0: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::const_new(0, 0); const INFO_EVENT_0: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::new(0, 0);
const INFO_EVENT_0_ERASED: EventU32 = EventU32::const_from_info(INFO_EVENT_0); const INFO_EVENT_0_ERASED: EventU32 = EventU32::const_from_info(INFO_EVENT_0);
// This is ideally auto-generated // This is ideally auto-generated
@ -36,7 +36,7 @@ const INFO_EVENT_0_INTROSPECTION: EventIntrospection = EventIntrospection {
}; };
//#[event(descr="This is some low severity event")] //#[event(descr="This is some low severity event")]
const SOME_LOW_SEV_EVENT: EventU32TypedSev<SeverityLow> = EventU32TypedSev::const_new(0, 12); const SOME_LOW_SEV_EVENT: EventU32TypedSev<SeverityLow> = EventU32TypedSev::new(0, 12);
//const EVENT_LIST: [&'static Event; 2] = [&INFO_EVENT_0, &SOME_LOW_SEV_EVENT]; //const EVENT_LIST: [&'static Event; 2] = [&INFO_EVENT_0, &SOME_LOW_SEV_EVENT];
@ -47,7 +47,7 @@ const TEST_GROUP_NAME_NAME: &str = "TEST_GROUP_NAME";
//#[event(desc="Some medium severity event")] //#[event(desc="Some medium severity event")]
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: EventU32TypedSev<SeverityMedium> = const MEDIUM_SEV_EVENT_IN_OTHER_GROUP: EventU32TypedSev<SeverityMedium> =
EventU32TypedSev::const_new(TEST_GROUP_NAME, 0); EventU32TypedSev::new(TEST_GROUP_NAME, 0);
const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_REDUCED: EventU32 = const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_REDUCED: EventU32 =
EventU32::const_from_medium(MEDIUM_SEV_EVENT_IN_OTHER_GROUP); EventU32::const_from_medium(MEDIUM_SEV_EVENT_IN_OTHER_GROUP);
@ -62,7 +62,7 @@ const MEDIUM_SEV_EVENT_IN_OTHER_GROUP_INTROSPECTION: EventIntrospection = EventI
info: "Some medium severity event", info: "Some medium severity event",
}; };
const CONST_SLICE: &'static [u8] = &[0, 1, 2, 3]; const CONST_SLICE: &[u8] = &[0, 1, 2, 3];
const INTROSPECTION_FOR_TEST_GROUP_0: [&EventIntrospection; 2] = const INTROSPECTION_FOR_TEST_GROUP_0: [&EventIntrospection; 2] =
[&INFO_EVENT_0_INTROSPECTION, &INFO_EVENT_0_INTROSPECTION]; [&INFO_EVENT_0_INTROSPECTION, &INFO_EVENT_0_INTROSPECTION];

View File

@ -14,9 +14,8 @@ use spacepackets::ecss::{PusError, PusPacket};
use std::sync::mpsc::{self, SendError, TryRecvError}; use std::sync::mpsc::{self, SendError, TryRecvError};
use std::thread; use std::thread;
const INFO_EVENT: EventU32TypedSev<SeverityInfo> = const INFO_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<SeverityInfo>::new(1, 0);
EventU32TypedSev::<SeverityInfo>::const_new(1, 0); const LOW_SEV_EVENT: EventU32 = EventU32::new(Severity::Low, 1, 5);
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
const EMPTY_STAMP: [u8; 7] = [0; 7]; const EMPTY_STAMP: [u8; 7] = [0; 7];
const TEST_APID: u16 = 0x02; const TEST_APID: u16 = 0x02;
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05); const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);