use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use tokio::sync::mpsc::UnboundedSender;
use atomcode_core::tool::PermissionDecision;
#[derive(Clone, Default)]
pub struct PermissionResponders {
inner: Arc<RwLock<HashMap<String, UnboundedSender<PermissionDecision>>>>,
}
impl PermissionResponders {
pub fn new() -> Self {
Self::default()
}
pub fn register(&self, session_id: String, tx: UnboundedSender<PermissionDecision>) {
self.inner.write().unwrap().insert(session_id, tx);
}
pub fn unregister(&self, session_id: &str) {
self.inner.write().unwrap().remove(session_id);
}
pub fn deliver(&self, session_id: &str, decision: PermissionDecision) -> bool {
if let Some(tx) = self.inner.read().unwrap().get(session_id) {
tx.send(decision).is_ok()
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use atomcode_core::tool::PermissionDecision;
#[tokio::test]
async fn routes_decision_to_registered_session() {
let reg = PermissionResponders::new();
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
reg.register("sess-1".into(), tx);
assert!(reg.deliver("sess-1", PermissionDecision::Allow));
assert!(matches!(rx.recv().await, Some(PermissionDecision::Allow)));
}
#[test]
fn deliver_to_unknown_session_returns_false() {
let reg = PermissionResponders::new();
assert!(!reg.deliver("nope", PermissionDecision::Deny));
}
}