use std::{any::Any, marker::PhantomData, sync::Arc};
use conspiracy_theories::config::ConfigFetcher;
use crate::feature_control::{
set_global_tracker, FeatureSet, FeatureTracker, SetGlobalTrackerError,
};
pub struct ConspiracyFeatureTracker<T: FeatureSet, F: ConfigFetcher<T::State>> {
state_fetcher: F,
phantom: PhantomData<T>,
}
pub struct StaticFetcher<T: FeatureSet> {
state: Arc<T::State>,
}
impl<T: FeatureSet> ConfigFetcher<T::State> for StaticFetcher<T> {
fn latest_snapshot(&self) -> Arc<T::State> {
self.state.clone()
}
}
impl<T: FeatureSet> ConspiracyFeatureTracker<T, StaticFetcher<T>> {
pub fn from_default() -> Self {
Self::from_static(T::State::default())
}
pub fn from_static(state: T::State) -> Self {
Self {
state_fetcher: StaticFetcher {
state: Arc::new(state),
},
phantom: PhantomData,
}
}
}
impl<T: FeatureSet, F: ConfigFetcher<T::State> + 'static> ConspiracyFeatureTracker<T, F> {
pub fn set_as_global_tracker(self) -> Result<(), SetGlobalTrackerError> {
set_global_tracker::<T::State, Self>(self)
}
}
impl<T: FeatureSet, F: ConfigFetcher<T::State> + 'static> FeatureTracker
for ConspiracyFeatureTracker<T, F>
{
fn static_feature_state(&self) -> Arc<dyn Any + Send + Sync> {
self.state_fetcher.latest_snapshot()
}
}
pub(super) struct NoTracker;
const PANIC_MESSAGE: &str =
"No global tracker found, must be initialized with `set_global_tracker`";
impl FeatureTracker for NoTracker {
fn static_feature_state(&self) -> Arc<dyn Any + Send + Sync> {
panic!("{}", PANIC_MESSAGE)
}
}