Skip to main content

tuwunel_core/config/
sources.rs

1//! Defines the inputs used to assemble configuration.
2//!
3//! [`Sources`] retains file paths and optional overrides so reloads reproduce
4//! startup inputs. Loading layers extra paths before applying those overrides.
5
6#[cfg(test)]
7mod tests;
8
9use std::path::{Path, PathBuf};
10
11use super::{Config, Figment};
12use crate::{Result, implement};
13
14/// Applies the entry point's own contribution to a freshly loaded
15/// configuration.
16pub type Overrides = dyn Fn(Figment) -> Result<Figment> + Send + Sync;
17
18/// Retains the inputs used to assemble a server configuration.
19///
20/// Reloads reuse these paths and the optional override to reproduce startup
21/// behavior. Environment providers are added by the configuration loader
22/// itself.
23#[derive(Default)]
24pub struct Sources {
25	/// Lists configuration files in merge order.
26	///
27	/// Later paths overlay values from earlier paths. Reloads begin with this
28	/// same ordered sequence before adding any explicit extra paths.
29	pub paths: Vec<PathBuf>,
30
31	/// Applies an optional transform after the standard providers are merged.
32	///
33	/// The callback can add synthetic overrides after standard loading. Reloads
34	/// retain it so those values are not silently discarded.
35	pub overrides: Option<Box<Overrides>>,
36}
37
38/// Builds a raw configuration from these sources, with `extra` paths layered
39/// after them.
40#[implement(Sources)]
41pub fn load<'a, I>(&'a self, extra: I) -> Result<Figment>
42where
43	I: Iterator<Item = &'a Path>,
44{
45	let paths = self
46		.paths
47		.iter()
48		.map(PathBuf::as_path)
49		.chain(extra);
50
51	Config::load(paths).and_then(|raw| self.apply(raw))
52}
53
54#[implement(Sources)]
55#[inline]
56pub(crate) fn file_paths(&self) -> impl Iterator<Item = PathBuf> + '_ {
57	Config::file_paths(self.paths.iter().map(PathBuf::as_path))
58}
59
60#[implement(Sources)]
61fn apply(&self, raw: Figment) -> Result<Figment> {
62	match &self.overrides {
63		| None => Ok(raw),
64		| Some(overrides) => overrides(raw),
65	}
66}