use std::collections::{BTreeMap, BTreeSet};
use serde_json::Value;
use crate::path::{canonicalize_path_with_aliases, normalize_path};
use super::super::Layer;
pub(in crate::loader) fn canonicalize_layer_path(
value: &Value,
path: &str,
aliases: &BTreeMap<String, String>,
) -> String {
let runtime = canonicalize_runtime_path(value, path);
canonicalize_path_with_aliases(&runtime, aliases)
}
pub(in crate::loader) fn canonicalize_runtime_path(value: &Value, path: &str) -> String {
if path.is_empty() {
return String::new();
}
let segments = path.split('.').collect::<Vec<_>>();
let mut current = value;
let mut canonical = Vec::new();
let mut index = 0;
while index < segments.len() {
let segment = segments[index];
match current {
Value::Object(map) => {
canonical.push(segment.to_owned());
let Some(next) = map.get(segment) else {
append_remaining_segments(&mut canonical, &segments[index + 1..]);
break;
};
current = next;
}
Value::Array(values) => {
let Ok(array_index) = segment.parse::<usize>() else {
canonical.push(segment.to_owned());
append_remaining_segments(&mut canonical, &segments[index + 1..]);
break;
};
canonical.push(array_index.to_string());
let Some(next) = values.get(array_index) else {
append_remaining_segments(&mut canonical, &segments[index + 1..]);
break;
};
current = next;
}
_ => {
canonical.push(segment.to_owned());
append_remaining_segments(&mut canonical, &segments[index + 1..]);
break;
}
}
index += 1;
}
canonical.join(".")
}
pub(in crate::loader) fn canonicalize_secret_paths(
secret_paths: &BTreeSet<String>,
aliases: &BTreeMap<String, String>,
) -> BTreeSet<String> {
secret_paths
.iter()
.map(|path| canonicalize_path_with_aliases(path, aliases))
.collect()
}
pub(in crate::loader) fn canonicalize_secret_paths_against_layers(
secret_paths: &BTreeSet<String>,
layers: &[Layer],
aliases: &BTreeMap<String, String>,
) -> BTreeSet<String> {
secret_paths
.iter()
.map(|path| {
layers.iter().fold(path.clone(), |current, layer| {
canonicalize_layer_path(&layer.value, ¤t, aliases)
})
})
.collect()
}
pub(in crate::loader) fn canonicalize_secret_paths_against_value(
secret_paths: &BTreeSet<String>,
value: &Value,
aliases: &BTreeMap<String, String>,
) -> BTreeSet<String> {
secret_paths
.iter()
.map(|path| canonicalize_layer_path(value, path, aliases))
.collect()
}
pub(in crate::loader) fn canonicalize_runtime_paths_against_value<I>(
paths: I,
value: &Value,
) -> Vec<String>
where
I: IntoIterator<Item = String>,
{
let mut canonicalized = Vec::new();
for path in paths {
let canonical = canonicalize_runtime_path(value, &path);
if canonical.is_empty() || canonicalized.contains(&canonical) {
continue;
}
canonicalized.push(canonical);
}
canonicalized
}
pub(in crate::loader) fn canonicalize_runtime_paths_across_layers<I>(
paths: I,
layers: &[Layer],
) -> Vec<String>
where
I: IntoIterator<Item = String>,
{
let mut canonicalized = Vec::new();
for path in paths {
let canonical = canonicalize_runtime_path_across_layers(&path, layers);
if canonical.is_empty() || canonicalized.contains(&canonical) {
continue;
}
canonicalized.push(canonical);
}
canonicalized
}
pub(in crate::loader) fn canonicalize_runtime_path_across_layers(
path: &str,
layers: &[Layer],
) -> String {
layers.iter().fold(normalize_path(path), |current, layer| {
canonicalize_runtime_path(&layer.value, ¤t)
})
}
pub(in crate::loader) fn canonicalize_paths_with_aliases<I>(
paths: I,
aliases: &BTreeMap<String, String>,
) -> Vec<String>
where
I: IntoIterator<Item = String>,
{
let mut canonicalized = Vec::new();
for path in paths {
let canonical = canonicalize_path_with_aliases(&path, aliases);
if canonical.is_empty() || canonicalized.contains(&canonical) {
continue;
}
canonicalized.push(canonical);
}
canonicalized
}
fn append_remaining_segments(canonical: &mut Vec<String>, segments: &[&str]) {
canonical.extend(segments.iter().map(|segment| (*segment).to_owned()));
}