use alloc::string::String;
use crate::channel::{self, Publisher, Subscribable, Subscriber};
use crate::pod::Pod;
use hashbrown::HashMap;
use spin::Mutex;
pub struct Photon<T: Pod> {
topics: Mutex<HashMap<String, TopicEntry<T>>>,
default_capacity: usize,
}
struct TopicEntry<T: Pod> {
subscribable: Subscribable<T>,
publisher: Option<Publisher<T>>,
}
impl<T: Pod> Photon<T> {
pub fn new(capacity: usize) -> Self {
Photon {
topics: Mutex::new(HashMap::new()),
default_capacity: capacity,
}
}
pub fn publisher(&self, topic: &str) -> Publisher<T> {
let mut topics = self.topics.lock();
let entry = topics
.entry_ref(topic)
.or_insert_with(|| Self::make_entry(self.default_capacity));
entry
.publisher
.take()
.unwrap_or_else(|| panic!("publisher already taken for topic '{}'", topic))
}
pub fn try_publisher(&self, topic: &str) -> Option<Publisher<T>> {
let mut topics = self.topics.lock();
let entry = topics
.entry_ref(topic)
.or_insert_with(|| Self::make_entry(self.default_capacity));
entry.publisher.take()
}
pub fn subscribe(&self, topic: &str) -> Subscriber<T> {
let mut topics = self.topics.lock();
let entry = topics
.entry_ref(topic)
.or_insert_with(|| Self::make_entry(self.default_capacity));
entry.subscribable.subscribe()
}
pub fn subscribable(&self, topic: &str) -> Subscribable<T> {
let mut topics = self.topics.lock();
let entry = topics
.entry_ref(topic)
.or_insert_with(|| Self::make_entry(self.default_capacity));
entry.subscribable.clone()
}
fn make_entry(capacity: usize) -> TopicEntry<T> {
let (pub_, sub_) = channel::channel(capacity);
TopicEntry {
subscribable: sub_,
publisher: Some(pub_),
}
}
}