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