sans_io_runtime/bus/
local_hub.rs1use std::{collections::HashMap, fmt::Debug, hash::Hash};
2
3#[derive(Debug)]
4pub struct BusLocalHub<Owner, ChannelId: Hash + PartialEq + Eq> {
5 channels: HashMap<ChannelId, Vec<Owner>>,
6}
7
8impl<Owner, ChannelId: Hash + PartialEq + Eq> Default for BusLocalHub<Owner, ChannelId> {
9 fn default() -> Self {
10 Self {
11 channels: HashMap::new(),
12 }
13 }
14}
15
16impl<Owner: Clone + Debug + PartialEq, ChannelId: Debug + Clone + Copy + Hash + PartialEq + Eq>
17 BusLocalHub<Owner, ChannelId>
18{
19 pub fn subscribe(&mut self, owner: Owner, channel: ChannelId) -> bool {
21 let entry = self.channels.entry(channel).or_default();
22 if entry.contains(&owner) {
23 false
24 } else {
25 entry.push(owner);
26 entry.len() == 1
27 }
28 }
29
30 pub fn unsubscribe(&mut self, owner: Owner, channel: ChannelId) -> bool {
32 log::info!("channels: {:?}", self.channels);
33 if let Some(entry) = self.channels.get_mut(&channel) {
34 log::info!("remove owner {:?} with list {:?}", owner, entry);
35 if let Some(pos) = entry.iter().position(|x| *x == owner) {
36 log::info!("remove owner {:?}", owner);
37 entry.swap_remove(pos);
38 if entry.is_empty() {
39 self.channels.remove(&channel);
40 true
41 } else {
42 false
43 }
44 } else {
45 false
46 }
47 } else {
48 false
49 }
50 }
51
52 pub fn get_subscribers(&self, channel: ChannelId) -> Option<Vec<Owner>> {
54 self.channels.get(&channel).cloned()
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::group_owner_type;
61
62 use super::*;
63
64 group_owner_type!(DemoOwner);
65
66 #[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
67 enum Channel {
68 A,
69 B,
70 C,
71 }
72
73 #[test]
74 fn test_subscribe_unsubscribe() {
75 let mut hub: BusLocalHub<DemoOwner, Channel> = BusLocalHub::default();
76 let owner1 = DemoOwner(1);
77 let owner2 = DemoOwner(2);
78
79 assert_eq!(hub.subscribe(owner1, Channel::A), true);
80 assert_eq!(hub.subscribe(owner2, Channel::A), false);
81 assert_eq!(hub.subscribe(owner1, Channel::B), true);
82 assert_eq!(hub.subscribe(owner1, Channel::C), true);
83
84 assert_eq!(hub.unsubscribe(owner1, Channel::A), false);
85 assert_eq!(hub.unsubscribe(owner2, Channel::A), true);
86 assert_eq!(hub.unsubscribe(owner1, Channel::B), true);
87 assert_eq!(hub.unsubscribe(owner1, Channel::C), true);
88 }
89
90 #[test]
91 fn test_get_subscribers() {
92 let mut hub: BusLocalHub<DemoOwner, Channel> = BusLocalHub::default();
93 let owner1 = DemoOwner(1);
94 let owner2 = DemoOwner(2);
95
96 hub.subscribe(owner1, Channel::A);
97 hub.subscribe(owner1, Channel::B);
98 hub.subscribe(owner2, Channel::A);
99
100 assert_eq!(hub.get_subscribers(Channel::A), Some(vec![owner1, owner2]));
101 assert_eq!(hub.get_subscribers(Channel::B), Some(vec![owner1]));
102 assert_eq!(hub.get_subscribers(Channel::C), None);
103 }
104}