use crate::pipeline::parser::ValueNode;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValidationTask<'a> {
CheckTypeMatch {
key: std::borrow::Cow<'a, str>,
value: std::borrow::Cow<'a, str>,
type_name: std::borrow::Cow<'a, str>,
line: usize,
},
VerifySchemaExists {
schema_name: std::borrow::Cow<'a, str>,
line: usize,
},
VerifyFileExists {
path: std::borrow::Cow<'a, str>,
line: usize,
},
ValidateAgainstSchema {
schema_name: std::borrow::Cow<'a, str>,
key: std::borrow::Cow<'a, str>,
value: std::borrow::Cow<'a, str>,
line: usize,
},
CheckSchemaCompleteness {
schema_name: std::borrow::Cow<'a, str>,
missing_fields: Vec<std::borrow::Cow<'a, str>>,
line: usize,
},
CheckNoCircularReference {
key: std::borrow::Cow<'a, str>,
line: usize,
},
CheckDeriveCompleteness {
derive_path: std::borrow::Cow<'a, str>,
current_key: std::borrow::Cow<'a, str>,
line: usize,
},
ValidateListElements {
key: std::borrow::Cow<'a, str>,
items: std::sync::Arc<[ValueNode<'a>]>,
element_type: std::borrow::Cow<'a, str>,
line: usize,
},
ValidateObjectStructure {
key: std::borrow::Cow<'a, str>,
pairs: std::sync::Arc<[(std::borrow::Cow<'a, str>, ValueNode<'a>)]>,
line: usize,
},
}
impl<'a> ValidationTask<'a> {
pub fn line(&self) -> usize {
match self {
ValidationTask::CheckTypeMatch { line, .. } => *line,
ValidationTask::VerifySchemaExists { line, .. } => *line,
ValidationTask::VerifyFileExists { line, .. } => *line,
ValidationTask::ValidateAgainstSchema { line, .. } => *line,
ValidationTask::CheckSchemaCompleteness { line, .. } => *line,
ValidationTask::CheckDeriveCompleteness { line, .. } => *line,
ValidationTask::CheckNoCircularReference { line, .. } => *line,
ValidationTask::ValidateListElements { line, .. } => *line,
ValidationTask::ValidateObjectStructure { line, .. } => *line,
}
}
pub fn description(&self) -> String {
match self {
ValidationTask::CheckTypeMatch { type_name, .. } => {
format!("Check type match against '{}'", type_name)
}
ValidationTask::VerifySchemaExists { schema_name, .. } => {
format!("Verify schema '{}' exists", schema_name)
}
ValidationTask::VerifyFileExists { path, .. } => {
format!("Verify file '{}' exists", path)
}
ValidationTask::ValidateAgainstSchema { schema_name, .. } => {
format!("Validate against schema '{}'", schema_name)
}
ValidationTask::CheckSchemaCompleteness { schema_name, .. } => {
format!("Check completeness of schema '{}'", schema_name)
}
ValidationTask::CheckDeriveCompleteness { derive_path, .. } => {
format!("Check derive completeness for '{}'", derive_path)
}
ValidationTask::CheckNoCircularReference { .. } => {
"Check for circular references".to_string()
}
ValidationTask::ValidateListElements { element_type, .. } => {
format!("Validate list elements are type '{}'", element_type)
}
ValidationTask::ValidateObjectStructure { .. } => {
"Validate inline object structure".to_string()
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseTask<'a> {
ResolveModuleReference {
module_name: std::borrow::Cow<'a, str>,
scope: std::borrow::Cow<'a, str>,
line: usize,
},
ResolveDeriveImport {
derive_path: std::borrow::Cow<'a, str>,
line: usize,
},
ProcessVariable {
variable_name: std::borrow::Cow<'a, str>,
value: std::borrow::Cow<'a, str>,
scope: std::borrow::Cow<'a, str>,
line: usize,
},
ManageScope {
scope: std::borrow::Cow<'a, str>,
is_entry: bool,
line: usize,
},
ExecuteDirective {
directive_name: std::borrow::Cow<'a, str>,
arguments: std::borrow::Cow<'a, str>,
line: usize,
},
RegisterType {
type_name: std::borrow::Cow<'a, str>,
type_spec: std::borrow::Cow<'a, str>,
line: usize,
},
RegisterSchema {
schema_name: std::borrow::Cow<'a, str>,
fields: std::borrow::Cow<'a, str>,
line: usize,
},
}
impl<'a> ParseTask<'a> {
pub fn line(&self) -> usize {
match self {
ParseTask::ResolveModuleReference { line, .. } => *line,
ParseTask::ResolveDeriveImport { line, .. } => *line,
ParseTask::ProcessVariable { line, .. } => *line,
ParseTask::ManageScope { line, .. } => *line,
ParseTask::ExecuteDirective { line, .. } => *line,
ParseTask::RegisterType { line, .. } => *line,
ParseTask::RegisterSchema { line, .. } => *line,
}
}
pub fn description(&self) -> String {
match self {
ParseTask::ResolveModuleReference { module_name, .. } => {
format!("Resolve module reference '{}'", module_name)
}
ParseTask::ResolveDeriveImport { derive_path, .. } => {
format!("Resolve derive import '{}'", derive_path)
}
ParseTask::ProcessVariable { variable_name, .. } => {
format!("Process variable '{}'", variable_name)
}
ParseTask::ManageScope {
scope, is_entry, ..
} => {
let action = if *is_entry { "Enter" } else { "Exit" };
format!("{} scope '{}'", action, scope)
}
ParseTask::ExecuteDirective { directive_name, .. } => {
format!("Execute directive '@{}'", directive_name)
}
ParseTask::RegisterType { type_name, .. } => {
format!("Register type '{}'", type_name)
}
ParseTask::RegisterSchema { schema_name, .. } => {
format!("Register schema '{}'", schema_name)
}
}
}
pub fn validate_stateless(&self) -> Result<(), TaskError> {
if let ParseTask::ExecuteDirective {
directive_name,
line,
..
} = self
&& !matches!(directive_name.as_ref(), "import" | "derive")
{
return Err(TaskError {
line: *line,
message: format!("Unknown directive: @{}", directive_name),
task_description: self.description(),
aaml_error: None,
});
}
Ok(())
}
}
#[derive(Debug, Clone)]
pub enum ExecutionTask<'a> {
SetValue {
key: std::borrow::Cow<'a, str>,
value: std::borrow::Cow<'a, str>,
line: usize,
},
MergeValue {
key: std::borrow::Cow<'a, str>,
value: std::borrow::Cow<'a, str>,
line: usize,
},
ApplySchema {
schema_name: std::borrow::Cow<'a, str>,
root_keys: Vec<std::borrow::Cow<'a, str>>,
line: usize,
},
ExecuteInheritance {
derive_path: std::borrow::Cow<'a, str>,
child_key: std::borrow::Cow<'a, str>,
line: usize,
},
ImportFile {
file_path: std::borrow::Cow<'a, str>,
merge_strategy: std::borrow::Cow<'a, str>,
line: usize,
},
ResolveReference {
source_key: std::borrow::Cow<'a, str>,
target_key: std::borrow::Cow<'a, str>,
line: usize,
},
}
impl<'a> ExecutionTask<'a> {
pub fn line(&self) -> usize {
match self {
ExecutionTask::SetValue { line, .. } => *line,
ExecutionTask::MergeValue { line, .. } => *line,
ExecutionTask::ApplySchema { line, .. } => *line,
ExecutionTask::ExecuteInheritance { line, .. } => *line,
ExecutionTask::ImportFile { line, .. } => *line,
ExecutionTask::ResolveReference { line, .. } => *line,
}
}
pub fn description(&self) -> String {
match self {
ExecutionTask::SetValue { key, .. } => format!("Set value for key '{}'", key),
ExecutionTask::MergeValue { key, .. } => format!("Merge value for key '{}'", key),
ExecutionTask::ApplySchema { schema_name, .. } => {
format!("Apply schema '{}'", schema_name)
}
ExecutionTask::ExecuteInheritance {
derive_path,
child_key,
..
} => {
format!("Execute inheritance: '{}' <- '{}'", child_key, derive_path)
}
ExecutionTask::ImportFile { file_path, .. } => {
format!("Import file '{}'", file_path)
}
ExecutionTask::ResolveReference {
source_key,
target_key,
..
} => {
format!("Resolve reference: '{}' -> '{}'", source_key, target_key)
}
}
}
}
#[derive(Debug, Clone)]
pub struct TaskExecutionResult {
pub success: bool,
pub errors: Vec<TaskError>,
pub stats: ExecutionStats,
}
#[derive(Debug, Clone)]
pub struct TaskError {
pub line: usize,
pub message: String,
pub task_description: String,
pub aaml_error: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ExecutionStats {
pub total_tasks: usize,
pub successful_tasks: usize,
pub failed_tasks: usize,
pub validation_ms: u64,
pub parsing_ms: u64,
pub execution_ms: u64,
}
#[cfg(test)]
mod tests {
use super::*;
use std::borrow::Cow;
#[test]
fn test_validation_task_line_numbers() {
let task = ValidationTask::CheckTypeMatch {
key: Cow::from("foo".to_string()),
value: Cow::from("bar"),
type_name: Cow::from("string".to_string()),
line: 42,
};
assert_eq!(task.line(), 42);
}
#[test]
fn test_parse_task_description() {
let task = ParseTask::ExecuteDirective {
directive_name: Cow::from("import"),
arguments: Cow::from("base.aam"),
line: 10,
};
assert_eq!(task.description(), "Execute directive '@import'");
}
#[test]
fn test_execution_task_inheritance() {
let task = ExecutionTask::ExecuteInheritance {
derive_path: Cow::from("base.aam::Parent"),
child_key: Cow::from("child"),
line: 5,
};
assert_eq!(
task.description(),
"Execute inheritance: 'child' <- 'base.aam::Parent'"
);
}
}