use nom::{
Parser,
branch::alt,
bytes::complete::{tag, take_till},
combinator::{cut, map, opt},
};
use super::{
Res, Span, opt_param, param, parse_char, parse_char_upper, parse_f32, parse_u32, parse_xy,
};
use crate::ast::cmd;
use crate::ast::commons::{Barcode1DKind, Justification, YesNo};
pub fn cmd_xa(input: Span) -> Res<cmd::Command> {
map(tag("^XA"), |_| cmd::Command::StartFormat).parse(input)
}
pub fn cmd_xz(input: Span) -> Res<cmd::Command> {
map(tag("^XZ"), |_| cmd::Command::EndFormat).parse(input)
}
pub fn cmd_lh(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^LH").parse(input)?;
let (input, (x, y)) = cut(parse_xy).parse(input)?;
Ok((input, cmd::Command::LabelHome { x, y }))
}
pub fn cmd_ll(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^LL").parse(input)?;
let (input, length) = cut(opt_param(parse_u32)).parse(input)?;
Ok((input, cmd::Command::LabelLength { length }))
}
pub fn cmd_fo(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FO").parse(input)?;
let (input, (x, y)) = cut(parse_xy).parse(input)?;
Ok((input, cmd::Command::FieldOrigin { x, y }))
}
pub fn cmd_ft(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FT").parse(input)?;
let (input, (x, y)) = cut(parse_xy).parse(input)?;
Ok((input, cmd::Command::FieldTypeset { x, y }))
}
pub fn cmd_fs(input: Span) -> Res<cmd::Command> {
map(tag("^FS"), |_| cmd::Command::FieldSeparator).parse(input)
}
pub fn cmd_lr(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^LR").parse(input)?;
let (input, val_opt) = cut(opt_param(parse_char)).parse(input)?;
Ok((
input,
cmd::Command::LabelReverse {
reverse: val_opt.map(|c: char| YesNo::from(c)),
},
))
}
pub fn cmd_fx(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FX").parse(input)?;
let (input, data) = take_till(|c| c == '^').parse(input)?;
Ok((
input,
cmd::Command::Comment {
text: data.trim().to_owned(),
},
))
}
pub fn cmd_a(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^A").parse(input)?;
let (input, font) = cut(parse_char).parse(input)?;
let (input, orientation_opt) = opt_param(parse_char).parse(input)?;
let (input, height_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, width_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::FontSpecFull {
font_name: font,
orientation: orientation_opt,
height: height_opt,
width: width_opt,
},
))
}
pub fn cmd_cf(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^CF").parse(input)?;
let (input, font) = cut(parse_char).parse(input)?;
let (input, height_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, width_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::FontSpec {
font_name: font,
height: height_opt,
width: width_opt,
},
))
}
pub fn cmd_fd(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FD").parse(input)?;
let (input, data) = take_till(|c| c == '^').parse(input)?;
Ok((
input,
cmd::Command::FieldData {
data: data.trim().to_owned(),
},
))
}
pub fn cmd_fb(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FB").parse(input)?;
let (input, w_opt) = cut(opt_param(parse_u32)).parse(input)?;
let (input, m_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, l_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, j_opt) = param(parse_char).parse(input).unwrap_or((input, None));
let (input, i_opt) = param(parse_u32).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::FieldBlock {
width: w_opt,
max_lines: m_opt,
line_spacing: l_opt,
justification: j_opt.map(|c: char| Justification::from(c)),
indent: i_opt,
},
))
}
pub fn cmd_fr(input: Span) -> Res<cmd::Command> {
map(tag("^FR"), |_| cmd::Command::FieldReverse).parse(input)
}
pub fn cmd_gb(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^GB").parse(input)?;
let (input, width) = cut(parse_u32).parse(input)?;
let (input, _) = cut(tag(",")).parse(input)?;
let (input, height) = cut(parse_u32).parse(input)?;
let (input, border_thickness) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, line_color) = param(parse_char).parse(input).unwrap_or((input, None));
let (input, corner_rounding) = param(parse_u32).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::GraphicBox {
width,
height,
border_thickness,
line_color,
corner_rounding,
},
))
}
pub fn cmd_gc(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^GC").parse(input)?;
let (input, diameter) = cut(opt_param(parse_u32)).parse(input)?;
let (input, border_thickness) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, line_color) = param(parse_char).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::GraphicCircle {
diameter,
border_thickness,
line_color,
},
))
}
pub fn cmd_ge(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^GE").parse(input)?;
let (input, width) = cut(opt_param(parse_u32)).parse(input)?;
let (input, height) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, border_thickness) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, line_color) = param(parse_char).parse(input).unwrap_or((input, None));
Ok((
input,
cmd::Command::GraphicEllipse {
width,
height,
border_thickness,
line_color,
},
))
}
pub fn cmd_gf(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^GF").parse(input)?;
let (input, compression_type) = cut(opt_param(parse_char)).parse(input)?;
let (input, binary_byte_count) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, graphic_field_count) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, bytes_per_row) = param(parse_u32).parse(input).unwrap_or((input, None));
let (input, _) = opt(tag(",")).parse(input)?;
let (input, raw_data) = take_till(|c| c == '^').parse(input)?;
Ok((
input,
cmd::Command::GraphicField {
compression_type,
binary_byte_count,
graphic_field_count,
bytes_per_row,
data: raw_data.trim().to_owned(),
},
))
}
pub fn cmd_bc(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BC").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line_above) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, check_digit) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, mode) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Code128 {
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit,
mode,
},
))
}
pub fn cmd_bq(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BQ").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, model) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, magnification) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, error_correction) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, mask) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::QRCode {
orientation,
model,
magnification,
error_correction,
mask,
},
))
}
pub fn cmd_b3(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^B3").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, check_digit) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, interpretation_line_above) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Code39 {
orientation,
check_digit,
height,
interpretation_line,
interpretation_line_above,
},
))
}
pub fn cmd_by(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BY").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, module_width) = opt_param(parse_u32).parse(args)?;
let (args_input, ratio) = param(parse_f32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::BarcodeDefault {
module_width,
ratio,
height,
},
))
}
pub fn cmd_bx(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BX").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, quality) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, columns) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, rows) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::DataMatrix {
orientation,
height,
quality,
columns,
rows,
},
))
}
fn parse_barcode_1d(input: Span, kind: Barcode1DKind) -> Res<cmd::Command> {
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line_above) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, check_digit) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit,
},
))
}
pub fn cmd_be(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BE").parse(input)?;
parse_barcode_1d(input, Barcode1DKind::Ean13)
}
pub fn cmd_bu(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BU").parse(input)?;
parse_barcode_1d(input, Barcode1DKind::UpcA)
}
pub fn cmd_b2(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^B2").parse(input)?;
parse_barcode_1d(input, Barcode1DKind::Interleaved2of5)
}
pub fn cmd_ba(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BA").parse(input)?;
parse_barcode_1d(input, Barcode1DKind::Code93)
}
pub fn cmd_gd(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^GD").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, width) = opt_param(parse_u32).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, thickness) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, line_color) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, diagonal_orientation) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::GraphicDiagonal {
width,
height,
thickness,
line_color,
diagonal_orientation,
},
))
}
pub fn cmd_b7(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^B7").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, security_level) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, columns) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, rows) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, truncate) = param(parse_char)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Pdf417 {
orientation,
height,
security_level,
columns,
rows,
truncate: truncate.map(YesNo::from),
},
))
}
pub fn cmd_b8(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^B8").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::Ean8,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit: Some('Y'),
},
))
}
pub fn cmd_b9(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^B9").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, check_digit) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::UpcE,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit,
},
))
}
pub fn cmd_bb(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BB").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, check_digit) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::Codabar,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit,
},
))
}
pub fn cmd_bm(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BM").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, check_digit) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::Msi,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit,
},
))
}
pub fn cmd_bz(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BZ").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::Postnet,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit: Some('Y'),
},
))
}
pub fn cmd_bs(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BS").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, interpretation_line) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, interpretation_line_above) = param(parse_char_upper)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::Barcode1D {
kind: Barcode1DKind::Extension25,
orientation,
height,
interpretation_line,
interpretation_line_above,
check_digit: Some('N'),
},
))
}
pub fn cmd_b0(input: Span) -> Res<cmd::Command> {
let (input, _) = alt((tag("^B0"), tag("^BO"))).parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, magnification) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, extended_channel) = param(parse_char_upper)
.parse(args_input)
.map(|(i, c)| (i, c.map(|ch| ch == 'Y')))
.unwrap_or((args_input, None));
let (args_input, ecc_percent) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, menu_symbol) = param(parse_char_upper)
.parse(args_input)
.map(|(i, c)| (i, c.map(|ch| ch == 'Y')))
.unwrap_or((args_input, None));
let (args_input, symbols_count) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, id_field) = param(take_till(|c| c == ',' || c == '^'))
.parse(args_input)
.map(|(i, s)| (i, s.map(|val| val.to_string())))
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::AztecCode {
orientation,
magnification,
extended_channel,
ecc_percent,
menu_symbol,
symbols_count,
id_field,
},
))
}
pub fn cmd_bf(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BF").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, mode) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::MicroPdf417 {
orientation,
height,
mode,
},
))
}
pub fn cmd_br(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^BR").parse(input)?;
let (rest, args) = cut(take_till(|c| c == '^')).parse(input)?;
let (args_input, orientation) = opt_param(parse_char_upper).parse(args)?;
let (args_input, symbology_type) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, magnification) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, separator_height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (args_input, height) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
let (_, segment_width) = param(parse_u32)
.parse(args_input)
.unwrap_or((args_input, None));
Ok((
rest,
cmd::Command::GS1DataBar {
orientation,
symbology_type,
magnification,
separator_height,
height,
segment_width,
},
))
}
pub fn cmd_fh(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^FH").parse(input)?;
let (input, indicator) = opt_param(parse_char).parse(input)?;
Ok((
input,
cmd::Command::FieldHexEscape {
indicator: indicator.or(Some('_')),
},
))
}
pub fn cmd_ci(input: Span) -> Res<cmd::Command> {
let (input, _) = tag("^CI").parse(input)?;
let (input, charset) = cut(opt_param(parse_u32)).parse(input)?;
Ok((input, cmd::Command::ChangeIntFont { charset }))
}