use std::sync::{Arc, RwLock};
use state::TypeMap;
pub struct ConfigMap(Arc<RwLock<TypeMap![Sync + Send]>>);
impl ConfigMap {
#[must_use]
pub fn fetch<AC: AcceptsConfig>(&self) -> ConfigHolder<AC> {
let ch = self.0.read().unwrap().try_get::<ConfigHolder<AC>>().cloned();
ch.map_or_else(move || {
let cfg = ConfigHolder(Arc::new(AC::Cfg::default()));
self.0.write().unwrap().set::<ConfigHolder<AC>>(ConfigHolder::clone(&cfg));
cfg
}, |cfg| cfg)
}
pub fn set<AC: AcceptsConfig>(&self, cfg: AC::Cfg) {
self.0.write().unwrap().set::<ConfigHolder<AC>>(ConfigHolder(Arc::new(cfg)));
}
}
impl Clone for ConfigMap {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl Default for ConfigMap {
fn default() -> Self {
Self(Arc::new(RwLock::new(<TypeMap![Sync + Send]>::new())))
}
}
pub trait AcceptsConfig: 'static {
type Cfg: 'static + Send + Sync + Default;
}
pub struct ConfigHolder<AC: AcceptsConfig>(Arc<AC::Cfg>);
impl<AC: AcceptsConfig> Clone for ConfigHolder<AC> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<AC: AcceptsConfig> std::ops::Deref for ConfigHolder<AC> {
type Target = AC::Cfg;
fn deref(&self) -> &Self::Target {
&self.0
}
}
macro_rules! acfg {
($(#[doc = $doc:expr])? $ac:ident : $cfg:ty) => {
$(#[doc = $doc])?
pub enum $ac {}
impl crate::cfg::AcceptsConfig for $ac {
type Cfg = $cfg;
}
};
}
pub(crate) use acfg;
#[cfg(feature = "_any-zopfli")]
#[cfg_attr(feature = "serde-cfg", derive(serde::Serialize, serde::Deserialize), serde(untagged))]
pub enum CfgZopfli {
Switch(bool),
Iter(u8)
}
#[cfg(feature = "_any-zopfli")]
impl Default for CfgZopfli {
fn default() -> Self {
Self::Switch(false)
}
}
#[cfg(feature = "_any-zopfli")]
impl CfgZopfli {
#[inline]
#[must_use]
pub const fn iter_count(&self) -> Option<std::num::NonZeroU8> {
match self {
Self::Switch(false) => None,
Self::Iter(x) => std::num::NonZeroU8::new(*x),
Self::Switch(true) => std::num::NonZeroU8::new(10)
}
}
}