open-standards/wai/wai-rs/tests/jpegai_e2e_chain.rs
Transaction Science f4de2c781c wai: D2c M7b gate 6: the switch; the decode's networks run through the operator set
- jpegai_decode::{decode, decode_with_stages} load the bundle's networks
  (load_networks, under acc64) beside its scale path and run the hyper decoders,
  context stages and synthesis through rec_y, rec_uv, syn_y and syn_uv;
  decode_loaded(data, icci, norm, scale path, networks, observe) decodes with
  both loaded once. The direct networks are reached only from
  jpegai_decode::legacy (Front::Direct, Back::Direct, test-only, legacy_int).
- The loaders no longer panic: Weights::from_json, IntNet::from_json and
  IcciNet::from_json return Result<_, BadMember>; a mistyped member is
  model_mismatch. IntNet keeps only well-formed tensors, so a member §13.6.1 reads
  that is mistyped is missing, as the lowering of the bytes refuses it.
- The neural sink lowers and loads the networks from their eight files' bytes
  through the store of loaded sets (keyed by their listing, at acc64), parses only
  the eICCI net besides, and reports a refusal (model_mismatch, field_range)
  without falling back: a_refused_exact_decode_does_not_fall_back gains a
  non-integer network weight and a mistyped eICCI field.
- The browser crate's decodeJpegAiFull reports a mistyped member.
- Goldens, unchanged (build host, release): jpegai_cross_platform's nine pinned
  hashes, the Synthesis stage d56695726bb6ebed… among them; the decoded RGB
  SHA-256 dbc494a5a670914e… (jpegai_reconstruction_binding with
  WAI_JPEGAI_EXPECT_SHA256, jpegai_e2e_full: max|Δ| = 1 on 4.446%).
- Memory (jpegai_memory, reference kernels): with the scale path and the networks
  loaded beforehand the decode holds 72,752,387 bytes, the direct decode
  175,465,380; the networks take 89,727,913 to load and hold 55,530,900.
- Also green: clippy's disallowed-methods guard and jpegai_decode_symbols, the
  sink's three dispatch tests, wai-web's tests and its wasm32 build; include/wai.h
  unchanged.
- CHANGELOG: the M7b entry.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 02:00:19 -04:00

66 lines
3.4 KiB
Rust
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! End-to-end chain: **codestream → hyper-latent → scale indices**, with no fixture
//! input beyond the normative assets.
//!
//! ```text
//! test256.bin → parse_container → SOZ → mANS fac decode → −31 → z
//! → decode_hyper_scale(z) → i_s
//! ```
//!
//! Both links were validated independently (the entropy path from marker syntax, the
//! scale net from its ONNX); this runs them as one pipeline off raw bytes and requires
//! the result to be byte-exact against the reference `i_s`.
//!
//! env: WAI_JPEGAI_CHAIN_FIXTURE = e2e_chain_fixture.json
//! { codestream:[u8], cdfs_y:[u8;160*63], per_channel, z_shape, i_s_expected }
//! WAI_JPEGAI_HYPERSCALE_WEIGHTS = hyperscale_y_weights.json
#![cfg(all(feature = "neural_int", feature = "legacy_int"))]
use wai::jpegai_bitstream::{find_segment, parse_container, Marker};
use wai::jpegai_mans::MansDecoder;
use wai::jpegai_synthesis::{decode_hyper_scale, IntNet};
const Z_OFFSET: i64 = 31;
#[test]
fn codestream_to_scale_indices() {
let fx = match std::env::var("WAI_JPEGAI_CHAIN_FIXTURE") {
Ok(p) if std::path::Path::new(&p).exists() => p,
_ => { eprintln!("skip: set WAI_JPEGAI_CHAIN_FIXTURE"); return; }
};
let wj = match std::env::var("WAI_JPEGAI_HYPERSCALE_WEIGHTS") {
Ok(p) if std::path::Path::new(&p).exists() => p,
_ => { eprintln!("skip: set WAI_JPEGAI_HYPERSCALE_WEIGHTS"); return; }
};
let v: serde_json::Value = serde_json::from_slice(&std::fs::read(&fx).unwrap()).unwrap();
let u8v = |k: &str| v[k].as_array().unwrap().iter().map(|x| x.as_u64().unwrap() as u8).collect::<Vec<u8>>();
let data = u8v("codestream");
let cdfs = u8v("cdfs_y");
let per_channel = v["per_channel"].as_u64().unwrap() as usize;
let zs: Vec<usize> = v["z_shape"].as_array().unwrap().iter().map(|x| x.as_u64().unwrap() as usize).collect();
let (c, zh, zw) = (zs[1], zs[2], zs[3]);
let i_s_expected: Vec<i64> = v["i_s_expected"].as_array().unwrap().iter().map(|x| x.as_i64().unwrap()).collect();
// 1. codestream → SOZ → z (luma plane)
let segs = parse_container(&data);
let soz = find_segment(&segs, Marker::Soz).expect("SOZ");
let mem = &data[soz.start..soz.start + soz.len];
let mut dec = MansDecoder::new(mem, &[mem.len() as u32]);
let mut symbols = vec![0u8; c * per_channel];
dec.decode_factorize(&cdfs, &mut symbols, c, per_channel);
let z: Vec<i64> = symbols.iter().map(|&s| s as i64 - Z_OFFSET).collect();
assert_eq!(z.len(), c * zh * zw, "z is [{c}, {zh}, {zw}]");
eprintln!("z from codestream: {} vals, {} non-zero", z.len(), z.iter().filter(|&&x| x != 0).count());
// 2. z → hyper-scale net → i_s
let net = IntNet::from_json(&serde_json::from_slice(&std::fs::read(&wj).unwrap()).unwrap()).unwrap();
let (i_s, co, ho, wo) = decode_hyper_scale(&z, c, zh, zw, &net);
eprintln!("i_s: [{co},{ho},{wo}] = {} vals", i_s.len());
assert_eq!(i_s.len(), i_s_expected.len());
let mism = i_s.iter().zip(&i_s_expected).filter(|(a, b)| a != b).count();
if let Some((i, (a, b))) = i_s.iter().zip(&i_s_expected).enumerate().find(|(_, (a, b))| a != b) {
eprintln!("first mismatch @ {i}: got {a} exp {b}");
}
eprintln!("i_s from codestream: {}/{} exact", i_s.len() - mism, i_s.len());
assert_eq!(mism, 0, "codestream → z → i_s must be byte-exact");
}