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 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
27pub 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}