1use crate::{path, settings, Builder, Reloadable, Section, Settings};
2use arc_swap::ArcSwap;
3use std::collections::VecDeque;
4use std::fmt::{self, Debug, Display, Formatter, Write};
5use std::{any::Any, sync::Arc};
6use tokens::{ChangeToken, CompositeChangeToken, Registration, SharedChangeToken, SingleChangeToken};
7use tracing::{error, trace};
8
9#[cfg(feature = "binder")]
10use {crate::prelude::Binder, serde::de::DeserializeOwned, std::str::FromStr};
11
12#[derive(Clone)]
14pub struct Configuration {
15 pub(crate) settings: Settings,
16 token: SharedChangeToken<CompositeChangeToken>,
17 pub(crate) providers: Vec<String>,
18}
19
20impl Configuration {
21 #[inline]
29 pub fn new(
30 settings: Settings,
31 tokens: impl IntoIterator<Item = Box<dyn ChangeToken>>,
32 providers: Vec<String>,
33 ) -> Self {
34 Self {
35 settings,
36 token: SharedChangeToken::new(CompositeChangeToken::new(tokens.into_iter())),
37 providers,
38 }
39 }
40
41 #[inline]
47 pub fn get(&self, key: &str) -> Option<&str> {
48 self.settings.get(key)
49 }
50
51 #[inline]
57 pub fn section(&self, key: impl Into<String>) -> Section<'_> {
58 Section::new(self, key.into())
59 }
60
61 pub fn sections(&self) -> Vec<Section<'_>> {
63 let mut keys = Vec::new();
64
65 for (path, _) in self {
66 let Some(key) = path::next(path, None) else {
67 continue;
68 };
69
70 if !keys.iter().any(|k: &String| k.eq_ignore_ascii_case(key)) {
71 keys.push(key.to_owned());
72 }
73 }
74
75 keys.into_iter().map(|key| self.section(key)).collect()
76 }
77
78 #[inline]
80 pub fn change_token(&self) -> impl ChangeToken {
81 self.token.clone()
82 }
83}
84
85impl<'a> IntoIterator for &'a Configuration {
86 type Item = (&'a str, &'a str);
87 type IntoIter = settings::Iter<'a>;
88
89 #[inline]
90 fn into_iter(self) -> Self::IntoIter {
91 (&self.settings).into_iter()
92 }
93}
94
95impl IntoIterator for Configuration {
96 type Item = (String, String);
97 type IntoIter = settings::IntoIter;
98
99 #[inline]
100 fn into_iter(self) -> Self::IntoIter {
101 self.settings.into_iter()
102 }
103}
104
105impl<'a> From<&'a Configuration> for Vec<Section<'a>> {
106 #[inline]
107 fn from(config: &'a Configuration) -> Self {
108 config.sections()
109 }
110}
111
112impl Debug for Configuration {
113 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
114 Debug::fmt(&self.settings, f)
115 }
116}
117
118impl Display for Configuration {
119 #[inline]
120 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
121 let mut sections: VecDeque<_> = self.sections().into_iter().map(|s| (0, s)).collect();
122
123 while let Some((depth, section)) = sections.pop_front() {
124 write!(f, "{:width$}", "", width = depth * 2)?;
125 Display::fmt(§ion, f)?;
126
127 for (i, child) in section.sections().into_iter().map(|s| (depth + 1, s)).enumerate() {
128 sections.insert(i, child);
129 }
130
131 if !sections.is_empty() {
132 f.write_char('\n')?;
133 }
134 }
135
136 Ok(())
137 }
138}
139
140fn on_changed(state: Option<Arc<dyn Any + Send + Sync + 'static>>) {
141 let Some(state) = state else {
142 return;
143 };
144
145 let inner = state.downcast_ref::<Inner>().expect("received state other than Inner");
146
147 match inner.builder.build() {
148 Ok(config) => {
149 let registration = inner
150 .config
151 .load()
152 .change_token()
153 .register(Box::new(on_changed), Some(state.clone()));
154 let token = inner.token.swap(Arc::new(SharedChangeToken::default()));
155
156 inner.config.store(Arc::new(config));
157 inner.registration.store(Arc::new(registration));
158
159 trace!("Reloaded the configuration");
160
161 token.notify();
162 }
163 Err(error) => error!("Failed to reload the configuration. {error:?}"),
164 }
165}
166
167struct Inner {
168 builder: Builder,
169 config: ArcSwap<Configuration>,
170 registration: ArcSwap<Registration>,
171 token: ArcSwap<SharedChangeToken<SingleChangeToken>>,
172}
173
174pub struct ReloadableConfiguration(Arc<Inner>);
176
177impl ReloadableConfiguration {
178 pub fn new(builder: Builder, configuration: Configuration) -> Self {
185 let inner = Arc::new(Inner {
186 builder,
187 config: ArcSwap::from_pointee(configuration),
188 registration: ArcSwap::from_pointee(Registration::none()),
189 token: ArcSwap::from_pointee(SharedChangeToken::default()),
190 });
191 let registration = inner
192 .config
193 .load()
194 .change_token()
195 .register(Box::new(on_changed), Some(inner.clone()));
196
197 inner.registration.store(registration.into());
198 Self(inner)
199 }
200
201 #[inline]
208 pub fn current(&self) -> Arc<Configuration> {
209 self.0.config.load_full()
210 }
211}
212
213#[cfg(feature = "binder")]
214impl ReloadableConfiguration {
215 #[inline]
217 pub fn reify<T: DeserializeOwned>(&self) -> crate::Result<T> {
218 self.0.config.load().reify()
219 }
220
221 #[inline]
227 pub fn bind<T: DeserializeOwned>(&self, instance: &mut T) -> crate::Result {
228 self.0.config.load().bind(instance)
229 }
230
231 #[inline]
238 pub fn bind_at<T: DeserializeOwned>(&self, key: impl AsRef<str>, instance: &mut T) -> crate::Result {
239 self.0.config.load().bind_at(key, instance)
240 }
241
242 #[inline]
248 pub fn get_value<T: FromStr>(&self, key: impl AsRef<str>) -> Result<Option<T>, T::Err> {
249 self.0.config.load().get_value(key)
250 }
251
252 #[inline]
258 pub fn get_value_or_default<T: FromStr + Default>(&self, key: impl AsRef<str>) -> Result<T, T::Err> {
259 self.0.config.load().get_value_or_default(key)
260 }
261}
262
263impl Clone for ReloadableConfiguration {
264 #[inline]
265 fn clone(&self) -> Self {
266 Self(self.0.clone())
267 }
268}
269
270impl Reloadable for ReloadableConfiguration {
271 #[inline]
272 fn can_reload(&self) -> bool {
273 true
274 }
275
276 #[inline]
277 fn reload_token(&self) -> impl ChangeToken + 'static {
278 (**self.0.token.load()).clone()
279 }
280}
281
282impl Debug for ReloadableConfiguration {
283 #[inline]
284 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
285 Debug::fmt(&*self.current(), f)
286 }
287}
288
289impl Display for ReloadableConfiguration {
290 #[inline]
291 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
292 Display::fmt(&*self.current(), f)
293 }
294}
295
296impl From<ReloadableConfiguration> for Arc<Configuration> {
297 #[inline]
298 fn from(rc: ReloadableConfiguration) -> Self {
299 rc.current()
300 }
301}
302
303impl From<&ReloadableConfiguration> for Arc<Configuration> {
304 #[inline]
305 fn from(rc: &ReloadableConfiguration) -> Self {
306 rc.current()
307 }
308}
309
310impl TryFrom<Builder> for ReloadableConfiguration {
311 type Error = crate::Error;
312
313 fn try_from(builder: Builder) -> crate::Result<Self> {
314 let config = builder.build()?;
315 Ok(Self::new(builder, config))
316 }
317}