use figment::value::Dict;
use figment::Figment;
use serde::de::DeserializeOwned;
use crate::error::Error;
use crate::layer::{FLAGS_NAME, OVERRIDES_NAME};
use crate::snapshot::Snapshot;
use crate::source::LoadSpec;
use super::aliases_pass::apply_aliases;
use super::environment::{environment, merge_env_files};
use super::origin::convert;
use super::sections::Cached;
pub(crate) fn recover<T: DeserializeOwned>(
spec: &LoadSpec<'_>,
cached: &Snapshot,
) -> Result<(T, Snapshot), Error> {
let mut figment = Figment::new().merge(Cached {
values: cached.values().clone(),
profile: figment::Profile::from(spec.key),
});
figment = merge_env_files(figment, spec)?;
if let Some(prefix) = spec.full_env_prefix() {
figment = figment.merge(environment(
&prefix,
spec.key,
spec.nest,
spec.allow_empty_env,
));
}
if let Some(bindings) = spec.env_bindings {
for binding in bindings.providers(spec.key, spec.allow_empty_env) {
figment = figment.merge(binding);
}
}
if let Some(flags) = spec.flags {
figment = figment.merge(flags.provider(spec.key, FLAGS_NAME));
}
if let Some(overrides) = spec.overrides {
figment = figment.merge(overrides.provider(spec.key, OVERRIDES_NAME));
}
let figment = apply_aliases(figment, spec).select(spec.key);
let resolved: Dict = figment.extract().map_err(convert)?;
let config: T = figment.extract().map_err(convert)?;
Ok((config, Snapshot::new(resolved)))
}