1#[cfg(feature = "pdf")]
8pub mod pdf_native;
9#[cfg(feature = "png")]
10pub mod png;
11
12#[cfg(any(feature = "png", feature = "pdf"))]
14pub(crate) fn barcode_1d_format(kind: crate::engine::Barcode1DKind) -> rxing::BarcodeFormat {
15 match kind {
16 crate::engine::Barcode1DKind::Ean13 => rxing::BarcodeFormat::EAN_13,
17 crate::engine::Barcode1DKind::UpcA => rxing::BarcodeFormat::UPC_A,
18 crate::engine::Barcode1DKind::Interleaved2of5 => rxing::BarcodeFormat::ITF,
19 crate::engine::Barcode1DKind::Code93 => rxing::BarcodeFormat::CODE_93,
20 }
21}
22
23#[cfg(any(feature = "png", feature = "pdf"))]
29pub(crate) mod barcode_cache {
30 use std::collections::HashMap;
31 use std::sync::{Arc, Mutex, OnceLock};
32
33 use rxing::common::BitMatrix;
34 use rxing::{BarcodeFormat, EncodeHints, MultiFormatWriter, Writer};
35
36 use crate::{ZplError, ZplResult};
37
38 const MAX_ENTRIES: usize = 512;
41
42 type Key = (&'static str, String, String);
43
44 fn cache() -> &'static Mutex<HashMap<Key, Arc<BitMatrix>>> {
45 static CACHE: OnceLock<Mutex<HashMap<Key, Arc<BitMatrix>>>> = OnceLock::new();
46 CACHE.get_or_init(|| Mutex::new(HashMap::new()))
47 }
48
49 fn format_key(format: &BarcodeFormat) -> &'static str {
50 match format {
51 BarcodeFormat::CODE_128 => "c128",
52 BarcodeFormat::CODE_39 => "c39",
53 BarcodeFormat::CODE_93 => "c93",
54 BarcodeFormat::QR_CODE => "qr",
55 BarcodeFormat::DATA_MATRIX => "dm",
56 BarcodeFormat::PDF_417 => "p417",
57 BarcodeFormat::EAN_13 => "e13",
58 BarcodeFormat::UPC_A => "upca",
59 BarcodeFormat::ITF => "itf",
60 _ => "other",
61 }
62 }
63
64 #[allow(clippy::collapsible_if)]
68 pub fn encode_cached(
69 format: BarcodeFormat,
70 data: &str,
71 hints_key: &str,
72 hints: Option<&EncodeHints>,
73 ) -> ZplResult<Arc<BitMatrix>> {
74 let key: Key = (format_key(&format), data.to_string(), hints_key.to_string());
75
76 if let Ok(guard) = cache().lock() {
77 if let Some(hit) = guard.get(&key) {
78 return Ok(hit.clone());
79 }
80 }
81
82 let writer = MultiFormatWriter;
83 let matrix = match hints {
84 Some(h) => writer.encode_with_hints(data, &format, 0, 0, h),
85 None => writer.encode(data, &format, 0, 0),
86 }
87 .map_err(|e| ZplError::BackendError(format!("Barcode Generation Error: {}", e)))?;
88
89 let matrix = Arc::new(matrix);
90 if let Ok(mut guard) = cache().lock() {
91 if guard.len() >= MAX_ENTRIES {
92 guard.clear();
93 }
94 guard.insert(key, matrix.clone());
95 }
96 Ok(matrix)
97 }
98}