use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Severity {
Error,
Warning,
}
impl Severity {
pub fn as_str(&self) -> &'static str {
match self {
Severity::Error => "error",
Severity::Warning => "warning",
}
}
}
struct ErrorRegistryEntry {
severity: Severity,
message_template: &'static str,
}
fn error_registry() -> HashMap<&'static str, ErrorRegistryEntry> {
let mut m = HashMap::new();
m.insert(
"E001",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Type mismatch: expected {expected}, got {actual}",
},
);
m.insert(
"E002",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Required property \"{property}\" is missing",
},
);
m.insert(
"E003",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Additional property \"{property}\" is not allowed",
},
);
m.insert(
"E004",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "String constraint violation: {constraint}",
},
);
m.insert(
"E005",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Number constraint violation: {constraint}",
},
);
m.insert(
"E006",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Array constraint violation: {constraint}",
},
);
m.insert(
"E007",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Object constraint violation: {constraint}",
},
);
m.insert(
"E008",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Format validation failed: expected {format}, got \"{value}\"",
},
);
m.insert(
"E009",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Value {value} does not match {constraint}",
},
);
m.insert(
"E010",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Composition constraint \"{keyword}\" not satisfied",
},
);
m.insert(
"E011",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Failed to resolve $ref: \"{ref}\"",
},
);
m.insert(
"E012",
ErrorRegistryEntry {
severity: Severity::Error,
message_template: "Invalid protocol: {reason}",
},
);
m.insert(
"W001",
ErrorRegistryEntry {
severity: Severity::Warning,
message_template: "Field \"{field}\" is deprecated: {reason}",
},
);
m.insert(
"W002",
ErrorRegistryEntry {
severity: Severity::Warning,
message_template: "Unknown extension property: \"{property}\"",
},
);
m
}
fn format_template(template: &str, context: &HashMap<&str, String>) -> String {
let mut result = template.to_string();
for (key, value) in context {
let placeholder = format!("{{{}}}", key);
result = result.replace(&placeholder, value);
}
result
}
use crate::types::ValidationError;
pub fn create_error(code: &str, path: &str, context: HashMap<&str, String>) -> ValidationError {
let registry = error_registry();
match registry.get(code) {
Some(entry) => ValidationError {
code: code.to_string(),
path: path.to_string(),
message: format_template(entry.message_template, &context),
severity: entry.severity.as_str().to_string(),
suggestion: None,
},
None => ValidationError {
code: code.to_string(),
path: path.to_string(),
message: format!("Unknown error code: {}", code),
severity: "error".to_string(),
suggestion: None,
},
}
}