1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
use crate::{ error::{ProtoError, ProtoErrorKind, ProtoErrorResultExt}, message::{ChannelName, NowVirtualChannel}, sm::VirtualChannelSM, }; use alloc::collections::BTreeMap; pub type ChannelsManagerResult<'a> = Result<Option<(ChannelName, NowVirtualChannel<'a>)>, ProtoError>; pub struct ChannelsManager { state_machines: BTreeMap<ChannelName, Box<dyn VirtualChannelSM>>, } impl Default for ChannelsManager { fn default() -> Self { Self::new() } } impl ChannelsManager { pub fn new() -> Self { Self { state_machines: BTreeMap::new(), } } pub fn with_sm<VirtChanSM>(mut self, state_machine: VirtChanSM) -> Self where VirtChanSM: VirtualChannelSM + 'static, { self.add_channel_sm(state_machine); self } pub fn add_channel_sm<VirtChanSM>(&mut self, state_machine: VirtChanSM) -> Option<Box<dyn VirtualChannelSM>> where VirtChanSM: VirtualChannelSM + 'static, { self.state_machines .insert(state_machine.get_channel_name(), Box::new(state_machine)) } pub fn update_with_virt_msg<'msg: 'a, 'a>( &mut self, chan_msg: &'a NowVirtualChannel<'msg>, ) -> ChannelsManagerResult<'msg> { if let Some(sm) = self.state_machines.get_mut(chan_msg.get_name()) { sm.update_with_chan_msg(chan_msg) .map(|o| o.map(|chan| (sm.get_channel_name(), chan))) } else { ProtoError::new(ProtoErrorKind::ChannelsManager) .or_desc(format!("state machine for channel {:?} not found", chan_msg.get_name())) } } pub fn update_without_virt_msg<'msg>(&mut self) -> ChannelsManagerResult<'msg> { for sm in self.state_machines.values_mut() { if !sm.waiting_for_packet() { return sm .update_without_chan_msg() .map(|o| o.map(|chan| (sm.get_channel_name(), chan))); } } ProtoError::new(ProtoErrorKind::ChannelsManager) .or_desc("no channel state machine is ready to update without message") } pub fn waiting_for_packet(&self) -> bool { for sm in self.state_machines.values() { if !sm.waiting_for_packet() { return false; } } true } }