mod common;
use dcbor::prelude::*;
use dcbor_parse::parse_dcbor_item;
use dcbor_pattern::{format_paths, *};
use indoc::indoc;
fn cbor(s: &str) -> CBOR { parse_dcbor_item(s).unwrap() }
#[test]
fn test_vm_array_navigation() {
let cbor_data = cbor("[42]");
let code = vec![
Instr::PushAxis(Axis::ArrayElement), Instr::CaptureStart(0), Instr::MatchPredicate(0), Instr::CaptureEnd(0), Instr::Accept, ];
let literals = vec![
Pattern::number(42), ];
let capture_names = vec!["item".to_string()];
let program = Program { code, literals, capture_names };
let (vm_paths, vm_captures) = run(&program, &cbor_data);
#[rustfmt::skip]
let expected_paths = indoc! {r#"
[42]
42
"#}.trim();
assert_actual_expected!(format_paths(&vm_paths), expected_paths);
assert_eq!(vm_captures.len(), 1);
assert!(vm_captures.contains_key("item"));
let captured_paths = &vm_captures["item"];
assert_eq!(captured_paths.len(), 1);
assert_eq!(captured_paths[0], vec![cbor("[42]"), cbor("42")]);
}
#[test]
fn test_vm_map_navigation() {
let cbor_data = cbor(r#"{"key": "value"}"#);
let code = vec![
Instr::PushAxis(Axis::MapValue), Instr::CaptureStart(0), Instr::MatchPredicate(0), Instr::CaptureEnd(0), Instr::Accept, ];
let literals = vec![
Pattern::text("value"), ];
let capture_names = vec!["value".to_string()];
let program = Program { code, literals, capture_names };
let (vm_paths, vm_captures) = run(&program, &cbor_data);
#[rustfmt::skip]
let expected_paths = indoc! {r#"
{"key": "value"}
"value"
"#}.trim();
assert_actual_expected!(format_paths(&vm_paths), expected_paths);
assert_eq!(vm_captures.len(), 1);
assert!(vm_captures.contains_key("value"));
let captured_paths = &vm_captures["value"];
assert_eq!(captured_paths.len(), 1);
assert_eq!(
captured_paths[0],
vec![cbor(r#"{"key": "value"}"#), cbor(r#""value""#)]
);
}
#[test]
fn test_vm_nested_navigation() {
let cbor_data = cbor(r#"[{"inner": 42}]"#);
let code = vec![
Instr::PushAxis(Axis::ArrayElement), Instr::PushAxis(Axis::MapValue), Instr::CaptureStart(0), Instr::MatchPredicate(0), Instr::CaptureEnd(0), Instr::Accept, ];
let literals = vec![
Pattern::number(42), ];
let capture_names = vec!["nested".to_string()];
let program = Program { code, literals, capture_names };
let (vm_paths, vm_captures) = run(&program, &cbor_data);
#[rustfmt::skip]
let expected_paths = indoc! {r#"
[{"inner": 42}]
{"inner": 42}
42
"#}.trim();
assert_actual_expected!(format_paths(&vm_paths), expected_paths);
assert_eq!(vm_captures.len(), 1);
assert!(vm_captures.contains_key("nested"));
let captured_paths = &vm_captures["nested"];
assert_eq!(captured_paths.len(), 1);
assert_eq!(
captured_paths[0],
vec![
cbor(r#"[{"inner": 42}]"#),
cbor(r#"{"inner": 42}"#),
cbor("42")
]
);
}
#[test]
fn test_vm_multiple_captures() {
let cbor_data = cbor("[42, 100]");
let code = vec![
Instr::PushAxis(Axis::ArrayElement), Instr::CaptureStart(0), Instr::MatchPredicate(0), Instr::CaptureEnd(0), Instr::Accept, ];
let literals = vec![
Pattern::any(), ];
let capture_names = vec!["element".to_string()];
let program = Program { code, literals, capture_names };
let (vm_paths, vm_captures) = run(&program, &cbor_data);
#[rustfmt::skip]
let expected_paths = indoc! {r#"
[42, 100]
100
[42, 100]
42
"#}.trim();
assert_actual_expected!(format_paths(&vm_paths), expected_paths);
assert!(!vm_captures.is_empty());
}
#[test]
fn test_vm_no_match_navigation() {
let cbor_data = cbor("[100]");
let code = vec![
Instr::PushAxis(Axis::ArrayElement), Instr::CaptureStart(0), Instr::MatchPredicate(0), Instr::CaptureEnd(0), Instr::Accept, ];
let literals = vec![
Pattern::number(42), ];
let capture_names = vec!["item".to_string()];
let program = Program { code, literals, capture_names };
let (vm_paths, vm_captures) = run(&program, &cbor_data);
assert!(
vm_paths.is_empty(),
"No paths should be returned for non-matching pattern"
);
assert!(
vm_captures.is_empty(),
"No captures should be returned for non-matching pattern"
);
}