mod common;
use dcbor::prelude::*;
use dcbor_parse::parse_dcbor_item;
use dcbor_pattern::{
ArrayPattern, MapPattern, Matcher, Pattern, TaggedPattern, format_paths,
};
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_pattern_any() {
let pattern = parse("array");
let empty_array = cbor("[]");
let paths = pattern.paths(&empty_array);
#[rustfmt::skip]
let expected = indoc! {r#"
[]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let array = cbor("[1, 2, 3]");
let paths = pattern.paths(&array);
#[rustfmt::skip]
let expected = indoc! {r#"
[1, 2, 3]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let not_array = cbor(r#""not an array""#);
assert!(!pattern.matches(¬_array));
}
#[test]
fn test_array_pattern_single_any_element() {
let pattern = parse("[*]");
let single_element_array = cbor("[42]");
let paths = pattern.paths(&single_element_array);
#[rustfmt::skip]
let expected = indoc! {r#"
[42]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let single_string_array = cbor(r#"["hello"]"#);
let paths = pattern.paths(&single_string_array);
#[rustfmt::skip]
let expected = indoc! {r#"
["hello"]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let empty_array = cbor("[]");
assert!(!pattern.matches(&empty_array));
let multi_element_array = cbor("[1, 2, 3]");
assert!(!pattern.matches(&multi_element_array));
let not_array = cbor(r#""not an array""#);
assert!(!pattern.matches(¬_array));
}
#[test]
fn test_array_pattern_with_length() {
let pattern = parse("[{2}]");
let array = cbor("[1, 2]");
let paths = pattern.paths(&array);
#[rustfmt::skip]
let expected = indoc! {r#"
[1, 2]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let wrong_length = cbor("[1, 2, 3]");
assert!(!pattern.matches(&wrong_length));
let not_array = cbor(r#""not an array""#);
assert!(!pattern.matches(¬_array));
}
#[test]
fn test_array_pattern_with_elements() {
let number_pattern = parse("42");
let pattern = ArrayPattern::with_elements(number_pattern);
let single_element = cbor("[42]");
let paths = pattern.paths(&single_element);
#[rustfmt::skip]
let expected = indoc! {r#"
[42]
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let multi_element = cbor("[1, 42, 3]");
assert!(
!pattern.matches(&multi_element),
"[42] should only match [42], not [1, 42, 3]"
);
let no_match = cbor("[1, 2, 3]");
assert!(!pattern.matches(&no_match));
let empty = cbor("[]");
assert!(!pattern.matches(&empty));
}
#[test]
fn test_map_pattern_any() {
let pattern = parse("map");
let empty_map = cbor("{}");
let paths = pattern.paths(&empty_map);
#[rustfmt::skip]
let expected = indoc! {r#"
{}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let cbor_map = cbor(r#"{"key": "value"}"#);
let paths = pattern.paths(&cbor_map);
#[rustfmt::skip]
let expected = indoc! {r#"
{"key": "value"}
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let not_map = cbor(r#""not a map""#);
assert!(!pattern.matches(¬_map));
}
#[test]
fn test_tagged_pattern_any() {
let pattern = TaggedPattern::any();
let tagged = cbor(r#"1234("content")"#);
let paths = pattern.paths(&tagged);
#[rustfmt::skip]
let expected = indoc! {r#"
1234("content")
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let not_tagged = cbor(r#""not tagged""#);
assert!(!pattern.matches(¬_tagged));
}
#[test]
fn test_tagged_pattern_with_tag_and_any() {
let target_tag = Tag::new(1234, "test_tag");
let pattern = TaggedPattern::with_tag(target_tag.clone(), Pattern::any());
let tagged = cbor(r#"1234("content")"#);
let paths = pattern.paths(&tagged);
#[rustfmt::skip]
let expected = indoc! {r#"
1234("content")
"#}.trim();
assert_actual_expected!(format_paths(&paths), expected);
let wrong_tagged = cbor(r#"5678("content")"#);
assert!(!pattern.matches(&wrong_tagged));
let not_tagged = cbor(r#""not tagged""#);
assert!(!pattern.matches(¬_tagged));
}
#[test]
fn test_structure_pattern_display() {
assert_eq!(parse("[*]").to_string(), "[*]");
assert_eq!(parse("[{5}]").to_string(), "[{5}]");
assert_eq!(
format!("{}", ArrayPattern::with_length_range(1..=10)),
"[{1,10}]"
);
assert_eq!(parse("map").to_string(), "map");
assert_eq!(parse("{{3}}").to_string(), "{{3}}");
assert_eq!(
format!("{}", MapPattern::with_length_range(2..=8)),
"{{2,8}}"
);
assert_eq!(format!("{}", TaggedPattern::any()), "tagged");
let tag = Tag::new(1234, "test");
assert_eq!(
format!("{}", TaggedPattern::with_tag(tag, Pattern::any())),
"tagged(1234, *)"
);
}