1use std::sync::{Arc, RwLock};
2
3use state::TypeMap;
4
5pub struct ConfigMap(Arc<RwLock<TypeMap![Sync + Send]>>);
7impl ConfigMap {
8 #[must_use]
12 pub fn fetch<AC: AcceptsConfig>(&self) -> ConfigHolder<AC> {
13 let ch = self.0.read().unwrap().try_get::<ConfigHolder<AC>>().cloned();
14 ch.map_or_else(move || {
15 let cfg = ConfigHolder(Arc::new(AC::Cfg::default()));
16 self.0.write().unwrap().set::<ConfigHolder<AC>>(ConfigHolder::clone(&cfg));
17 cfg
18 }, |cfg| cfg)
19 }
20
21 pub fn set<AC: AcceptsConfig>(&self, cfg: AC::Cfg) {
25 self.0.write().unwrap().set::<ConfigHolder<AC>>(ConfigHolder(Arc::new(cfg)));
26 }
27}
28impl Clone for ConfigMap {
29 fn clone(&self) -> Self {
30 Self(self.0.clone())
31 }
32}
33impl Default for ConfigMap {
34 fn default() -> Self {
35 Self(Arc::new(RwLock::new(<TypeMap![Sync + Send]>::new())))
36 }
37}
38
39pub trait AcceptsConfig: 'static {
41 type Cfg: 'static + Send + Sync + Default;
43}
44
45pub struct ConfigHolder<AC: AcceptsConfig>(Arc<AC::Cfg>);
47impl<AC: AcceptsConfig> Clone for ConfigHolder<AC> {
48 fn clone(&self) -> Self {
49 Self(self.0.clone())
50 }
51}
52impl<AC: AcceptsConfig> std::ops::Deref for ConfigHolder<AC> {
53 type Target = AC::Cfg;
54 fn deref(&self) -> &Self::Target {
55 &self.0
56 }
57}
58
59macro_rules! acfg {
60 ($(#[doc = $doc:expr])? $ac:ident : $cfg:ty) => {
61 $(#[doc = $doc])?
62 pub enum $ac {}
64 impl crate::cfg::AcceptsConfig for $ac {
65 type Cfg = $cfg;
66 }
67 };
68}
69pub(crate) use acfg;
70
71#[cfg(feature = "_any-zopfli")]
72#[cfg_attr(feature = "serde-cfg", derive(serde::Serialize, serde::Deserialize), serde(untagged))]
75pub enum CfgZopfli {
76 Switch(bool),
79 Iter(u8)
81}
82#[cfg(feature = "_any-zopfli")]
83impl Default for CfgZopfli {
84 fn default() -> Self {
85 Self::Switch(false)
86 }
87}
88
89#[cfg(feature = "_any-zopfli")]
90impl CfgZopfli {
91 #[inline]
93 #[must_use]
94 pub const fn iter_count(&self) -> Option<std::num::NonZeroU8> {
95 match self {
96 Self::Switch(false) => None,
97 Self::Iter(x) => std::num::NonZeroU8::new(*x),
98 Self::Switch(true) => std::num::NonZeroU8::new(10)
99 }
100 }
101}
102