ocr_b_checksum/
lib.rs

1pub fn ocr_b_checksum(ocr: &str) -> u32 {
2    let mut weight = 2;
3    let mut sum = 0;
4
5    for ch in ocr.chars().rev() {
6        if let Some(digit) = ch.to_digit(10) {
7            let product = digit * weight;
8
9            if product >= 10 {
10                sum += product / 10 + product % 10;
11            } else {
12                sum += product;
13            }
14
15            // Toggle the weight between 1 and 2.
16            weight = 3 - weight;
17        } else {
18            panic!("must be digits")
19        }
20    }
21
22    let checksum = (10 - (sum % 10)) % 10;
23
24    checksum
25}
26
27// https://www.bankgirot.se/tjanster/inbetalningar/bankgiro-inbetalningar/ocr-referenskontroll/
28// create with length digit and a final checksum
29pub fn ocr_b_string(invoice_id: &str) -> String {
30    let total_len = invoice_id.len() + 1 + 1;
31    let length_mod = total_len % 10;
32    let ocr_without_checksum_digit = invoice_id.to_string() + &length_mod.to_string();
33    let checksum_digit = ocr_b_checksum(ocr_without_checksum_digit.as_str());
34    ocr_without_checksum_digit + &checksum_digit.to_string()
35}
36
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn it_works() {
44        let result = ocr_b_checksum("32619000006095");
45        assert_eq!(result, 0);
46
47        let result2 = ocr_b_checksum("32619000005815");
48        assert_eq!(result2, 2);
49    }
50
51    #[test]
52    fn it_works_with_string() {
53        let result = ocr_b_string("52456");
54        assert_eq!(result, "5245675");
55    }
56}