use super::barcode_text_position::BarcodeTextPosition;
use super::barcode_type::BarcodeType;
use crate::commands_esc_pos::text::text_type::get_styles_diff;
use crate::models::print_sections::{Barcode as BarcodeSection, GlobalStyles};
#[derive(Debug, Clone)]
pub struct Barcode {
barcode_type: BarcodeType,
data: String,
height: u8,
width: u8,
text_position: BarcodeTextPosition,
}
impl Barcode {
pub fn new(barcode_type: BarcodeType, data: String) -> Self {
Self {
barcode_type,
data,
height: 162, width: 3, text_position: BarcodeTextPosition::Below,
}
}
pub fn set_height(mut self, height: u8) -> Self {
self.height = height;
self
}
pub fn set_width(mut self, width: u8) -> Self {
if (2..=6).contains(&width) {
self.width = width;
}
self
}
pub fn set_text_position(mut self, position: BarcodeTextPosition) -> Self {
self.text_position = position;
self
}
pub fn get_command(&self) -> Vec<u8> {
let mut output = Vec::new();
let data_bytes = self.data.as_bytes();
output.push(0x1D); output.push(0x68); output.push(self.height);
output.push(0x1D); output.push(0x77); output.push(self.width);
output.push(0x1D); output.push(0x48); output.push(self.text_position.value());
output.push(0x1D); output.push(0x6B); output.push(self.barcode_type.value()); output.push(data_bytes.len() as u8); output.extend_from_slice(data_bytes);
output
}
}
pub fn process_section(
barcode: &BarcodeSection,
current_styles: &GlobalStyles,
) -> Result<Vec<u8>, String> {
if barcode.data.is_empty() {
return Err("Barcode data cannot be empty".to_string());
}
if barcode.height == 0 {
return Err("Barcode height must be greater than 0".to_string());
}
let barcode_type = match barcode.barcode_type.as_str() {
"UPC-A" => BarcodeType::UpcA,
"UPC-E" => BarcodeType::UpcE,
"EAN13" => BarcodeType::Ean13,
"EAN8" => BarcodeType::Ean8,
"CODE39" => BarcodeType::Code39,
"ITF" => BarcodeType::Itf,
"CODABAR" => BarcodeType::Codabar,
"CODE93" => BarcodeType::Code93,
"CODE128" => BarcodeType::Code128,
_ => BarcodeType::Code128,
};
if barcode_type.requires_numeric_data()
&& !barcode.data.chars().all(|c| c.is_ascii_digit())
{
return Err(format!(
"Barcode type '{}' only accepts numeric digits",
barcode.barcode_type
));
}
let text_position = match barcode.text_position.as_str() {
"none" => BarcodeTextPosition::NotPrinted,
"above" => BarcodeTextPosition::Above,
"below" => BarcodeTextPosition::Below,
"both" => BarcodeTextPosition::Both,
_ => BarcodeTextPosition::NotPrinted,
};
let esc_pos_barcode = Barcode::new(barcode_type, barcode.data.clone())
.set_height(barcode.height)
.set_width(barcode.width)
.set_text_position(text_position);
let mut data = Vec::new();
if let Some(ref align) = barcode.align {
let mut temp_styles = current_styles.clone();
temp_styles.align = Some(align.clone());
data.extend_from_slice(&get_styles_diff(current_styles, &temp_styles));
data.extend_from_slice(&esc_pos_barcode.get_command());
data.extend_from_slice(b"\n");
data.extend_from_slice(&get_styles_diff(&temp_styles, current_styles));
} else {
data.extend_from_slice(&esc_pos_barcode.get_command());
data.extend_from_slice(b"\n");
}
Ok(data)
}
impl Barcode {
}