rust_dot 0.6.0

RustDOT is mostly the Graphviz DOT language, lightly rustified.
Documentation
use std::{collections::HashSet, fs, path::Path};

const FAIL: [&str; 8] = [
    // multiple graphs
    "1845.dot",
    "graphs/multi.gv",
    // broken subgraph nesting
    "1308_1.dot",
    // broken Latin-1
    "1676.dot",
    "regression_tests/vuln/input/nullderefrebuildlist.dot",
    "regression_tests/vuln/reference/nullderefrebuildlist.xdot",
    // invalid DOT
    "1411.dot",
    // not DOT
    "share/b545.gv",
];

#[test]
#[ignore]
/// Test external files whose dir is pointed at by environment variable GRAPHVIZ_TESTS.
fn compatible() {
    let Some(graphviz_tests) = option_env!("GRAPHVIZ_TESTS") else {
        panic!("For this test point environment variable GRAPHVIZ_TESTS at a dir of .gv and/or .dot files.");
    };
    test_dir(Path::new(graphviz_tests), "", &FAIL.into_iter().collect())
}

fn test_dir(dir: &Path, rel: &str, fail: &HashSet<&'static str>) {
    // Implement walking dir hierarchy, as there is no test-dependencies option.
    let mut file = dir.join(Path::new("x"));
    for entry in fs::read_dir(dir).unwrap() {
        let entry = entry.unwrap().file_name();
        let str = format!("{rel}{}", entry.to_str().unwrap());
        file.set_file_name(&entry);
        if let Some((_, suf)) = str.rsplit_once('.') {
            // ordered by frequency
            if ["gv", "xdot", "dot"].contains(&suf) {
                let result = std::panic::catch_unwind(|| crate::parse_file(&file));
                if fail.contains::<str>(&str) {
                    eprintln!("^^^ {file:?} should have failed ^^^");
                    assert!(result.is_err());
                } else {
                    eprintln!("{file:?}");
                    assert!(result.is_ok());
                }
                continue;
            }
        }
        if file.is_dir() {
            test_dir(&file, &(str + "/"), fail)
        }
    }
}