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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use ansi_term::Color::RGB;

pub fn hexyfile<T: std::io::Read>(mut input: T) -> usize {
    let mut len: usize = 0;
    loop {
        // Read in up to 512 bytes at a time
        let mut a: [u8; 512] = [0; 512];
        let chunk = input.read(&mut a).unwrap();

        // If read was empty we're done
        if chunk == 0 {
            break;
        }

        // Print this chunk hexily
        hexydump(&a, &len, &chunk);
        len += chunk;
    }
    println!();

    // Return total length
    len
}

pub fn hexy_c(a: u8) {
    let c = if a.is_ascii_graphic() { a as char } else { '.' };

    print!(
        "{}",
        RGB(
            ((a << 1) & 0xf0) | 0x0f,
            ((a << 3) & 0xf0) | 0x0f,
            ((a << 5) & 0xf0) | 0x0f
        )
        .paint(format!("{}", c))
    );
}

pub fn hexy_x(a: u8) {
    print!(
        "{}",
        RGB(
            ((a << 1) & 0xf0) | 0x0f,
            ((a << 3) & 0xf0) | 0x0f,
            ((a << 5) & 0xf0) | 0x0f
        )
        .paint(format!("{:02x}", a))
    );
}

pub fn hexydump(a: &[u8], length: &usize, piece: &usize) {
    let mut len = *length;
    let chunk = *piece;
    // Iterate through all of the bytes of the file
    for (n, i) in a.iter().enumerate() {
        if n == chunk {
            break;
        }
        // Every 16 bytes, print summary ascii bytes
        if (n % 16) == 0 {
            // Make sure this is after the first 16 bytes
            if n > 0 {
                // Print ascii bytes in hexdump -C -like style
                hexy_c(b'|');
                for item in a.iter().take(n).skip(n - 16) {
                    // Print colorful ascii
                    hexy_c(*item);
                }
                hexy_c(b'|');
            }
            println!();

            // Print hex address for line
            print!("{:08x} ", len);
            len += 16;
        }

        // Add extra space between 8th and 9th hex values
        if (n % 8) == 0 {
            print!(" ");
        }

        // Print hex byte
        hexy_x(*i);
        print!(" ");
    }

    let mut n = 0;
    // This is the cleanup for the last line of the hexdump
    if (chunk % 16) != 0 {
        // Figure out how many bytes are at the end
        n = chunk % 16;

        // Add spaces to move cursor
        for _ in 0..(16 - n) * 3 {
            print!(" ");
        }

        // Add extra space if fewer than 8 chars
        if n <= 8 {
            print!(" ");
        }
    }

    if n == 0 {
        n = 16;
    }
    hexy_c(b'|');
    for i in 0..n {
        if a[chunk - n + i].is_ascii_graphic() {
            hexy_c(a[chunk - n + i]);
        } else {
            hexy_c(b'.');
        }
    }
    hexy_c(b'|');
}