use edgefirst_decoder::schema::{LogicalType, SchemaV2};
use edgefirst_decoder::DecoderBuilder;
use std::env;
use std::fs;
use std::io::{Cursor, Read};
fn try_extract_edgefirst_json(data: &[u8]) -> Result<Option<String>, String> {
let reader = Cursor::new(data);
let mut archive = match zip::ZipArchive::new(reader) {
Ok(a) => a,
Err(_) => return Ok(None),
};
let mut file = archive
.by_name("edgefirst.json")
.map_err(|e| format!("archive present but missing edgefirst.json: {e}"))?;
let mut json = String::new();
file.read_to_string(&mut json)
.map_err(|e| format!("decode edgefirst.json as utf-8: {e}"))?;
Ok(Some(json))
}
fn print_output_summary(schema: &SchemaV2) {
for (i, out) in schema.outputs.iter().enumerate() {
let name = out.name.as_deref().unwrap_or("<unnamed>");
let role = match out.type_ {
Some(LogicalType::Boxes) => "boxes",
Some(LogicalType::Scores) => "scores",
Some(LogicalType::MaskCoefs) => "mask_coefs",
Some(LogicalType::Detection) => "detection (fused)",
Some(LogicalType::Protos) => "protos",
Some(_) => "other",
None => "additional",
};
let physical = if out.outputs.is_empty() {
"1 physical".to_string()
} else {
format!("{} per-scale physical", out.outputs.len())
};
let shape = format!("{:?}", out.shape);
println!(" output[{i}] {name:<24} role={role:<18} shape={shape:<22} ({physical})");
}
}
fn main() {
let path = env::args().nth(1).expect("usage: parse_edgefirst <path>");
let bytes = fs::read(&path).expect("read");
let json_str = match try_extract_edgefirst_json(&bytes) {
Ok(Some(json)) => {
println!("INPUT {path} (TFLite with ZIP-trailer metadata)");
json
}
Ok(None) => {
let text = String::from_utf8(bytes).unwrap_or_else(|e| {
eprintln!("INPUT-ERR {path}\n not a TFLite archive and not valid UTF-8: {e}");
std::process::exit(1);
});
println!("INPUT {path} (plain edgefirst.json)");
text
}
Err(e) => {
eprintln!("INPUT-ERR {path}\n {e}");
std::process::exit(1);
}
};
let schema = match SchemaV2::parse_json(&json_str) {
Ok(s) => s,
Err(e) => {
println!("PARSE-ERR {path}\n {e}");
std::process::exit(1);
}
};
println!(
"PARSE-OK schema_version={} decoder_version={:?} nms={:?} outputs={}",
schema.schema_version,
schema.decoder_version,
schema.nms,
schema.outputs.len()
);
if let Some(input) = &schema.input {
println!(
" input shape={:?} cameraadaptor={:?}",
input.shape, input.cameraadaptor
);
}
print_output_summary(&schema);
let decoder = match DecoderBuilder::new().with_schema(schema).build() {
Ok(d) => d,
Err(e) => {
println!("BUILD-ERR {path}\n {e}");
std::process::exit(2);
}
};
println!(
"BUILD-OK model_type={:?} input_dims={:?} normalized_boxes={:?}",
decoder.model_type(),
decoder.input_dims(),
decoder.normalized_boxes()
);
}