bc_envelope_pattern/pattern/
pattern_impl.rs1use std::{
56 cell::RefCell,
57 collections::HashMap,
58 ops::{RangeBounds, RangeInclusive},
59};
60
61use bc_envelope::prelude::*;
62use known_values::KnownValue;
63
64use super::{
65 Matcher, Path,
66 leaf::{
67 ArrayPattern, BoolPattern, ByteStringPattern, DatePattern,
68 KnownValuePattern, LeafPattern, MapPattern, NullPattern, NumberPattern,
69 TextPattern,
70 },
71 meta::{
72 AndPattern, AnyPattern, CapturePattern, GroupPattern, MetaPattern, NotPattern,
73 OrPattern, SearchPattern, TraversePattern,
74 },
75 structure::{
76 AssertionsPattern, DigestPattern, LeafStructurePattern, NodePattern,
77 ObjectPattern, ObscuredPattern, PredicatePattern, StructurePattern,
78 SubjectPattern, WrappedPattern,
79 },
80 vm,
81};
82use crate::{
83 DCBORPattern, Quantifier, Reluctance,
84 pattern::{
85 leaf::CBORPattern,
86 vm::Instr,
87 },
88};
89
90#[derive(Debug, Clone, Hash, PartialEq, Eq)]
92pub enum Pattern {
93 Leaf(LeafPattern),
95
96 Structure(StructurePattern),
98
99 Meta(MetaPattern),
101}
102
103impl Matcher for Pattern {
104 fn paths_with_captures(
105 &self,
106 haystack: &Envelope,
107 ) -> (Vec<Path>, HashMap<String, Vec<Path>>) {
108 let results = self.vm_run(haystack);
109 let mut paths = Vec::new();
110 let mut captures: HashMap<String, Vec<Path>> = HashMap::new();
111 for (p, caps) in results {
112 paths.push(p);
113 for (name, mut vals) in caps {
114 captures.entry(name).or_default().append(&mut vals);
115 }
116 }
117 (paths, captures)
118 }
119
120 fn is_complex(&self) -> bool {
121 match self {
122 Pattern::Leaf(leaf) => leaf.is_complex(),
123 Pattern::Structure(structure) => structure.is_complex(),
124 Pattern::Meta(meta) => meta.is_complex(),
125 }
126 }
127}
128
129impl Pattern {
134 pub fn any_cbor() -> Self {
136 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::any()))
137 }
138
139 pub fn cbor(cbor: impl CBOREncodable) -> Self {
141 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::value(cbor)))
142 }
143
144 pub fn cbor_pattern(pattern: DCBORPattern) -> Self {
147 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::pattern(pattern)))
148 }
149}
150
151impl Pattern {
152 pub fn any_bool() -> Self {
154 Pattern::Leaf(LeafPattern::Bool(BoolPattern::any()))
155 }
156
157 pub fn bool(b: bool) -> Self {
159 Pattern::Leaf(LeafPattern::Bool(BoolPattern::value(b)))
160 }
161}
162
163impl Pattern {
164 pub fn any_text() -> Self {
166 Pattern::Leaf(LeafPattern::Text(TextPattern::any()))
167 }
168
169 pub fn text<T: Into<String>>(value: T) -> Self {
171 Pattern::Leaf(LeafPattern::Text(TextPattern::value(value)))
172 }
173
174 pub fn text_regex(regex: regex::Regex) -> Self {
177 Pattern::Leaf(LeafPattern::Text(TextPattern::regex(regex)))
178 }
179}
180
181impl Pattern {
182 pub fn any_date() -> Self {
184 Pattern::Leaf(LeafPattern::Date(DatePattern::any()))
185 }
186
187 pub fn date(date: Date) -> Self {
189 Pattern::Leaf(LeafPattern::Date(DatePattern::value(date)))
190 }
191
192 pub fn date_range(range: RangeInclusive<Date>) -> Self {
195 Pattern::Leaf(LeafPattern::Date(DatePattern::range(range)))
196 }
197
198 pub fn date_earliest(date: Date) -> Self {
201 Pattern::Leaf(LeafPattern::Date(DatePattern::earliest(date)))
202 }
203
204 pub fn date_latest(date: Date) -> Self {
207 Pattern::Leaf(LeafPattern::Date(DatePattern::latest(date)))
208 }
209
210 pub fn date_iso8601(iso_string: impl Into<String>) -> Self {
213 Pattern::Leaf(LeafPattern::Date(DatePattern::string(iso_string)))
214 }
215
216 pub fn date_regex(regex: regex::Regex) -> Self {
219 Pattern::Leaf(LeafPattern::Date(DatePattern::regex(regex)))
220 }
221}
222
223impl Pattern {
224 pub fn any_number() -> Self {
226 Pattern::Leaf(LeafPattern::Number(NumberPattern::any()))
227 }
228
229 pub fn number<T: Into<f64>>(value: T) -> Self {
231 Pattern::Leaf(LeafPattern::Number(NumberPattern::exact(value)))
232 }
233
234 pub fn number_range<A: Into<f64> + Copy>(range: RangeInclusive<A>) -> Self {
237 Pattern::Leaf(LeafPattern::Number(NumberPattern::range(range)))
238 }
239
240 pub fn number_greater_than<T: Into<f64>>(value: T) -> Self {
243 Pattern::Leaf(LeafPattern::Number(NumberPattern::greater_than(value)))
244 }
245
246 pub fn number_greater_than_or_equal<T: Into<f64>>(value: T) -> Self {
249 Pattern::Leaf(LeafPattern::Number(
250 NumberPattern::greater_than_or_equal(value),
251 ))
252 }
253
254 pub fn number_less_than<T: Into<f64>>(value: T) -> Self {
257 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than(value)))
258 }
259
260 pub fn number_less_than_or_equal<T: Into<f64>>(value: T) -> Self {
263 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than_or_equal(
264 value,
265 )))
266 }
267
268 pub fn number_nan() -> Self {
271 Pattern::Leaf(LeafPattern::Number(NumberPattern::nan()))
272 }
273}
274
275impl Pattern {
276 pub fn any_byte_string() -> Self {
278 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::any()))
279 }
280
281 pub fn byte_string(value: impl AsRef<[u8]>) -> Self {
283 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::value(value)))
284 }
285
286 pub fn byte_string_binary_regex(regex: regex::bytes::Regex) -> Self {
289 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::regex(regex)))
290 }
291}
292
293impl Pattern {
294 pub fn any_known_value() -> Self {
295 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::any()))
296 }
297
298 pub fn known_value(value: KnownValue) -> Self {
299 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::value(value)))
300 }
301
302 pub fn known_value_named<T: Into<String>>(name: T) -> Self {
303 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::named(name)))
304 }
305
306 pub fn known_value_regex(regex: regex::Regex) -> Self {
307 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::regex(regex)))
308 }
309
310 pub fn unit() -> Self {
311 Self::known_value(known_values::UNIT)
312 }
313}
314
315impl Pattern {
316 pub fn any_array() -> Self {
317 Pattern::Leaf(LeafPattern::Array(ArrayPattern::any()))
318 }
319
320 pub fn array_with_range(interval: impl RangeBounds<usize>) -> Self {
321 Pattern::Leaf(LeafPattern::Array(ArrayPattern::interval(interval)))
322 }
323
324 pub fn array_with_count(count: usize) -> Self {
325 Pattern::Leaf(LeafPattern::Array(ArrayPattern::count(count)))
326 }
327
328 pub fn array_from_dcbor_pattern(pattern: DCBORPattern) -> Self {
331 Pattern::Leaf(LeafPattern::Array(ArrayPattern::from_dcbor_pattern(
332 pattern,
333 )))
334 }
335}
336
337impl Pattern {
338 pub fn any_map() -> Self {
339 Pattern::Leaf(LeafPattern::Map(MapPattern::any()))
340 }
341
342 pub fn map_with_range(interval: impl RangeBounds<usize>) -> Self {
343 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(interval)))
344 }
345
346 pub fn map_with_count(count: usize) -> Self {
347 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(count..=count)))
348 }
349}
350
351impl Pattern {
352 pub fn null() -> Self {
353 Pattern::Leaf(LeafPattern::Null(NullPattern))
354 }
355}
356
357impl Pattern {
358 pub fn any_tag() -> Self {
361 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
362 crate::pattern::leaf::TaggedPattern::any(),
363 ))
364 }
365
366 pub fn tagged(tag: impl Into<Tag>, pattern: DCBORPattern) -> Self {
369 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
370 crate::pattern::leaf::TaggedPattern::with_tag(tag, pattern),
371 ))
372 }
373
374 pub fn tagged_name(name: impl Into<String>, pattern: DCBORPattern) -> Self {
378 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
379 crate::pattern::leaf::TaggedPattern::with_name(
380 name.into(),
381 pattern,
382 ),
383 ))
384 }
385
386 pub fn tagged_regex(regex: regex::Regex, pattern: DCBORPattern) -> Self {
390 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
391 crate::pattern::leaf::TaggedPattern::with_regex(regex, pattern),
392 ))
393 }
394
395 pub(crate) fn tagged_from_dcbor_pattern(
399 tagged_pattern: dcbor_pattern::TaggedPattern,
400 ) -> Self {
401 Pattern::Leaf(crate::pattern::leaf::LeafPattern::Tag(
402 crate::pattern::leaf::TaggedPattern::from_dcbor_pattern(
403 tagged_pattern,
404 ),
405 ))
406 }
407}
408
409impl Pattern {
418 pub fn leaf() -> Self {
419 Pattern::Structure(StructurePattern::Leaf(LeafStructurePattern::new()))
420 }
421
422 pub fn any_assertion() -> Self {
423 Pattern::Structure(StructurePattern::Assertions(
424 AssertionsPattern::any(),
425 ))
426 }
427
428 pub fn assertion_with_predicate(pattern: Pattern) -> Self {
429 Pattern::Structure(StructurePattern::Assertions(
430 AssertionsPattern::with_predicate(pattern),
431 ))
432 }
433
434 pub fn assertion_with_object(pattern: Pattern) -> Self {
435 Pattern::Structure(StructurePattern::Assertions(
436 AssertionsPattern::with_object(pattern),
437 ))
438 }
439}
440
441impl Pattern {
442 pub fn any_subject() -> Self {
443 Pattern::Structure(StructurePattern::Subject(SubjectPattern::any()))
444 }
445
446 pub fn subject(pattern: Pattern) -> Self {
447 Pattern::Structure(StructurePattern::Subject(SubjectPattern::pattern(
448 pattern,
449 )))
450 }
451}
452
453impl Pattern {
454 pub fn any_predicate() -> Self {
455 Pattern::Structure(StructurePattern::Predicate(PredicatePattern::any()))
456 }
457
458 pub fn predicate(pattern: Pattern) -> Self {
459 Pattern::Structure(StructurePattern::Predicate(
460 PredicatePattern::pattern(pattern),
461 ))
462 }
463
464 pub fn any_object() -> Self {
465 Pattern::Structure(StructurePattern::Object(ObjectPattern::any()))
466 }
467
468 pub fn object(pattern: Pattern) -> Self {
469 Pattern::Structure(StructurePattern::Object(ObjectPattern::pattern(
470 pattern,
471 )))
472 }
473}
474
475impl Pattern {
476 pub fn digest(digest: bc_components::Digest) -> Self {
477 Pattern::Structure(StructurePattern::Digest(DigestPattern::digest(
478 digest,
479 )))
480 }
481
482 pub fn digest_prefix(prefix: impl AsRef<[u8]>) -> Self {
483 Pattern::Structure(StructurePattern::Digest(DigestPattern::prefix(
484 prefix,
485 )))
486 }
487
488 pub fn digest_binary_regex(regex: regex::bytes::Regex) -> Self {
489 Pattern::Structure(StructurePattern::Digest(
490 DigestPattern::binary_regex(regex),
491 ))
492 }
493
494 pub fn any_node() -> Self {
495 Pattern::Structure(StructurePattern::Node(NodePattern::any()))
496 }
497
498 pub fn node_with_assertions_range(range: impl RangeBounds<usize>) -> Self {
499 Pattern::Structure(StructurePattern::Node(NodePattern::interval(range)))
500 }
501
502 pub fn node_with_assertions_count(count: usize) -> Self {
503 Pattern::Structure(StructurePattern::Node(NodePattern::interval(
504 count..=count,
505 )))
506 }
507
508 pub fn obscured() -> Self {
509 Pattern::Structure(StructurePattern::Obscured(ObscuredPattern::any()))
510 }
511
512 pub fn elided() -> Self {
513 Pattern::Structure(
514 StructurePattern::Obscured(ObscuredPattern::elided()),
515 )
516 }
517
518 pub fn encrypted() -> Self {
519 Pattern::Structure(StructurePattern::Obscured(
520 ObscuredPattern::encrypted(),
521 ))
522 }
523
524 pub fn compressed() -> Self {
525 Pattern::Structure(StructurePattern::Obscured(
526 ObscuredPattern::compressed(),
527 ))
528 }
529}
530
531impl Pattern {
540 pub fn any() -> Self {
542 Pattern::Meta(MetaPattern::Any(AnyPattern::new()))
543 }
544}
545
546impl Pattern {
547 pub fn and(patterns: Vec<Pattern>) -> Self {
550 Pattern::Meta(MetaPattern::And(AndPattern::new(patterns)))
551 }
552
553 pub fn or(patterns: Vec<Pattern>) -> Self {
556 Pattern::Meta(MetaPattern::Or(OrPattern::new(patterns)))
557 }
558}
559
560impl Pattern {
561 pub fn traverse(patterns: Vec<Pattern>) -> Self {
563 Pattern::Meta(MetaPattern::Traverse(TraversePattern::new(patterns)))
564 }
565}
566
567impl Pattern {
568 pub fn search(pattern: Pattern) -> Self {
572 Pattern::Meta(MetaPattern::Search(SearchPattern::new(pattern)))
573 }
574}
575
576impl Pattern {
577 pub fn not_matching(pattern: Pattern) -> Self {
580 Pattern::Meta(MetaPattern::Not(NotPattern::new(pattern)))
581 }
582}
583
584impl Pattern {
585 pub(crate) fn compile(
587 &self,
588 code: &mut Vec<Instr>,
589 lits: &mut Vec<Pattern>,
590 captures: &mut Vec<String>,
591 ) {
592 use Pattern::*;
593 match self {
594 Leaf(leaf_pattern) => leaf_pattern.compile(code, lits, captures),
595 Structure(struct_pattern) => {
596 struct_pattern.compile(code, lits, captures)
597 }
598 Meta(meta_pattern) => meta_pattern.compile(code, lits, captures),
599 }
600 }
601}
602
603impl Pattern {
604 pub fn repeat(
619 pattern: Pattern,
620 interval: impl RangeBounds<usize>,
621 reluctance: Reluctance,
622 ) -> Self {
623 Pattern::Meta(MetaPattern::Group(GroupPattern::repeat(
624 pattern,
625 Quantifier::new(interval, reluctance),
626 )))
627 }
628
629 pub fn group(pattern: Pattern) -> Self {
630 Pattern::Meta(MetaPattern::Group(GroupPattern::new(pattern)))
631 }
632}
633
634impl Pattern {
635 pub fn capture(name: impl AsRef<str>, pattern: Pattern) -> Self {
637 Pattern::Meta(MetaPattern::Capture(CapturePattern::new(name, pattern)))
638 }
639}
640
641impl std::fmt::Display for Pattern {
646 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
647 match self {
648 Pattern::Leaf(leaf) => write!(f, "{}", leaf),
649 Pattern::Structure(structure) => write!(f, "{}", structure),
650 Pattern::Meta(meta) => write!(f, "{}", meta),
651 }
652 }
653}
654
655impl Pattern {
656 fn vm_run(
659 &self,
660 env: &Envelope,
661 ) -> Vec<(Path, HashMap<String, Vec<Path>>)> {
662 thread_local! {
663 static PROG: RefCell<HashMap<u64, vm::Program>> = RefCell::new(HashMap::new());
664 }
665
666 use std::{
668 collections::hash_map::DefaultHasher,
669 hash::{Hash, Hasher},
670 };
671 let mut h = DefaultHasher::new();
672 self.hash(&mut h);
673 let key = h.finish();
674
675 let prog = PROG
676 .with(|cell| cell.borrow().get(&key).cloned())
677 .unwrap_or_else(|| {
678 let mut p = vm::Program {
679 code: Vec::new(),
680 literals: Vec::new(),
681 capture_names: Vec::new(),
682 };
683 self.compile(
684 &mut p.code,
685 &mut p.literals,
686 &mut p.capture_names,
687 );
688 p.code.push(Instr::Accept);
689 PROG.with(|cell| {
690 cell.borrow_mut().insert(key, p.clone());
691 });
692 p
693 });
694
695 vm::run(&prog, env)
696 }
697
698 #[allow(dead_code)]
699 fn vm_paths(&self, env: &Envelope) -> Vec<Path> {
700 self.vm_run(env).into_iter().map(|(p, _)| p).collect()
701 }
702
703 pub(crate) fn collect_capture_names(&self, out: &mut Vec<String>) {
704 if let Pattern::Meta(meta) = self {
705 meta.collect_capture_names(out)
706 }
707 }
708}
709
710impl Pattern {
711 pub fn wrapped() -> Self {
715 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::new()))
716 }
717
718 pub fn unwrap_matching(pattern: Pattern) -> Self {
721 Pattern::Structure(StructurePattern::Wrapped(
722 WrappedPattern::unwrap_matching(pattern),
723 ))
724 }
725
726 pub fn unwrap() -> Self {
729 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::unwrap()))
730 }
731}