use anyd::codes::datamatrix::{DataMatrixDecoder, DataMatrixEncoder};
use anyd::output::Encoding;
use anyd::traits::{Decode, Encode};
fn assert_lossless(data: &[u8]) {
let enc = DataMatrixEncoder::new();
let symbol = enc.build(data).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let decoded = DataMatrixDecoder::new().decode(&encoding).unwrap();
assert_eq!(
decoded.payload_bytes(),
data,
"payload differs after decode"
);
assert_eq!(
decoded.segments, symbol.segments,
"segments differ after decode"
);
assert_eq!(decoded.meta, symbol.meta, "meta differs after decode");
let reencoded = enc.encode(&decoded).unwrap();
assert_eq!(reencoded, encoding, "re-encoding is not byte-identical");
}
#[test]
fn ascii_digits() {
assert_lossless(b"123456");
assert_lossless(b"1234567890");
assert_lossless(b"7"); assert_lossless(b"12345"); }
#[test]
fn ascii_text() {
assert_lossless(b"HELLO WORLD");
assert_lossless(b"Data Matrix ECC 200!");
assert_lossless(b"mix3d 12 t3xt 34 and digits 5678");
}
#[test]
fn base256_high_bytes() {
assert_lossless(&[0x00, 0x80, 0xFF, 0xAB, 0xCD]);
assert_lossless(&(0u16..=255).map(|b| b as u8).collect::<Vec<u8>>());
}
#[test]
fn mixed_ascii_and_base256() {
let mut data = b"ABC".to_vec();
data.extend_from_slice(&[0x80, 0x90, 0xA0]);
data.extend_from_slice(b"789012");
data.extend_from_slice(&[0xFF]);
assert_lossless(&data);
}
#[test]
fn segment_structure_is_recovered() {
let enc = DataMatrixEncoder::new();
let symbol = enc.build(&[b'A', 0x80, b'B']).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let decoded = DataMatrixDecoder::new().decode(&encoding).unwrap();
use anyd::codes::datamatrix::Encodation;
use anyd::symbol::SymbolMeta;
let SymbolMeta::DataMatrix(meta) = &decoded.meta else {
panic!("expected Data Matrix meta");
};
assert_eq!(
meta.encodations,
vec![Encodation::Ascii, Encodation::Base256, Encodation::Ascii]
);
assert_eq!(decoded.segments.len(), 3);
}
#[test]
fn spans_many_sizes() {
for n in [1usize, 5, 20, 60, 120, 260, 600, 1000] {
let data: Vec<u8> = (0..n).map(|i| b'0' + (i % 10) as u8).collect();
assert_lossless(&data);
}
}
#[test]
fn forced_size_pads_correctly() {
let enc = DataMatrixEncoder::new();
let symbol = enc.build_sized(b"12", 26).unwrap();
let encoding = enc.encode(&symbol).unwrap();
let Encoding::Matrix(m) = &encoding else {
panic!("expected matrix");
};
assert_eq!((m.width(), m.height()), (26, 26));
let decoded = DataMatrixDecoder::new().decode(&encoding).unwrap();
assert_eq!(decoded.payload_bytes(), b"12");
assert_eq!(enc.encode(&decoded).unwrap(), encoding);
}
#[test]
fn survives_correctable_errors() {
let enc = DataMatrixEncoder::new();
let symbol = enc.build_sized(b"RESILIENT DATA MATRIX 2026", 26).unwrap();
let Encoding::Matrix(mut matrix) = enc.encode(&symbol).unwrap() else {
panic!("expected matrix");
};
for k in 0..6 {
let x = 3 + k * 3;
let y = 3 + k * 2;
let v = matrix.get(x, y);
matrix.set(x, y, !v);
}
let decoded = DataMatrixDecoder::new()
.decode(&Encoding::Matrix(matrix))
.unwrap();
assert_eq!(
decoded.text().as_deref(),
Some("RESILIENT DATA MATRIX 2026")
);
}
#[test]
fn text_convenience_roundtrip() {
let enc = DataMatrixEncoder::new();
let symbol = enc.build_text("https://example.com/anydcode").unwrap();
let encoding = enc.encode(&symbol).unwrap();
let decoded = DataMatrixDecoder::new().decode(&encoding).unwrap();
assert_eq!(
decoded.text().as_deref(),
Some("https://example.com/anydcode")
);
assert_eq!(enc.encode(&decoded).unwrap(), encoding);
}