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
extern crate byteorder;

use self::byteorder::{ByteOrder, BigEndian};

pub fn checksum(bytes: Vec<&u8>) -> [u8; 2] {
  let mut checksum: u16 = 0xFFFF;
  let generator_polynomial = 0x8408;

  for byte in bytes {
    checksum = checksum ^ (*byte as u16);

    for _ in (0..8) {
      if checksum & 1 == 1 {
        checksum = (checksum >> 1) ^ generator_polynomial
      } else {
        checksum = checksum >> 1
      }
    }
  }

  checksum = checksum ^ 0xFFFF;
  let mut buf = [0u8; 2];
  byteorder::BigEndian::write_u16(&mut buf, checksum as u16);

  return buf;
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn creates_correct_checksum() {
    let mut vec: Vec<&u8> = Vec::new();

    for byte in "FZGX".as_bytes() {
      vec.push(byte);
    }
    let checksum = checksum(vec);

    assert_eq!(checksum, [0x84, 0xC9]);
  }
}