granit-parser 0.0.2

A YAML parser in pure Rust with strict compliance
Documentation
use granit_parser::{Event, Parser, ScanError};

const README: &str = include_str!("../README.md");

fn minimal_example_section() -> &'static str {
    README
        .split_once("## Minimal example")
        .and_then(|(_, tail)| tail.split_once("\n## ").map(|(section, _)| section))
        .expect("README must contain a '## Minimal example' section before the next heading")
}

fn extract_yaml_input(section: &str) -> &str {
    section
        .split_once("let yaml = r#\"")
        .and_then(|(_, tail)| tail.split_once("\"#;").map(|(yaml, _)| yaml))
        .expect("README minimal example must contain a raw string YAML input")
}

fn extract_expected_output(section: &str) -> &str {
    section
        .split_once("```text\n")
        .and_then(|(_, tail)| tail.split_once("\n```").map(|(text, _)| text))
        .expect("README minimal example must contain a fenced text block with expected output")
}

fn render_readme_example(yaml: &str) -> Result<String, ScanError> {
    let mut lines = Vec::new();

    for next in Parser::new_from_str(yaml) {
        let (event, _span) = next?;

        match &event {
            Event::SequenceStart(_, Some(tag)) => {
                lines.push(format!("sequence tag: {}{}", tag.handle, tag.suffix));
            }
            Event::Scalar(value, _, _, Some(tag)) => {
                lines.push(format!(
                    "scalar tag: {}{} for {value:?}",
                    tag.handle, tag.suffix
                ));
            }
            _ => {}
        }

        lines.push(format!("{event:?}"));
    }

    Ok(lines.join("\n"))
}

#[test]
fn minimal_example_output_matches_readme() {
    let section = minimal_example_section();
    let yaml = extract_yaml_input(section);
    let expected = extract_expected_output(section);
    let actual =
        render_readme_example(yaml).expect("README example YAML should parse successfully");

    println!("Actual output:\n{}", actual);
    println!("Expected output:\n{}", expected);

    assert_eq!(actual, expected, "README example output is out of sync");
}