1use barcoders::sym::codabar::Codabar;
8use barcoders::sym::code128::Code128;
9use barcoders::sym::code39::Code39;
10use barcoders::sym::ean13::EAN13;
11use barcoders::sym::ean8::EAN8;
12
13#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
15pub enum BarcodeFormat {
16 #[default]
17 Code128,
18 Code39,
19 #[serde(rename = "EAN13")]
20 Ean13,
21 #[serde(rename = "EAN8")]
22 Ean8,
23 Codabar,
24}
25
26#[derive(Debug, Clone)]
28pub struct BarcodeData {
29 pub bars: Vec<u8>,
31}
32
33pub fn generate_barcode(data: &str, format: BarcodeFormat) -> Result<BarcodeData, String> {
35 let bars = match format {
36 BarcodeFormat::Code128 => {
37 let input = if data.starts_with('À') || data.starts_with('Ɓ') || data.starts_with('Ć')
40 {
41 data.to_string()
42 } else {
43 format!("Ɓ{data}")
44 };
45 let barcode = Code128::new(&input).map_err(|e| format!("Code128 error: {e}"))?;
46 barcode.encode()
47 }
48 BarcodeFormat::Code39 => {
49 let barcode = Code39::new(data).map_err(|e| format!("Code39 error: {e}"))?;
50 barcode.encode()
51 }
52 BarcodeFormat::Ean13 => {
53 let barcode = EAN13::new(data).map_err(|e| format!("EAN13 error: {e}"))?;
54 barcode.encode()
55 }
56 BarcodeFormat::Ean8 => {
57 let barcode = EAN8::new(data).map_err(|e| format!("EAN8 error: {e}"))?;
58 barcode.encode()
59 }
60 BarcodeFormat::Codabar => {
61 let barcode = Codabar::new(data).map_err(|e| format!("Codabar error: {e}"))?;
62 barcode.encode()
63 }
64 };
65
66 Ok(BarcodeData { bars })
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn test_code128() {
75 let bc = generate_barcode("Hello", BarcodeFormat::Code128).unwrap();
76 assert!(!bc.bars.is_empty());
77 assert!(bc.bars.iter().all(|&b| b == 0 || b == 1));
78 }
79
80 #[test]
81 fn test_code39() {
82 let bc = generate_barcode("HELLO", BarcodeFormat::Code39).unwrap();
83 assert!(!bc.bars.is_empty());
84 }
85
86 #[test]
87 fn test_ean13() {
88 let bc = generate_barcode("5901234123457", BarcodeFormat::Ean13).unwrap();
89 assert!(!bc.bars.is_empty());
90 }
91
92 #[test]
93 fn test_ean8() {
94 let bc = generate_barcode("65833254", BarcodeFormat::Ean8).unwrap();
95 assert!(!bc.bars.is_empty());
96 }
97
98 #[test]
99 fn test_invalid_ean13() {
100 let result = generate_barcode("123", BarcodeFormat::Ean13);
101 assert!(result.is_err());
102 }
103
104 #[test]
105 fn test_bars_contain_dark() {
106 let bc = generate_barcode("Test", BarcodeFormat::Code128).unwrap();
107 assert!(bc.bars.iter().any(|&b| b == 1), "Should have dark bars");
108 }
109}