pub(in crate::inspect::smp) fn find_u16_le_offsets(bytes: &[u8], needle: u16) -> Vec<usize> {
    let pattern = needle.to_le_bytes();
    bytes
        .windows(pattern.len())
        .enumerate()
        .filter_map(|(offset, window)| (window == pattern).then_some(offset))
        .collect()
}

pub(in crate::inspect::smp) fn find_u32_le_offsets(bytes: &[u8], needle: u32) -> Vec<usize> {
    let pattern = needle.to_le_bytes();
    bytes
        .windows(pattern.len())
        .enumerate()
        .filter_map(|(offset, window)| (window == pattern).then_some(offset))
        .collect()
}

pub(in crate::inspect::smp) fn find_next_nonzero_offset(
    bytes: &[u8],
    start: usize,
) -> Option<usize> {
    bytes
        .iter()
        .enumerate()
        .skip(start)
        .find_map(|(offset, byte)| (*byte != 0).then_some(offset))
}

pub(in crate::inspect::smp) fn find_zero_run(
    bytes: &[u8],
    start: usize,
    min_len: usize,
) -> Option<usize> {
    let mut run_start = None;
    let mut run_len = 0usize;

    for (offset, byte) in bytes.iter().enumerate().skip(start) {
        if *byte == 0 {
            run_start.get_or_insert(offset);
            run_len += 1;
            if run_len >= min_len {
                return run_start;
            }
        } else {
            run_start = None;
            run_len = 0;
        }
    }

    None
}
