bmatcher_core/
target.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
/// A trait for targets that can be matched against a binary pattern.
///
/// Implementing this trait allows matching against data sources that may not be
/// continuous (e.g., fragmented data or packed representations), offering greater flexibility
/// compared to directly using a `u8` slice.
///
/// By default a `u8` slice does implement this trait.
pub trait MatchTarget {
    /// Returns the total length of the data which will be scaned when matching a binary pattern.
    fn match_length(&self) -> usize;

    /// Retrieves a subrange of the data, starting at the specified offset and spanning the given number of bytes.
    ///
    /// # Parameters
    /// - `offset`: The starting position within the data.
    /// - `byte_count`: The number of bytes to include in the subrange.
    ///
    /// # Returns
    /// An `Option` containing a slice of the data if the range is valid; otherwise, `None`.
    fn subrange(&self, offset: usize, byte_count: usize) -> Option<&[u8]>;

    /// Translates an absolute address to an index within the matchable data.
    ///
    /// # Parameters
    /// - `address`: The absolute address to translate.
    ///
    /// # Returns
    /// An `Option` containing the translated index if the address is valid; otherwise, `None`.
    fn translate_absolute_address(&self, address: u64) -> Option<usize>;
}

impl MatchTarget for &[u8] {
    fn match_length(&self) -> usize {
        self.len()
    }

    fn subrange(&self, offset: usize, byte_count: usize) -> Option<&[u8]> {
        if offset + byte_count > self.len() {
            return None;
        }

        Some(&self[offset..offset + byte_count])
    }

    fn translate_absolute_address(&self, address: u64) -> Option<usize> {
        let own_address = self.as_ptr() as u64;
        if own_address < address || address >= own_address + self.len() as u64 {
            None
        } else {
            Some((address - own_address) as usize)
        }
    }
}