bc_envelope_pattern/pattern/
mod.rs1mod matcher;
3mod vm;
4
5mod leaf;
7mod meta;
8mod structure;
9
10pub mod dcbor_integration;
12
13use std::{
15 cell::RefCell,
16 collections::HashMap,
17 ops::{RangeBounds, RangeInclusive},
18};
19
20use bc_envelope::prelude::*;
21use known_values::KnownValue;
22pub use matcher::{Matcher, Path, compile_as_atomic};
23
24use self::{
25 leaf::{
26 ArrayPattern, BoolPattern, ByteStringPattern, DatePattern,
27 KnownValuePattern, LeafPattern, MapPattern, NullPattern, NumberPattern,
28 TextPattern,
29 },
30 meta::{
31 AndPattern, AnyPattern, CapturePattern, GroupPattern, MetaPattern,
32 NotPattern, OrPattern, SearchPattern, TraversePattern,
33 },
34 structure::{
35 AssertionsPattern, DigestPattern, LeafStructurePattern, NodePattern,
36 ObjectPattern, ObscuredPattern, PredicatePattern, StructurePattern,
37 SubjectPattern, WrappedPattern,
38 },
39};
40use crate::{
41 DCBORPattern, Quantifier, Reluctance,
42 pattern::{leaf::CBORPattern, vm::Instr},
43};
44
45#[derive(Debug, Clone, Hash, PartialEq, Eq)]
47pub enum Pattern {
48 Leaf(LeafPattern),
50
51 Structure(StructurePattern),
53
54 Meta(MetaPattern),
56}
57
58impl Matcher for Pattern {
59 fn paths_with_captures(
60 &self,
61 haystack: &Envelope,
62 ) -> (Vec<Path>, HashMap<String, Vec<Path>>) {
63 let results = self.vm_run(haystack);
64 let mut paths = Vec::new();
65 let mut captures: HashMap<String, Vec<Path>> = HashMap::new();
66 for (p, caps) in results {
67 paths.push(p);
68 for (name, mut vals) in caps {
69 captures.entry(name).or_default().append(&mut vals);
70 }
71 }
72 (paths, captures)
73 }
74
75 fn is_complex(&self) -> bool {
76 match self {
77 Pattern::Leaf(leaf) => leaf.is_complex(),
78 Pattern::Structure(structure) => structure.is_complex(),
79 Pattern::Meta(meta) => meta.is_complex(),
80 }
81 }
82}
83
84impl Pattern {
89 pub fn any_cbor() -> Self {
91 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::any()))
92 }
93
94 pub fn cbor(cbor: impl CBOREncodable) -> Self {
96 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::value(cbor)))
97 }
98
99 pub fn cbor_pattern(pattern: DCBORPattern) -> Self {
102 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::pattern(pattern)))
103 }
104}
105
106impl Pattern {
107 pub fn any_bool() -> Self {
109 Pattern::Leaf(LeafPattern::Bool(BoolPattern::any()))
110 }
111
112 pub fn bool(b: bool) -> Self {
114 Pattern::Leaf(LeafPattern::Bool(BoolPattern::value(b)))
115 }
116}
117
118impl Pattern {
119 pub fn any_text() -> Self {
121 Pattern::Leaf(LeafPattern::Text(TextPattern::any()))
122 }
123
124 pub fn text<T: Into<String>>(value: T) -> Self {
126 Pattern::Leaf(LeafPattern::Text(TextPattern::value(value)))
127 }
128
129 pub fn text_regex(regex: regex::Regex) -> Self {
132 Pattern::Leaf(LeafPattern::Text(TextPattern::regex(regex)))
133 }
134}
135
136impl Pattern {
137 pub fn any_date() -> Self {
139 Pattern::Leaf(LeafPattern::Date(DatePattern::any()))
140 }
141
142 pub fn date(date: Date) -> Self {
144 Pattern::Leaf(LeafPattern::Date(DatePattern::value(date)))
145 }
146
147 pub fn date_range(range: RangeInclusive<Date>) -> Self {
150 Pattern::Leaf(LeafPattern::Date(DatePattern::range(range)))
151 }
152
153 pub fn date_earliest(date: Date) -> Self {
156 Pattern::Leaf(LeafPattern::Date(DatePattern::earliest(date)))
157 }
158
159 pub fn date_latest(date: Date) -> Self {
162 Pattern::Leaf(LeafPattern::Date(DatePattern::latest(date)))
163 }
164
165 pub fn date_iso8601(iso_string: impl Into<String>) -> Self {
168 Pattern::Leaf(LeafPattern::Date(DatePattern::string(iso_string)))
169 }
170
171 pub fn date_regex(regex: regex::Regex) -> Self {
174 Pattern::Leaf(LeafPattern::Date(DatePattern::regex(regex)))
175 }
176}
177
178impl Pattern {
179 pub fn any_number() -> Self {
181 Pattern::Leaf(LeafPattern::Number(NumberPattern::any()))
182 }
183
184 pub fn number<T: Into<f64>>(value: T) -> Self {
186 Pattern::Leaf(LeafPattern::Number(NumberPattern::exact(value)))
187 }
188
189 pub fn number_range<A: Into<f64> + Copy>(range: RangeInclusive<A>) -> Self {
192 Pattern::Leaf(LeafPattern::Number(NumberPattern::range(range)))
193 }
194
195 pub fn number_greater_than<T: Into<f64>>(value: T) -> Self {
198 Pattern::Leaf(LeafPattern::Number(NumberPattern::greater_than(value)))
199 }
200
201 pub fn number_greater_than_or_equal<T: Into<f64>>(value: T) -> Self {
204 Pattern::Leaf(LeafPattern::Number(
205 NumberPattern::greater_than_or_equal(value),
206 ))
207 }
208
209 pub fn number_less_than<T: Into<f64>>(value: T) -> Self {
212 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than(value)))
213 }
214
215 pub fn number_less_than_or_equal<T: Into<f64>>(value: T) -> Self {
218 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than_or_equal(
219 value,
220 )))
221 }
222
223 pub fn number_nan() -> Self {
226 Pattern::Leaf(LeafPattern::Number(NumberPattern::nan()))
227 }
228}
229
230impl Pattern {
231 pub fn any_byte_string() -> Self {
233 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::any()))
234 }
235
236 pub fn byte_string(value: impl AsRef<[u8]>) -> Self {
238 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::value(value)))
239 }
240
241 pub fn byte_string_binary_regex(regex: regex::bytes::Regex) -> Self {
244 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::regex(regex)))
245 }
246}
247
248impl Pattern {
249 pub fn any_known_value() -> Self {
250 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::any()))
251 }
252
253 pub fn known_value(value: KnownValue) -> Self {
254 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::value(value)))
255 }
256
257 pub fn known_value_named<T: Into<String>>(name: T) -> Self {
258 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::named(name)))
259 }
260
261 pub fn known_value_regex(regex: regex::Regex) -> Self {
262 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::regex(regex)))
263 }
264
265 pub fn unit() -> Self { Self::known_value(known_values::UNIT) }
266}
267
268impl Pattern {
269 pub fn any_array() -> Self {
270 Pattern::Leaf(LeafPattern::Array(ArrayPattern::any()))
271 }
272
273 pub fn array_with_range(interval: impl RangeBounds<usize>) -> Self {
274 Pattern::Leaf(LeafPattern::Array(ArrayPattern::interval(interval)))
275 }
276
277 pub fn array_with_count(count: usize) -> Self {
278 Pattern::Leaf(LeafPattern::Array(ArrayPattern::count(count)))
279 }
280
281 pub fn array_from_dcbor_pattern(pattern: DCBORPattern) -> Self {
284 Pattern::Leaf(LeafPattern::Array(ArrayPattern::from_dcbor_pattern(
285 pattern,
286 )))
287 }
288}
289
290impl Pattern {
291 pub fn any_map() -> Self {
292 Pattern::Leaf(LeafPattern::Map(MapPattern::any()))
293 }
294
295 pub fn map_with_range(interval: impl RangeBounds<usize>) -> Self {
296 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(interval)))
297 }
298
299 pub fn map_with_count(count: usize) -> Self {
300 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(count..=count)))
301 }
302}
303
304impl Pattern {
305 pub fn null() -> Self { Pattern::Leaf(LeafPattern::Null(NullPattern)) }
306}
307
308impl Pattern {
309 pub fn any_tag() -> Self {
312 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
313 crate::pattern::leaf::TaggedPattern::any(),
314 ))
315 }
316
317 pub fn tagged(tag: impl Into<Tag>, pattern: DCBORPattern) -> Self {
320 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
321 crate::pattern::leaf::TaggedPattern::with_tag(tag, pattern),
322 ))
323 }
324
325 pub fn tagged_name(name: impl Into<String>, pattern: DCBORPattern) -> Self {
329 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
330 crate::pattern::leaf::TaggedPattern::with_name(
331 name.into(),
332 pattern,
333 ),
334 ))
335 }
336
337 pub fn tagged_regex(regex: regex::Regex, pattern: DCBORPattern) -> Self {
341 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
342 crate::pattern::leaf::TaggedPattern::with_regex(regex, pattern),
343 ))
344 }
345
346 pub(crate) fn tagged_from_dcbor_pattern(
350 tagged_pattern: dcbor_pattern::TaggedPattern,
351 ) -> Self {
352 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
353 crate::pattern::leaf::TaggedPattern::from_dcbor_pattern(
354 tagged_pattern,
355 ),
356 ))
357 }
358}
359
360impl Pattern {
369 pub fn leaf() -> Self {
370 Pattern::Structure(StructurePattern::Leaf(LeafStructurePattern::new()))
371 }
372
373 pub fn any_assertion() -> Self {
374 Pattern::Structure(StructurePattern::Assertions(
375 AssertionsPattern::any(),
376 ))
377 }
378
379 pub fn assertion_with_predicate(pattern: Pattern) -> Self {
380 Pattern::Structure(StructurePattern::Assertions(
381 AssertionsPattern::with_predicate(pattern),
382 ))
383 }
384
385 pub fn assertion_with_object(pattern: Pattern) -> Self {
386 Pattern::Structure(StructurePattern::Assertions(
387 AssertionsPattern::with_object(pattern),
388 ))
389 }
390}
391
392impl Pattern {
393 pub fn any_subject() -> Self {
394 Pattern::Structure(StructurePattern::Subject(SubjectPattern::any()))
395 }
396
397 pub fn subject(pattern: Pattern) -> Self {
398 Pattern::Structure(StructurePattern::Subject(SubjectPattern::pattern(
399 pattern,
400 )))
401 }
402}
403
404impl Pattern {
405 pub fn any_predicate() -> Self {
406 Pattern::Structure(StructurePattern::Predicate(PredicatePattern::any()))
407 }
408
409 pub fn predicate(pattern: Pattern) -> Self {
410 Pattern::Structure(StructurePattern::Predicate(
411 PredicatePattern::pattern(pattern),
412 ))
413 }
414
415 pub fn any_object() -> Self {
416 Pattern::Structure(StructurePattern::Object(ObjectPattern::any()))
417 }
418
419 pub fn object(pattern: Pattern) -> Self {
420 Pattern::Structure(StructurePattern::Object(ObjectPattern::pattern(
421 pattern,
422 )))
423 }
424}
425
426impl Pattern {
427 pub fn digest(digest: bc_components::Digest) -> Self {
428 Pattern::Structure(StructurePattern::Digest(DigestPattern::digest(
429 digest,
430 )))
431 }
432
433 pub fn digest_prefix(prefix: impl AsRef<[u8]>) -> Self {
434 Pattern::Structure(StructurePattern::Digest(DigestPattern::prefix(
435 prefix,
436 )))
437 }
438
439 pub fn digest_binary_regex(regex: regex::bytes::Regex) -> Self {
440 Pattern::Structure(StructurePattern::Digest(
441 DigestPattern::binary_regex(regex),
442 ))
443 }
444
445 pub fn any_node() -> Self {
446 Pattern::Structure(StructurePattern::Node(NodePattern::any()))
447 }
448
449 pub fn node_with_assertions_range(range: impl RangeBounds<usize>) -> Self {
450 Pattern::Structure(StructurePattern::Node(NodePattern::interval(range)))
451 }
452
453 pub fn node_with_assertions_count(count: usize) -> Self {
454 Pattern::Structure(StructurePattern::Node(NodePattern::interval(
455 count..=count,
456 )))
457 }
458
459 pub fn obscured() -> Self {
460 Pattern::Structure(StructurePattern::Obscured(ObscuredPattern::any()))
461 }
462
463 pub fn elided() -> Self {
464 Pattern::Structure(
465 StructurePattern::Obscured(ObscuredPattern::elided()),
466 )
467 }
468
469 pub fn encrypted() -> Self {
470 Pattern::Structure(StructurePattern::Obscured(
471 ObscuredPattern::encrypted(),
472 ))
473 }
474
475 pub fn compressed() -> Self {
476 Pattern::Structure(StructurePattern::Obscured(
477 ObscuredPattern::compressed(),
478 ))
479 }
480}
481
482impl Pattern {
491 pub fn any() -> Self { Pattern::Meta(MetaPattern::Any(AnyPattern::new())) }
493}
494
495impl Pattern {
496 pub fn and(patterns: Vec<Pattern>) -> Self {
499 Pattern::Meta(MetaPattern::And(AndPattern::new(patterns)))
500 }
501
502 pub fn or(patterns: Vec<Pattern>) -> Self {
505 Pattern::Meta(MetaPattern::Or(OrPattern::new(patterns)))
506 }
507}
508
509impl Pattern {
510 pub fn traverse(patterns: Vec<Pattern>) -> Self {
512 Pattern::Meta(MetaPattern::Traverse(TraversePattern::new(patterns)))
513 }
514}
515
516impl Pattern {
517 pub fn search(pattern: Pattern) -> Self {
521 Pattern::Meta(MetaPattern::Search(SearchPattern::new(pattern)))
522 }
523}
524
525impl Pattern {
526 pub fn not_matching(pattern: Pattern) -> Self {
529 Pattern::Meta(MetaPattern::Not(NotPattern::new(pattern)))
530 }
531}
532
533impl Pattern {
534 pub(crate) fn compile(
536 &self,
537 code: &mut Vec<Instr>,
538 lits: &mut Vec<Pattern>,
539 captures: &mut Vec<String>,
540 ) {
541 use Pattern::*;
542 match self {
543 Leaf(leaf_pattern) => leaf_pattern.compile(code, lits, captures),
544 Structure(struct_pattern) => {
545 struct_pattern.compile(code, lits, captures)
546 }
547 Meta(meta_pattern) => meta_pattern.compile(code, lits, captures),
548 }
549 }
550}
551
552impl Pattern {
553 pub fn repeat(
568 pattern: Pattern,
569 interval: impl RangeBounds<usize>,
570 reluctance: Reluctance,
571 ) -> Self {
572 Pattern::Meta(MetaPattern::Group(GroupPattern::repeat(
573 pattern,
574 Quantifier::new(interval, reluctance),
575 )))
576 }
577
578 pub fn group(pattern: Pattern) -> Self {
579 Pattern::Meta(MetaPattern::Group(GroupPattern::new(pattern)))
580 }
581}
582
583impl Pattern {
584 pub fn capture(name: impl AsRef<str>, pattern: Pattern) -> Self {
586 Pattern::Meta(MetaPattern::Capture(CapturePattern::new(name, pattern)))
587 }
588}
589
590impl std::fmt::Display for Pattern {
595 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
596 match self {
597 Pattern::Leaf(leaf) => write!(f, "{}", leaf),
598 Pattern::Structure(structure) => write!(f, "{}", structure),
599 Pattern::Meta(meta) => write!(f, "{}", meta),
600 }
601 }
602}
603
604impl Pattern {
605 fn vm_run(
608 &self,
609 env: &Envelope,
610 ) -> Vec<(Path, HashMap<String, Vec<Path>>)> {
611 thread_local! {
612 static PROG: RefCell<HashMap<u64, vm::Program>> = RefCell::new(HashMap::new());
613 }
614
615 use std::{
617 collections::hash_map::DefaultHasher,
618 hash::{Hash, Hasher},
619 };
620 let mut h = DefaultHasher::new();
621 self.hash(&mut h);
622 let key = h.finish();
623
624 let prog = PROG
625 .with(|cell| cell.borrow().get(&key).cloned())
626 .unwrap_or_else(|| {
627 let mut p = vm::Program {
628 code: Vec::new(),
629 literals: Vec::new(),
630 capture_names: Vec::new(),
631 };
632 self.compile(
633 &mut p.code,
634 &mut p.literals,
635 &mut p.capture_names,
636 );
637 p.code.push(Instr::Accept);
638 PROG.with(|cell| {
639 cell.borrow_mut().insert(key, p.clone());
640 });
641 p
642 });
643
644 vm::run(&prog, env)
645 }
646
647 #[allow(dead_code)]
648 fn vm_paths(&self, env: &Envelope) -> Vec<Path> {
649 self.vm_run(env).into_iter().map(|(p, _)| p).collect()
650 }
651
652 pub(crate) fn collect_capture_names(&self, out: &mut Vec<String>) {
653 if let Pattern::Meta(meta) = self {
654 meta.collect_capture_names(out)
655 }
656 }
657}
658
659impl Pattern {
660 pub fn wrapped() -> Self {
664 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::new()))
665 }
666
667 pub fn unwrap_matching(pattern: Pattern) -> Self {
670 Pattern::Structure(StructurePattern::Wrapped(
671 WrappedPattern::unwrap_matching(pattern),
672 ))
673 }
674
675 pub fn unwrap() -> Self {
678 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::unwrap()))
679 }
680}