bmatcher_core/
pattern.rs

1use alloc::vec::Vec;
2use core::fmt::Debug;
3
4use crate::Atom;
5
6/// A binary pattern is a structure used in matching processes and consists of two main components:
7///
8/// 1. Atoms  
9///    A list of instructions or actions that define how the matcher should process the data at the current cursor.
10///    
11/// 2. Byte Sequence  
12///    A sequence of bytes that the atoms can reference to match against actual input data.
13pub trait BinaryPattern: Send + Sync + Debug {
14    /// Retrieves the list of atoms within this binary pattern.
15    ///
16    /// The atoms define the actions or matching logic for the pattern.
17    fn atoms(&self) -> &[Atom];
18
19    /// Retrieves the byte sequence referenced by the atoms.
20    ///
21    /// This sequence represents the actual data to be matched against.
22    fn byte_sequence(&self) -> &[u8];
23
24    /// Returns an upper bound for the length of the save stack.
25    ///
26    /// # Note
27    /// This is only an upper bound. The actual length used might be smaller.
28    fn save_len(&self) -> usize {
29        self.atoms()
30            .iter()
31            .filter(|atom| {
32                matches!(
33                    atom,
34                    Atom::Read(_) | Atom::SaveCursor | Atom::SaveConstant(_)
35                )
36            })
37            .count()
38    }
39
40    /// Returns an upper bound for the length of the cursor stack.
41    ///
42    /// # Note
43    /// This is only an upper bound. The actual length used might be smaller.
44    fn cursor_len(&self) -> usize {
45        self.atoms()
46            .iter()
47            .filter(|atom| matches!(atom, Atom::CursorPush))
48            .count()
49    }
50}
51
52/// An implementation of the [BinaryPattern] interface that borrows the [Atom]s and byte sequence array.
53///
54/// This struct is primarily used alongside the [bmatcher_proc::pattern] macro to generate patterns at runtime.
55#[derive(Debug, Clone, Copy)]
56pub struct BorrowedBinaryPattern<'a> {
57    atoms: &'a [Atom],
58    byte_sequence: &'a [u8],
59}
60
61impl<'a> BorrowedBinaryPattern<'a> {
62    pub const fn new(atoms: &'a [Atom], byte_sequence: &'a [u8]) -> Self {
63        Self {
64            atoms,
65            byte_sequence,
66        }
67    }
68}
69
70impl BinaryPattern for BorrowedBinaryPattern<'_> {
71    fn atoms(&self) -> &[Atom] {
72        self.atoms
73    }
74
75    fn byte_sequence(&self) -> &[u8] {
76        self.byte_sequence
77    }
78}
79
80/// An implementation of the [BinaryPattern] interface that allocates a `Vec` for the [Atom]s and the byte sequence.
81///
82/// This struct is primarily used with [crate::compiler::parse_pattern] to parse binary patterns at runtime.
83#[derive(Debug, Default)]
84pub struct OwnedBinaryPattern {
85    atoms: Vec<Atom>,
86    byte_sequence: Vec<u8>,
87}
88
89impl OwnedBinaryPattern {
90    pub fn new(atoms: Vec<Atom>, byte_sequence: Vec<u8>) -> Self {
91        Self {
92            byte_sequence,
93            atoms,
94        }
95    }
96}
97
98impl BinaryPattern for OwnedBinaryPattern {
99    fn byte_sequence(&self) -> &[u8] {
100        &self.byte_sequence
101    }
102
103    fn atoms(&self) -> &[Atom] {
104        &self.atoms
105    }
106}