use std::collections::BTreeMap;
use std::sync::Arc;
use crate::error::ConfigError;
use crate::path::canonicalize_path_with_aliases;
use crate::{ConfigMetadata, EnvDecoder};
use super::canonical::canonicalize_runtime_path_across_layers;
use super::path::try_normalize_external_path;
use super::{CustomEnvDecoder, Layer};
pub(super) fn canonicalize_custom_env_decoders(
decoders: &BTreeMap<String, CustomEnvDecoder>,
metadata: &ConfigMetadata,
layers: &[Layer],
) -> Result<BTreeMap<String, CustomEnvDecoder>, ConfigError> {
let aliases = metadata.alias_overrides()?;
let mut canonicalized = BTreeMap::new();
let mut origins = BTreeMap::<String, String>::new();
for (path, decoder) in decoders {
let normalized = canonicalize_runtime_path_across_layers(
&normalize_decoder_registration_path(path)?,
layers,
);
let canonical = canonicalize_path_with_aliases(&normalized, &aliases);
if let Some(first_path) = origins.get(&canonical)
&& first_path != &normalized
{
return Err(ConfigError::MetadataConflict {
kind: "environment decoder",
name: canonical,
first_path: first_path.clone(),
second_path: normalized,
});
}
origins.insert(canonical.clone(), normalized);
canonicalized.insert(canonical, Arc::clone(decoder));
}
Ok(canonicalized)
}
pub(super) fn canonicalize_env_decoders(
decoders: &BTreeMap<String, EnvDecoder>,
metadata: &ConfigMetadata,
layers: &[Layer],
) -> Result<BTreeMap<String, EnvDecoder>, ConfigError> {
let aliases = metadata.alias_overrides()?;
let mut canonicalized = BTreeMap::new();
let mut origins = BTreeMap::<String, (String, EnvDecoder)>::new();
for (path, decoder) in decoders {
let normalized = canonicalize_runtime_path_across_layers(
&normalize_decoder_registration_path(path)?,
layers,
);
let canonical = canonicalize_path_with_aliases(&normalized, &aliases);
if let Some((first_path, first_decoder)) = origins.get(&canonical)
&& (first_path != &normalized || *first_decoder != *decoder)
{
return Err(ConfigError::MetadataConflict {
kind: "environment decoder",
name: canonical,
first_path: first_path.clone(),
second_path: normalized,
});
}
origins.insert(canonical.clone(), (normalized, *decoder));
canonicalized.insert(canonical, *decoder);
}
Ok(canonicalized)
}
fn normalize_decoder_registration_path(path: &str) -> Result<String, ConfigError> {
let normalized =
try_normalize_external_path(path).map_err(|message| ConfigError::MetadataInvalid {
path: path.to_owned(),
message: format!("invalid environment decoder path: {message}"),
})?;
if normalized.is_empty() {
return Err(ConfigError::MetadataInvalid {
path: path.to_owned(),
message: "invalid environment decoder path: configuration path cannot be empty"
.to_owned(),
});
}
Ok(normalized)
}