Skip to main content

stackforge_core/utils/
compare.rs

1//! Binary comparison and diff utilities.
2
3use std::fmt::Write;
4
5/// Compare two byte slices and return the first differing index.
6#[must_use]
7pub fn find_diff(a: &[u8], b: &[u8]) -> Option<usize> {
8    let min_len = a.len().min(b.len());
9
10    for i in 0..min_len {
11        if a[i] != b[i] {
12            return Some(i);
13        }
14    }
15
16    if a.len() == b.len() {
17        None
18    } else {
19        Some(min_len)
20    }
21}
22
23/// Generate a diff between two byte slices.
24#[must_use]
25pub fn byte_diff(a: &[u8], b: &[u8]) -> String {
26    let mut output = String::new();
27    let max_len = a.len().max(b.len());
28
29    writeln!(output, "Comparing {} bytes vs {} bytes", a.len(), b.len()).unwrap();
30
31    for i in 0..max_len {
32        let byte_a = a.get(i).copied();
33        let byte_b = b.get(i).copied();
34
35        if byte_a != byte_b {
36            let a_str = byte_a.map_or_else(|| "--".to_string(), |b| format!("{b:02x}"));
37            let b_str = byte_b.map_or_else(|| "--".to_string(), |b| format!("{b:02x}"));
38            writeln!(output, "  offset {i:04x}: {a_str} != {b_str}").unwrap();
39        }
40    }
41
42    output
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48
49    #[test]
50    fn test_find_diff() {
51        let a = [1, 2, 3, 4, 5];
52        let b = [1, 2, 9, 4, 5];
53        assert_eq!(find_diff(&a, &b), Some(2));
54
55        let c = [1, 2, 3, 4, 5];
56        assert_eq!(find_diff(&a, &c), None);
57
58        let d = [1, 2, 3];
59        assert_eq!(find_diff(&a, &d), Some(3));
60    }
61}