use gfeh_core::NodeRef;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Exposed {
pub node: NodeRef,
pub filename: Option<String>,
pub enabled: bool,
}
pub trait Exposures: Send + Sync + 'static {
fn resolve(&self, token: &str) -> Option<Exposed>;
}
#[derive(Debug, Default, Clone)]
pub struct StaticExposures {
entries: Arc<RwLock<HashMap<String, Exposed>>>,
}
impl StaticExposures {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn with(self, token: &str, exposed: Exposed) -> Self {
self.publish(token, exposed);
self
}
pub fn publish(&self, token: &str, exposed: Exposed) {
if let Ok(mut entries) = self.entries.write() {
entries.insert(token.to_string(), exposed);
}
}
pub fn set_enabled(&self, token: &str, enabled: bool) {
if let Ok(mut entries) = self.entries.write()
&& let Some(entry) = entries.get_mut(token)
{
entry.enabled = enabled;
}
}
pub fn withdraw(&self, token: &str) {
if let Ok(mut entries) = self.entries.write() {
entries.remove(token);
}
}
}
impl Exposures for StaticExposures {
fn resolve(&self, token: &str) -> Option<Exposed> {
self.entries.read().ok()?.get(token).cloned()
}
}
#[cfg(test)]
mod tests {
use super::*;
use gfeh_core::{NodeId, PartitionId};
fn exposed() -> Exposed {
Exposed {
node: NodeRef::Id(PartitionId(uuid_nil()), NodeId(7)),
filename: None,
enabled: true,
}
}
fn uuid_nil() -> uuid::Uuid {
uuid::Uuid::nil()
}
#[test]
fn a_published_token_resolves_and_an_unknown_one_does_not() {
let table = StaticExposures::new().with("tok", exposed());
assert_eq!(table.resolve("tok"), Some(exposed()));
assert_eq!(table.resolve("other"), None);
}
#[test]
fn disabling_keeps_the_token_and_clears_the_link() {
let table = StaticExposures::new().with("tok", exposed());
table.set_enabled("tok", false);
assert_eq!(table.resolve("tok").map(|e| e.enabled), Some(false));
table.set_enabled("tok", true);
assert_eq!(table.resolve("tok").map(|e| e.enabled), Some(true));
}
#[test]
fn withdrawing_removes_it() {
let table = StaticExposures::new().with("tok", exposed());
table.withdraw("tok");
assert_eq!(table.resolve("tok"), None);
}
}