use std::sync::Arc;
use crate::types::EpicsValue;
pub trait LinkSet: Send + Sync {
fn is_connected(&self, name: &str) -> bool;
fn get_value(&self, name: &str) -> Option<EpicsValue>;
fn put_value(&self, name: &str, value: EpicsValue) -> Result<(), String> {
let _ = (name, value);
Err("link set is read-only".into())
}
fn alarm_message(&self, _name: &str) -> Option<String> {
None
}
fn time_stamp(&self, _name: &str) -> Option<(i64, i32)> {
None
}
fn link_names(&self) -> Vec<String> {
Vec::new()
}
}
pub type DynLinkSet = Arc<dyn LinkSet>;
#[derive(Default)]
pub struct LinkSetRegistry {
inner: std::collections::HashMap<String, DynLinkSet>,
}
impl LinkSetRegistry {
pub fn new() -> Self {
Self {
inner: std::collections::HashMap::new(),
}
}
pub fn register(&mut self, scheme: &str, lset: DynLinkSet) {
self.inner.insert(scheme.to_string(), lset);
}
pub fn get(&self, scheme: &str) -> Option<DynLinkSet> {
self.inner.get(scheme).cloned()
}
pub fn schemes(&self) -> Vec<String> {
self.inner.keys().cloned().collect()
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
struct StubLset;
impl LinkSet for StubLset {
fn is_connected(&self, _: &str) -> bool {
true
}
fn get_value(&self, _: &str) -> Option<EpicsValue> {
Some(EpicsValue::Long(42))
}
}
#[test]
fn register_and_lookup() {
let mut reg = LinkSetRegistry::new();
assert!(reg.is_empty());
reg.register("pva", Arc::new(StubLset));
assert_eq!(reg.len(), 1);
let lset = reg.get("pva").expect("registered");
assert!(lset.is_connected("anything"));
assert_eq!(lset.get_value("anything"), Some(EpicsValue::Long(42)));
}
#[test]
fn unknown_scheme_returns_none() {
let reg = LinkSetRegistry::new();
assert!(reg.get("missing").is_none());
}
}