xpat
This commit is contained in:
83
sub/xpat/src/atoms.rs
Normal file
83
sub/xpat/src/atoms.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
pub type Pattern<'l> = &'l[Atom];
|
||||
|
||||
/// Pattern atoms.
|
||||
///
|
||||
/// The scanner will silently ignore nonsensical arguments.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Atom {
|
||||
/// Matches a single byte.
|
||||
Byte(u8),
|
||||
/// Captures the cursor in the save array at the specified index.
|
||||
Save(u8),
|
||||
/// After a Pop later continue matching at the current cursor plus the argument.
|
||||
Push(u8),
|
||||
/// Pops the cursor from the stack and continues matching.
|
||||
Pop,
|
||||
/// Sets a mask to apply on next byte match.
|
||||
Fuzzy(u8),
|
||||
/// Skips a fixed number of bytes.
|
||||
Skip(u8),
|
||||
/// Rewinds the cursor a fixed number of bytes.
|
||||
Back(u8),
|
||||
/// Extends the push, skip, back and many range by `argument * 256`.
|
||||
Rangext(u8),
|
||||
/// Looks for the next pattern at most a certain number of bytes ahead.
|
||||
Many(u8),
|
||||
/// Follows a signed 1 byte jump.
|
||||
///
|
||||
/// Reads the byte under the cursor, sign extends it, adds it plus 1 to the cursor and continues matching.
|
||||
Jump1,
|
||||
/// Follows a signed 4 byte jump.
|
||||
///
|
||||
/// Reads the dword under the cursor and adds it plus 4 to the cursor and continues matching.
|
||||
Jump4,
|
||||
/// Follows an absolute pointer.
|
||||
///
|
||||
/// Reads the pointer under the cursor, translates it to an RVA, assigns it to the cursor and continues matching.
|
||||
///
|
||||
/// Matching fails immediately when translation to an RVA fails.
|
||||
Ptr,
|
||||
/// Follows a position independent reference.
|
||||
///
|
||||
/// Reads the dword under the cursor and adds it to the saved cursor for the given slot and continues matching.
|
||||
Pir(u8),
|
||||
/// Compares the cursor with the value in the given save slot and fails if they're not equal.
|
||||
Check(u8),
|
||||
/// Checks if the cursor is aligned to `(1 << value)`.
|
||||
Aligned(u8),
|
||||
/// Reads and sign-extends the byte under the cursor, writes to the given slot and advances the cursor by 1.
|
||||
ReadI8(u8),
|
||||
/// Reads and zero-extends the byte under the cursor, writes to the given slot and advances the cursor by 1.
|
||||
ReadU8(u8),
|
||||
/// Reads and sign-extends the word under the cursor, writes to the given slot and advances the cursor by 2.
|
||||
ReadI16(u8),
|
||||
/// Reads and zero-extends the word under the cursor, writes to the given slot and advances the cursor by 2.
|
||||
ReadU16(u8),
|
||||
/// Reads the dword under the cursor, writes to the given slot and advances the cursor by 4.
|
||||
ReadI32(u8),
|
||||
/// Reads the dword under the cursor, writes to the given slot and advances the cursor by 4.
|
||||
ReadU32(u8),
|
||||
/// Writes zero to the given save slot.
|
||||
Zero(u8),
|
||||
/// Sets a retry point when matching fails.
|
||||
///
|
||||
/// When matching fails the cursor is restored and matching begins again skipping _N_ atoms.
|
||||
Case(u8),
|
||||
/// Continues matching after a case atom, skipping the next _N_ atoms.
|
||||
Break(u8),
|
||||
/// Null instruction, used to make the parser easier to write.
|
||||
Nop,
|
||||
}
|
||||
|
||||
impl Atom {
|
||||
pub fn save_len(pat: &[Atom]) -> usize {
|
||||
pat.iter().filter_map(|&atom| {
|
||||
match atom {
|
||||
Atom::Save(slot) | Atom::Pir(slot) | Atom::Check(slot) | Atom::Zero(slot) |
|
||||
Atom::ReadI8(slot) | Atom::ReadI16(slot) | Atom::ReadI32(slot) |
|
||||
Atom::ReadU8(slot) | Atom::ReadU16(slot)| Atom::ReadU32(slot) => Some(slot as usize + 1),
|
||||
_ => None,
|
||||
}
|
||||
}).max().unwrap_or(0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user