bc_envelope_pattern/pattern/
pattern_impl.rs1use std::{
55 cell::RefCell,
56 collections::HashMap,
57 ops::{RangeBounds, RangeInclusive},
58};
59
60use bc_envelope::Envelope;
61use dcbor::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 TaggedPattern, TextPattern,
70 },
71 meta::{
72 AndPattern, CapturePattern, GroupPattern, MetaPattern, NotPattern,
73 OrPattern, SearchPattern, SequencePattern,
74 },
75 structure::{
76 AssertionsPattern, DigestPattern, NodePattern, ObjectPattern,
77 ObscuredPattern, PredicatePattern, StructurePattern, SubjectPattern,
78 WrappedPattern,
79 },
80 vm,
81};
82use crate::{
83 Quantifier, Reluctance,
84 pattern::{
85 leaf::CBORPattern,
86 meta::{AnyPattern, NonePattern},
87 vm::Instr,
88 },
89};
90
91#[derive(Debug, Clone, Hash, PartialEq, Eq)]
93pub enum Pattern {
94 Leaf(LeafPattern),
96
97 Structure(StructurePattern),
99
100 Meta(MetaPattern),
102}
103
104impl Matcher for Pattern {
105 fn paths(&self, env: &Envelope) -> Vec<Path> {
106 self.paths_with_captures(env).0
107 }
108
109 fn paths_with_captures(
110 &self,
111 env: &Envelope,
112 ) -> (Vec<Path>, HashMap<String, Vec<Path>>) {
113 let results = self.vm_run(env);
114 let mut paths = Vec::new();
115 let mut captures: HashMap<String, Vec<Path>> = HashMap::new();
116 for (p, caps) in results {
117 paths.push(p);
118 for (name, mut vals) in caps {
119 captures.entry(name).or_default().append(&mut vals);
120 }
121 }
122 (paths, captures)
123 }
124
125 fn is_complex(&self) -> bool {
126 match self {
127 Pattern::Leaf(leaf) => leaf.is_complex(),
128 Pattern::Structure(structure) => structure.is_complex(),
129 Pattern::Meta(meta) => meta.is_complex(),
130 }
131 }
132}
133
134impl Pattern {
139 pub fn any_leaf() -> Self { Pattern::Leaf(LeafPattern::Any) }
141}
142
143impl Pattern {
144 pub fn any_cbor() -> Self {
146 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::any()))
147 }
148
149 pub fn cbor(cbor: impl CBOREncodable) -> Self {
151 Pattern::Leaf(LeafPattern::Cbor(CBORPattern::value(cbor)))
152 }
153}
154
155impl Pattern {
156 pub fn any_bool() -> Self {
158 Pattern::Leaf(LeafPattern::Bool(BoolPattern::any()))
159 }
160
161 pub fn bool(b: bool) -> Self {
163 Pattern::Leaf(LeafPattern::Bool(BoolPattern::value(b)))
164 }
165}
166
167impl Pattern {
168 pub fn any_text() -> Self {
170 Pattern::Leaf(LeafPattern::Text(TextPattern::any()))
171 }
172
173 pub fn text<T: Into<String>>(value: T) -> Self {
175 Pattern::Leaf(LeafPattern::Text(TextPattern::value(value)))
176 }
177
178 pub fn text_regex(regex: regex::Regex) -> Self {
181 Pattern::Leaf(LeafPattern::Text(TextPattern::regex(regex)))
182 }
183}
184
185impl Pattern {
186 pub fn any_date() -> Self {
188 Pattern::Leaf(LeafPattern::Date(DatePattern::any()))
189 }
190
191 pub fn date(date: dcbor::Date) -> Self {
193 Pattern::Leaf(LeafPattern::Date(DatePattern::value(date)))
194 }
195
196 pub fn date_range(range: RangeInclusive<dcbor::Date>) -> Self {
199 Pattern::Leaf(LeafPattern::Date(DatePattern::range(range)))
200 }
201
202 pub fn date_earliest(date: dcbor::Date) -> Self {
205 Pattern::Leaf(LeafPattern::Date(DatePattern::earliest(date)))
206 }
207
208 pub fn date_latest(date: dcbor::Date) -> Self {
211 Pattern::Leaf(LeafPattern::Date(DatePattern::latest(date)))
212 }
213
214 pub fn date_iso8601(iso_string: impl Into<String>) -> Self {
217 Pattern::Leaf(LeafPattern::Date(DatePattern::iso8601(iso_string)))
218 }
219
220 pub fn date_regex(regex: regex::Regex) -> Self {
223 Pattern::Leaf(LeafPattern::Date(DatePattern::regex(regex)))
224 }
225}
226
227impl Pattern {
228 pub fn any_number() -> Self {
230 Pattern::Leaf(LeafPattern::Number(NumberPattern::any()))
231 }
232
233 pub fn number<T: Into<f64>>(value: T) -> Self {
235 Pattern::Leaf(LeafPattern::Number(NumberPattern::exact(value)))
236 }
237
238 pub fn number_range<A: Into<f64> + Copy>(range: RangeInclusive<A>) -> Self {
241 Pattern::Leaf(LeafPattern::Number(NumberPattern::range(range)))
242 }
243
244 pub fn number_greater_than<T: Into<f64>>(value: T) -> Self {
247 Pattern::Leaf(LeafPattern::Number(NumberPattern::greater_than(value)))
248 }
249
250 pub fn number_greater_than_or_equal<T: Into<f64>>(value: T) -> Self {
253 Pattern::Leaf(LeafPattern::Number(
254 NumberPattern::greater_than_or_equal(value),
255 ))
256 }
257
258 pub fn number_less_than<T: Into<f64>>(value: T) -> Self {
261 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than(value)))
262 }
263
264 pub fn number_less_than_or_equal<T: Into<f64>>(value: T) -> Self {
267 Pattern::Leaf(LeafPattern::Number(NumberPattern::less_than_or_equal(
268 value,
269 )))
270 }
271
272 pub fn number_nan() -> Self {
275 Pattern::Leaf(LeafPattern::Number(NumberPattern::nan()))
276 }
277}
278
279impl Pattern {
280 pub fn any_byte_string() -> Self {
282 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::any()))
283 }
284
285 pub fn byte_string(value: impl AsRef<[u8]>) -> Self {
287 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::value(value)))
288 }
289
290 pub fn byte_string_binary_regex(regex: regex::bytes::Regex) -> Self {
293 Pattern::Leaf(LeafPattern::ByteString(ByteStringPattern::regex(regex)))
294 }
295}
296
297impl Pattern {
298 pub fn any_known_value() -> Self {
299 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::any()))
300 }
301
302 pub fn known_value(value: KnownValue) -> Self {
303 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::value(value)))
304 }
305
306 pub fn known_value_named<T: Into<String>>(name: T) -> Self {
307 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::named(name)))
308 }
309
310 pub fn known_value_regex(regex: regex::Regex) -> Self {
311 Pattern::Leaf(LeafPattern::KnownValue(KnownValuePattern::regex(regex)))
312 }
313
314 pub fn unit() -> Self { Self::known_value(known_values::UNIT) }
315}
316
317impl Pattern {
318 pub fn any_array() -> Self {
319 Pattern::Leaf(LeafPattern::Array(ArrayPattern::any()))
320 }
321
322 pub fn array_with_range(interval: impl RangeBounds<usize>) -> Self {
323 Pattern::Leaf(LeafPattern::Array(ArrayPattern::interval(interval)))
324 }
325
326 pub fn array_with_count(count: usize) -> Self {
327 Pattern::Leaf(LeafPattern::Array(ArrayPattern::interval(count..=count)))
328 }
329}
330
331impl Pattern {
332 pub fn any_map() -> Self {
333 Pattern::Leaf(LeafPattern::Map(MapPattern::any()))
334 }
335
336 pub fn map_with_range(interval: impl RangeBounds<usize>) -> Self {
337 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(interval)))
338 }
339
340 pub fn map_with_count(count: usize) -> Self {
341 Pattern::Leaf(LeafPattern::Map(MapPattern::interval(count..=count)))
342 }
343}
344
345impl Pattern {
346 pub fn null() -> Self {
347 Pattern::Leaf(LeafPattern::Null(NullPattern::new()))
348 }
349}
350
351impl Pattern {
352 pub fn any_tag() -> Self {
353 Pattern::Leaf(LeafPattern::Tag(TaggedPattern::any()))
354 }
355
356 pub fn tagged(tag: dcbor::Tag) -> Self {
357 Pattern::Leaf(LeafPattern::Tag(TaggedPattern::value(tag)))
358 }
359
360 pub fn tagged_with_value(value: u64) -> Self {
361 Pattern::Leaf(LeafPattern::Tag(TaggedPattern::value(value)))
362 }
363
364 pub fn tagged_with_name(name: impl Into<String>) -> Self {
365 Pattern::Leaf(LeafPattern::Tag(TaggedPattern::named(name)))
366 }
367
368 pub fn tagged_with_regex(regex: regex::Regex) -> Self {
369 Pattern::Leaf(LeafPattern::Tag(TaggedPattern::regex(regex)))
370 }
371}
372
373impl Pattern {
382 pub fn any_assertion() -> Self {
383 Pattern::Structure(StructurePattern::Assertions(
384 AssertionsPattern::any(),
385 ))
386 }
387
388 pub fn assertion_with_predicate(pattern: Pattern) -> Self {
389 Pattern::Structure(StructurePattern::Assertions(
390 AssertionsPattern::with_predicate(pattern),
391 ))
392 }
393
394 pub fn assertion_with_object(pattern: Pattern) -> Self {
395 Pattern::Structure(StructurePattern::Assertions(
396 AssertionsPattern::with_object(pattern),
397 ))
398 }
399}
400
401impl Pattern {
402 pub fn any_subject() -> Self {
403 Pattern::Structure(StructurePattern::Subject(SubjectPattern::any()))
404 }
405
406 pub fn subject(pattern: Pattern) -> Self {
407 Pattern::Structure(StructurePattern::Subject(SubjectPattern::pattern(
408 pattern,
409 )))
410 }
411}
412
413impl Pattern {
414 pub fn any_predicate() -> Self {
415 Pattern::Structure(StructurePattern::Predicate(PredicatePattern::any()))
416 }
417
418 pub fn predicate(pattern: Pattern) -> Self {
419 Pattern::Structure(StructurePattern::Predicate(
420 PredicatePattern::pattern(pattern),
421 ))
422 }
423
424 pub fn any_object() -> Self {
425 Pattern::Structure(StructurePattern::Object(ObjectPattern::any()))
426 }
427
428 pub fn object(pattern: Pattern) -> Self {
429 Pattern::Structure(StructurePattern::Object(ObjectPattern::pattern(
430 pattern,
431 )))
432 }
433}
434
435impl Pattern {
436 pub fn digest(digest: bc_components::Digest) -> Self {
437 Pattern::Structure(StructurePattern::Digest(DigestPattern::digest(
438 digest,
439 )))
440 }
441
442 pub fn digest_prefix(prefix: impl AsRef<[u8]>) -> Self {
443 Pattern::Structure(StructurePattern::Digest(DigestPattern::prefix(
444 prefix,
445 )))
446 }
447
448 pub fn digest_binary_regex(regex: regex::bytes::Regex) -> Self {
449 Pattern::Structure(StructurePattern::Digest(
450 DigestPattern::binary_regex(regex),
451 ))
452 }
453
454 pub fn any_node() -> Self {
455 Pattern::Structure(StructurePattern::Node(NodePattern::any()))
456 }
457
458 pub fn node_with_assertions_range(range: impl RangeBounds<usize>) -> Self {
459 Pattern::Structure(StructurePattern::Node(NodePattern::interval(range)))
460 }
461
462 pub fn node_with_assertions_count(count: usize) -> Self {
463 Pattern::Structure(StructurePattern::Node(NodePattern::interval(
464 count..=count,
465 )))
466 }
467
468 pub fn obscured() -> Self {
469 Pattern::Structure(StructurePattern::Obscured(ObscuredPattern::any()))
470 }
471
472 pub fn elided() -> Self {
473 Pattern::Structure(
474 StructurePattern::Obscured(ObscuredPattern::elided()),
475 )
476 }
477
478 pub fn encrypted() -> Self {
479 Pattern::Structure(StructurePattern::Obscured(
480 ObscuredPattern::encrypted(),
481 ))
482 }
483
484 pub fn compressed() -> Self {
485 Pattern::Structure(StructurePattern::Obscured(
486 ObscuredPattern::compressed(),
487 ))
488 }
489}
490
491impl Pattern {
500 pub fn any() -> Self { Pattern::Meta(MetaPattern::Any(AnyPattern::new())) }
502
503 pub fn none() -> Self {
505 Pattern::Meta(MetaPattern::None(NonePattern::new()))
506 }
507}
508
509impl Pattern {
510 pub fn and(patterns: Vec<Pattern>) -> Self {
513 Pattern::Meta(MetaPattern::And(AndPattern::new(patterns)))
514 }
515
516 pub fn or(patterns: Vec<Pattern>) -> Self {
519 Pattern::Meta(MetaPattern::Or(OrPattern::new(patterns)))
520 }
521}
522
523impl Pattern {
524 pub fn sequence(patterns: Vec<Pattern>) -> Self {
526 Pattern::Meta(MetaPattern::Sequence(SequencePattern::new(patterns)))
527 }
528}
529
530impl Pattern {
531 pub fn search(pattern: Pattern) -> Self {
535 Pattern::Meta(MetaPattern::Search(SearchPattern::new(pattern)))
536 }
537}
538
539impl Pattern {
540 pub fn not_matching(pattern: Pattern) -> Self {
543 Pattern::Meta(MetaPattern::Not(NotPattern::new(pattern)))
544 }
545}
546
547impl Pattern {
548 pub(crate) fn compile(
550 &self,
551 code: &mut Vec<Instr>,
552 lits: &mut Vec<Pattern>,
553 captures: &mut Vec<String>,
554 ) {
555 use Pattern::*;
556 match self {
557 Leaf(leaf_pattern) => leaf_pattern.compile(code, lits, captures),
558 Structure(struct_pattern) => {
559 struct_pattern.compile(code, lits, captures)
560 }
561 Meta(meta_pattern) => meta_pattern.compile(code, lits, captures),
562 }
563 }
564}
565
566impl Pattern {
567 pub fn repeat(
582 pattern: Pattern,
583 interval: impl RangeBounds<usize>,
584 reluctance: Reluctance,
585 ) -> Self {
586 Pattern::Meta(MetaPattern::Group(GroupPattern::repeat(
587 pattern,
588 Quantifier::new(interval, reluctance),
589 )))
590 }
591
592 pub fn group(pattern: Pattern) -> Self {
593 Pattern::Meta(MetaPattern::Group(GroupPattern::new(pattern)))
594 }
595}
596
597impl Pattern {
598 pub fn capture(name: impl AsRef<str>, pattern: Pattern) -> Self {
600 Pattern::Meta(MetaPattern::Capture(CapturePattern::new(name, pattern)))
601 }
602}
603
604impl std::fmt::Display for Pattern {
609 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610 match self {
611 Pattern::Leaf(leaf) => write!(f, "{}", leaf),
612 Pattern::Structure(structure) => write!(f, "{}", structure),
613 Pattern::Meta(meta) => write!(f, "{}", meta),
614 }
615 }
616}
617
618impl Pattern {
619 fn vm_run(
622 &self,
623 env: &Envelope,
624 ) -> Vec<(Path, HashMap<String, Vec<Path>>)> {
625 thread_local! {
626 static PROG: RefCell<HashMap<u64, vm::Program>> = RefCell::new(HashMap::new());
627 }
628
629 use std::{
631 collections::hash_map::DefaultHasher,
632 hash::{Hash, Hasher},
633 };
634 let mut h = DefaultHasher::new();
635 self.hash(&mut h);
636 let key = h.finish();
637
638 let prog = PROG
639 .with(|cell| cell.borrow().get(&key).cloned())
640 .unwrap_or_else(|| {
641 let mut p = vm::Program {
642 code: Vec::new(),
643 literals: Vec::new(),
644 capture_names: Vec::new(),
645 };
646 self.compile(
647 &mut p.code,
648 &mut p.literals,
649 &mut p.capture_names,
650 );
651 p.code.push(Instr::Accept);
652 PROG.with(|cell| {
653 cell.borrow_mut().insert(key, p.clone());
654 });
655 p
656 });
657
658 vm::run(&prog, env)
659 }
660
661 #[allow(dead_code)]
662 fn vm_paths(&self, env: &Envelope) -> Vec<Path> {
663 self.vm_run(env).into_iter().map(|(p, _)| p).collect()
664 }
665
666 pub(crate) fn collect_capture_names(&self, out: &mut Vec<String>) {
667 if let Pattern::Meta(meta) = self {
668 meta.collect_capture_names(out)
669 }
670 }
671}
672
673impl Pattern {
674 pub fn wrapped() -> Self {
678 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::new()))
679 }
680
681 pub fn unwrap_matching(pattern: Pattern) -> Self {
684 Pattern::Structure(StructurePattern::Wrapped(
685 WrappedPattern::unwrap_matching(pattern),
686 ))
687 }
688
689 pub fn unwrap() -> Self {
692 Pattern::Structure(StructurePattern::Wrapped(WrappedPattern::unwrap()))
693 }
694}