1use alloc::string::String;
5
6use crate::channel::{self, Publisher, Subscribable, Subscriber};
7use crate::pod::Pod;
8use hashbrown::HashMap;
9use spin::Mutex;
10
11pub struct Photon<T: Pod> {
24 topics: Mutex<HashMap<String, TopicEntry<T>>>,
25 default_capacity: usize,
26}
27
28struct TopicEntry<T: Pod> {
29 subscribable: Subscribable<T>,
30 publisher: Option<Publisher<T>>,
31}
32
33impl<T: Pod> Photon<T> {
34 pub fn new(capacity: usize) -> Self {
36 Photon {
37 topics: Mutex::new(HashMap::new()),
38 default_capacity: capacity,
39 }
40 }
41
42 pub fn publisher(&self, topic: &str) -> Publisher<T> {
47 let mut topics = self.topics.lock();
48 let entry = topics
49 .entry_ref(topic)
50 .or_insert_with(|| Self::make_entry(self.default_capacity));
51 entry
52 .publisher
53 .take()
54 .unwrap_or_else(|| panic!("publisher already taken for topic '{}'", topic))
55 }
56
57 pub fn try_publisher(&self, topic: &str) -> Option<Publisher<T>> {
60 let mut topics = self.topics.lock();
61 let entry = topics
62 .entry_ref(topic)
63 .or_insert_with(|| Self::make_entry(self.default_capacity));
64 entry.publisher.take()
65 }
66
67 pub fn subscribe(&self, topic: &str) -> Subscriber<T> {
69 let mut topics = self.topics.lock();
70 let entry = topics
71 .entry_ref(topic)
72 .or_insert_with(|| Self::make_entry(self.default_capacity));
73 entry.subscribable.subscribe()
74 }
75
76 pub fn subscribable(&self, topic: &str) -> Subscribable<T> {
78 let mut topics = self.topics.lock();
79 let entry = topics
80 .entry_ref(topic)
81 .or_insert_with(|| Self::make_entry(self.default_capacity));
82 entry.subscribable.clone()
83 }
84
85 fn make_entry(capacity: usize) -> TopicEntry<T> {
86 let (pub_, sub_) = channel::channel(capacity);
87 TopicEntry {
88 subscribable: sub_,
89 publisher: Some(pub_),
90 }
91 }
92}