aboutsummaryrefslogtreecommitdiffstats
path: root/src/crc16.zig
blob: 3ea5a1562848c626695ea671d12aa689775ea1cb (plain) (blame)
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
pub const InvalidChecksumError = error{InvalidChecksum};

const crc16tab: [256]u16 = tab: {
    @setEvalBranchQuota(5000);

    // CRC-16-CCITT/XMODEM
    const poly: u32 = 0x1021;
    var table: [256]u16 = undefined;

    for (table) |*crc, i| {
        crc.* = @as(u16, i) << 8;
        var j = 0;
        while (j < 8) : (j += 1) {
            if (crc.* >> 15 != 0) {
                crc.* = (crc.* << 1) ^ poly;
            } else {
                crc.* <<= 1;
            }
        }
    }

    break :tab table;
};

pub fn update(crc: u16, with_data: []const u8) u16 {
    var new_crc = crc;
    for (with_data) |b| {
        new_crc = (new_crc << 8) ^ crc16tab[@truncate(u8, new_crc >> 8) ^ b];
    }
    return new_crc;
}

// make returns the CRC-16 checksum for the data provided.
pub fn make(data: []const u8) u16 {
    return update(0, data);
}

// validate will check the calculated CRC-16 checksum for data against the expected.
pub fn validate(data: []const u8, expected: u16) InvalidChecksumError!void {
    if (make(data) != expected) return error.InvalidChecksum;
}