use core::mem::size_of; use satrs_shared::res_code::ResultU16; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use spacepackets::ByteConversionError; #[cfg(feature = "alloc")] pub use alloc_mod::*; #[cfg(feature = "std")] pub use std_mod::*; use crate::{ queue::GenericTargetedMessagingError, request::{GenericMessage, MessageReceiver, MessageReceiverWithId, RequestId}, ChannelId, ComponentId, }; pub type Mode = u32; pub type Submode = u16; #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ModeAndSubmode { mode: Mode, submode: Submode, } impl ModeAndSubmode { const RAW_LEN: usize = size_of::() + size_of::(); pub const fn new_mode_only(mode: Mode) -> Self { Self { mode, submode: 0 } } pub const fn new(mode: Mode, submode: Submode) -> Self { Self { mode, submode } } pub fn from_be_bytes(buf: &[u8]) -> Result { if buf.len() < 6 { return Err(ByteConversionError::FromSliceTooSmall { expected: Self::RAW_LEN, found: buf.len(), }); } Ok(Self { mode: Mode::from_be_bytes(buf[0..size_of::()].try_into().unwrap()), submode: Submode::from_be_bytes( buf[size_of::()..size_of::() + size_of::()] .try_into() .unwrap(), ), }) } pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { if buf.len() < Self::RAW_LEN { return Err(ByteConversionError::ToSliceTooSmall { expected: Self::RAW_LEN, found: buf.len(), }); } buf[0..size_of::()].copy_from_slice(&self.mode.to_be_bytes()); buf[size_of::()..Self::RAW_LEN].copy_from_slice(&self.submode.to_be_bytes()); Ok(Self::RAW_LEN) } pub fn mode(&self) -> Mode { self.mode } pub fn submode(&self) -> Submode { self.submode } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TargetedModeCommand { pub address: ComponentId, pub mode_submode: ModeAndSubmode, } impl TargetedModeCommand { pub const fn new(address: ComponentId, mode_submode: ModeAndSubmode) -> Self { Self { address, mode_submode, } } pub fn address(&self) -> ComponentId { self.address } pub fn mode_submode(&self) -> ModeAndSubmode { self.mode_submode } pub fn mode(&self) -> u32 { self.mode_submode.mode } pub fn submode(&self) -> u16 { self.mode_submode.submode } } #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeRequest { SetMode(ModeAndSubmode), ReadMode, AnnounceMode, AnnounceModeRecursive, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TargetedModeRequest { target_id: ComponentId, mode_request: ModeRequest, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeReply { /// Unrequest mode information. Can be used to notify other components of changed modes. ModeInfo(ModeAndSubmode), /// Reply to a mode request to confirm the commanded mode was reached. ModeReply(ModeAndSubmode), // Can not reach the commanded mode. Contains a reason as a [ResultU16]. CantReachMode(ResultU16), WrongMode { expected: ModeAndSubmode, reached: ModeAndSubmode, }, } pub type GenericModeReply = GenericMessage; pub trait ModeRequestSender { fn local_channel_id(&self) -> ChannelId; fn send_mode_request( &self, request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError>; } pub trait ModeRequestReceiver { fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError>; } impl> ModeRequestReceiver for MessageReceiverWithId { fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } } pub trait ModeProvider { fn mode_and_submode(&self) -> ModeAndSubmode; } #[derive(Debug, Clone)] pub enum ModeError { Messaging(GenericTargetedMessagingError), } impl From for ModeError { fn from(value: GenericTargetedMessagingError) -> Self { Self::Messaging(value) } } pub trait ModeRequestHandler: ModeProvider { fn start_transition( &mut self, request_id: RequestId, sender_id: ChannelId, mode_and_submode: ModeAndSubmode, ) -> Result<(), ModeError>; fn announce_mode(&self, request_id: RequestId, sender_id: ChannelId, recursive: bool); fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>; } pub trait ModeReplyReceiver { fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError>; } impl> ModeReplyReceiver for MessageReceiverWithId { fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } } pub trait ModeReplySender { fn local_channel_id(&self) -> ChannelId; fn send_mode_reply( &self, request_id: RequestId, target_id: ChannelId, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError>; } #[cfg(feature = "alloc")] #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub mod alloc_mod { use crate::{ mode::ModeRequest, queue::GenericTargetedMessagingError, request::{ MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId, RequestAndReplySenderAndReceiver, RequestId, }, ChannelId, }; use super::*; impl> MessageSenderMap { pub fn send_mode_reply( &self, request_id: RequestId, local_id: ChannelId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, local_id, target_id, request) } pub fn add_reply_target(&mut self, target_id: ChannelId, request_sender: S) { self.add_message_target(target_id, request_sender) } } impl> ModeReplySender for MessageSenderMapWithId { fn send_mode_reply( &self, request_id: RequestId, target_channel_id: ChannelId, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, target_channel_id, reply) } fn local_channel_id(&self) -> ChannelId { self.local_channel_id } } impl, R: MessageReceiver> ModeReplySender for MessageSenderAndReceiver { fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } fn send_mode_reply( &self, request_id: RequestId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map.send_mode_reply( request_id, self.local_channel_id(), target_id, request, ) } } impl, R: MessageReceiver> ModeReplyReceiver for MessageSenderAndReceiver { fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { self.message_receiver.try_recv_message() } } impl< REQUEST, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > RequestAndReplySenderAndReceiver { pub fn add_reply_target(&mut self, target_id: ChannelId, reply_sender: S1) { self.reply_sender_map .add_message_target(target_id, reply_sender) } } impl< REQUEST, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > ModeReplySender for RequestAndReplySenderAndReceiver { fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } fn send_mode_reply( &self, request_id: RequestId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.reply_sender_map.send_mode_reply( request_id, self.local_channel_id(), target_id, request, ) } } impl< REQUEST, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > ModeReplyReceiver for RequestAndReplySenderAndReceiver { fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { self.reply_receiver.try_recv_message() } } /// Helper type definition for a mode handler which can handle mode requests. pub type ModeRequestHandlerInterface = MessageSenderAndReceiver; impl, R: MessageReceiver> ModeRequestHandlerInterface { pub fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } pub fn send_mode_reply( &self, request_id: RequestId, target_id: ChannelId, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, target_id, reply) } } /// Helper type defintion for a mode handler object which can send mode requests and receive /// mode replies. pub type ModeRequestorInterface = MessageSenderAndReceiver; impl, R: MessageReceiver> ModeRequestorInterface { pub fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } pub fn send_mode_request( &self, request_id: RequestId, target_id: ChannelId, reply: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, target_id, reply) } } /// Helper type defintion for a mode handler object which can both send mode requests and /// process mode requests. pub type ModeInterface = RequestAndReplySenderAndReceiver; impl> MessageSenderMap { pub fn send_mode_request( &self, request_id: RequestId, local_id: ChannelId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, local_id, target_id, request) } pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) { self.add_message_target(target_id, request_sender) } } impl> ModeRequestSender for MessageSenderMapWithId { fn local_channel_id(&self) -> ChannelId { self.local_channel_id } fn send_mode_request( &self, request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.send_message(request_id, target_id, request) } } impl, R: MessageReceiver> ModeRequestReceiver for MessageSenderAndReceiver { fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { self.message_receiver.try_recv_message() } } impl, R: MessageReceiver> ModeRequestSender for MessageSenderAndReceiver { fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } fn send_mode_request( &self, request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map.send_mode_request( request_id, self.local_channel_id(), target_id, request, ) } } impl< REPLY, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > RequestAndReplySenderAndReceiver { pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) { self.request_sender_map .add_message_target(target_id, request_sender) } } impl< REPLY, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > ModeRequestSender for RequestAndReplySenderAndReceiver { fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } fn send_mode_request( &self, request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { self.request_sender_map.send_mode_request( request_id, self.local_channel_id(), target_id, request, ) } } impl< REPLY, S0: MessageSender, R0: MessageReceiver, S1: MessageSender, R1: MessageReceiver, > ModeRequestReceiver for RequestAndReplySenderAndReceiver { fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { self.request_receiver.try_recv_message() } } } #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { use std::sync::mpsc; use crate::request::GenericMessage; use super::*; pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface< mpsc::Sender>, mpsc::Receiver>, >; pub type ModeRequestHandlerMpscBounded = ModeRequestHandlerInterface< mpsc::SyncSender>, mpsc::Receiver>, >; pub type ModeRequestorMpsc = ModeRequestorInterface< mpsc::Sender>, mpsc::Receiver>, >; pub type ModeRequestorBoundedMpsc = ModeRequestorInterface< mpsc::SyncSender>, mpsc::Receiver>, >; pub type ModeRequestorAndHandlerMpsc = ModeInterface< mpsc::Sender>, mpsc::Receiver>, mpsc::Sender>, mpsc::Receiver>, >; pub type ModeRequestorAndHandlerMpscBounded = ModeInterface< mpsc::SyncSender>, mpsc::Receiver>, mpsc::SyncSender>, mpsc::Receiver>, >; } #[cfg(test)] mod tests {}