use std::sync::Arc;
use arc_swap::ArcSwap;
pub trait ConfigKey: 'static {
type Config: Send + Sync + 'static;
const NAME: &'static str;
}
#[derive(Debug)]
pub struct ConfigHandle<T: Send + Sync + 'static> {
inner: Arc<ArcSwap<T>>,
}
impl<T: Send + Sync + 'static> ConfigHandle<T> {
pub fn new(value: T) -> Self {
ConfigHandle {
inner: Arc::new(ArcSwap::new(Arc::new(value))),
}
}
pub fn load(&self) -> Arc<T> {
self.inner.load_full()
}
pub fn set(&self, value: T) {
self.inner.store(Arc::new(value));
}
}
impl<T: Send + Sync + 'static> Clone for ConfigHandle<T> {
fn clone(&self) -> Self {
ConfigHandle {
inner: Arc::clone(&self.inner),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[allow(dead_code)]
struct TestConfig;
impl ConfigKey for TestConfig {
type Config = i32;
const NAME: &'static str = "test_config";
}
#[test]
fn new_creates_handle_with_initial_value() {
let handle = ConfigHandle::new(42);
assert_eq!(*handle.load(), 42);
}
#[test]
fn load_returns_current_value() {
let handle = ConfigHandle::new(10);
assert_eq!(*handle.load(), 10);
}
#[test]
fn set_updates_value() {
let handle = ConfigHandle::new(1);
handle.set(2);
assert_eq!(*handle.load(), 2);
}
#[test]
fn clone_shares_same_inner_cell() {
let handle = ConfigHandle::new(100);
let cloned = handle.clone();
handle.set(200);
assert_eq!(*cloned.load(), 200);
}
}