mod common;
use dcbor::prelude::*;
use dcbor_parse::parse_dcbor_item;
use dcbor_pattern::{
Matcher, Pattern, format_paths, format_paths_with_captures,
};
use indoc::indoc;
fn cbor(s: &str) -> CBOR { parse_dcbor_item(s).unwrap() }
fn parse(s: &str) -> Pattern { Pattern::parse(s).unwrap() }
#[test]
fn test_array_capture_basic() {
let pattern = parse("[@item(42)]");
let cbor_data = cbor("[42]");
let (paths, captures) = pattern.paths_with_captures(&cbor_data);
#[rustfmt::skip]
let expected_output = indoc! {r#"
@item
[42]
42
[42]
"#}.trim();
assert_actual_expected!(
format_paths_with_captures(
&paths,
&captures,
dcbor_pattern::FormatPathsOpts::default()
),
expected_output
);
let normal_paths = pattern.paths(&cbor_data);
#[rustfmt::skip]
let expected_paths = indoc! {r#"
[42]
"#}.trim();
assert_actual_expected!(format_paths(&normal_paths), expected_paths);
}
#[test]
fn test_array_capture_multiple_items() {
let pattern = parse("[@first(number), @second(number)]");
let cbor_data = cbor("[42, 100]");
let (paths, captures) = pattern.paths_with_captures(&cbor_data);
#[rustfmt::skip]
let expected_output = indoc! {r#"
@first
[42, 100]
42
@second
[42, 100]
100
[42, 100]
"#}.trim();
assert_actual_expected!(
format_paths_with_captures(
&paths,
&captures,
dcbor_pattern::FormatPathsOpts::default()
),
expected_output
);
}
#[test]
fn test_array_capture_with_any_pattern() {
let pattern = parse("[@any_item(*)]");
let cbor_data = cbor("[\"hello\"]");
let (paths, captures) = pattern.paths_with_captures(&cbor_data);
#[rustfmt::skip]
let expected_output = indoc! {r#"
@any_item
["hello"]
"hello"
["hello"]
"hello"
["hello"]
"#}.trim();
assert_actual_expected!(
format_paths_with_captures(
&paths,
&captures,
dcbor_pattern::FormatPathsOpts::default()
),
expected_output
);
}
#[test]
fn test_array_vm_compilation_and_execution() {
let pattern = parse("[@item(42)]");
let mut code = Vec::new();
let mut literals = Vec::new();
let mut captures = Vec::new();
pattern.compile(&mut code, &mut literals, &mut captures);
code.push(dcbor_pattern::Instr::Accept);
assert!(!code.is_empty(), "Code should not be empty");
assert!(
!captures.is_empty(),
"Should have at least one capture name"
);
assert!(
captures.contains(&"item".to_string()),
"Should contain 'item' capture"
);
let program =
dcbor_pattern::Program { code, literals, capture_names: captures };
let cbor_data = cbor("[42]");
let (vm_paths, vm_captures) = dcbor_pattern::run(&program, &cbor_data);
#[rustfmt::skip]
let expected_vm_output = indoc! {r#"
@item
[42]
42
[42]
"#}.trim();
assert_actual_expected!(
format_paths_with_captures(
&vm_paths,
&vm_captures,
dcbor_pattern::FormatPathsOpts::default()
),
expected_vm_output
);
}
#[test]
fn test_array_nested_capture() {
let pattern = parse("@arr([@item(number)])");
let cbor_data = cbor("[99]");
let (paths, captures) = pattern.paths_with_captures(&cbor_data);
#[rustfmt::skip]
let expected_output = indoc! {r#"
@arr
[99]
@item
[99]
99
[99]
"#}.trim();
assert_actual_expected!(
format_paths_with_captures(
&paths,
&captures,
dcbor_pattern::FormatPathsOpts::default()
),
expected_output
);
}
#[test]
fn test_array_capture_non_matching() {
let pattern = Pattern::parse("[@item(42)]").unwrap();
let cbor_data = cbor("[100]");
assert!(!pattern.matches(&cbor_data));
let paths = pattern.paths(&cbor_data);
assert!(
paths.is_empty(),
"No paths should be returned for non-matching pattern"
);
}