use anyd::codes::code39::{Code39Decoder, Code39Encoder};
use anyd::output::Encoding;
use anyd::segment::Segment;
use anyd::symbol::SymbolMeta;
use anyd::traits::{Decode, Encode};
fn bits(s: &str) -> Vec<bool> {
s.bytes().map(|b| b == b'1').collect()
}
fn modules(enc: &Encoding) -> &Vec<bool> {
match enc {
Encoding::Linear(p) => &p.modules,
Encoding::Matrix(_) => panic!("expected linear"),
}
}
#[test]
fn reference_vector_star_a_star() {
let enc = Code39Encoder::new();
let symbol = enc.build(b"A", false, false).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let star = "100101101101";
let a = "110101001011";
let expected = bits(&format!("{star}0{a}0{star}"));
assert_eq!(modules(&encoding), &expected);
}
#[test]
fn reference_vector_mod43_check_abc_is_x() {
let enc = Code39Encoder::new();
let with_check = enc
.encode(&enc.build(b"ABC", false, true).unwrap())
.unwrap();
let literal = enc
.encode(&enc.build(b"ABCX", false, false).unwrap())
.unwrap();
assert_eq!(modules(&with_check), modules(&literal));
}
fn assert_roundtrip(data: &[u8], full_ascii: bool, check_digit: bool) {
let enc = Code39Encoder::new();
let dec = Code39Decoder::new()
.with_full_ascii(full_ascii)
.with_check_digit(check_digit);
let symbol = enc.build(data, full_ascii, check_digit).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let decoded = dec.decode(&encoding).unwrap();
assert_eq!(decoded.segments, symbol.segments, "segments differ");
assert_eq!(decoded.meta, symbol.meta, "meta differs");
match &decoded.meta {
SymbolMeta::Code39(m) => {
assert_eq!(m.full_ascii, full_ascii);
assert_eq!(m.check_digit, check_digit);
}
_ => panic!("wrong meta variant"),
}
let reencoded = enc.encode(&decoded).unwrap();
assert_eq!(reencoded, encoding, "re-encode not byte-identical");
}
#[test]
fn roundtrip_standard_option_matrix() {
for &check in &[false, true] {
assert_roundtrip(b"CODE39", false, check);
assert_roundtrip(b"ABC-123 $/+%.", false, check);
assert_roundtrip(b"0123456789", false, check);
assert_roundtrip(b"", false, check);
}
}
#[test]
fn roundtrip_full_ascii_option_matrix() {
for &check in &[false, true] {
assert_roundtrip(b"Hello, World!", true, check);
assert_roundtrip(b"abc-XYZ_123", true, check);
assert_roundtrip(b"ABC 123", true, check);
}
}
#[test]
fn roundtrip_all_ascii_bytes() {
let all: Vec<u8> = (0u8..128).collect();
assert_roundtrip(&all, true, true);
}
#[test]
fn decoded_payload_is_recoverable_text() {
let enc = Code39Encoder::new();
let symbol = enc.build(b"Hello!", true, false).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let decoded = Code39Decoder::new()
.with_full_ascii(true)
.decode(&encoding)
.unwrap();
assert_eq!(decoded.text().as_deref(), Some("Hello!"));
assert_eq!(decoded.segments, vec![Segment::byte(b"Hello!".to_vec())]);
}
#[test]
fn corrupt_check_is_rejected() {
let enc = Code39Encoder::new();
let symbol = enc.build(b"CODE39", false, false).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let result = Code39Decoder::new()
.with_check_digit(true)
.decode(&encoding);
assert!(result.is_err());
}