use crate::encoding::{ColorMatrix, Rgb8};
use crate::error::Error;
use crate::options::Options;
pub const ULTRACODE_PALETTE: [Rgb8; 8] = [
Rgb8::new(0xff, 0xff, 0xff), Rgb8::new(0x00, 0xff, 0xff), Rgb8::new(0xff, 0x00, 0xff), Rgb8::new(0xff, 0xff, 0x00), Rgb8::new(0x00, 0xff, 0x00), Rgb8::new(0x00, 0x00, 0x00), Rgb8::new(0xff, 0xff, 0xff), Rgb8::new(0xff, 0xff, 0xff), ];
pub const BWIPP_TILE_DIGIT_TO_PALETTE_IDX: [u8; 10] = [
0, 1, 0, 2, 0, 3, 4, 0, 0, 5, ];
pub const ULTRACODE_METRICS: [[u32; 4]; 4] = [
[2, 7, 37, 5],
[3, 36, 84, 13],
[4, 85, 161, 22],
[5, 142, 282, 29],
];
pub const ULTRACODE_TILES: [u32; 285] = [
13135, 13136, 13153, 13156, 13163, 13165, 13513, 13515, 13516, 13531, 13535, 13536, 13561,
13563, 13565, 13613, 13615, 13616, 13631, 13635, 13636, 13651, 13653, 13656, 15135, 15136,
15153, 15163, 15165, 15313, 15315, 15316, 15351, 15353, 15356, 15361, 15363, 15365, 15613,
15615, 15616, 15631, 15635, 15636, 15651, 15653, 15656, 16135, 16136, 16153, 16156, 16165,
16313, 16315, 16316, 16351, 16353, 16356, 16361, 16363, 16365, 16513, 16515, 16516, 16531,
16535, 16536, 16561, 16563, 16565, 31315, 31316, 31351, 31356, 31361, 31365, 31513, 31515,
31516, 31531, 31535, 31536, 31561, 31563, 31565, 31613, 31615, 31631, 31635, 31636, 31651,
31653, 31656, 35131, 35135, 35136, 35151, 35153, 35156, 35161, 35163, 35165, 35315, 35316,
35351, 35356, 35361, 35365, 35613, 35615, 35616, 35631, 35635, 35636, 35651, 35653, 35656,
36131, 36135, 36136, 36151, 36153, 36156, 36163, 36165, 36315, 36316, 36351, 36356, 36361,
36365, 36513, 36515, 36516, 36531, 36535, 36536, 36561, 36563, 36565, 51313, 51315, 51316,
51351, 51353, 51356, 51361, 51363, 51365, 51513, 51516, 51531, 51536, 51561, 51563, 51613,
51615, 51616, 51631, 51635, 51636, 51651, 51653, 51656, 53131, 53135, 53136, 53151, 53153,
53156, 53161, 53163, 53165, 53513, 53516, 53531, 53536, 53561, 53563, 53613, 53615, 53616,
53631, 53635, 53636, 53651, 53653, 53656, 56131, 56135, 56136, 56151, 56153, 56156, 56161,
56163, 56165, 56313, 56315, 56316, 56351, 56353, 56356, 56361, 56363, 56365, 56513, 56516,
56531, 56536, 56561, 56563, 61313, 61315, 61316, 61351, 61353, 61356, 61361, 61363, 61365,
61513, 61515, 61516, 61531, 61535, 61536, 61561, 61563, 61565, 61615, 61631, 61635, 61651,
61653, 63131, 63135, 63136, 63151, 63153, 63156, 63161, 63163, 63165, 63513, 63515, 63516,
63531, 63535, 63536, 63561, 63563, 63565, 63613, 63615, 63631, 63635, 63651, 63653, 65131,
65135, 65136, 65151, 65153, 65156, 65161, 65163, 65165, 65313, 65315, 65316, 65351, 65353,
65356, 65361, 65363, 65365, 65613, 65615, 65631, 65635, 65651, 65653, 56565, 51515,
];
pub const ULTRACODE_DCCUREV1: [u32; 32] = [
51363, 51563, 51653, 53153, 53163, 53513, 53563, 53613, 53653, 56153, 56163, 56313, 56353,
56363, 56513, 56563, 51316, 51356, 51536, 51616, 53156, 53516, 53536, 53616, 53636, 53656,
56136, 56156, 56316, 56356, 56516, 56536,
];
pub const ULTRACODE_DCCLREV1: [u32; 32] = [
61351, 61361, 61531, 61561, 61631, 61651, 63131, 63151, 63161, 63531, 63561, 63631, 65131,
65161, 65351, 65631, 31351, 31361, 31531, 31561, 31631, 31651, 35131, 35151, 35161, 35361,
35631, 35651, 36131, 36151, 36351, 36531,
];
pub const ULTRACODE_DCCUREV2: [u32; 32] = [
15316, 16316, 13516, 16516, 13616, 15616, 13136, 15136, 16136, 13536, 16536, 13636, 13156,
16156, 15356, 13656, 15313, 16313, 13513, 16513, 13613, 15613, 13153, 15153, 16153, 16353,
13653, 15653, 13163, 15163, 15363, 13563,
];
pub const ULTRACODE_DCCLREV2: [u32; 32] = [
36315, 36515, 35615, 35135, 36135, 31535, 36535, 31635, 35635, 35165, 36165, 31365, 35365,
36365, 31565, 36565, 61315, 65315, 63515, 61615, 65135, 61535, 63535, 61635, 63635, 65635,
63165, 65165, 61365, 65365, 61565, 63565,
];
pub const ULTRACODE_QCCFACT: [u32; 6] = [0, 1, 2, 4, 6, 8];
pub const ULTRACODE_RS_PRIME: u32 = 283;
pub const ULTRACODE_RS_PRIMITIVE: u32 = 3;
pub const ULTRACODE_CW_FNC1: u32 = 268;
pub const ULTRACODE_CW_FNC3: u32 = 269;
pub const ULTRACODE_CW_PAD: u32 = 284;
pub const ULTRACODE_CW_START: u32 = 257;
#[allow(dead_code)] fn build_rs_tables() -> ([u32; 282], [u32; 283]) {
let mut alog = [0u32; 282];
let mut log = [0u32; 283];
let mut acc: u32 = 1;
for entry in alog.iter_mut() {
*entry = acc;
acc = (acc * ULTRACODE_RS_PRIMITIVE) % ULTRACODE_RS_PRIME;
}
for (i, &v) in alog.iter().enumerate().skip(1) {
log[v as usize] = i as u32;
}
(alog, log)
}
#[allow(dead_code)] #[inline]
fn rs_prod(x: u32, y: u32, alog: &[u32; 282], log: &[u32; 283]) -> u32 {
if x == 0 || y == 0 {
0
} else {
alog[((log[x as usize] + log[y as usize]) % 282) as usize]
}
}
#[allow(dead_code)] pub(crate) fn gen_coeffs(k: usize) -> Vec<u32> {
let (alog, log) = build_rs_tables();
let mut coeffs = vec![0u32; k + 1];
coeffs[0] = 1;
for b in 1..=k {
coeffs[b] = coeffs[b - 1];
let tmp = alog[b];
for g in (1..b).rev() {
let prev = coeffs[g - 1];
coeffs[g] = (rs_prod(coeffs[g], tmp, &alog, &log) + prev) % ULTRACODE_RS_PRIME;
}
coeffs[0] = rs_prod(coeffs[0], tmp, &alog, &log);
}
coeffs.truncate(k);
let mut z = coeffs.len() as isize - 1;
while z >= 0 {
coeffs[z as usize] = ULTRACODE_RS_PRIME - coeffs[z as usize];
z -= 2;
}
coeffs
}
#[allow(dead_code)] pub(crate) fn rs_ecprime(data: &[u32], coeffs: &[u32], nc: usize, prime: u32) -> Vec<u32> {
let mut lfsr = vec![0u32; nc];
for &d in data {
let feedback = (d + prime - lfsr[0]) % prime;
for l in 0..nc.saturating_sub(1) {
let c = coeffs[nc - l - 1];
lfsr[l] = (lfsr[l + 1] + c * feedback % prime) % prime;
}
lfsr[nc - 1] = (coeffs[0] * feedback) % prime;
}
lfsr
}
#[allow(dead_code)] pub(crate) fn ecc_codewords(rsdata: &[u32], qcc: usize) -> Vec<u32> {
let coeffs = gen_coeffs(qcc);
rs_ecprime(rsdata, &coeffs, qcc, ULTRACODE_RS_PRIME)
}
pub(crate) fn ultracode_metadata(dcws_len: usize, eclval: u32, link1: u32) -> (u32, u32, u32, u32) {
let mcc = (dcws_len as u32) + 3;
let qcc = if eclval == 0 {
3
} else {
let fact = ULTRACODE_QCCFACT[eclval as usize];
let mut bucket = mcc / 25;
if mcc % 25 != 0 {
bucket += 1;
}
fact * bucket + 5
};
let acc = (qcc - 3) + 78 * link1;
let tcc = mcc + qcc;
(mcc, qcc, acc, tcc)
}
fn build_dcws_default(input: &str) -> Vec<u32> {
input.bytes().map(|b| b as u32).collect()
}
fn build_dcws_from_opts(input: &str, opts: &UltracodeOpts) -> Result<Vec<u32>, Error> {
if opts.raw {
parse_raw_codewords_ultracode(input.as_bytes()).map_err(Error::InvalidData)
} else if opts.parse || opts.parsefnc {
build_dcws_with_input_opts(input, opts.parse, opts.parsefnc).map_err(Error::InvalidData)
} else {
Ok(build_dcws_default(input))
}
}
const ULTRACODE_PARSE_CTRL: &[(&str, u8)] = &[
("NUL", 0),
("SOH", 1),
("STX", 2),
("ETX", 3),
("EOT", 4),
("ENQ", 5),
("ACK", 6),
("BEL", 7),
("BS", 8),
("TAB", 9),
("LF", 10),
("VT", 11),
("FF", 12),
("CR", 13),
("DLE", 16),
("DC1", 17),
("DC2", 18),
("DC3", 19),
("DC4", 20),
("NAK", 21),
("SYN", 22),
("ETB", 23),
("CAN", 24),
("EM", 25),
("SUB", 26),
("ESC", 27),
("FS", 28),
("GS", 29),
("RS", 30),
("US", 31),
];
fn parse_raw_codewords_ultracode(input: &[u8]) -> Result<Vec<u32>, String> {
let mut out: Vec<u32> = Vec::with_capacity(input.len() / 4);
let mut i = 0;
while i + 4 <= input.len() {
if input[i] != b'^' {
return Err(format!(
"ultracode: raw codewords must be formatted as ^NNN; \
expected `^` at offset {i}, got 0x{:02X}",
input[i],
));
}
let mut value: u32 = 0;
for j in 1..=3 {
let c = input[i + j];
if !c.is_ascii_digit() {
return Err(format!(
"ultracode: raw codewords must be formatted as ^NNN; \
non-digit 0x{c:02X} at offset {}",
i + j,
));
}
value = value * 10 + u32::from(c - b'0');
}
if value > 284 {
return Err(format!(
"ultracode: raw codewords must be 0..=284; got {value}",
));
}
out.push(value);
i += 4;
}
if i != input.len() {
return Err(format!(
"ultracode: raw codewords must be formatted as ^NNN; \
{} trailing byte(s) at offset {i}",
input.len() - i,
));
}
Ok(out)
}
fn build_dcws_with_input_opts(
input: &str,
parse: bool,
parsefnc: bool,
) -> Result<Vec<u32>, String> {
let bytes = input.as_bytes();
let mut out: Vec<u32> = Vec::with_capacity(bytes.len());
let mut i = 0;
while i < bytes.len() {
let c = bytes[i];
if c != b'^' {
out.push(u32::from(c));
i += 1;
continue;
}
let mut matched = false;
if parsefnc {
if i + 5 <= bytes.len() && &bytes[i..i + 5] == b"^FNC1" {
out.push(ULTRACODE_CW_FNC1);
i += 5;
continue;
}
if i + 5 <= bytes.len() && &bytes[i..i + 5] == b"^FNC3" {
out.push(ULTRACODE_CW_FNC3);
i += 5;
continue;
}
if i + 2 <= bytes.len() && bytes[i + 1] == b'^' {
out.push(94);
i += 2;
continue;
}
}
if parse {
if i + 4 <= bytes.len() {
let candidate = &bytes[i + 1..i + 4];
if let Some((_, byte)) = ULTRACODE_PARSE_CTRL
.iter()
.find(|(name, _)| name.len() == 3 && name.as_bytes() == candidate)
{
out.push(u32::from(*byte));
i += 4;
matched = true;
}
}
if !matched && i + 3 <= bytes.len() {
let candidate = &bytes[i + 1..i + 3];
if let Some((_, byte)) = ULTRACODE_PARSE_CTRL
.iter()
.find(|(name, _)| name.len() == 2 && name.as_bytes() == candidate)
{
out.push(u32::from(*byte));
i += 3;
matched = true;
}
}
if !matched && i + 4 <= bytes.len() {
let candidate = &bytes[i + 1..i + 4];
if candidate.iter().all(|b| b.is_ascii_digit()) {
let value: u32 = u32::from(candidate[0] - b'0') * 100
+ u32::from(candidate[1] - b'0') * 10
+ u32::from(candidate[2] - b'0');
if value > 255 {
return Err(format!(
"ultracode parse: ordinal must be 000..=255; got {value}",
));
}
out.push(value);
i += 4;
matched = true;
}
}
}
if !matched {
out.push(94);
i += 1;
}
}
Ok(out)
}
fn pick_symbol_size(tcc: u32) -> Option<(usize, u32, u32, u32)> {
let (m_idx, metric) = ULTRACODE_METRICS
.iter()
.enumerate()
.find(|(_, m)| tcc >= m[1] && tcc <= m[2])?;
let rows = metric[0];
let mcol = metric[3];
for cols in mcol..=61 {
let mut adj = cols;
if cols >= 15 {
adj -= 1;
}
if cols >= 31 {
adj -= 1;
}
if cols >= 47 {
adj -= 1;
}
let usable = adj * rows;
if usable >= 3 + tcc {
let pads = usable - 3 - tcc;
return Some((m_idx, rows, cols, pads));
}
}
None
}
fn layout_pixs(rows: u32, cols: u32, dcc: u32, rev: u32, tileseq: &[u32]) -> Vec<i32> {
let rows = rows as usize;
let cols = cols as usize;
let total = rows * cols;
let mut pixs: Vec<i32> = vec![-1; total];
let qmv = |col: usize, row: usize| row * cols + col;
for i in 0..cols {
if i >= 5 {
let mut j = 0usize;
while j < rows {
pixs[qmv(i, j)] = ((i % 2) as i32) * 9;
j += 6;
}
}
pixs[qmv(i, 0)] = 9;
pixs[qmv(i, rows - 1)] = 9;
}
for i in 1..=rows.saturating_sub(2) {
let mut j = 3usize;
while j < cols {
pixs[qmv(j, i)] = ((1 - (i % 2)) as i32) * 9;
j += 16;
}
pixs[qmv(0, i)] = 9;
pixs[qmv(1, i)] = ((1 - (i % 2)) as i32) * 9;
pixs[qmv(2, i)] = 0;
pixs[qmv(3, i)] = 9;
pixs[qmv(4, i)] = 0;
pixs[qmv(cols - 1, i)] = 9;
}
let dccu = if rev == 1 {
&ULTRACODE_DCCUREV1
} else {
&ULTRACODE_DCCUREV2
};
let dccl = if rev == 1 {
&ULTRACODE_DCCLREV1
} else {
&ULTRACODE_DCCLREV2
};
let dcc_u = dccu[dcc as usize];
let dcc_l = dccl[dcc as usize];
let mut dcc_digits: Vec<i32> = Vec::with_capacity(11);
for d in digits_5(dcc_u) {
dcc_digits.push(d as i32);
}
dcc_digits.push(0);
for d in digits_5(dcc_l) {
dcc_digits.push(d as i32);
}
let row_start = (rows / 2) - 5;
for (k, &d) in dcc_digits.iter().enumerate() {
pixs[qmv(2, row_start + k)] = d;
}
let mut x: usize = 5;
let mut y: usize = 1;
for &cw in tileseq {
let tile = ULTRACODE_TILES[cw as usize];
for d in digits_5(tile) {
pixs[qmv(x, y)] = d as i32;
y += 1;
}
if y != rows - 1 {
y += 1;
} else {
x += 1;
y = 1;
if pixs[qmv(x, y)] != -1 {
x += 1;
}
}
}
pixs
}
fn digits_5(v: u32) -> [u8; 5] {
let mut out = [0u8; 5];
let mut t = v;
for slot in out.iter_mut().rev() {
*slot = (t % 10) as u8;
t /= 10;
}
out
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct UltracodeOpts {
pub eclval: u32,
pub rev: u32,
pub link1: u32,
pub start: u32,
pub raw: bool,
pub parse: bool,
pub parsefnc: bool,
}
impl Default for UltracodeOpts {
fn default() -> Self {
Self {
eclval: 2,
rev: 2,
link1: 0,
start: 257,
raw: false,
parse: false,
parsefnc: false,
}
}
}
fn check_ultracode_opts(opts: &Options) -> Result<UltracodeOpts, Error> {
let mut parsed = UltracodeOpts::default();
if let Some(v) = opts.get("rev") {
match v {
"1" => parsed.rev = 1,
"2" => parsed.rev = 2,
_ => {
return Err(Error::InvalidOption(format!(
"ultracode: rev={v:?} is not a valid BWIPP value (valid: 1 or 2)"
)));
}
}
}
if let Some(v) = opts.get("eclevel") {
let eclval = match v {
"EC0" => 0u32,
"EC1" => 1,
"EC2" => 2,
"EC3" => 3,
"EC4" => 4,
"EC5" => 5,
_ => {
return Err(Error::InvalidOption(format!(
"ultracode: eclevel={v:?} is not a valid BWIPP value \
(valid: EC0/EC1/EC2/EC3/EC4/EC5)"
)));
}
};
let min_ecl = if parsed.rev == 2 { 1 } else { 0 };
if eclval < min_ecl {
return Err(Error::InvalidOption(format!(
"ultracode: eclevel={v} requires rev=1 (rev=2 requires EC1..EC5)"
)));
}
parsed.eclval = eclval;
}
if let Some(v) = opts.get("parsefnc") {
match v {
"false" => {}
"true" => parsed.parsefnc = true,
_ => {
return Err(Error::InvalidOption(format!(
"ultracode: parsefnc={v:?} must be \"true\" or \"false\""
)));
}
}
}
if let Some(v) = opts.get("raw") {
match v {
"false" => {}
"true" => parsed.raw = true,
_ => {
return Err(Error::InvalidOption(format!(
"ultracode: raw={v:?} must be \"true\" or \"false\""
)));
}
}
}
if let Some(v) = opts.get("parse") {
match v {
"false" => {}
"true" => parsed.parse = true,
_ => {
return Err(Error::InvalidOption(format!(
"ultracode: parse={v:?} must be \"true\" or \"false\""
)));
}
}
}
if let Some(v) = opts.get("link1") {
match v.parse::<u32>() {
Ok(n) => parsed.link1 = n,
Err(_) => {
return Err(Error::InvalidOption(format!(
"ultracode: link1={v:?} must be a non-negative integer"
)));
}
}
}
if let Some(v) = opts.get("start") {
match v.parse::<u32>() {
Ok(n) => parsed.start = n,
Err(_) => {
return Err(Error::InvalidOption(format!(
"ultracode: start={v:?} must be a non-negative integer"
)));
}
}
}
Ok(parsed)
}
pub fn encode(data: &str, opts: &Options) -> Result<ColorMatrix, Error> {
if data.is_empty() {
return Err(Error::InvalidData("ultracode: empty input".to_string()));
}
if data.len() > 2500 {
return Err(Error::InvalidData(
"ultracode: input exceeds BWIPP's 2500-byte limit".to_string(),
));
}
let parsed = check_ultracode_opts(opts)?;
let dcws = build_dcws_from_opts(data, &parsed)?;
let eclval = parsed.eclval;
let rev = parsed.rev;
let link1 = parsed.link1;
let (mcc, qcc, acc, tcc) = ultracode_metadata(dcws.len(), eclval, link1);
let (_m_idx, rows, cols_picked, pads) = pick_symbol_size(tcc).ok_or_else(|| {
Error::InvalidData("ultracode: payload exceeds maximum symbol size".to_string())
})?;
let dcc = cols_picked
- ULTRACODE_METRICS
.iter()
.find(|m| m[0] == rows)
.map(|m| m[3])
.unwrap_or(0);
let mut rsdata = vec![parsed.start, mcc, acc];
rsdata.extend_from_slice(&dcws);
let ecws = ecc_codewords(&rsdata, qcc as usize);
let mut tileseq: Vec<u32> =
Vec::with_capacity(2 + ecws.len() + 1 + 1 + 1 + dcws.len() + pads as usize + 1);
tileseq.push(parsed.start);
tileseq.push(mcc);
tileseq.extend_from_slice(&ecws);
tileseq.push(tcc);
tileseq.push(283); tileseq.push(acc);
tileseq.extend_from_slice(&dcws);
tileseq.extend(std::iter::repeat_n(ULTRACODE_CW_PAD, pads as usize));
tileseq.push(qcc);
let final_rows = rows * 6 + 1;
let final_cols = cols_picked + 6;
let pixs = layout_pixs(final_rows, final_cols, dcc, rev, &tileseq);
let mut matrix = ColorMatrix::new(final_cols as usize, final_rows as usize, ULTRACODE_PALETTE);
for y in 0..final_rows as usize {
for x in 0..final_cols as usize {
let cell = pixs[y * final_cols as usize + x];
let palette_idx = if cell < 0 {
0
} else {
BWIPP_TILE_DIGIT_TO_PALETTE_IDX[cell as usize]
};
matrix.set(x, y, palette_idx);
}
}
Ok(matrix)
}
#[cfg(test)]
pub(crate) fn encode_pixs_default(data: &str) -> Result<(u32, u32, Vec<i32>), Error> {
encode_pixs_with_opts(data, UltracodeOpts::default())
}
#[cfg(test)]
pub(crate) fn encode_pixs_with_opts(
data: &str,
opts: UltracodeOpts,
) -> Result<(u32, u32, Vec<i32>), Error> {
if data.is_empty() {
return Err(Error::InvalidData("ultracode: empty input".to_string()));
}
if data.len() > 2500 {
return Err(Error::InvalidData(
"ultracode: input exceeds BWIPP's 2500-byte limit".to_string(),
));
}
let dcws = build_dcws_from_opts(data, &opts)?;
let (mcc, qcc, acc, tcc) = ultracode_metadata(dcws.len(), opts.eclval, opts.link1);
let (_m_idx, rows, cols_picked, pads) = pick_symbol_size(tcc)
.ok_or_else(|| Error::InvalidData("ultracode: payload too large".to_string()))?;
let dcc = cols_picked
- ULTRACODE_METRICS
.iter()
.find(|m| m[0] == rows)
.map(|m| m[3])
.unwrap_or(0);
let mut rsdata = vec![opts.start, mcc, acc];
rsdata.extend_from_slice(&dcws);
let ecws = ecc_codewords(&rsdata, qcc as usize);
let mut tileseq: Vec<u32> = Vec::new();
tileseq.push(opts.start);
tileseq.push(mcc);
tileseq.extend_from_slice(&ecws);
tileseq.push(tcc);
tileseq.push(283);
tileseq.push(acc);
tileseq.extend_from_slice(&dcws);
tileseq.extend(std::iter::repeat_n(ULTRACODE_CW_PAD, pads as usize));
tileseq.push(qcc);
let final_rows = rows * 6 + 1;
let final_cols = cols_picked + 6;
let pixs = layout_pixs(final_rows, final_cols, dcc, opts.rev, &tileseq);
Ok((final_rows, final_cols, pixs))
}
#[cfg(test)]
mod tests {
use super::*;
const ULTRACODE_PIXS_A: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 3, 3, 3, 5, 5, 1, 9, 9, 9, 3, 9,
0, 3, 5, 1, 6, 3, 6, 6, 9, 9, 0, 5, 9, 0, 6, 1, 5, 5, 1, 5, 5, 9, 9, 9, 1, 9, 0, 5, 6, 1,
1, 5, 6, 3, 9, 9, 0, 6, 9, 0, 1, 3, 6, 3, 6, 5, 5, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9,
9, 9, 0, 3, 9, 0, 1, 1, 3, 6, 1, 1, 1, 9, 9, 9, 5, 9, 0, 3, 3, 1, 3, 3, 3, 3, 9, 9, 0, 6,
9, 0, 1, 1, 3, 5, 5, 1, 5, 9, 9, 9, 1, 9, 0, 6, 5, 1, 6, 3, 6, 1, 9, 9, 0, 5, 9, 0, 3, 3,
5, 3, 6, 3, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_HELLO: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 5, 6, 1, 3, 5, 3, 3, 3, 9,
9, 9, 3, 9, 0, 3, 1, 3, 6, 6, 6, 1, 5, 5, 9, 9, 0, 6, 9, 0, 6, 6, 5, 1, 5, 5, 3, 6, 6, 9,
9, 9, 1, 9, 0, 5, 3, 3, 5, 6, 6, 5, 1, 3, 9, 9, 0, 6, 9, 0, 1, 5, 6, 6, 5, 5, 1, 3, 1, 9,
9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 1, 5, 5, 5, 1, 1, 3, 3, 1, 9,
9, 9, 6, 9, 0, 3, 1, 1, 1, 3, 3, 5, 5, 3, 9, 9, 0, 1, 9, 0, 5, 3, 5, 3, 6, 1, 1, 6, 5, 9,
9, 9, 3, 9, 0, 1, 5, 1, 6, 1, 6, 6, 1, 1, 9, 9, 0, 5, 9, 0, 6, 1, 6, 1, 3, 3, 5, 3, 5, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_HELLO_WORLD: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 5, 5, 5, 6, 5,
3, 3, 3, 1, 3, 3, 1, 9, 9, 9, 6, 9, 0, 3, 6, 6, 6, 5, 6, 1, 5, 5, 5, 5, 5, 5, 9, 9, 0, 1,
9, 0, 6, 5, 3, 1, 3, 5, 3, 6, 6, 3, 6, 6, 3, 9, 9, 9, 3, 9, 0, 5, 3, 1, 6, 1, 6, 5, 1, 3,
5, 3, 1, 5, 9, 9, 0, 6, 9, 0, 1, 1, 3, 5, 6, 5, 1, 3, 1, 1, 1, 3, 3, 9, 9, 9, 0, 9, 0, 9,
0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 1, 3, 5, 3, 1, 1, 3, 3, 1, 3, 3, 3,
1, 9, 9, 9, 5, 9, 0, 3, 5, 3, 5, 3, 3, 5, 5, 5, 1, 5, 5, 3, 9, 9, 0, 6, 9, 0, 6, 1, 5, 6,
6, 1, 1, 6, 6, 6, 6, 1, 5, 9, 9, 9, 3, 9, 0, 1, 5, 6, 5, 5, 6, 6, 1, 5, 3, 5, 6, 1, 9, 9,
0, 5, 9, 0, 5, 3, 3, 1, 6, 3, 5, 3, 1, 1, 1, 3, 5, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_12345: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 1, 1, 6, 1, 5, 1, 1, 1, 9,
9, 9, 3, 9, 0, 3, 3, 6, 5, 3, 6, 6, 6, 6, 9, 9, 0, 6, 9, 0, 6, 5, 1, 3, 5, 5, 1, 1, 3, 9,
9, 9, 1, 9, 0, 5, 6, 5, 1, 6, 6, 5, 6, 1, 9, 9, 0, 6, 9, 0, 1, 5, 3, 5, 5, 5, 3, 5, 5, 9,
9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 1, 5, 6, 6, 1, 1, 1, 1, 1, 9,
9, 9, 6, 9, 0, 3, 6, 3, 1, 3, 3, 6, 6, 3, 9, 9, 0, 1, 9, 0, 5, 1, 1, 5, 6, 1, 1, 3, 5, 9,
9, 9, 3, 9, 0, 1, 3, 5, 6, 1, 6, 5, 1, 1, 9, 9, 0, 5, 9, 0, 6, 6, 1, 1, 3, 3, 6, 3, 5, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_ALPHA: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0, 9, 0, 6, 5, 5, 6, 5,
1, 1, 3, 3, 3, 3, 3, 3, 3, 9, 9, 9, 0, 9, 0, 3, 6, 6, 5, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 9,
9, 0, 0, 9, 0, 6, 1, 1, 6, 5, 5, 5, 3, 3, 5, 5, 5, 6, 6, 9, 9, 9, 1, 9, 0, 5, 3, 3, 5, 6,
3, 6, 5, 6, 1, 3, 6, 3, 5, 9, 9, 0, 6, 9, 0, 1, 1, 5, 3, 5, 6, 5, 1, 5, 6, 6, 5, 1, 1, 9,
9, 9, 3, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 0, 1, 9, 0, 1, 5, 5, 3, 1,
1, 3, 3, 3, 3, 3, 3, 3, 5, 9, 9, 9, 6, 9, 0, 5, 6, 6, 6, 3, 6, 1, 1, 1, 1, 1, 1, 1, 1, 9,
9, 0, 0, 9, 0, 3, 3, 3, 1, 5, 5, 3, 3, 5, 5, 5, 6, 6, 5, 9, 9, 9, 3, 9, 0, 1, 1, 1, 5, 1,
6, 1, 5, 1, 3, 6, 1, 3, 1, 9, 9, 0, 6, 9, 0, 3, 6, 3, 1, 3, 1, 5, 6, 3, 1, 1, 3, 5, 5, 9,
9, 9, 5, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 0, 1, 9, 0, 6, 1, 5, 1, 1,
1, 3, 3, 3, 3, 3, 3, 3, 1, 9, 9, 9, 5, 9, 0, 5, 6, 1, 5, 6, 6, 1, 1, 1, 1, 1, 1, 1, 3, 9,
9, 0, 0, 9, 0, 1, 5, 5, 6, 5, 5, 3, 3, 5, 5, 5, 6, 6, 5, 9, 9, 9, 0, 9, 0, 3, 3, 6, 1, 3,
6, 1, 6, 1, 3, 6, 1, 3, 3, 9, 9, 0, 0, 9, 0, 5, 1, 3, 3, 5, 3, 6, 1, 5, 5, 3, 5, 6, 1, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_ALPHANUM: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 1, 1,
3, 6, 5, 3, 3, 3, 1, 1, 1, 1, 1, 0, 5, 9, 9, 9, 3, 9, 0, 3, 6, 3, 5, 1, 6, 5, 5, 5, 6, 6,
6, 6, 6, 9, 1, 9, 9, 0, 6, 9, 0, 6, 1, 5, 3, 3, 5, 1, 1, 1, 1, 1, 3, 3, 3, 0, 5, 9, 9, 9,
3, 9, 0, 5, 5, 1, 5, 1, 6, 5, 6, 6, 3, 5, 1, 1, 5, 9, 1, 9, 9, 0, 6, 9, 0, 1, 6, 6, 6, 6,
5, 3, 1, 5, 6, 6, 3, 6, 3, 0, 5, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9,
0, 9, 0, 9, 9, 0, 3, 9, 0, 1, 3, 5, 6, 1, 1, 3, 3, 3, 1, 1, 1, 1, 1, 0, 1, 9, 9, 9, 1, 9,
0, 3, 6, 1, 3, 5, 3, 5, 5, 5, 6, 6, 6, 6, 6, 9, 3, 9, 9, 0, 3, 9, 0, 6, 5, 5, 1, 1, 1, 1,
1, 3, 1, 1, 3, 3, 3, 0, 5, 9, 9, 9, 6, 9, 0, 3, 3, 3, 5, 5, 6, 5, 6, 1, 5, 6, 1, 5, 5, 9,
1, 9, 9, 0, 5, 9, 0, 5, 1, 1, 3, 3, 3, 6, 3, 5, 3, 5, 5, 1, 6, 0, 5, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_UTF8: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 3, 3, 6, 6, 5, 1, 1,
5, 5, 5, 9, 9, 9, 3, 9, 0, 3, 5, 5, 5, 1, 6, 3, 3, 6, 6, 1, 9, 9, 0, 1, 9, 0, 6, 1, 3, 1,
5, 5, 1, 1, 1, 1, 5, 9, 9, 9, 3, 9, 0, 5, 6, 5, 3, 6, 6, 3, 5, 6, 6, 1, 9, 9, 0, 6, 9, 0,
1, 3, 1, 6, 1, 5, 5, 3, 1, 3, 5, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9,
0, 3, 9, 0, 1, 3, 1, 5, 1, 1, 1, 3, 3, 5, 1, 9, 9, 9, 6, 9, 0, 3, 6, 6, 3, 3, 3, 3, 6, 6,
6, 3, 9, 9, 0, 5, 9, 0, 5, 5, 5, 1, 6, 1, 1, 3, 3, 1, 5, 9, 9, 9, 3, 9, 0, 3, 1, 6, 5, 3,
6, 3, 5, 5, 5, 1, 9, 9, 0, 5, 9, 0, 6, 6, 5, 6, 1, 3, 6, 1, 6, 1, 5, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
const ULTRACODE_PIXS_FOX: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 0,
9, 0, 6, 5, 6, 1, 5, 3, 3, 3, 3, 3, 3, 1, 3, 1, 0, 3, 3, 1, 3, 3, 1, 9, 9, 9, 0, 9, 0, 3,
3, 5, 6, 6, 5, 5, 5, 5, 6, 5, 5, 5, 5, 9, 5, 5, 5, 6, 5, 5, 9, 9, 0, 0, 9, 0, 6, 1, 6, 3,
5, 3, 6, 1, 1, 1, 3, 3, 6, 3, 0, 1, 6, 3, 1, 1, 6, 9, 9, 9, 1, 9, 0, 5, 5, 3, 6, 6, 5, 3,
6, 5, 3, 1, 5, 1, 5, 9, 6, 5, 5, 5, 6, 5, 9, 9, 0, 6, 9, 0, 1, 6, 1, 3, 5, 1, 6, 1, 6, 6,
5, 1, 5, 1, 0, 5, 6, 1, 6, 3, 6, 9, 9, 9, 1, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9,
0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 1, 6, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3,
3, 3, 3, 3, 5, 9, 9, 9, 6, 9, 0, 6, 5, 6, 5, 3, 5, 6, 5, 5, 5, 5, 5, 5, 5, 9, 5, 5, 5, 6,
5, 1, 9, 9, 0, 0, 9, 0, 1, 3, 1, 3, 5, 1, 1, 3, 6, 6, 6, 3, 6, 6, 0, 6, 3, 6, 1, 6, 5, 9,
9, 9, 3, 9, 0, 3, 6, 5, 6, 1, 6, 3, 6, 5, 1, 3, 6, 3, 3, 9, 5, 5, 1, 5, 3, 1, 9, 9, 0, 5,
9, 0, 5, 3, 3, 1, 3, 5, 1, 5, 1, 6, 1, 1, 5, 1, 0, 1, 1, 3, 3, 1, 5, 9, 9, 9, 6, 9, 0, 9,
0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 6, 3, 6, 1,
3, 1, 3, 1, 3, 1, 3, 3, 3, 3, 0, 1, 3, 3, 1, 3, 1, 9, 9, 9, 5, 9, 0, 3, 6, 1, 6, 1, 5, 5,
5, 5, 5, 6, 6, 5, 6, 9, 5, 5, 5, 5, 5, 3, 9, 9, 0, 0, 9, 0, 5, 5, 3, 3, 5, 3, 3, 3, 6, 3,
1, 1, 6, 1, 0, 3, 1, 1, 3, 3, 5, 9, 9, 9, 0, 9, 0, 6, 1, 1, 5, 6, 5, 5, 5, 3, 5, 5, 3, 5,
3, 9, 5, 6, 5, 5, 1, 3, 9, 9, 0, 0, 9, 0, 5, 5, 3, 3, 5, 1, 6, 1, 1, 1, 1, 1, 3, 5, 0, 1,
5, 3, 1, 6, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
9, 9, 9,
];
#[test]
fn palette_shape_and_anchors() {
assert_eq!(ULTRACODE_PALETTE.len(), 8);
assert_eq!(ULTRACODE_PALETTE[0], Rgb8::new(0xff, 0xff, 0xff));
assert_eq!(ULTRACODE_PALETTE[1], Rgb8::new(0x00, 0xff, 0xff)); assert_eq!(ULTRACODE_PALETTE[2], Rgb8::new(0xff, 0x00, 0xff)); assert_eq!(ULTRACODE_PALETTE[3], Rgb8::new(0xff, 0xff, 0x00)); assert_eq!(ULTRACODE_PALETTE[4], Rgb8::new(0x00, 0xff, 0x00)); assert_eq!(ULTRACODE_PALETTE[5], Rgb8::new(0x00, 0x00, 0x00));
assert_eq!(ULTRACODE_PALETTE[6], ULTRACODE_PALETTE[0]);
assert_eq!(ULTRACODE_PALETTE[7], ULTRACODE_PALETTE[0]);
}
#[test]
fn bwipp_tile_digit_lookup_matches_colormap() {
assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[0], 0); assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[1], 1); assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[3], 2); assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[5], 3); assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[6], 4); assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[9], 5);
assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[2], 0);
assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[4], 0);
assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[7], 0);
assert_eq!(BWIPP_TILE_DIGIT_TO_PALETTE_IDX[8], 0);
assert_eq!(
ULTRACODE_PALETTE[BWIPP_TILE_DIGIT_TO_PALETTE_IDX[3] as usize],
Rgb8::new(0xff, 0x00, 0xff)
);
assert_eq!(
ULTRACODE_PALETTE[BWIPP_TILE_DIGIT_TO_PALETTE_IDX[9] as usize],
Rgb8::new(0x00, 0x00, 0x00)
);
}
#[test]
fn encode_rejects_empty_input() {
let err = encode("", &Options::default()).unwrap_err();
match err {
Error::InvalidData(msg) => {
assert!(
msg.contains("ultracode:"),
"empty diagnostic must carry ultracode prefix; got {msg}"
);
assert!(
msg.contains("empty input"),
"empty diagnostic must carry the predicate; got {msg}"
);
assert!(
!msg.contains("2500-byte"),
"empty diagnostic must NOT leak the size-limit arm wording; got {msg}"
);
}
other => panic!("expected InvalidData, got {other:?}"),
}
}
#[test]
fn encode_rejects_oversized_input() {
let input = "A".repeat(2501);
let err = encode(&input, &Options::default()).unwrap_err();
match err {
Error::InvalidData(msg) => {
assert!(
msg.contains("ultracode:"),
"oversize diagnostic must carry ultracode prefix; got {msg}"
);
assert!(
msg.contains("exceeds BWIPP"),
"oversize diagnostic must attribute the limit to BWIPP; got {msg}"
);
assert!(
msg.contains("2500-byte limit"),
"oversize diagnostic must name the 2500-byte cap; got {msg}"
);
assert!(
!msg.contains("empty input"),
"oversize diagnostic must NOT leak the empty-arm wording; got {msg}"
);
}
other => panic!("expected InvalidData, got {other:?}"),
}
}
#[test]
fn encode_default_options_equivalent_to_explicit_default() {
let baseline = encode("Hello", &Options::default()).unwrap_or_else(|e| {
panic!("ultracode encode(\"Hello\", default Options) failed: {e:?}")
});
let explicit = Options::default()
.with("eclevel", "EC2")
.with("rev", "2")
.with("parsefnc", "false")
.with("raw", "false")
.with("parse", "false")
.with("link1", "0")
.with("start", "257");
let restated = encode("Hello", &explicit).unwrap_or_else(|e| {
panic!(
"ultracode encode(\"Hello\", explicit-default Options eclevel=EC2 rev=2 parsefnc=false raw=false parse=false link1=0 start=257) failed: {e:?}"
)
});
assert_eq!(baseline.width(), restated.width());
assert_eq!(baseline.height(), restated.height());
for y in 0..baseline.height() {
for x in 0..baseline.width() {
assert_eq!(
baseline.get(x, y),
restated.get(x, y),
"cell ({x},{y}) drift between default and explicit-default options"
);
}
}
}
#[test]
fn encode_no_longer_returns_unimplemented_for_any_ultracode_opt() {
let trigger_cases: &[(&str, &str)] = &[
("eclevel", "EC0"), ("eclevel", "EC1"),
("eclevel", "EC3"),
("eclevel", "EC4"),
("eclevel", "EC5"),
("rev", "1"),
("link1", "1"),
("start", "258"),
("raw", "true"),
("parse", "true"),
("parsefnc", "true"),
];
for &(k, v) in trigger_cases {
let mut opts = Options::default().with(k, v);
if (k, v) == ("eclevel", "EC0") {
opts = opts.with("rev", "1");
}
let input = if k == "raw" { "^001^002" } else { "Hello" };
let result = encode(input, &opts);
if let Err(err) = result {
let kind = format!("{err:?}");
assert!(
!kind.starts_with("Unimplemented("),
"unexpected unimplemented variant for {k}={v:?}: {err:?}"
);
}
}
}
#[test]
fn encode_opts_corpus_matches_bwip_js_metadata() {
type OptsRow = (&'static str, u32, u32, u32, (u32, u32, u32, u32));
let cases: &[OptsRow] = &[
("Hello", 1, 2, 0, (8, 6, 3, 14)),
("Hello", 3, 2, 0, (8, 9, 6, 17)),
("Hello", 4, 2, 0, (8, 11, 8, 19)),
("Hello", 5, 2, 0, (8, 13, 10, 21)),
(
"The quick brown fox jumps over the lazy dog.",
3,
2,
0,
(47, 13, 10, 60),
),
("Hello", 2, 1, 0, (8, 7, 4, 15)),
("ABCDEFGHIJKLMNOP", 2, 1, 0, (19, 7, 4, 26)),
("Hello", 0, 1, 0, (8, 3, 0, 11)),
("A1B2C3", 0, 1, 0, (9, 3, 0, 12)),
("Hello", 2, 2, 1, (8, 7, 82, 15)),
("Hello", 2, 2, 2, (8, 7, 160, 15)),
];
for (text, eclval, rev, link1, want) in cases {
let dcws = build_dcws_default(text);
let got = ultracode_metadata(dcws.len(), *eclval, *link1);
assert_eq!(
got, *want,
"metadata mismatch for {text:?} eclvalue={eclval} rev={rev} link1={link1}"
);
let mut opts = Options::default();
let ecl_str = match eclval {
0 => "EC0",
1 => "EC1",
2 => "EC2",
3 => "EC3",
4 => "EC4",
5 => "EC5",
_ => unreachable!(),
};
opts = opts.with("eclevel", ecl_str);
opts = opts.with("rev", rev.to_string());
if *link1 > 0 {
opts = opts.with("link1", link1.to_string());
}
let parsed = check_ultracode_opts(&opts).expect("opts validate for in-corpus combo");
assert_eq!(parsed.eclval, *eclval);
assert_eq!(parsed.rev, *rev);
assert_eq!(parsed.link1, *link1);
let m = encode(text, &opts)
.unwrap_or_else(|e| panic!("encode failed for {text:?} {opts:?}: {e:?}"));
assert!(
m.width() > 0 && m.height() > 0,
"Ultracode encode({text:?}, eclvalue={eclval}, rev={rev}, link1={link1}) (metadata-corpus combo) must produce non-empty matrix; got {}×{}",
m.width(),
m.height()
);
}
}
#[test]
fn encode_ec0_requires_rev1() {
let err = encode("Hello", &Options::default().with("eclevel", "EC0")).unwrap_err();
match err {
Error::InvalidOption(msg) => {
assert!(
msg.contains("ultracode:"),
"EC0 cross-check must carry the ultracode prefix; got {msg:?}"
);
assert!(
msg.contains("eclevel=EC0"),
"EC0 cross-check must echo the parsed eclevel=EC0; got {msg:?}"
);
assert!(
msg.contains("requires rev=1"),
"EC0 cross-check must name the rev=1 requirement; got {msg:?}"
);
assert!(
msg.contains("(rev=2 requires EC1..EC5)"),
"EC0 cross-check must carry the rev=2 cross-reference hint; got {msg:?}"
);
}
other => panic!("expected InvalidOption, got {other:?}"),
}
let opts = Options::default().with("eclevel", "EC0").with("rev", "1");
assert!(
encode("Hello", &opts).is_ok(),
"encode(\"Hello\", eclevel=\"EC0\", rev=\"1\") (EC0 qcc=3 + rev=1 dccu/dccl path) must accept — the EC0+rev=1 combination is the smallest non-default Ultracode symbol"
);
}
#[test]
fn encode_start_threads_through_parsed_opts() {
let parsed = check_ultracode_opts(&Options::default().with("start", "258")).expect(
"check_ultracode_opts(start=258) (Ultracode start-option validation: 258 must reach parsed.start) must succeed",
);
assert_eq!(parsed.start, 258);
let parsed = check_ultracode_opts(&Options::default().with("start", "261")).expect(
"check_ultracode_opts(start=261) (Ultracode start-option validation: 261 must reach parsed.start) must succeed",
);
assert_eq!(parsed.start, 261);
assert!(
encode("Hello", &Options::default().with("start", "258")).is_ok(),
"encode(\"Hello\", start=\"258\") (start=258 threads through parsed_opts.start to the tile-sequence first codeword) must accept end-to-end"
);
}
#[test]
fn encode_pixs_ec0_rev1_matches_bwip_js() {
let opts = UltracodeOpts {
eclval: 0,
rev: 1,
link1: 0,
start: 257,
raw: false,
parse: false,
parsefnc: false,
};
let (rows, cols, pixs) = encode_pixs_with_opts("Hello", opts).expect(
"encode_pixs_with_opts(\"Hello\", EC0 rev=1) (Ultracode EC0+rev=1 shortest non-default: qcc=3 + rev=1 dccu/dccl; 13×13 pixs oracle) must succeed",
);
assert_eq!(rows, 13);
assert_eq!(cols, 13);
let want: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 5, 9, 0, 6, 5, 3, 5, 3, 3, 3, 9, 9, 9, 1,
9, 0, 3, 6, 5, 6, 1, 5, 5, 9, 9, 0, 6, 9, 0, 6, 1, 6, 5, 3, 6, 6, 9, 9, 9, 5, 9, 0, 5,
5, 1, 6, 5, 1, 3, 9, 9, 0, 3, 9, 0, 1, 6, 3, 5, 1, 3, 1, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0,
9, 0, 9, 9, 9, 0, 6, 9, 0, 1, 6, 1, 1, 3, 3, 1, 9, 9, 9, 1, 9, 0, 3, 1, 3, 3, 5, 5, 3,
9, 9, 0, 5, 9, 0, 5, 3, 5, 1, 1, 6, 1, 9, 9, 9, 3, 9, 0, 1, 1, 3, 3, 6, 1, 5, 9, 9, 0,
1, 9, 0, 6, 3, 6, 5, 5, 3, 6, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
assert_eq!(pixs.len(), 169);
assert_eq!(want.len(), 169);
assert_eq!(pixs, want, "pixs mismatch for Hello EC0 rev=1");
}
#[test]
fn encode_raw_dcws_matches_bwip_js_corpus() {
let cases: &[(&str, &[u32])] = &[
("^001^002^003", &[1, 2, 3]),
("^000^283^284", &[0, 283, 284]),
(
"^001^002^003^004^005^006^007^008^009^010^011^012",
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
),
];
for (text, want) in cases {
let got = parse_raw_codewords_ultracode(text.as_bytes()).unwrap_or_else(|e| {
panic!(
"parse_raw_codewords_ultracode({text:?}) (Ultracode raw=true ^NNN parser corpus) must succeed: {e:?}",
)
});
assert_eq!(&got, want, "dcws mismatch for {text:?}");
let bm = encode(text, &Options::default().with("raw", "true"))
.unwrap_or_else(|e| panic!("encode failed for {text:?}: {e:?}"));
assert!(bm.width() > 0 && bm.height() > 0);
}
}
#[test]
fn parse_raw_codewords_ultracode_rejects_malformed() {
let err = parse_raw_codewords_ultracode(b"AAA0").unwrap_err();
assert!(
err.contains("ultracode: raw codewords")
&& err.contains("expected `^` at offset 0")
&& err.contains("0x41"),
"bad-prefix must pin prefix-format + offset 0 + 'A' byte echo; got {err:?}"
);
let err = parse_raw_codewords_ultracode(b"^00X").unwrap_err();
assert!(
err.contains("non-digit") && err.contains("0x58") && err.contains("at offset 3"),
"non-digit must pin 'non-digit' + 'X' byte echo + offset 3; got {err:?}"
);
let err = parse_raw_codewords_ultracode(b"^285").unwrap_err();
assert!(
err.contains("must be 0..=284") && err.contains("285"),
"value-range must pin 0..=284 bound + 285 value echo; got {err:?}"
);
assert!(
!err.contains("non-digit") && !err.contains("expected `^`"),
"value-range must not leak other arms; got {err:?}"
);
let err = parse_raw_codewords_ultracode(b"^001^00").unwrap_err();
assert!(
err.contains("trailing")
&& err.contains("3 trailing byte(s)")
&& err.contains("at offset 4"),
"trailing-bytes must pin 'trailing' + count + offset 4; got {err:?}"
);
}
#[test]
fn parse_raw_codewords_ultracode_success_path_arithmetic_and_boundaries() {
assert_eq!(
parse_raw_codewords_ultracode(b"").unwrap(),
Vec::<u32>::new(),
"empty input → empty output"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^000").unwrap(),
vec![0u32],
"^000 → [0]"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^284").unwrap(),
vec![284u32],
"^284 → [284] (boundary value, must be accepted)"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^123").unwrap(),
vec![123u32],
"^123 → [123] (3-digit value pins accumulator)"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^001^002^003").unwrap(),
vec![1u32, 2, 3],
"^001^002^003 → [1, 2, 3] (pins stride + multi-token packing)"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^099^099").unwrap(),
vec![99u32, 99],
"^099^099 → [99, 99]"
);
assert_eq!(
parse_raw_codewords_ultracode(b"^200").unwrap(),
vec![200u32],
"^200 → [200] (full 3-digit window)"
);
}
#[test]
fn encode_parse_dcws_matches_bwip_js_corpus() {
let cases: &[(&str, &[u32])] = &[
("^065BC", &[65, 66, 67]),
("^065^066^067", &[65, 66, 67]),
("X^TABY", &[88, 9, 89]),
("FOO^^BAR", &[70, 79, 79, 94, 94, 66, 65, 82]),
];
for (text, want) in cases {
let got = build_dcws_with_input_opts(text, true, false).unwrap_or_else(|e| {
panic!(
"build_dcws_with_input_opts({text:?}, parse=true, parsefnc=false) (Ultracode parseinput corpus, no `^^` collapse) must succeed: {e:?}",
)
});
assert_eq!(&got, want, "dcws mismatch for {text:?}");
assert!(
encode(text, &Options::default().with("parse", "true")).is_ok(),
"encode({text:?}, parse=\"true\") (Ultracode parse-true corpus item) must succeed end-to-end after dcws byte-for-byte match"
);
}
}
#[test]
fn encode_parsefnc_dcws_matches_bwip_js_corpus() {
let cases: &[(&str, &[u32])] = &[
("ABC^FNC1DEF", &[65, 66, 67, 268, 68, 69, 70]),
("^FNC1A^FNC3B", &[268, 65, 269, 66]),
("FOO^^BAR", &[70, 79, 79, 94, 66, 65, 82]),
];
for (text, want) in cases {
let got = build_dcws_with_input_opts(text, false, true).unwrap_or_else(|e| {
panic!(
"build_dcws_with_input_opts({text:?}, parse=false, parsefnc=true) (Ultracode parsefnc corpus emitting FNC1=268 / FNC3=269 + `^^` collapse) must succeed: {e:?}",
)
});
assert_eq!(&got, want, "dcws mismatch for {text:?}");
assert!(
encode(text, &Options::default().with("parsefnc", "true")).is_ok(),
"encode({text:?}, parsefnc=\"true\") (Ultracode parsefnc-true corpus item with FNC1=268 / FNC3=269 codewords) must succeed end-to-end"
);
}
}
#[test]
fn encode_rejects_invalid_input_opt_values() {
for k in &["raw", "parse", "parsefnc"] {
let err = encode("Hello", &Options::default().with(*k, "maybe")).unwrap_err();
match err {
Error::InvalidOption(msg) => {
assert!(
msg.contains("ultracode:"),
"missing ultracode prefix for {k}: {msg:?}"
);
let kv = format!("{k}=\"maybe\"");
assert!(
msg.contains(&kv),
"missing key=value echo {kv:?} for {k}: {msg:?}"
);
assert!(
msg.contains("must be"),
"missing predicate `must be` for {k}: {msg:?}"
);
assert!(
msg.contains("\"true\"") && msg.contains("\"false\""),
"missing valid-values \"true\"/\"false\" for {k}: {msg:?}"
);
match *k {
"raw" => {
assert!(
!msg.contains("parse=") && !msg.contains("parsefnc="),
"cross-option contamination: raw={msg:?}"
);
}
"parse" => {
assert!(
!msg.contains("parsefnc="),
"cross-option contamination: parse= leaked parsefnc=: {msg:?}"
);
assert!(
!msg.contains("raw="),
"cross-option contamination: parse= leaked raw=: {msg:?}"
);
}
"parsefnc" => {
assert!(
!msg.contains("raw="),
"cross-option contamination: parsefnc= leaked raw=: {msg:?}"
);
}
_ => unreachable!(),
}
}
other => panic!("expected InvalidOption for {k}, got {other:?}"),
}
}
}
#[test]
fn encode_parse_rejects_ordinal_above_255() {
let err = encode("^999X", &Options::default().with("parse", "true")).unwrap_err();
let Error::InvalidData(msg) = err else {
panic!("parse=true with ^999 must yield InvalidData; got {err:?}");
};
assert!(
msg.contains("ultracode parse:"),
"diagnostic must carry the 'ultracode parse:' prefix; got {msg:?}"
);
assert!(
msg.contains("ordinal must be 000..=255"),
"diagnostic must carry the 000..=255 bound text; got {msg:?}"
);
assert!(
msg.contains("999"),
"diagnostic must echo the offending value 999 via {{value}}; got {msg:?}"
);
}
#[test]
fn encode_pixs_ec1_rev2_matches_bwip_js() {
let opts = UltracodeOpts {
eclval: 1,
rev: 2,
link1: 0,
start: 257,
raw: false,
parse: false,
parsefnc: false,
};
let (rows, cols, pixs) = encode_pixs_with_opts("Hello", opts).expect(
"encode_pixs_with_opts(\"Hello\", EC1 rev=2) (Ultracode EC1+rev=2 smallest non-default eclevel; 13×15 pixs oracle) must succeed",
);
assert_eq!(rows, 13);
assert_eq!(cols, 15);
let want: &[i32] = &[
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 1, 9, 0, 6, 1, 5, 1, 1, 1, 3, 3, 5,
9, 9, 9, 3, 9, 0, 3, 3, 1, 5, 3, 3, 5, 5, 1, 9, 9, 0, 6, 9, 0, 6, 1, 6, 3, 5, 1, 1, 6,
5, 9, 9, 9, 1, 9, 0, 5, 5, 3, 6, 6, 5, 6, 1, 1, 9, 9, 0, 6, 9, 0, 1, 3, 5, 5, 5, 6, 5,
3, 5, 9, 9, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 0, 9, 9, 9, 0, 3, 9, 0, 1, 6, 3, 6, 5, 3,
3, 3, 1, 9, 9, 9, 6, 9, 0, 3, 3, 6, 5, 6, 1, 5, 5, 3, 9, 9, 0, 1, 9, 0, 5, 5, 3, 6, 5,
3, 6, 6, 5, 9, 9, 9, 3, 9, 0, 1, 6, 1, 1, 6, 5, 1, 3, 1, 9, 9, 0, 5, 9, 0, 6, 1, 6, 3,
5, 1, 3, 1, 3, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
];
assert_eq!(pixs, want, "pixs mismatch for Hello EC1 rev=2");
}
#[test]
fn encode_rejects_invalid_option_values() {
let cases: &[(&str, &str)] = &[
("eclevel", "XX"),
("eclevel", "EC9"),
("rev", "3"),
("rev", "abc"),
("parsefnc", "maybe"),
("raw", "yes"),
("parse", "no"),
("link1", "-1"),
("link1", "1.5"),
("start", "-2"),
("start", "x"),
];
for &(k, v) in cases {
let opts = Options::default().with(k, v);
let err = encode("Hello", &opts).unwrap_err();
match err {
Error::InvalidOption(msg) => {
assert!(
msg.contains("ultracode:"),
"missing ultracode prefix for {k}={v:?}: {msg:?}"
);
let kv = format!("{k}={v:?}");
assert!(
msg.contains(&kv),
"missing key=value echo {kv:?} for {k}={v:?}: {msg:?}"
);
match k {
"eclevel" | "rev" => {
assert!(
msg.contains("is not a valid BWIPP value"),
"missing predicate for {k}={v:?}: {msg:?}"
);
}
"parsefnc" | "raw" | "parse" => {
assert!(
msg.contains("must be")
&& msg.contains("\"true\"")
&& msg.contains("\"false\""),
"missing must-be true/false for {k}={v:?}: {msg:?}"
);
}
"link1" | "start" => {
assert!(
msg.contains("must be a non-negative integer"),
"missing non-negative-integer predicate for {k}={v:?}: {msg:?}"
);
}
_ => unreachable!(),
}
for other in ["eclevel", "rev", "parsefnc", "link1", "start"] {
if other == k {
continue;
}
if k == "parsefnc" && other == "parse" {
continue;
}
if other == "raw" {
continue;
}
assert!(
!msg.contains(&format!("{other}=")),
"cross-key contamination: {k}={v:?} msg mentions {other}=: {msg:?}"
);
}
}
other => panic!("expected InvalidOption for {k}={v:?}, got {other:?}"),
}
}
}
#[test]
fn metrics_shape_matches_bwipp() {
assert_eq!(ULTRACODE_METRICS.len(), 4);
assert_eq!(ULTRACODE_METRICS[0], [2, 7, 37, 5]);
assert_eq!(ULTRACODE_METRICS[1], [3, 36, 84, 13]);
assert_eq!(ULTRACODE_METRICS[2], [4, 85, 161, 22]);
assert_eq!(ULTRACODE_METRICS[3], [5, 142, 282, 29]);
for [rows, minc, maxc, _mcol] in ULTRACODE_METRICS {
assert!((2..=5).contains(&rows), "rows must be in 2..=5");
assert!(minc <= maxc, "metrics row must have minc <= maxc");
}
for w in ULTRACODE_METRICS.windows(2) {
assert!(w[0][0] < w[1][0], "rows strictly monotonic");
}
}
#[test]
fn tiles_shape_and_sentinel_values() {
assert_eq!(ULTRACODE_TILES.len(), 285);
assert_eq!(ULTRACODE_TILES[0], 13135);
assert_eq!(ULTRACODE_TILES[1], 13136);
assert_eq!(ULTRACODE_TILES[107], 35365);
assert_eq!(ULTRACODE_TILES[283], 56565);
assert_eq!(ULTRACODE_TILES[284], 51515);
for (i, &tile) in ULTRACODE_TILES.iter().enumerate() {
assert!(
(10000..=99999).contains(&tile),
"tile[{i}] = {tile} is not a 5-digit number"
);
let mut t = tile;
for _ in 0..5 {
let d = t % 10;
assert!(
matches!(d, 0 | 1 | 3 | 5 | 6 | 9),
"tile[{i}] = {tile} uses undefined BWIPP digit {d}"
);
t /= 10;
}
}
}
#[test]
fn dccu_dccl_revs_shape_and_anchors() {
for t in [
&ULTRACODE_DCCUREV1,
&ULTRACODE_DCCLREV1,
&ULTRACODE_DCCUREV2,
&ULTRACODE_DCCLREV2,
] {
assert_eq!(t.len(), 32);
for &v in t.iter() {
assert!((10000..=99999).contains(&v), "dcc tile {v} is not 5 digits");
}
}
assert_eq!(ULTRACODE_DCCUREV1[0], 51363);
assert_eq!(ULTRACODE_DCCUREV1[31], 56536);
assert_eq!(ULTRACODE_DCCLREV1[0], 61351);
assert_eq!(ULTRACODE_DCCLREV1[31], 36531);
assert_eq!(ULTRACODE_DCCUREV2[0], 15316);
assert_eq!(ULTRACODE_DCCUREV2[31], 13563);
assert_eq!(ULTRACODE_DCCLREV2[0], 36315);
assert_eq!(ULTRACODE_DCCLREV2[31], 63565);
}
#[test]
fn qccfact_matches_bwipp() {
assert_eq!(ULTRACODE_QCCFACT, [0, 1, 2, 4, 6, 8]);
}
#[test]
fn ultracode_metadata_arithmetic() {
assert_eq!(ultracode_metadata(10, 0, 0), (13, 3, 0, 16));
assert_eq!(
ultracode_metadata(50, 0, 0),
(53, 3, 0, 56),
"eclval=0 → qcc=3 regardless of mcc"
);
assert_eq!(ultracode_metadata(10, 2, 0), (13, 7, 4, 20));
assert_eq!(
ultracode_metadata(22, 2, 0),
(25, 7, 4, 32),
"mcc=25 exact: bucket=1, not 2"
);
assert_eq!(ultracode_metadata(25, 3, 1), (28, 13, 88, 41));
assert_eq!(ultracode_metadata(22, 5, 2), (25, 13, 166, 38));
let (mcc, qcc, _, tcc) = ultracode_metadata(15, 4, 0);
assert_eq!(tcc, mcc + qcc, "tcc = mcc + qcc invariant");
}
#[test]
fn rs_field_and_reserved_codewords() {
assert_eq!(ULTRACODE_RS_PRIME, 283);
assert_eq!(ULTRACODE_RS_PRIMITIVE, 3);
let n = ULTRACODE_RS_PRIME;
for k in 2..=((n as f64).sqrt() as u32) {
assert!(n % k != 0, "{n} unexpectedly divisible by {k}");
}
assert_eq!(ULTRACODE_CW_START, 257);
assert_eq!(ULTRACODE_CW_FNC1, 268);
assert_eq!(ULTRACODE_CW_FNC3, 269);
assert_eq!(ULTRACODE_CW_PAD, 284);
}
#[test]
fn rs_tables_are_inverse_pairs() {
let (alog, log) = build_rs_tables();
assert_eq!(alog.len(), 282);
assert_eq!(log.len(), 283);
assert_eq!(alog[0], 1);
for i in 1..282 {
assert_eq!(log[alog[i] as usize], i as u32);
}
let mut seen = vec![false; 283];
for &v in &alog {
assert!(v != 0 && !seen[v as usize], "alog repeats or hits 0");
seen[v as usize] = true;
}
}
#[test]
fn rs_prod_basics() {
let (alog, log) = build_rs_tables();
assert_eq!(rs_prod(0, 5, &alog, &log), 0);
assert_eq!(rs_prod(5, 0, &alog, &log), 0);
assert_eq!(rs_prod(1, 1, &alog, &log), 1);
assert_eq!(rs_prod(3, 3, &alog, &log), 9);
}
#[test]
fn rs_ecprime_pins_lfsr_arithmetic_with_small_field() {
let coeffs_a = vec![1u32, 2, 3];
assert_eq!(
rs_ecprime(&[1], &coeffs_a, 3, 5),
vec![3, 2, 1],
"(A) nc=3, prime=5, coeffs=[1,2,3], data=[1]: \
lfsr must be coefficient-reversed (pins coeffs[nc-l-1] indexing)"
);
assert_eq!(
rs_ecprime(&[1, 2], &coeffs_a, 3, 5),
vec![4, 4, 4],
"(B) nc=3, prime=5, coeffs=[1,2,3], data=[1,2]: \
all-4 result confirms feedback + lfsr forward-shift"
);
let coeffs_c = vec![2u32, 3];
assert_eq!(
rs_ecprime(&[1], &coeffs_c, 2, 5),
vec![3, 2],
"(C) nc=2, prime=5, coeffs=[2,3], data=[1]: lfsr=[3,2]"
);
assert_eq!(
rs_ecprime(&[1, 2], &coeffs_c, 2, 5),
vec![4, 3],
"(D) nc=2, prime=5, coeffs=[2,3], data=[1,2]: lfsr=[4,3]"
);
let coeffs_e = vec![3u32];
assert_eq!(
rs_ecprime(&[2], &coeffs_e, 1, 5),
vec![1],
"(E) nc=1, prime=5, coeffs=[3], data=[2]: \
only the final-slot assignment runs"
);
assert_eq!(
rs_ecprime(&[], &coeffs_a, 3, 5),
vec![0, 0, 0],
"(F) empty data: lfsr stays at initial zeros"
);
}
#[test]
fn metadata_matches_corpus() {
let cases: &[(&str, usize, u32, u32, u32, u32)] = &[
("A", 1, 2, 4, 7, 11),
("Hello", 5, 2, 8, 7, 15),
("Hello, World!", 13, 2, 16, 7, 23),
("12345", 5, 2, 8, 7, 15),
("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26, 2, 29, 9, 38),
("abcdef0123456789", 16, 2, 19, 7, 26),
("\\x00..\\xff (utf8)", 8, 2, 11, 7, 18),
(
"The quick brown fox jumps over the lazy dog.",
44,
2,
47,
9,
56,
),
];
for &(label, dcws_len, eclval, exp_mcc, exp_qcc, exp_tcc) in cases {
let (mcc, qcc, acc, tcc) = ultracode_metadata(dcws_len, eclval, 0);
assert_eq!(mcc, exp_mcc, "mcc for {label:?}");
assert_eq!(qcc, exp_qcc, "qcc for {label:?}");
assert_eq!(tcc, exp_tcc, "tcc for {label:?}");
assert_eq!(acc, exp_qcc - 3, "acc derivation for {label:?}");
}
}
#[test]
fn gen_coeffs_matches_corpus() {
let cases: &[(usize, &[u32])] = &[
(7, &[87, 125, 83, 280, 21, 114, 117]),
(9, &[225, 27, 162, 126, 127, 81, 3, 21, 192]),
];
for &(qcc, expected) in cases {
let got = gen_coeffs(qcc);
assert_eq!(got, expected, "gen_coeffs({qcc}) mismatch");
}
}
#[test]
fn pick_symbol_size_matches_corpus() {
let cases: &[(&str, u32, u32, u32)] = &[
("A", 11, 13, 13),
("Hello", 15, 13, 15),
("Hello, World!", 23, 13, 19),
("12345", 15, 13, 15),
("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 38, 19, 20),
("abcdef0123456789", 26, 13, 22),
("UTF8 high-byte", 18, 13, 17),
("the quick brown fox", 56, 19, 27),
];
for &(label, tcc, exp_rows, exp_cols) in cases {
let (_m, rows, cols, _pads) = pick_symbol_size(tcc).unwrap_or_else(|| {
panic!("pick_symbol_size returned None for {label} (tcc={tcc})")
});
assert_eq!(
rows * 6 + 1,
exp_rows,
"rows mismatch for {label}: got {rows}*6+1={}, expected {exp_rows}",
rows * 6 + 1
);
assert_eq!(
cols + 6,
exp_cols,
"cols mismatch for {label}: got {cols}+6={}, expected {exp_cols}",
cols + 6
);
}
}
#[test]
fn digits_5_matches_bwipp_zero_padding() {
assert_eq!(digits_5(13135), [1, 3, 1, 3, 5]);
assert_eq!(digits_5(56565), [5, 6, 5, 6, 5]);
assert_eq!(digits_5(51363), [5, 1, 3, 6, 3]);
assert_eq!(digits_5(0), [0, 0, 0, 0, 0]);
assert_eq!(digits_5(7), [0, 0, 0, 0, 7]);
}
#[test]
fn encode_pixs_default_matches_corpus() {
type Row = (&'static str, u32, u32, &'static [i32]);
let cases: &[Row] = &[
("A", 13, 13, ULTRACODE_PIXS_A),
("Hello", 13, 15, ULTRACODE_PIXS_HELLO),
("Hello, World!", 13, 19, ULTRACODE_PIXS_HELLO_WORLD),
("12345", 13, 15, ULTRACODE_PIXS_12345),
("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 19, 20, ULTRACODE_PIXS_ALPHA),
("abcdef0123456789", 13, 22, ULTRACODE_PIXS_ALPHANUM),
(
"\u{0}\u{1}\u{2}\u{7f}\u{80}\u{ff}",
13,
17,
ULTRACODE_PIXS_UTF8,
),
(
"The quick brown fox jumps over the lazy dog.",
19,
27,
ULTRACODE_PIXS_FOX,
),
];
for &(input, exp_rows, exp_cols, expected) in cases {
let (rows, cols, got) =
encode_pixs_default(input).unwrap_or_else(|e| panic!("{input:?}: {e:?}"));
assert_eq!(rows, exp_rows, "rows mismatch for {input:?}");
assert_eq!(cols, exp_cols, "cols mismatch for {input:?}");
assert_eq!(got.len(), expected.len(), "pixs length for {input:?}");
for (i, &v) in got.iter().enumerate() {
assert!(v >= 0, "{input:?}: pixs[{i}] is -1 (unset)");
}
assert_eq!(
got, expected,
"{input:?}: pixs grid mismatch (rows={rows}, cols={cols})"
);
}
}
#[test]
fn encode_public_returns_color_matrix_with_correct_palette() {
let matrix = encode("A", &Options::default()).expect("encode 'A'");
assert_eq!(matrix.width(), 13);
assert_eq!(matrix.height(), 13);
assert_eq!(matrix.cell_color(0, 0), Rgb8::new(0, 0, 0));
assert_eq!(matrix.palette()[1], Rgb8::new(0x00, 0xff, 0xff));
}
#[test]
fn ecc_codewords_match_corpus() {
type Row = (&'static str, &'static [u32], u32, u32, &'static [u32]);
let cases: &[Row] = &[
("A", &[65], 4, 7, &[100, 2, 78, 70, 131, 251, 169]),
(
"Hello",
&[72, 101, 108, 108, 111],
8,
7,
&[159, 143, 249, 150, 50, 146, 139],
),
(
"Hello, World!",
&[72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33],
16,
7,
&[208, 97, 197, 178, 196, 114, 270],
),
(
"12345",
&[49, 50, 51, 52, 53],
8,
7,
&[14, 190, 49, 238, 269, 227, 14],
),
(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
&[
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
85, 86, 87, 88, 89, 90,
],
29,
9,
&[260, 188, 199, 64, 189, 197, 154, 282, 120],
),
(
"abcdef0123456789",
&[
97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
],
19,
7,
&[50, 134, 8, 151, 105, 239, 214],
),
(
"high-byte UTF-8",
&[0, 1, 2, 127, 194, 128, 195, 191],
11,
7,
&[100, 133, 104, 69, 261, 169, 227],
),
(
"The quick brown fox jumps over the lazy dog.",
&[
84, 104, 101, 32, 113, 117, 105, 99, 107, 32, 98, 114, 111, 119, 110, 32, 102,
111, 120, 32, 106, 117, 109, 112, 115, 32, 111, 118, 101, 114, 32, 116, 104,
101, 32, 108, 97, 122, 121, 32, 100, 111, 103, 46,
],
47,
9,
&[252, 169, 275, 132, 279, 49, 212, 59, 106],
),
];
for &(label, dcws, mcc, qcc, expected) in cases {
let acc = qcc - 3; let mut rsdata = vec![ULTRACODE_CW_START, mcc, acc];
rsdata.extend_from_slice(dcws);
let got = ecc_codewords(&rsdata, qcc as usize);
assert_eq!(
got, expected,
"ecws mismatch for {label:?}: got {got:?}, expected {expected:?}"
);
}
}
#[test]
fn encode_property_random_inputs_never_panic_and_use_only_defined_palette() {
let mut state: u32 = 0x1234_5678;
let mut next = || {
state = state.wrapping_mul(1_103_515_245).wrapping_add(12345);
state
};
const MAX_LEN: usize = 250;
for iter in 0..200 {
let len = 1 + (next() as usize % MAX_LEN); let mut input = Vec::with_capacity(len);
for _ in 0..len {
input.push((next() & 0xff) as u8);
}
let s = String::from_utf8_lossy(&input);
let matrix = match encode(&s, &Options::default()) {
Ok(m) => m,
Err(Error::InvalidData(_)) => continue,
Err(other) => panic!("iter {iter}: unexpected error {other:?}"),
};
let w = matrix.width() as u32;
let h = matrix.height() as u32;
assert!((h - 1) % 6 == 0, "iter {iter}: height {h} is not rows*6+1");
let rows = (h - 1) / 6;
assert!(
(2..=5).contains(&rows),
"iter {iter}: derived rows {rows} out of range 2..=5"
);
assert!(
w >= 6 + ULTRACODE_METRICS[(rows - 2) as usize][3],
"iter {iter}: width {w} below mcol+6 for rows={rows}"
);
for y in 0..matrix.height() {
for x in 0..matrix.width() {
let idx = matrix.get(x, y);
assert!(
idx <= 5,
"iter {iter}: cell ({x},{y}) has reserved palette idx {idx}"
);
}
}
}
}
#[test]
fn digits_5_boundary_values() {
assert_eq!(digits_5(0), [0, 0, 0, 0, 0]);
assert_eq!(digits_5(1), [0, 0, 0, 0, 1]);
assert_eq!(digits_5(10), [0, 0, 0, 1, 0]);
assert_eq!(digits_5(12345), [1, 2, 3, 4, 5]);
assert_eq!(digits_5(99999), [9, 9, 9, 9, 9]);
assert_eq!(digits_5(100000), [0, 0, 0, 0, 0]);
}
#[test]
fn rs_prod_zero_short_circuit() {
let (alog, log) = build_rs_tables();
assert_eq!(rs_prod(0, 5, &alog, &log), 0);
assert_eq!(rs_prod(0, 200, &alog, &log), 0);
assert_eq!(rs_prod(5, 0, &alog, &log), 0);
assert_eq!(rs_prod(200, 0, &alog, &log), 0);
assert_eq!(rs_prod(0, 0, &alog, &log), 0);
assert_eq!(rs_prod(1, 5, &alog, &log), 5);
assert_eq!(rs_prod(5, 1, &alog, &log), 5);
assert_eq!(rs_prod(1, 1, &alog, &log), 1);
let prod = rs_prod(2, 3, &alog, &log);
assert_ne!(prod, 0);
}
#[test]
fn build_dcws_default_byte_to_u32_mapping_preserves_order() {
assert_eq!(build_dcws_default(""), Vec::<u32>::new());
assert_eq!(build_dcws_default("A"), vec![65]);
assert_eq!(
build_dcws_default("ABC"),
vec![65, 66, 67],
"ASCII order preserved (catches .rev() mutant)"
);
assert_eq!(build_dcws_default("0"), vec![48]);
assert_eq!(build_dcws_default("9"), vec![57]);
assert_eq!(build_dcws_default("Hello"), vec![72, 101, 108, 108, 111]);
let out = build_dcws_default("é");
assert_eq!(
out,
vec![0xC3, 0xA9],
"UTF-8 multi-byte char emits each byte as separate u32"
);
for s in [
"",
"x",
"xy",
"Hello, world!",
"0123456789",
&"a".repeat(50),
] {
let out = build_dcws_default(s);
assert_eq!(
out.len(),
s.len(),
"ASCII input {s:?}: byte length must equal output length"
);
}
}
#[test]
fn digits_5_lsb_at_end_with_msb_first_layout() {
assert_eq!(
super::digits_5(0),
[0, 0, 0, 0, 0],
"zero input → all-zero output"
);
assert_eq!(
super::digits_5(7),
[0, 0, 0, 0, 7],
"single-digit input lands in LSB slot (index 4)"
);
assert_eq!(
super::digits_5(70_000),
[7, 0, 0, 0, 0],
"10000×d lands in MSB slot (index 0)"
);
assert_eq!(
super::digits_5(12_345),
[1, 2, 3, 4, 5],
"12345 → [1,2,3,4,5] (MSB→LSB layout, distinct per slot)"
);
assert_eq!(
super::digits_5(54_321),
[5, 4, 3, 2, 1],
"54321 → [5,4,3,2,1] (reverse pattern)"
);
assert_eq!(
super::digits_5(99_999),
[9, 9, 9, 9, 9],
"99999 → all-9 (saturated 5-digit)"
);
assert_eq!(
super::digits_5(10_000),
[1, 0, 0, 0, 0],
"10000 → leading 1, four trailing zeros"
);
assert_eq!(
super::digits_5(100_000),
[0, 0, 0, 0, 0],
"100000 wraps modulo 10^5 → all zero"
);
assert_eq!(
super::digits_5(123_456),
[2, 3, 4, 5, 6],
"123456 wraps to bottom 5 base-10 digits → [2,3,4,5,6]"
);
for v in [0u32, 1, 9, 10, 99, 100, 9_999, 10_000, 99_999] {
let d = super::digits_5(v);
for (i, &di) in d.iter().enumerate() {
assert!(di <= 9, "digit {di} at slot {i} (v={v}) exceeds 0..=9");
}
let reconstructed = u32::from(d[0]) * 10_000
+ u32::from(d[1]) * 1_000
+ u32::from(d[2]) * 100
+ u32::from(d[3]) * 10
+ u32::from(d[4]);
assert_eq!(
reconstructed, v,
"digits_5({v}) = {d:?} should reconstruct via MSB→LSB place values"
);
}
}
#[test]
fn check_ultracode_opts_rejection_arms() {
use crate::error::Error;
let opts = Options::default().with("rev", "3");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => {
assert!(
m.contains("ultracode:"),
"rev=3 diagnostic must carry the ultracode prefix; got {m}"
);
assert!(
m.contains("rev=\"3\""),
"rev=3 diagnostic must Debug-echo the raw value; got {m}"
);
assert!(
m.contains("not a valid BWIPP value"),
"rev=3 diagnostic must carry the predicate; got {m}"
);
assert!(
m.contains("(valid: 1 or 2)"),
"rev=3 diagnostic must name the valid revs (1 or 2); got {m}"
);
}
other => panic!("rev=3 should reject, got {other:?}"),
}
let opts = Options::default().with("eclevel", "EC9");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => {
assert!(
m.contains("ultracode:"),
"eclevel=EC9 diagnostic must carry the ultracode prefix; got {m}"
);
assert!(
m.contains("eclevel=\"EC9\""),
"eclevel=EC9 diagnostic must Debug-echo the raw value; got {m}"
);
assert!(
m.contains("not a valid BWIPP value"),
"eclevel=EC9 diagnostic must carry the predicate; got {m}"
);
assert!(
m.contains("(valid: EC0/EC1/EC2/EC3/EC4/EC5)"),
"eclevel=EC9 diagnostic must name all valid ec levels; got {m}"
);
}
other => panic!("eclevel=EC9 should reject, got {other:?}"),
}
let opts = Options::default().with("eclevel", "EC0");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => assert!(
m.contains("eclevel=EC0") && m.contains("rev=1"),
"expected EC0+rev=2 cross-check, got: {m}"
),
other => panic!("EC0 with default rev=2 should reject, got {other:?}"),
}
let opts = Options::default().with("eclevel", "EC0").with("rev", "1");
assert!(
check_ultracode_opts(&opts).is_ok(),
"EC0 + rev=1 should validate cleanly (cross-check minimum satisfied)"
);
let opts = Options::default().with("parsefnc", "maybe");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => {
assert!(
m.contains("ultracode: parsefnc=\"maybe\""),
"parsefnc=maybe must echo full prefix + Debug-value; got {m}"
);
assert!(
m.contains("must be"),
"parsefnc=maybe must carry the predicate; got {m}"
);
assert!(
m.contains("\"true\"") && m.contains("\"false\""),
"parsefnc=maybe must name BOTH valid values; got {m}"
);
}
other => panic!("parsefnc=maybe should reject, got {other:?}"),
}
let opts = Options::default().with("raw", "yes");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => {
assert!(
m.contains("ultracode: raw=\"yes\""),
"raw=yes must echo full prefix + Debug-value; got {m}"
);
assert!(
m.contains("must be"),
"raw=yes must carry the predicate; got {m}"
);
assert!(
m.contains("\"true\"") && m.contains("\"false\""),
"raw=yes must name BOTH valid values; got {m}"
);
}
other => panic!("raw=yes should reject, got {other:?}"),
}
let opts = Options::default().with("parse", "off");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => {
assert!(
m.contains("ultracode: parse=\"off\""),
"parse=off must echo full prefix + Debug-value; got {m}"
);
assert!(
m.contains("must be"),
"parse=off must carry the predicate; got {m}"
);
assert!(
m.contains("\"true\"") && m.contains("\"false\""),
"parse=off must name BOTH valid values; got {m}"
);
}
other => panic!("parse=off should reject, got {other:?}"),
}
let opts = Options::default().with("link1", "abc");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => assert!(
m.contains("link1=\"abc\"") && m.contains("non-negative integer"),
"expected link1 parse-fail rejection, got: {m}"
),
other => panic!("link1=abc should reject, got {other:?}"),
}
let opts = Options::default().with("start", "-1");
match check_ultracode_opts(&opts) {
Err(Error::InvalidOption(m)) => assert!(
m.contains("start=\"-1\"") && m.contains("non-negative integer"),
"expected start parse-fail rejection, got: {m}"
),
other => panic!("start=-1 should reject, got {other:?}"),
}
}
#[test]
fn build_dcws_with_input_opts_escape_grid_fingerprint_pinned() {
fn fp(v: Result<Vec<u32>, String>) -> (bool, usize, u64) {
match v {
Ok(dcws) => {
let mut s: u64 = 0;
for (i, &c) in dcws.iter().enumerate() {
s =
s.wrapping_add((c as u64).wrapping_mul(
(i as u64).wrapping_add(1).wrapping_mul(2_654_435_761),
));
}
(true, dcws.len(), s)
}
Err(_) => (false, 0, 0),
}
}
let cases: &[(&str, &str, bool, bool, (bool, usize, u64))] = &[
("plain", "Hello, World!", false, false, FP_DCWS_PLAIN),
("fnc1", "A^FNC1B", false, true, FP_DCWS_FNC1),
("fnc3", "^FNC3X", false, true, FP_DCWS_FNC3),
("caret_lit", "X^^Y", false, true, FP_DCWS_CARET_LIT),
("ctrl_tab", "A^TABB", true, false, FP_DCWS_CTRL_TAB),
("ctrl_lf", "A^LFB", true, false, FP_DCWS_CTRL_LF),
("ctrl_esc", "A^ESCB", true, false, FP_DCWS_CTRL_ESC),
("ord_065", "^065^066", true, false, FP_DCWS_ORD_ABC),
("ord_999", "^999", true, false, FP_DCWS_ORD_999_ERR),
("unmatched", "A^XYZ", true, false, FP_DCWS_UNMATCHED),
("both_fnc", "^FNC1^065", true, true, FP_DCWS_BOTH),
("eos_short", "A^FN", false, true, FP_DCWS_EOS_SHORT),
("eos_3byte", "A^TA", true, false, FP_DCWS_EOS_3BYTE),
];
for (tag, input, parse, parsefnc, want) in cases {
let got = fp(build_dcws_with_input_opts(input, *parse, *parsefnc));
assert_eq!(got, *want, "fingerprint changed for {tag}");
}
}
const FP_DCWS_PLAIN: (bool, usize, u64) = (true, 13, 20505516253725);
const FP_DCWS_FNC1: (bool, usize, u64) = (true, 3, 2120894173039);
const FP_DCWS_FNC3: (bool, usize, u64) = (true, 2, 1181223913645);
const FP_DCWS_CARET_LIT: (bool, usize, u64) = (true, 3, 1441358618223);
const FP_DCWS_CTRL_TAB: (bool, usize, u64) = (true, 3, 745896448841);
const FP_DCWS_CTRL_LF: (bool, usize, u64) = (true, 3, 751205320363);
const FP_DCWS_CTRL_ESC: (bool, usize, u64) = (true, 3, 841456136237);
const FP_DCWS_ORD_ABC: (bool, usize, u64) = (true, 2, 522923844917);
const FP_DCWS_ORD_999_ERR: (bool, usize, u64) = (false, 0, 0);
const FP_DCWS_UNMATCHED: (bool, usize, u64) = (true, 5, 3511818511803);
const FP_DCWS_BOTH: (bool, usize, u64) = (true, 2, 1056465432878);
const FP_DCWS_EOS_SHORT: (bool, usize, u64) = (true, 4, 2057187714775);
const FP_DCWS_EOS_3BYTE: (bool, usize, u64) = (true, 4, 2030643357165);
#[test]
fn encode_palette_grid_fingerprint_pinned() {
fn fp(matrix: &crate::encoding::ColorMatrix) -> (usize, usize, u64) {
let w = matrix.width();
let h = matrix.height();
let mut s: u64 = 0;
for y in 0..h {
for x in 0..w {
let v = u64::from(matrix.get(x, y));
let idx = (y as u64) * (w as u64) + (x as u64);
s = s.wrapping_add(
v.wrapping_mul(idx.wrapping_add(1).wrapping_mul(2_654_435_761)),
);
}
}
(w, h, s)
}
let long_100 = "X".repeat(100);
let long_200 = "X".repeat(200);
let cases: &[(&str, &str, (usize, usize, u64))] = &[
("A", "A", FP_ENC_A),
("HELLO", "HELLO", FP_ENC_HELLO),
("HelloWorld", "Hello World", FP_ENC_HW),
("12345", "12345", FP_ENC_12345),
("long_100x", long_100.as_str(), FP_ENC_LONG_100),
("long_200x", long_200.as_str(), FP_ENC_LONG_200),
];
for (tag, data, want) in cases {
let m = encode(data, &Options::default())
.unwrap_or_else(|e| panic!("encode({tag}) ok: {e:?}"));
let got = fp(&m);
assert_eq!(got, *want, "fingerprint changed for {tag}");
}
}
const FP_ENC_A: (usize, usize, u64) = (13, 13, 119192128976183);
const FP_ENC_HELLO: (usize, usize, u64) = (15, 13, 157769043890796);
const FP_ENC_HW: (usize, usize, u64) = (18, 13, 221852432032858);
const FP_ENC_12345: (usize, usize, u64) = (15, 13, 157113398257829);
const FP_ENC_LONG_100: (usize, usize, u64) = (39, 25, 3457965319083832);
const FP_ENC_LONG_200: (usize, usize, u64) = (55, 31, 10302109396531012);
#[test]
fn pick_symbol_size_sweep_fingerprint_pinned() {
fn pack(opt: Option<(usize, u32, u32, u32)>) -> u64 {
match opt {
None => 0,
Some((m, r, c, p)) => {
((m as u64) & 0xFFFF)
| (((r as u64) & 0xFFFF) << 16)
| (((c as u64) & 0xFFFF) << 32)
| (((p as u64) & 0xFFFF) << 48)
}
}
}
let mut s: u64 = 0;
let mut count_some: u32 = 0;
let mut count_none: u32 = 0;
for tcc in 1u32..=512 {
let res = pick_symbol_size(tcc);
if res.is_some() {
count_some += 1;
} else {
count_none += 1;
}
let v = pack(res);
s = s.wrapping_add(
v.wrapping_mul((tcc as u64).wrapping_add(1).wrapping_mul(2_654_435_761)),
);
}
let got = (count_some, count_none, s);
assert_eq!(got, FP_PICK_SIZE_SWEEP, "fingerprint changed");
}
const FP_PICK_SIZE_SWEEP: (u32, u32, u64) = (276, 236, 12514356780962302335);
#[test]
fn build_dcws_caret_collapse_index_pins_plus_not_times() {
let got = build_dcws_with_input_opts("01234^^", false, true)
.expect("parsefnc `^^` collapse must succeed");
assert_eq!(
got,
vec![48, 49, 50, 51, 52, 94],
"`^^` at index 5 of a 7-byte input must collapse to a single \
caret — pins `i + 2` (mutant `i * 2` would not collapse, \
emitting two carets)"
);
}
#[test]
fn build_dcws_two_char_guard_pins_and_not_or() {
let got = build_dcws_with_input_opts("^NUL_BS", true, false)
.expect("parse 3-char ctrl name must succeed");
assert_eq!(
got,
vec![0, 95, 66, 83],
"after a 3-char ctrl match the 2-char block must NOT re-fire — \
pins `!matched && …` (mutant `||` would consume the trailing \
`BS` as a control name)"
);
}
#[test]
fn build_dcws_two_char_bound_pins_plus_not_times() {
let got = build_dcws_with_input_opts("____^BS", true, false)
.expect("parse 2-char ctrl name must succeed");
assert_eq!(
got,
vec![95, 95, 95, 95, 8],
"`^BS` at index 4 of a 7-byte input must decode to BS=8 — pins \
`i + 3` (mutant `i * 3` would skip the block, yielding \
[95,95,95,95,94,66,83])"
);
}
#[test]
fn build_dcws_ordinal_boundary_pins_gt_not_ge() {
let got = build_dcws_with_input_opts("^255", true, false)
.expect("ordinal 255 must be accepted (boundary)");
assert_eq!(
got,
vec![255],
"`^255` is in range (000..=255) — pins `value > 255` (mutant \
`>= 255` would reject the boundary value)"
);
assert!(
build_dcws_with_input_opts("^256", true, false).is_err(),
"`^256` must be rejected by both original and mutant"
);
}
#[test]
fn encode_length_boundary_pins_gt_not_ge() {
let data = "A".repeat(2500);
let err = encode(&data, &Options::default())
.expect_err("2500 bytes overflows the largest symbol size");
let msg = format!("{err:?}");
assert!(
msg.contains("maximum symbol size"),
"at exactly 2500 bytes the length guard must NOT fire — pins \
`data.len() > 2500` (mutant `>= 2500` would return the \
2500-byte-limit error instead); got: {msg}"
);
assert!(
!msg.contains("2500-byte limit"),
"the 2500-byte-limit branch must not be taken at len == 2500; \
got: {msg}"
);
let too_long = "A".repeat(2501);
let err2 = encode(&too_long, &Options::default()).expect_err("2501 bytes must be rejected");
assert!(
format!("{err2:?}").contains("2500-byte limit"),
"2501 bytes must hit the explicit 2500-byte-limit guard"
);
}
#[test]
fn ultracode_equivalence_notes() {
let prime = ULTRACODE_RS_PRIME;
for c in [0u32, 1, 2, 7, 42, 200, 282] {
for f in [0u32, 1, 3, 99, 282] {
assert_eq!(
(c * (f + prime)) % prime,
(c * f) % prime,
"L300 `%→+` invariant: adding `prime` to feedback is \
absorbed by the downstream `% prime`"
);
}
}
for a in [0u32, 1, 4, 100, 282] {
for p in [0u32, 5, 283, 1000, 79_999] {
assert_eq!(
(a + (p % prime)) % prime,
(a + p) % prime,
"L305:51 `%→+` invariant: inner reduction is redundant \
given the surviving outer `% prime`"
);
}
}
for tcc in 1u32..=512 {
if let Some((_m, rows_pre, _cols, _pads)) = pick_symbol_size(tcc) {
let final_rows = rows_pre * 6 + 1;
assert_eq!(
final_rows % 6,
1,
"layout_pixs rows must be ≡ 1 (mod 6) so the j-loop \
(j ≡ 0 mod 6) never lands on `rows`"
);
}
}
let long = "X".repeat(200);
for data in [
"A",
"HELLO",
"Hello World",
"12345",
"X".repeat(100).as_str(),
long.as_str(),
] {
let (_rows, _cols, pixs) =
super::encode_pixs_default(data).expect("encode_pixs_default ok");
assert!(
pixs.iter().all(|&c| c >= 0),
"layout fills every cell — no `-1` sentinel reaches the \
`cell < 0` branch (input {data:?})"
);
}
}
}