use crate::memory::Region;
#[derive(Debug)]
pub(crate) struct VarMatches<'a> {
matches: &'a [Vec<StringMatch>],
}
impl<'a> VarMatches<'a> {
pub fn new(matches: &'a [Vec<StringMatch>]) -> Self {
Self { matches }
}
pub fn find(&self, var_index: usize) -> bool {
!self.matches[var_index].is_empty()
}
pub fn find_match_occurence(
&self,
var_index: usize,
occurence_number: usize,
) -> Option<&StringMatch> {
self.matches[var_index].get(occurence_number)
}
pub fn count_matches(&self, var_index: usize) -> u32 {
#[allow(clippy::cast_possible_truncation)]
{
self.matches[var_index].len() as u32
}
}
pub fn count_matches_in(&self, var_index: usize, from: usize, to: usize) -> u32 {
let start_idx = match self.matches[var_index]
.binary_search_by_key(&from, |mat| mat.offset.saturating_add(mat.base))
{
Ok(idx) => idx,
Err(idx) => idx,
};
let mut count = 0;
for mat in self.matches[var_index].iter().skip(start_idx) {
let mat_offset = mat.offset.saturating_add(mat.base);
if mat_offset > to {
return count;
}
count += 1;
}
count
}
pub fn find_at(&self, var_index: usize, offset: usize) -> bool {
self.matches[var_index]
.binary_search_by_key(&offset, |mat| mat.offset.saturating_add(mat.base))
.is_ok()
}
pub fn find_in(&self, var_index: usize, from: usize, to: usize) -> bool {
let start_idx = match self.matches[var_index]
.binary_search_by_key(&from, |mat| mat.offset.saturating_add(mat.base))
{
Ok(idx) => idx,
Err(idx) => idx,
};
self.matches[var_index].get(start_idx).is_some_and(|mat| {
let mat_offset = mat.offset.saturating_add(mat.base);
mat_offset <= to
})
}
}
#[derive(Clone, Debug)]
pub struct StringMatch {
pub base: usize,
pub offset: usize,
pub length: usize,
pub data: Box<[u8]>,
pub xor_key: u8,
}
impl StringMatch {
pub(crate) fn new(
region: &Region,
mat: std::ops::Range<usize>,
match_max_length: usize,
xor_key: u8,
) -> Self {
let length = mat.end - mat.start;
let capped_length = std::cmp::min(length, match_max_length);
Self {
base: region.start,
data: region.mem[mat.start..]
.iter()
.take(capped_length)
.copied()
.collect(),
offset: mat.start,
length,
xor_key,
}
}
}
#[cfg(test)]
mod tests {
use crate::test_helpers::{test_type_traits, test_type_traits_non_clonable};
use super::*;
#[test]
fn test_types_traits() {
test_type_traits_non_clonable(VarMatches { matches: &[] });
test_type_traits(StringMatch {
base: 0,
offset: 0,
length: 0,
data: Box::new([]),
xor_key: 0,
});
}
}