use petgraph::prelude::*;
use std::cmp::min;
use std::iter::zip;
fn from_u8_singlerule(bytes: &[u8], rule: &super::MagicRule) -> bool {
let bound_min = rule.start_off as usize;
if bound_min > bytes.len() {
return false;
}
let bound_max = rule.start_off as usize + rule.val.len() + rule.region_len as usize;
let bound_max = min(bound_max, bytes.len());
let testarea = &bytes[bound_min..bound_max];
testarea.windows(rule.val.len()).any(|window| {
match rule.mask {
None => rule.val == window,
Some(mask) => {
assert_eq!(window.len(), mask.len());
let masked = zip(window, mask).map(|(a, b)| a & b);
rule.val.iter().copied().eq(masked)
}
}
})
}
pub fn from_u8_walker(
bytes: &[u8],
graph: &DiGraph<super::MagicRule, u32>,
node: NodeIndex,
isroot: bool,
) -> bool {
let n = graph.neighbors_directed(node, Outgoing);
if isroot {
let rule = &graph[node];
if !from_u8_singlerule(bytes, rule) {
return false;
}
if n.clone().count() == 0 {
return true;
}
}
for y in n {
let rule = &graph[y];
if from_u8_singlerule(bytes, rule) {
if graph.neighbors_directed(y, Outgoing).count() != 0 {
return from_u8_walker(bytes, graph, y, false);
} else {
return true;
}
}
}
false
}