|
| 1 | +//! Dump the base `Network` header at the front of a serialized recognizer |
| 2 | +//! component (`eng.lstm`) — the Rust side of the network base-header byte-parity |
| 3 | +//! leaf, sibling to `recoder_dump`. Also prints the [`FacetCascade`] the node |
| 4 | +//! sinks onto (the ruff→OGAR harvest → V3 SoA target). |
| 5 | +//! |
| 6 | +//! ```sh |
| 7 | +//! # Extract the lstm component (starts with the network, lstmrecognizer.cpp:135): |
| 8 | +//! combine_tessdata -u $(dpkg -L tesseract-ocr-eng | grep eng.traineddata) /tmp/eng. |
| 9 | +//! # C++ oracle (network_spec_oracle.cpp): links libtesseract, calls the REAL |
| 10 | +//! # Network::CreateFromFile on the same bytes and dumps the loaded top node's |
| 11 | +//! # type / ni / no / num_weights / name + spec() (the known-answer self-check). |
| 12 | +//! # ./network_spec_oracle /tmp/eng.lstm > /tmp/oracle_network.txt |
| 13 | +//! # Rust side (parses only the base header — the shared prefix of every layer): |
| 14 | +//! cargo run -p lance-graph-contract --example network_dump -- /tmp/eng.lstm > /tmp/rust_network.txt |
| 15 | +//! # The "header:" line is byte-identical between the two => the base header |
| 16 | +//! # parse is byte-parity green. |
| 17 | +//! ``` |
| 18 | +
|
| 19 | +#![allow( |
| 20 | + clippy::print_stdout, |
| 21 | + reason = "a dump CLI example writes to stdout by design" |
| 22 | +)] |
| 23 | + |
| 24 | +use std::process::ExitCode; |
| 25 | + |
| 26 | +use lance_graph_contract::network::NetworkHeader; |
| 27 | + |
| 28 | +fn main() -> ExitCode { |
| 29 | + let Some(path) = std::env::args().nth(1) else { |
| 30 | + eprintln!("usage: network_dump <path/to/eng.lstm>"); |
| 31 | + return ExitCode::FAILURE; |
| 32 | + }; |
| 33 | + let bytes = match std::fs::read(&path) { |
| 34 | + Ok(b) => b, |
| 35 | + Err(err) => { |
| 36 | + eprintln!("error reading {path}: {err}"); |
| 37 | + return ExitCode::FAILURE; |
| 38 | + } |
| 39 | + }; |
| 40 | + match NetworkHeader::from_le_bytes(&bytes) { |
| 41 | + Ok((header, consumed)) => { |
| 42 | + // The byte-parity line (diffed against the oracle's loaded top node). |
| 43 | + println!("header: {}", header.dump()); |
| 44 | + // The V3 SoA sink: the 16-byte FacetCascade (classid + 6×8:8), hex. |
| 45 | + let f = header.to_facet(); |
| 46 | + let hex: String = f.to_bytes().iter().map(|b| format!("{b:02x}")).collect(); |
| 47 | + println!("facet: classid={:#010x} bytes={hex}", f.facet_classid); |
| 48 | + println!("consumed: {consumed} bytes (base header; subclass payload follows)"); |
| 49 | + ExitCode::SUCCESS |
| 50 | + } |
| 51 | + Err(err) => { |
| 52 | + eprintln!("error parsing header: {err:?}"); |
| 53 | + ExitCode::FAILURE |
| 54 | + } |
| 55 | + } |
| 56 | +} |
0 commit comments