Skip to main content

faker_rust/default/
barcode.rs

1//! Barcode generator - generates random barcode-related data
2
3use crate::base::{bothify, sample};
4use crate::locale::fetch_locale;
5
6/// Generate a random EAN-8 barcode
7pub fn ean_8() -> String {
8    let pattern = fetch_locale("barcode.ean_8", "en")
9        .map(|v| sample(&v))
10        .unwrap_or_else(|| "#######".to_string());
11
12    let base = bothify(&pattern);
13    let check_digit = calculate_ean_check_digit(&base);
14    format!("{}{}", base, check_digit)
15}
16
17/// Generate a random EAN-13 barcode
18pub fn ean_13() -> String {
19    let pattern = fetch_locale("barcode.ean_13", "en")
20        .map(|v| sample(&v))
21        .unwrap_or_else(|| "############".to_string());
22
23    let base = bothify(&pattern);
24    let check_digit = calculate_ean_check_digit(&base);
25    format!("{}{}", base, check_digit)
26}
27
28/// Generate a random UPC-A barcode
29pub fn upc_a() -> String {
30    let pattern = fetch_locale("barcode.upc_a", "en")
31        .map(|v| sample(&v))
32        .unwrap_or_else(|| "###########".to_string());
33
34    let base = bothify(&pattern);
35    let check_digit = calculate_ean_check_digit(&base);
36    format!("{}{}", base, check_digit)
37}
38
39/// Generate a random UPC-E barcode
40pub fn upc_e() -> String {
41    fetch_locale("barcode.upc_e", "en")
42        .map(|v| bothify(&sample(&v)))
43        .unwrap_or_else(|| bothify("0######"))
44}
45
46/// Generate a random ISBN barcode
47pub fn isbn() -> String {
48    fetch_locale("barcode.isbn", "en")
49        .map(|v| bothify(&sample(&v)))
50        .unwrap_or_else(|| bothify("978#########"))
51}
52
53/// Helper function to calculate EAN/UPC check digit
54fn calculate_ean_check_digit(s: &str) -> u32 {
55    let mut sum = 0;
56    let len = s.len();
57
58    for (i, c) in s.chars().enumerate() {
59        if let Some(digit) = c.to_digit(10) {
60            // Weights depend on position from RIGHT (starting at 1)
61            // For EAN-13 (12 digits input): index 0 weight 1, 1 weight 3, 2 weight 1...
62            // Basically: if (len - i) is even, weight is 3, else 1.
63            let weight = if (len - i) % 2 == 0 { 3 } else { 1 };
64            sum += digit * weight;
65        }
66    }
67
68    (10 - (sum % 10)) % 10
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_ean_8() {
77        let b = ean_8();
78        assert_eq!(b.len(), 8);
79    }
80
81    #[test]
82    fn test_ean_13() {
83        let b = ean_13();
84        assert_eq!(b.len(), 13);
85    }
86
87    #[test]
88    fn test_upc_a() {
89        let b = upc_a();
90        assert_eq!(b.len(), 12);
91    }
92}