use babbel_yaml::{
EnhancedError, ErrorCode, ErrorCollection, ErrorKind, ErrorSuggestion, RecoveryContext,
RecoveryHandler, RecoveryStrategy, Span, SuggestionBuilder, YamlError,
};
pub fn main() {
println!("=== Enhanced YAML Error Handling Example ===\n");
demo_error_codes();
demo_error_suggestions();
demo_error_recovery();
demo_enhanced_errors();
demo_suggestion_builder();
demo_recovery_context();
demo_error_collection();
}
fn demo_error_codes() {
println!("--- Example 1: Error Codes ---");
let error_codes = vec![
ErrorCode::E001,
ErrorCode::E002,
ErrorCode::E004,
ErrorCode::E007,
];
for code in error_codes {
println!("\n{}: {}", code, code.description());
println!(" Can be used to handle: {}", get_recovery_action(code));
}
println!();
}
fn get_recovery_action(code: ErrorCode) -> &'static str {
match code {
ErrorCode::E001 => "Add missing colon, skip line, or insert default",
ErrorCode::E002 => "Scan ahead to find closing quote or skip string",
ErrorCode::E004 => "Use default value or skip reference",
ErrorCode::E007 => "Adjust indentation or skip to next valid indent",
_ => "Apply generic recovery strategy",
}
}
fn demo_error_suggestions() {
println!("--- Example 2: Error Suggestions ---");
println!("\nScenario: User typed 'ture' instead of 'true'");
let suggestion = SuggestionBuilder::boolean_typo("ture");
println!(" Suggestion: {}", suggestion.message);
if let Some(replacement) = &suggestion.replacement {
println!(" Replacement: {}", replacement);
}
println!("\nScenario: User typed 'nil' instead of 'null'");
let suggestion = SuggestionBuilder::null_typo("nil");
println!(" Suggestion: {}", suggestion.message);
if let Some(replacement) = &suggestion.replacement {
println!(" Replacement: {}", replacement);
}
println!("\nScenario: User referenced undefined alias 'ancor1'");
let available = vec!["anchor1".to_string(), "myanchor".to_string()];
let suggestion = SuggestionBuilder::undefined_alias("ancor1", &available);
println!(" Suggestion: {}", suggestion.message);
println!("\nScenario: Wrong indentation (found 6, expected 4 spaces)");
let suggestion = SuggestionBuilder::indentation(4, 6);
println!(" Suggestion: {}", suggestion.message);
println!();
}
fn demo_error_recovery() {
println!("--- Example 3: Error Recovery Strategies ---");
let handlers = vec![
("Default", RecoveryHandler::new()),
("Strict (no recovery)", RecoveryHandler::strict()),
("Lenient (always recover)", RecoveryHandler::lenient()),
];
let test_errors = vec![
YamlError::new(ErrorKind::SyntaxError, "Missing colon in mapping"),
YamlError::new(ErrorKind::UnterminatedString, "String not closed"),
YamlError::new(ErrorKind::UndefinedAlias, "Alias not found"),
YamlError::new(ErrorKind::UnexpectedEof, "Unexpected end of file"),
];
for (name, handler) in handlers {
println!("\n{} recovery handler:", name);
for error in &test_errors {
let strategy = handler.recover(error);
println!(" {} -> {:?}", error.kind(), strategy);
}
}
println!();
}
fn demo_enhanced_errors() {
println!("--- Example 4: Enhanced Errors with Context ---");
let base_error =
YamlError::new(ErrorKind::SyntaxError, "Missing colon in mapping").with_position(5, 10);
let enhanced = EnhancedError::new(base_error)
.with_code(ErrorCode::E001)
.with_span(Span::new(5, 8, 5, 15))
.with_snippet(
r#"
3 | name: John Doe
4 | age: 30
5 | address 123 Main St
^^^^ missing colon here
6 | city: Springfield
"#,
)
.with_suggestion(
ErrorSuggestion::new("Add ':' after key name")
.with_replacement("address: 123 Main St")
.with_span(Span::new(5, 8, 5, 23)),
)
.with_note("YAML mappings require 'key: value' pairs");
println!("\n{}", enhanced.format_detailed());
println!("\nProgrammatic access:");
if let Some(code) = enhanced.code() {
println!(" Error code: {}", code);
}
println!(" Suggestions: {}", enhanced.suggestions().len());
println!(" Notes: {}", enhanced.notes().len());
println!();
}
fn demo_suggestion_builder() {
println!("--- Example 5: Suggestion Builder Patterns ---");
println!("\n1. Missing colon:");
let suggestion = SuggestionBuilder::missing_colon("address");
println!(" {}", suggestion.message);
if let Some(repl) = &suggestion.replacement {
println!(" Try: {}", repl);
}
println!("\n2. Unclosed quote:");
let suggestion = SuggestionBuilder::unclosed_quote('"');
println!(" {}", suggestion.message);
println!("\n3. Boolean typo 'flase':");
let suggestion = SuggestionBuilder::boolean_typo("flase");
println!(" {}", suggestion.message);
if let Some(repl) = &suggestion.replacement {
println!(" Try: {}", repl);
}
println!("\n4. Alias with typo 'anchro':");
let available = vec!["anchor".to_string(), "basenode".to_string()];
let suggestion = SuggestionBuilder::undefined_alias("anchro", &available);
println!(" {}", suggestion.message);
println!("\n5. No available anchors:");
let suggestion = SuggestionBuilder::undefined_alias("myalias", &vec![]);
println!(" {}", suggestion.message);
if let Some(repl) = &suggestion.replacement {
println!(" Example: {}", repl);
}
println!();
}
fn demo_recovery_context() {
println!("--- Example 6: Recovery Context Management ---");
let mut ctx = RecoveryContext::new();
println!("Initial state: {:?}", ctx.state);
println!("\nEntering block mapping...");
ctx.enter_block_mapping();
println!(" State: {:?}", ctx.state);
println!(
" Can recover with SkipLine: {}",
ctx.can_recover(RecoveryStrategy::SkipLine)
);
println!(
" Can recover with SkipToNextMapping: {}",
ctx.can_recover(RecoveryStrategy::SkipToNextMapping)
);
println!("\nEntering flow mapping...");
ctx.enter_flow_mapping();
println!(" State: {:?}", ctx.state);
println!(" In flow context: {}", ctx.in_flow);
println!(" Bracket depth: {}", ctx.bracket_depth);
println!(
" Can recover with SkipCollection: {}",
ctx.can_recover(RecoveryStrategy::SkipCollection)
);
println!("\nExiting flow...");
ctx.exit_flow();
println!(" In flow context: {}", ctx.in_flow);
println!(" Bracket depth: {}", ctx.bracket_depth);
println!("\nTesting abort strategy:");
println!(
" Can recover with Abort: {}",
ctx.can_recover(RecoveryStrategy::Abort)
);
println!();
}
fn demo_error_collection() {
println!("--- Example 7: Error Collection ---");
let mut collection = ErrorCollection::new();
println!("Created error collection");
println!(" Continue on error: true");
println!(" Max errors: 100");
println!("\nCollecting errors...");
let error1 = EnhancedError::new(
YamlError::new(ErrorKind::SyntaxError, "Missing colon").with_position(5, 10),
)
.with_code(ErrorCode::E001);
collection.add(error1);
println!(" Added error 1 (E001)");
println!(" Total errors: {}", collection.len());
println!(" Should continue: {}", collection.should_continue());
let error2 = EnhancedError::new(
YamlError::new(ErrorKind::UnterminatedString, "String not closed").with_position(8, 15),
)
.with_code(ErrorCode::E002);
collection.add(error2);
println!("\n Added error 2 (E002)");
println!(" Total errors: {}", collection.len());
println!(" Should continue: {}", collection.should_continue());
println!("\nAll collected errors:");
for (i, error) in collection.errors().iter().enumerate() {
println!(
" {}. {} - {}",
i + 1,
error.code().unwrap(),
error.base().message()
);
}
println!();
}