use std::sync::Arc;
use crate::topic::TopicEntry;
use crate::topic::TopicStore;
#[derive(Debug, Clone)]
pub struct Route {
pub entry: Arc<TopicEntry>,
}
pub trait TopicRouter: Send + Sync {
fn route(&self, topic: &str, routing_key: Option<&str>) -> Option<Route>;
}
pub struct LocalRouter {
pub store: TopicStore,
pub default_profile_factory: Arc<dyn Fn() -> crate::topic::TopicProfile + Send + Sync>,
}
impl std::fmt::Debug for LocalRouter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LocalRouter")
.field("store", &self.store)
.field("default_profile_factory", &"<fn>")
.finish()
}
}
impl LocalRouter {
pub fn new(
store: TopicStore,
default_profile_factory: Arc<dyn Fn() -> crate::topic::TopicProfile + Send + Sync>,
) -> Self {
Self {
store,
default_profile_factory,
}
}
}
impl TopicRouter for LocalRouter {
fn route(&self, topic: &str, _routing_key: Option<&str>) -> Option<Route> {
let entry = self
.store
.get_or_create(topic, (self.default_profile_factory)())
.ok()?;
Some(Route { entry })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn local_router_creates_topic() {
let store = TopicStore::new();
let router = LocalRouter::new(store, Arc::new(crate::topic::TopicProfile::default));
let route = router.route("room/1", None).unwrap();
assert_eq!(route.entry.name, "room/1");
}
}