use facet_format::{ContainerKind, FormatParser, ParseEvent, ParseEventKind, ScalarValue};
use facet_testhelpers::test;
use crate::StyxParser;
fn collect_events(input: &str) -> String {
let mut parser = StyxParser::new(input);
let mut lines = Vec::new();
let mut indent: usize = 0;
let _ = parser.next_event();
loop {
match parser.next_event() {
Ok(Some(event)) => {
if matches!(
event.kind,
ParseEventKind::StructEnd | ParseEventKind::SequenceEnd
) {
indent = indent.saturating_sub(1);
}
let prefix = " ".repeat(indent);
lines.push(format!("{}{}", prefix, format_event(&event)));
if matches!(
event.kind,
ParseEventKind::StructStart(_) | ParseEventKind::SequenceStart(_)
) {
indent += 1;
}
}
Ok(None) => break,
Err(e) => {
lines.push(format!("Error: {:?}", e));
break;
}
}
}
if lines.last().map(|s| s.trim()) == Some("StructEnd") {
lines.pop();
}
lines.join("\n")
}
fn format_event(event: &ParseEvent) -> String {
match &event.kind {
ParseEventKind::Scalar(ScalarValue::Unit) => "Scalar(Unit)".to_string(),
ParseEventKind::Scalar(ScalarValue::Null) => "Scalar(Unit)".to_string(),
ParseEventKind::Scalar(ScalarValue::I64(n)) => format!("Scalar({})", n),
ParseEventKind::Scalar(ScalarValue::Str(s)) => format!("Scalar({:?})", s.as_ref()),
ParseEventKind::Scalar(s) => format!("Scalar({:?})", s),
ParseEventKind::VariantTag(Some(name)) => format!("VariantTag({:?})", name),
ParseEventKind::VariantTag(None) => "VariantTag(None)".to_string(),
ParseEventKind::StructStart(ContainerKind::Object) => "StructStart".to_string(),
ParseEventKind::StructStart(k) => format!("StructStart({:?})", k),
ParseEventKind::StructEnd => "StructEnd".to_string(),
ParseEventKind::SequenceStart(_) => "SequenceStart".to_string(),
ParseEventKind::SequenceEnd => "SequenceEnd".to_string(),
ParseEventKind::FieldKey(k) => format!("FieldKey({:?})", k.name()),
other => format!("{:?}", other),
}
}
#[test]
fn test_01_bare_at() {
insta::assert_snapshot!(collect_events("x @"));
}
#[test]
fn test_02_unit_tag() {
insta::assert_snapshot!(collect_events("x @Foo"));
}
#[test]
fn test_03_tag_explicit_null() {
insta::assert_snapshot!(collect_events("x @Foo@"));
}
#[test]
fn test_04_tag_sequence() {
insta::assert_snapshot!(collect_events("x @Foo(a b)"));
}
#[test]
fn test_05_tag_struct() {
insta::assert_snapshot!(collect_events("y @Foo{x 1}"));
}
#[test]
fn test_06_nested_unit_tags() {
insta::assert_snapshot!(collect_events("x @Foo(@Bar)"));
}
#[test]
fn test_07_tag_struct_with_tag_value() {
insta::assert_snapshot!(collect_events("y @Foo{x @Bar}"));
}
#[test]
fn test_08_field_unit_tag() {
insta::assert_snapshot!(collect_events("x @Foo"));
}
#[test]
fn test_09_field_struct_tag() {
insta::assert_snapshot!(collect_events("x @Foo{y 1}"));
}
#[test]
fn test_10_sequence_unit_tags() {
insta::assert_snapshot!(collect_events("x (@Foo @Bar)"));
}
#[test]
fn test_11_deeply_nested() {
insta::assert_snapshot!(collect_events("y @Foo(@Bar{x 1})"));
}
#[test]
fn test_12_at_as_key() {
insta::assert_snapshot!(collect_events("@ {x 1}"));
}
#[test]
fn test_13_chained_tag_object_payload() {
insta::assert_snapshot!(collect_events(
"x @must_emit/@discover_start{executor default}"
));
}
#[test]
fn test_14_chained_tag_unit_payload() {
insta::assert_snapshot!(collect_events("x @must_not_emit/@exec_start"));
}