labels: distinguish "parser detected" from "parser succeeded"
Adds `parsers_detected: Vec<&'static str>` to `LabelAnalysis`. Records
every parser whose discriminator matched, regardless of whether its
parse() then returned Some/None.
Why: when `parser=None` we currently can't tell apart:
(a) no parser recognized this disc — missing parser, candidate for a
new module
(b) a parser recognized it but parse() returned None / empty —
capture truncated, or genuine empty authoring data, or a parser
bug
Surfaced concretely on the 11-disc capture session 2026-05-10:
disc-04 had `bluray_project.bin` in jar_inventory (pixelogic detect()
returned true) but parse() returned None because file content was
past the 1 GB capture window. Old API: parser=None — looked like
"missing parser." New API: detected=[pixelogic], parser=None — clearly
"capture problem, not a parser gap."
The tracing log line on the no-parser-emitted-labels path now
distinguishes the two cases too.
No behavior change to production rip path. extract() is unchanged;
only the diagnostic analyze() returns the richer result.
This commit is contained in:
+29
-5
@@ -289,21 +289,37 @@ fn extract(reader: &mut dyn SectorReader, udf: &UdfFs) -> Vec<StreamLabel> {
|
|||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub fn analyze(reader: &mut dyn SectorReader, udf: &UdfFs) -> LabelAnalysis {
|
pub fn analyze(reader: &mut dyn SectorReader, udf: &UdfFs) -> LabelAnalysis {
|
||||||
let inventory = jar_inventory(udf);
|
let inventory = jar_inventory(udf);
|
||||||
|
// Record every parser whose discriminator matched — even if its
|
||||||
|
// parse step then returned None — so the analyzer can distinguish
|
||||||
|
// "no parser recognized this disc" from "parser recognized it but
|
||||||
|
// couldn't read the file" (e.g. content past a truncated capture)
|
||||||
|
// or "parser ran but produced no labels."
|
||||||
|
let mut parsers_detected: Vec<&'static str> = Vec::new();
|
||||||
for (name, detect, parse) in PARSERS {
|
for (name, detect, parse) in PARSERS {
|
||||||
if detect(udf) {
|
if detect(udf) {
|
||||||
tracing::info!(parser = name, "label parser matched");
|
tracing::info!(parser = name, "label parser matched");
|
||||||
|
parsers_detected.push(name);
|
||||||
if let Some(labels) = parse(reader, udf) {
|
if let Some(labels) = parse(reader, udf) {
|
||||||
return LabelAnalysis {
|
return LabelAnalysis {
|
||||||
parser: Some(name),
|
parser: Some(name),
|
||||||
|
parsers_detected,
|
||||||
jar_inventory: inventory,
|
jar_inventory: inventory,
|
||||||
labels,
|
labels,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracing::info!("no label parser matched");
|
if parsers_detected.is_empty() {
|
||||||
|
tracing::info!("no label parser matched");
|
||||||
|
} else {
|
||||||
|
tracing::info!(
|
||||||
|
detected = ?parsers_detected,
|
||||||
|
"label parsers detected but produced no labels"
|
||||||
|
);
|
||||||
|
}
|
||||||
LabelAnalysis {
|
LabelAnalysis {
|
||||||
parser: None,
|
parser: None,
|
||||||
|
parsers_detected,
|
||||||
jar_inventory: inventory,
|
jar_inventory: inventory,
|
||||||
labels: Vec::new(),
|
labels: Vec::new(),
|
||||||
}
|
}
|
||||||
@@ -314,12 +330,20 @@ pub fn analyze(reader: &mut dyn SectorReader, udf: &UdfFs) -> LabelAnalysis {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LabelAnalysis {
|
pub struct LabelAnalysis {
|
||||||
/// Which parser matched ("paramount" / "criterion" / "pixelogic" /
|
/// Which parser matched ("paramount" / "criterion" / "pixelogic" /
|
||||||
/// "ctrm"), or `None` if no parser matched and the labels code
|
/// "ctrm") AND emitted labels. `None` means either no parser
|
||||||
/// would have fallen through to `fill_defaults`.
|
/// recognized the disc, OR a parser recognized it but its parse
|
||||||
|
/// step returned None (file unreadable, no parseable tokens). Use
|
||||||
|
/// `parsers_detected` to disambiguate.
|
||||||
pub parser: Option<&'static str>,
|
pub parser: Option<&'static str>,
|
||||||
|
/// Every parser whose discriminator matched, in priority order.
|
||||||
|
/// Distinguishes "we recognized this disc but couldn't extract
|
||||||
|
/// labels" from "we don't recognize this disc at all" — the
|
||||||
|
/// former points at a parser bug or a truncated capture, the
|
||||||
|
/// latter points at a missing parser.
|
||||||
|
pub parsers_detected: Vec<&'static str>,
|
||||||
/// Filenames found under any `/BDMV/JAR/*/` subdirectory, deduped
|
/// Filenames found under any `/BDMV/JAR/*/` subdirectory, deduped
|
||||||
/// and sorted. Helps spot unknown authoring formats when `parser`
|
/// and sorted. Helps spot unknown authoring formats when no
|
||||||
/// is `None`.
|
/// parser detected.
|
||||||
pub jar_inventory: Vec<String>,
|
pub jar_inventory: Vec<String>,
|
||||||
/// Raw labels emitted by the matched parser (empty if `parser` is
|
/// Raw labels emitted by the matched parser (empty if `parser` is
|
||||||
/// `None`).
|
/// `None`).
|
||||||
|
|||||||
Reference in New Issue
Block a user