use anyd::codes::code128::{Code128Decoder, Code128Encoder, Code128Input};
use anyd::output::Encoding;
use anyd::symbol::SymbolMeta;
use anyd::symbology::Symbology;
use anyd::traits::{Decode, Encode};
fn data(text: &str) -> Vec<Code128Input> {
text.bytes().map(Code128Input::Data).collect()
}
fn modules(enc: &Encoding) -> Vec<bool> {
match enc {
Encoding::Linear(p) => p.modules.clone(),
Encoding::Matrix(_) => panic!("expected linear"),
}
}
fn assert_roundtrip(input: &[Code128Input], gs1: bool) {
let encoder = Code128Encoder::new();
let built = if gs1 {
encoder.build_gs1(input).unwrap()
} else {
encoder.build(input).unwrap()
};
let encoding = encoder.encode(&built).unwrap();
let decoded = Code128Decoder::new().decode(&encoding).unwrap();
let reencoded = encoder.encode(&decoded).unwrap();
assert_eq!(encoding, reencoded, "re-encode differs from original");
assert_eq!(decoded.meta, built.meta, "meta not preserved");
assert_eq!(decoded.symbology, built.symbology);
}
#[test]
fn wikipedia_reference_vector() {
use anyd::Symbol;
use anyd::codes::code128::Code128Meta;
let meta = Code128Meta {
gs1: false,
symbols: vec![103, 48, 42, 42, 17, 18, 19, 35],
};
let symbol = Symbol::new(Symbology::Code128, Vec::new(), SymbolMeta::Code128(meta));
let encoding = Code128Encoder::new().encode(&symbol).unwrap();
let mut expected = Vec::new();
for widths in [
"211412", "313121", "112133", "112133", "123221", "223211", "221132", "131321",
"311123", "2331112", ] {
let mut bar = true;
for w in widths.bytes().map(|b| (b - b'0') as usize) {
expected.extend(std::iter::repeat_n(bar, w));
bar = !bar;
}
}
assert_eq!(modules(&encoding), expected);
let decoded = Code128Decoder::new().decode(&encoding).unwrap();
if let SymbolMeta::Code128(m) = &decoded.meta {
assert_eq!(m.symbols, vec![103, 48, 42, 42, 17, 18, 19, 35]);
} else {
panic!("expected Code128 meta");
}
assert_eq!(decoded.text().as_deref(), Some("PJJ123C"));
}
#[test]
fn roundtrip_code_b_text() {
let input = data("Hello, World!");
assert_roundtrip(&input, false);
let built = Code128Encoder::new().build(&input).unwrap();
assert_eq!(built.text().as_deref(), Some("Hello, World!"));
assert_eq!(built.symbology, Symbology::Code128);
}
#[test]
fn roundtrip_code_c_all_digits() {
let input = data("00112233445566778899");
assert_roundtrip(&input, false);
let built = Code128Encoder::new().build(&input).unwrap();
assert_eq!(built.text().as_deref(), Some("00112233445566778899"));
if let SymbolMeta::Code128(m) = &built.meta {
assert_eq!(m.symbols[0], 105); assert_eq!(m.symbols.len(), 11);
} else {
panic!();
}
}
#[test]
fn roundtrip_mixed_switches() {
assert_roundtrip(&data("ABC1234567890XYZ"), false);
assert_roundtrip(&data("X1234567Y"), false);
}
#[test]
fn roundtrip_code_a_controls_and_shift() {
let mut input = data("abc");
input.push(Code128Input::Data(0x09)); input.extend(data("def"));
assert_roundtrip(&input, false);
let input: Vec<Code128Input> = (1u8..=10).map(Code128Input::Data).collect();
assert_roundtrip(&input, false);
}
#[test]
fn roundtrip_gs1_ai_example() {
let mut input = data("0109521234543213"); input.extend(data("10ABC123")); input.push(Code128Input::Fnc1); input.extend(data("21XYZ")); assert_roundtrip(&input, true);
let built = Code128Encoder::new().build_gs1(&input).unwrap();
assert_eq!(built.symbology, Symbology::Gs1_128);
if let SymbolMeta::Code128(m) = &built.meta {
assert!(m.gs1);
assert_eq!(m.symbols[0], 105); assert_eq!(m.symbols[1], 102); } else {
panic!();
}
let bytes = built.payload_bytes();
assert!(
bytes.contains(&0x1D),
"AI separator should decode to GS byte"
);
}
#[test]
fn decode_rejects_bad_check_character() {
let encoder = Code128Encoder::new();
let built = encoder.build_text("TEST").unwrap();
let mut encoding = encoder.encode(&built).unwrap();
if let Encoding::Linear(p) = &mut encoding {
let mid = p.modules.len() / 2;
p.modules[mid] = !p.modules[mid];
}
assert!(Code128Decoder::new().decode(&encoding).is_err());
}
#[test]
fn encode_rejects_non_ascii_byte() {
let encoder = Code128Encoder::new();
let input = vec![Code128Input::Data(200)];
assert!(encoder.build(&input).is_err());
}