use figment::value::Dict;
use figment::{Figment, Metadata};
use crate::layer::DEFAULTS_NAME;
use crate::source::LoadSpec;
pub(super) fn apply_aliases(figment: Figment, spec: &LoadSpec<'_>) -> Figment {
let Some(aliases) = spec.aliases else {
return figment;
};
let mut figment = figment;
let pairs = aliases.pairs();
let mut progressed = true;
while progressed {
progressed = false;
for (from, to) in &pairs {
let selected = figment.clone().select(super::section_profile(spec.key));
let supplied_above_defaults = selected
.find_metadata(to)
.is_some_and(|metadata| metadata.name != DEFAULTS_NAME);
if supplied_above_defaults {
continue;
}
let Ok(value) = selected.find_value(from) else {
continue;
};
let mut values = Dict::new();
crate::layer::insert_path(&mut values, to, value);
figment = figment.merge(Aliased {
values,
profile: figment::Profile::from(super::section_profile(spec.key)),
from: from.clone(),
});
progressed = true;
}
}
figment
}
struct Aliased {
values: Dict,
profile: figment::Profile,
from: String,
}
impl figment::Provider for Aliased {
fn metadata(&self) -> Metadata {
Metadata::named(format!("{ALIAS_PREFIX}{}", self.from))
}
fn data(&self) -> figment::Result<figment::value::Map<figment::Profile, Dict>> {
let mut map = figment::value::Map::new();
map.insert(self.profile.clone(), self.values.clone());
Ok(map)
}
}
const ALIAS_PREFIX: &str = "an alias for ";