sat-rs/satrs/src/mode_tree.rs

304 lines
9.2 KiB
Rust
Raw Normal View History

use alloc::vec::Vec;
use hashbrown::HashMap;
use crate::{
2024-11-28 12:36:43 +01:00
mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode},
request::MessageSender,
ComponentId,
};
2024-11-26 10:25:56 +01:00
#[cfg(feature = "alloc")]
pub use alloc_mod::*;
2024-11-28 12:36:43 +01:00
/// Common trait for node modes which can have mode parents or mode children.
pub trait ModeNode {
fn id(&self) -> ComponentId;
}
/// Trait which denotes that an object is a parent in a mode tree.
///
/// A mode parent is capable of sending mode requests to child objects and has a unique component
/// ID.
pub trait ModeParent: ModeNode {
type Sender: MessageSender<ModeRequest>;
fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender);
}
/// Trait which denotes that an object is a child in a mode tree.
///
/// A child is capable of sending mode replies to parent objects and has a unique component ID.
pub trait ModeChild: ModeNode {
type Sender: MessageSender<ModeReply>;
fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender);
}
/// Utility method which connects a mode tree parent object to a child object by calling
/// [ModeParent::add_mode_child] on the [parent][ModeParent] and calling
/// [ModeChild::add_mode_parent] on the [child][ModeChild].
///
/// # Arguments
///
/// * `parent` - The parent object which implements [ModeParent].
/// * `request_sender` - Sender object to send mode requests to the child.
/// * `child` - The child object which implements [ModeChild].
/// * `reply_sender` - Sender object to send mode replies to the parent.
pub fn connect_mode_nodes<ReqSender, ReplySender>(
parent: &mut impl ModeParent<Sender = ReqSender>,
request_sender: ReqSender,
child: &mut impl ModeChild<Sender = ReplySender>,
reply_sender: ReplySender,
) {
parent.add_mode_child(child.id(), request_sender);
child.add_mode_parent(parent.id(), reply_sender);
}
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum TableEntryType {
/// Target table containing information of the expected children modes for given mode.
Target,
/// Sequence table which contains information about how to reach a target table, including
/// the order of the sequences.
Sequence,
}
2024-11-21 18:35:16 +01:00
/// Common fields required for both target and sequence table entries.
///
/// The most important parameters here are the target ID which this entry belongs to, and the mode
/// and submode the entry either will be commanded to for sequence table entries or which will be
/// monitored for target table entries.
#[derive(Debug, Copy, Clone)]
pub struct ModeTableEntryCommon {
/// Name of respective table entry.
pub name: &'static str,
2024-11-21 18:35:16 +01:00
/// Target component ID.
pub target_id: ComponentId,
/// Has a different meaning depending on whether this is a sequence table or a target table.
///
/// - For sequence tables, this denotes the mode which will be commanded
/// - For target tables, this is the mode which the target children should have and which
/// might be monitored depending on configuration.
pub mode_submode: ModeAndSubmode,
2024-11-21 18:35:16 +01:00
/// This mask allows to specify multiple allowed submodes for a given mode.
pub allowed_submode_mask: Option<Submode>,
}
2024-11-21 18:35:16 +01:00
impl ModeTableEntryCommon {
pub fn set_allowed_submode_mask(&mut self, mask: Submode) {
self.allowed_submode_mask = Some(mask);
}
pub fn allowed_submode_mask(&self) -> Option<Submode> {
self.allowed_submode_mask
}
}
/// An entry for the target tables.
#[derive(Debug)]
pub struct TargetTableEntry {
pub common: ModeTableEntryCommon,
pub monitor_state: bool,
}
impl TargetTableEntry {
pub fn new(
name: &'static str,
target_id: ComponentId,
mode_submode: ModeAndSubmode,
monitor_state: bool,
2024-11-28 12:36:43 +01:00
allowed_submode_mask: Option<Submode>,
) -> Self {
Self {
common: ModeTableEntryCommon {
name,
target_id,
mode_submode,
allowed_submode_mask,
},
monitor_state,
}
}
pub fn new_with_precise_submode(
name: &'static str,
target_id: ComponentId,
mode_submode: ModeAndSubmode,
monitor_state: bool,
2024-11-21 18:35:16 +01:00
) -> Self {
Self {
common: ModeTableEntryCommon {
name,
target_id,
mode_submode,
allowed_submode_mask: None,
},
monitor_state,
}
}
delegate::delegate! {
to self.common {
pub fn set_allowed_submode_mask(&mut self, mask: Submode);
pub fn allowed_submode_mask(&self) -> Option<Submode>;
}
}
}
/// An entry for the sequence tables.
///
/// The `check_success` field instructs the mode sequence executor to verify that the
/// target mode was actually reached before executing the next sequence.
2024-11-26 10:25:56 +01:00
#[derive(Debug)]
2024-11-21 18:35:16 +01:00
pub struct SequenceTableEntry {
pub common: ModeTableEntryCommon,
pub check_success: bool,
}
impl SequenceTableEntry {
pub fn new(
name: &'static str,
target_id: ComponentId,
mode_submode: ModeAndSubmode,
check_success: bool,
) -> Self {
Self {
common: ModeTableEntryCommon {
name,
target_id,
mode_submode,
allowed_submode_mask: None,
},
check_success,
}
}
delegate::delegate! {
to self.common {
pub fn set_allowed_submode_mask(&mut self, mask: Submode);
pub fn allowed_submode_mask(&self) -> Option<Submode>;
}
}
}
2024-11-26 10:25:56 +01:00
pub trait ModeStoreProvider {
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode);
fn get_mode(&self, target_id: ComponentId) -> Option<ModeAndSubmode>;
fn set_mode(&mut self, target_id: ComponentId, mode: ModeAndSubmode);
2024-11-21 18:35:16 +01:00
}
2024-11-26 10:25:56 +01:00
#[cfg(feature = "alloc")]
pub mod alloc_mod {
use super::*;
#[derive(Debug)]
2024-11-28 12:36:43 +01:00
pub struct TargetTablesMapValue {
2024-11-26 10:25:56 +01:00
/// Name for a given mode table entry.
pub name: &'static str,
/// These are the rows of the a target table.
pub entries: Vec<TargetTableEntry>,
}
2024-11-28 12:36:43 +01:00
impl TargetTablesMapValue {
2024-11-26 10:25:56 +01:00
pub fn new(name: &'static str) -> Self {
Self {
name,
entries: Default::default(),
}
}
pub fn add_entry(&mut self, entry: TargetTableEntry) {
self.entries.push(entry);
2024-11-21 18:35:16 +01:00
}
}
2024-11-26 10:25:56 +01:00
#[derive(Debug)]
pub struct SequenceTableMapTable {
/// Name for a given mode sequence.
pub name: &'static str,
/// These are the rows of the a sequence table.
pub entries: Vec<SequenceTableEntry>,
2024-11-21 18:35:16 +01:00
}
2024-11-26 10:25:56 +01:00
impl SequenceTableMapTable {
pub fn new(name: &'static str) -> Self {
Self {
name,
entries: Default::default(),
}
}
2024-11-21 18:35:16 +01:00
2024-11-26 10:25:56 +01:00
pub fn add_entry(&mut self, entry: SequenceTableEntry) {
self.entries.push(entry);
2024-11-21 18:35:16 +01:00
}
}
2024-11-26 10:25:56 +01:00
#[derive(Debug)]
2024-11-28 12:36:43 +01:00
pub struct SequenceTablesMapValue {
2024-11-26 10:25:56 +01:00
/// Name for a given mode sequence.
pub name: &'static str,
/// Each sequence can consists of multiple sequences that are executed consecutively.
pub entries: Vec<SequenceTableMapTable>,
2024-11-21 18:35:16 +01:00
}
2024-11-28 12:36:43 +01:00
impl SequenceTablesMapValue {
2024-11-26 10:25:56 +01:00
pub fn new(name: &'static str) -> Self {
Self {
name,
entries: Default::default(),
}
}
pub fn add_sequence_table(&mut self, entry: SequenceTableMapTable) {
self.entries.push(entry);
}
}
#[derive(Debug, Default)]
2024-11-28 12:36:43 +01:00
pub struct TargetModeTables(pub HashMap<Mode, TargetTablesMapValue>);
2024-11-26 10:25:56 +01:00
#[derive(Debug, Default)]
2024-11-28 12:36:43 +01:00
pub struct SequenceModeTables(pub HashMap<Mode, SequenceTablesMapValue>);
2024-11-26 10:25:56 +01:00
#[derive(Debug, Default)]
pub struct ModeStoreVec(pub alloc::vec::Vec<(ComponentId, ModeAndSubmode)>);
#[derive(Debug, Default)]
pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeAndSubmode>);
impl ModeStoreProvider for ModeStoreVec {
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
self.0.push((target_id, mode));
}
fn get_mode(&self, target_id: ComponentId) -> Option<ModeAndSubmode> {
self.0.iter().find_map(|(id, mode)| {
if *id == target_id {
return Some(*mode);
}
None
})
}
fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) {
self.0.iter_mut().for_each(|(id, mode)| {
if *id == target_id {
*mode = mode_to_set;
}
});
}
}
impl ModeStoreProvider for ModeStoreMap {
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
self.0.insert(target_id, mode);
}
fn get_mode(&self, target_id: ComponentId) -> Option<ModeAndSubmode> {
self.0.get(&target_id).copied()
}
fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) {
self.0.insert(target_id, mode_to_set);
}
}
}
#[cfg(test)]
mod tests {}