additional error handling; use path buffers; improve logic

This commit is contained in:
lost
2026-02-16 02:03:04 -07:00
parent 31311ee99e
commit 4177df0f4a
37 changed files with 178 additions and 267 deletions

View File

@@ -1,11 +1,11 @@
use crate::{dbug, info, verb, LogLevel};
use crate::{LogLevel, info, verb};
use regex::Regex;
use serde_json::{json, Map, Value};
use serde_yml;
use serde_json::{Map, Value, json};
use std::path::{Path, PathBuf};
use std::str::FromStr;
use std::{env, fmt, fs};
use walkdir::WalkDir;
use yaml_serde;
#[derive(Debug)]
pub struct Specification {
@@ -19,37 +19,25 @@ pub struct Specification {
impl Specification {
pub fn build(
partitional: &str,
regional: &str,
common: &str,
zonal: &str,
device: &str,
partitional: String,
regional: String,
common: String,
zonal: String,
device: String,
) -> Result<Self, Box<dyn std::error::Error>> {
// Read all YAML files
let yaml_contents: Vec<String> = [partitional, regional, common, zonal, device]
let json_values: Vec<Value> = [&partitional, &regional, &common, &zonal, &device]
.iter()
.filter_map(|path| fs::read_to_string(path).ok())
.collect();
// Convert each YAML to JSON Value and collect them
let json_values: Vec<Value> = yaml_contents
.iter()
.map(|content| serde_yml::from_str(content))
.map(|content| yaml_serde::from_str::<Value>(&content))
.collect::<Result<Vec<Value>, _>>()?;
// Merge all objects under a single key
let mut merged_map = Map::new();
for value in json_values {
if let Some(obj) = value.as_object() {
for (_key, value) in obj {
if let Some(inner_obj) = value.as_object() {
for (k, v) in inner_obj {
merged_map.insert(k.clone(), v.clone());
}
}
}
}
}
let merged_map: Map<String, Value> = json_values
.into_iter()
.filter_map(|v| v.as_object().cloned())
.flat_map(|obj| obj.into_values().filter_map(|v| v.as_object().cloned()))
.flatten()
.collect();
// Create the final merged object
let compiled = json!({"data": merged_map});
@@ -75,27 +63,13 @@ impl Specification {
.filter(|c| !c.is_numeric())
.collect::<String>()
}
pub fn get_hostname(&self) -> String {
PathBuf::from(&self.device)
.file_name()
.unwrap()
.to_string_lossy()
.into_owned()
}
}
impl fmt::Display for Specification {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Specification:\n\
Partitional: {}\n\
Regional: {}\n\
Common: {}\n\
Zonal: {}\n\
Device: {}\n\
Compiled:\n{}",
"Specification:\nPartitional: {}\nRegional: {}\nCommon: {}\nZonal: {}\nDevice: {}\nCompiled:\n{}",
self.partitional, self.regional, self.common, self.zonal, self.device, self.compiled
)
}
@@ -119,20 +93,8 @@ pub fn compile(pattern: &Regex, spec_path: &String, dbg: LogLevel) -> Vec<Specif
let regional: String = get_regional(&spec);
let partitional: String = get_partional(&common, &regional);
specifications.push(
match Specification::build(&partitional, &regional, &common, &zonal, &spec) {
Ok(compiled_spec) => {
dbug!(
dbg,
"Compiled Spec for '{}'\n | {}\n | {}\n | {}\n | {}\n | {}",
compiled_spec.get_hostname(),
compiled_spec.partitional,
compiled_spec.regional,
compiled_spec.common,
compiled_spec.zonal,
compiled_spec.device
);
compiled_spec
}
match Specification::build(partitional, regional, common, zonal, spec) {
Ok(compiled_spec) => compiled_spec,
Err(e) => panic!("failed to build Specification: {}", e),
},
)