use crate::aaml::AAML;
use crate::commands::Command;
use crate::error::AamlError;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DeriveCommand;
fn parse_derive_arg(raw: &str) -> (&str, Vec<&str>) {
let (path_raw, rest) = if raw.starts_with('"') || raw.starts_with('\'') {
let q = raw.chars().next().unwrap();
match raw[1..].find(q) {
Some(end) => {
let path = &raw[1..end + 1];
let after = raw[end + 2..].trim_start_matches(':').trim();
(path, after)
}
None => (raw, ""),
}
} else {
match raw.find("::") {
Some(pos) => (&raw[..pos], &raw[pos + 2..]),
None => (raw, ""),
}
};
let selectors = rest
.split("::")
.map(str::trim)
.filter(|s| !s.is_empty())
.collect();
(path_raw.trim(), selectors)
}
impl Command for DeriveCommand {
fn name(&self) -> &str {
"derive"
}
fn execute(&self, aaml: &mut AAML, args: &str) -> Result<(), AamlError> {
let (path, selectors) = parse_derive_arg(args.trim());
let mut base = AAML::load(path)?;
let original_schemas: Vec<String> = aaml.get_schemas().keys().cloned().collect();
if selectors.is_empty() {
let names: Vec<String> = base.get_schemas().keys().cloned().collect();
for name in names {
aaml.import_schema(&name, &mut base)?;
}
} else {
for name in selectors {
aaml.import_schema(name, &mut base)?;
}
}
aaml.merge_map_weak(base.get_map_mut());
let refs: Vec<&str> = original_schemas.iter().map(|s| s.as_str()).collect();
aaml.validate_schemas_completeness_for(&refs)?;
Ok(())
}
}