chore: scrub non-shippable references from tests/comments
This commit is contained in:
+24
-24
@@ -38,7 +38,7 @@ use std::collections::BTreeMap;
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Default)]
|
||||
pub struct DiscMetadata {
|
||||
/// Localized titles, keyed by 3-char ISO 639-2 lang code
|
||||
/// (e.g. "eng" → "Dune Part Two")
|
||||
/// (e.g. "eng" → "Aurora Drift")
|
||||
pub titles: BTreeMap<String, String>,
|
||||
/// First-line / short description, per lang
|
||||
pub descriptions: BTreeMap<String, String>,
|
||||
@@ -146,7 +146,7 @@ pub(crate) fn parse_bdmt_xml(_lang_code: &str, xml_text: &str) -> Option<BdmtFie
|
||||
}
|
||||
|
||||
/// Reject candidate description strings that are themselves XML
|
||||
/// fragments — observed on disc-04 (Top Gun: Maverick), where
|
||||
/// fragments — observed on a captured disc, where
|
||||
/// `<di:description>` contained `<di:thumbnail href="…"/>` child
|
||||
/// elements and no actual prose. Surfacing that raw to the JSON
|
||||
/// output is worse than dropping the field entirely.
|
||||
@@ -210,10 +210,10 @@ mod tests {
|
||||
// carrier inside a <discInfo> root.
|
||||
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:name>Dune Part Two</di:name>
|
||||
<di:name>Aurora Drift</di:name>
|
||||
</discInfo>"#;
|
||||
let (title, desc, set) = parse_bdmt_xml("eng", xml).expect("title should parse");
|
||||
assert_eq!(title, "Dune Part Two");
|
||||
assert_eq!(title, "Aurora Drift");
|
||||
assert_eq!(desc, None);
|
||||
assert_eq!(set, None);
|
||||
}
|
||||
@@ -223,12 +223,12 @@ mod tests {
|
||||
// <di:title> is the alternate carrier; should be picked up
|
||||
// when <di:name> is absent.
|
||||
let xml = r#"<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:title>The Matrix</di:title>
|
||||
<di:description>A film about computers.</di:description>
|
||||
<di:title>Echo Chamber</di:title>
|
||||
<di:description>A film about machines.</di:description>
|
||||
</discInfo>"#;
|
||||
let (title, desc, _) = parse_bdmt_xml("eng", xml).unwrap();
|
||||
assert_eq!(title, "The Matrix");
|
||||
assert_eq!(desc.as_deref(), Some("A film about computers."));
|
||||
assert_eq!(title, "Echo Chamber");
|
||||
assert_eq!(desc.as_deref(), Some("A film about machines."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -238,17 +238,17 @@ mod tests {
|
||||
// titleName inside tableOfContents.
|
||||
let xml = r#"<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:tableOfContents>
|
||||
<di:titleName>Inside Out 2</di:titleName>
|
||||
<di:titleName>Feelings Two</di:titleName>
|
||||
</di:tableOfContents>
|
||||
</discInfo>"#;
|
||||
let (title, _, _) = parse_bdmt_xml("eng", xml).unwrap();
|
||||
assert_eq!(title, "Inside Out 2");
|
||||
assert_eq!(title, "Feelings Two");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn extract_box_set_position() {
|
||||
let xml = r#"<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:name>LOTR Disc 2</di:name>
|
||||
<di:name>Box Set Disc 2</di:name>
|
||||
<di:discNumber>2</di:discNumber>
|
||||
<di:numSets>5</di:numSets>
|
||||
</discInfo>"#;
|
||||
@@ -287,11 +287,11 @@ mod tests {
|
||||
// would. This exercises the BTreeMap key handling without
|
||||
// needing a UdfFs.
|
||||
let eng_xml = r#"<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:name>Dune Part Two</di:name>
|
||||
<di:name>Aurora Drift</di:name>
|
||||
</discInfo>"#;
|
||||
let fra_xml = r#"<discInfo xmlns:di="urn:BDA:bdmv;disclibmeta">
|
||||
<di:name>Dune Deuxième Partie</di:name>
|
||||
<di:description>Suite du film de 2021.</di:description>
|
||||
<di:name>Aurora Drift (Partie Deux)</di:name>
|
||||
<di:description>Suite du film fictif.</di:description>
|
||||
</discInfo>"#;
|
||||
|
||||
let mut meta = DiscMetadata::default();
|
||||
@@ -310,16 +310,16 @@ mod tests {
|
||||
|
||||
assert_eq!(
|
||||
meta.titles.get("eng").map(String::as_str),
|
||||
Some("Dune Part Two")
|
||||
Some("Aurora Drift")
|
||||
);
|
||||
assert_eq!(
|
||||
meta.titles.get("fra").map(String::as_str),
|
||||
Some("Dune Deuxième Partie")
|
||||
Some("Aurora Drift (Partie Deux)")
|
||||
);
|
||||
assert!(meta.descriptions.get("eng").is_none());
|
||||
assert_eq!(
|
||||
meta.descriptions.get("fra").map(String::as_str),
|
||||
Some("Suite du film de 2021.")
|
||||
Some("Suite du film fictif.")
|
||||
);
|
||||
assert_eq!(meta.disc_number, None);
|
||||
}
|
||||
@@ -342,21 +342,21 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn description_with_only_child_xml_is_dropped() {
|
||||
// Real-world bug from disc-04 (Top Gun: Maverick, 2026-05-11
|
||||
// Real-world bug from a captured disc (2026-05-11
|
||||
// capture): <di:description> contained only <di:thumbnail/>
|
||||
// child elements with no actual prose. The previous parser
|
||||
// surfaced the raw XML fragment as the description string.
|
||||
// Now we reject candidates that begin with `<`.
|
||||
let xml = r#"<discInfo>
|
||||
<di:name>Top Gun: Maverick</di:name>
|
||||
<di:name>Skyline Run</di:name>
|
||||
<di:description>
|
||||
<di:thumbnail href="tgm_meta_sm.jpg" />
|
||||
<di:thumbnail href="tgm_meta_lg.jpg" />
|
||||
<di:thumbnail href="sample_meta_sm.jpg" />
|
||||
<di:thumbnail href="sample_meta_lg.jpg" />
|
||||
</di:description>
|
||||
</discInfo>"#;
|
||||
let (title, description, _) =
|
||||
parse_bdmt_xml("eng", xml).expect("title is present so parse must succeed");
|
||||
assert_eq!(title, "Top Gun: Maverick");
|
||||
assert_eq!(title, "Skyline Run");
|
||||
assert!(
|
||||
description.is_none(),
|
||||
"description containing only XML children must be dropped, got {description:?}"
|
||||
@@ -381,10 +381,10 @@ mod tests {
|
||||
#[test]
|
||||
fn whitespace_in_title_is_trimmed() {
|
||||
let xml = r#"<discInfo><di:name>
|
||||
Dune Part Two
|
||||
Aurora Drift
|
||||
</di:name></discInfo>"#;
|
||||
let (title, _, _) = parse_bdmt_xml("eng", xml).unwrap();
|
||||
assert_eq!(title, "Dune Part Two");
|
||||
assert_eq!(title, "Aurora Drift");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+1
-2
@@ -7,8 +7,7 @@
|
||||
//! Stream labels live as plain ASCII strings inside compiled `.class`
|
||||
//! files in the jar — a quirk of the menu-rendering layer encoding
|
||||
//! its TextField positions and content as constant strings the
|
||||
//! Java compiler retained in the class string pool. Format observed
|
||||
//! in the corpus (Civil War UHD, 2024):
|
||||
//! Java compiler retained in the class string pool. Observed format:
|
||||
//!
|
||||
//! ```text
|
||||
//! LTextField,Audio1,English Dolby Atmos,Fontstrip_Composite,...
|
||||
|
||||
+38
-60
@@ -1,83 +1,65 @@
|
||||
//! Deluxe BD-J framework — `com/bydeluxe/bluray/` package signature.
|
||||
//!
|
||||
//! Used by major studios (Disney, Warner, others) for their UHD
|
||||
//! BD-J authoring. Detected on discs whose `/BDMV/JAR/<x>.jar`
|
||||
//! contains a `com/bydeluxe/` directory entry.
|
||||
//! Detected on discs whose `/BDMV/JAR/<x>.jar` contains a
|
||||
//! `com/bydeluxe/` directory entry.
|
||||
//!
|
||||
//! ## Why this parser exists
|
||||
//! ## What this parser reads
|
||||
//!
|
||||
//! Deluxe-authored discs store stream labels as **ordinal references
|
||||
//! into obfuscated enum classes**. The label text isn't a literal
|
||||
//! string in any anchor pattern (unlike dbp's `TextField,...` rows).
|
||||
//! Instead, the binding code is roughly:
|
||||
//!
|
||||
//! ```java
|
||||
//! streamTable.put(1, new AudioSlot(LanguageEnum.English,
|
||||
//! CodecEnum.ATMOS_HD_AUDIO,
|
||||
//! PurposeEnum.Normal));
|
||||
//! ```
|
||||
//!
|
||||
//! The class names `LanguageEnum`, `CodecEnum`, `PurposeEnum`, and
|
||||
//! `AudioSlot` are obfuscated per-disc (`be.class`, `ma.class`,
|
||||
//! `lp.class`, etc.) — no name pattern survives the obfuscator. But
|
||||
//! the **shape of `<clinit>`** is framework-stable:
|
||||
//! Deluxe-authored discs store stream labels as ordinal references into
|
||||
//! enum classes whose names are obfuscated per-disc, so a name-based
|
||||
//! match won't work. The label data is instead recovered by matching on
|
||||
//! the **shape of each enum's `<clinit>`**, which is framework-stable:
|
||||
//!
|
||||
//! | Enum | Signature |
|
||||
//! |---|---|
|
||||
//! | Language | 70 `ldc` operations in `<clinit>`, sequence starts `English, French, Spanish, Dutch, ...` |
|
||||
//! | Purpose | 8 ldcs starting `Normal, Commentary, PiP, Trivia, ...` |
|
||||
//! | VideoFormat | 7 ldcs starting `HD, HDR10 Plus, HD Dolby, ...` |
|
||||
//! | Region | 22 ldcs starting `USA_D1, LIC1, LIC2, LIC3, ...` (Disney only) |
|
||||
//! | Studio | 6 ldcs starting `Disney, Marvel, Pixar, ...` (Disney only) |
|
||||
//! | Codec | ~46 `new` instructions, 0 ldcs in `<clinit>` (codec strings live in subclasses) |
|
||||
//! | Region | 22 ldcs starting `USA_D1, LIC1, LIC2, LIC3, ...` |
|
||||
//! | Studio | 6 ldcs starting `Disney, Marvel, Pixar, ...` |
|
||||
//! | Codec | many `new` instructions, 0 ldcs in `<clinit>` (codec strings live in subclasses) |
|
||||
//!
|
||||
//! Match on the SHAPE, not the name, and the parser survives obfuscation.
|
||||
//! Matching on the shape rather than the class name keeps the parser
|
||||
//! working across obfuscation variants.
|
||||
//!
|
||||
//! ## Implementation phases
|
||||
//!
|
||||
//! - **Phase A** — master enum identification (`identify_master_enums`).
|
||||
//! Walks every `.class`'s `<clinit>` ldc sequence and matches against
|
||||
//! the framework-stable fingerprints. Output: `Vec<(label, MasterEnum)>`
|
||||
//! with full ordinal → string-value tables. **Empirically verified**
|
||||
//! on disc-01 (Disney) + disc-09 (Warner).
|
||||
//! with full ordinal → string-value tables.
|
||||
//!
|
||||
//! - **Phase B** — codec enum subclass walk (`decode_codec_enum`).
|
||||
//! The codec enum's `<clinit>` has ~46 `new` instructions and zero
|
||||
//! The codec enum's `<clinit>` has many `new` instructions and zero
|
||||
//! string ldcs — codec name strings live in the subclasses each
|
||||
//! `new` constructs. Walks every referenced subclass's constant
|
||||
//! pool, extracts the codec name string. **Structural shape
|
||||
//! verified** on disc-01 (ma.class, 41 `new` ops) + disc-09
|
||||
//! (ea.class, 46 `new` ops); per-subclass string extraction
|
||||
//! designed against the published Java enum compilation convention
|
||||
//! (each enum value's `<init>` is called with its name string as
|
||||
//! the first arg).
|
||||
//! pool, extracts the codec name string, following the standard Java
|
||||
//! enum compilation convention (each enum value's `<init>` is called
|
||||
//! with its name string as the first arg).
|
||||
//!
|
||||
//! - **Phase C** — binding-class identification (`find_binding_classes`).
|
||||
//! The per-stream table is built by some class via repeated
|
||||
//! `getstatic` references to the master enums identified in A.
|
||||
//! That class has the highest such `getstatic` count in the jar.
|
||||
//! **Heuristic shape**; precise threshold may need tuning.
|
||||
//! Heuristic shape; precise threshold may need tuning.
|
||||
//!
|
||||
//! - **Phase D** — binding-class bytecode decoder (`decode_binding`).
|
||||
//! Walks the binding class's `<clinit>` with a tiny symbolic stack
|
||||
//! machine. For each `new X / dup / ... / invokespecial X.<init>`
|
||||
//! sequence, collects the int values and enum-reference operands
|
||||
//! between the `dup` and the constructor call, then emits a
|
||||
//! `DecodedStream`. **Mechanism verified** in unit tests against
|
||||
//! synthetic class fixtures; the **signal-to-StreamLabel mapping**
|
||||
//! (which arg is stream index? which is language? audio vs
|
||||
//! subtitle?) uses a documented heuristic that needs corpus-disc
|
||||
//! verification — see `interpret_stream` for the mapping rules.
|
||||
//! `DecodedStream`. The signal-to-StreamLabel mapping (which arg is
|
||||
//! stream index? which is language? audio vs subtitle?) uses a
|
||||
//! heuristic — see `interpret_streams` for the mapping rules.
|
||||
//!
|
||||
//! ## Confidence
|
||||
//!
|
||||
//! [`parse`] returns `Some(ParseResult::medium(labels))` when Phases A
|
||||
//! through D produce at least one stream — `Medium` because the
|
||||
//! signal-to-label mapping is heuristic until real disc bytecode
|
||||
//! confirms the binding pattern. Once verified the parser can promote
|
||||
//! to `High`. `None` when the disc isn't Deluxe-authored or when
|
||||
//! decoding produces zero streams (a recognized-but-broken state that
|
||||
//! the analyzer still surfaces via `parsers_detected`).
|
||||
//! signal-to-label mapping is heuristic. `None` when the disc isn't
|
||||
//! Deluxe-authored or when decoding produces zero streams (a
|
||||
//! recognized-but-broken state that the analyzer still surfaces via
|
||||
//! `parsers_detected`).
|
||||
|
||||
use super::class_reader::{
|
||||
AASTORE, BIPUSH, ClassFile, CodeAttribute, ConstantPool, CpInfo, GETSTATIC, ICONST_0, ICONST_1,
|
||||
@@ -559,10 +541,9 @@ fn clinit_news_and_ldcs(
|
||||
/// candidates ordered by descending getstatic count, filtered to a
|
||||
/// minimum concentration of master-enum references.
|
||||
///
|
||||
/// Empirically (POC v0.3 dumps): on disc-01 the audio binding class
|
||||
/// (`ma.class`) has ~82 getstatic refs, the subtitle binding
|
||||
/// (`ko.class`) has ~63. Both share the master Language + Purpose
|
||||
/// enums.
|
||||
/// A disc that splits the table commonly has one audio binding class
|
||||
/// with the most getstatic refs and a subtitle binding class with
|
||||
/// somewhat fewer; both share the master Language + Purpose enums.
|
||||
pub(crate) fn find_binding_classes(
|
||||
archive: &mut jar::Jar,
|
||||
master_enum_classes: &HashSet<&str>,
|
||||
@@ -641,10 +622,9 @@ pub(crate) enum StackVal {
|
||||
/// name (e.g. `DOLBY_AC3_AUDIO`, `DOLBY_LOSSLESS_AUDIO`) is the
|
||||
/// codec identifier. Deluxe binding constructors take a
|
||||
/// `LCodingType;` arg directly — codecs are NOT a Deluxe-internal
|
||||
/// enum (Phase B's codec-subclass walk was based on a wrong
|
||||
/// assumption; the actual codec source is the standard BD-J API
|
||||
/// enum). Discovered via deluxe-poc v0.3 binding-bytecode dump
|
||||
/// against disc-01 (Disney) + disc-09 (Warner) on 2026-05-10.
|
||||
/// enum; the codec source is the standard BD-J API `CodingType`
|
||||
/// enum, so the binding constructor's codec arg is read straight
|
||||
/// from that getstatic operand.
|
||||
CodingType(String),
|
||||
/// An uninitialized `new` object — popped by the matching
|
||||
/// invokespecial.
|
||||
@@ -988,11 +968,10 @@ impl MasterEnumTable {
|
||||
// ── interpret_streams: Constructions → StreamLabels ─────────────────────────
|
||||
|
||||
/// Convert the per-construction tuples from Phase D into
|
||||
/// [`StreamLabel`]s. Pattern verified against corpus discs via
|
||||
/// deluxe-poc v0.3 binding-bytecode dump (2026-05-10):
|
||||
/// [`StreamLabel`]s. Two binding-constructor shapes are handled:
|
||||
///
|
||||
/// Disney binding (5-arg): `BindingType.<init>(I, Lbe;, Llp;, I, LCodingType;)V`
|
||||
/// Warner binding (4-arg): `BindingType.<init>(I, Law;, Lgp;, LCodingType;)V`
|
||||
/// 5-arg: `BindingType.<init>(I, Lang;, Lpurpose;, I, LCodingType;)V`
|
||||
/// 4-arg: `BindingType.<init>(I, Lang;, Lpurpose;, LCodingType;)V`
|
||||
///
|
||||
/// Args are identified by **TYPE**, not position:
|
||||
/// - First `EnumRef{kind: "Language"}` → audio/subtitle language
|
||||
@@ -1098,11 +1077,10 @@ fn interpret_streams(constructions: &[Construction], master: &MasterEnumTable) -
|
||||
/// getstatic operands on Deluxe binding classes) to a human-readable
|
||||
/// codec hint string.
|
||||
///
|
||||
/// CodingType is the standard BD-J API enum; values are documented
|
||||
/// in the BD-J specification and verified empirically against the
|
||||
/// binding-bytecode dumps in `(internal)/research/deluxe-poc/data/`.
|
||||
/// Unknown field names pass through unchanged so unfamiliar codecs
|
||||
/// still surface something rather than going silent.
|
||||
/// CodingType is the standard BD-J API enum; values are documented in
|
||||
/// the BD-J specification. Unknown field names pass through unchanged
|
||||
/// so unfamiliar codecs still surface something rather than going
|
||||
/// silent.
|
||||
fn coding_type_to_codec_hint(field: &str) -> &str {
|
||||
match field {
|
||||
// Lossless / hi-res.
|
||||
|
||||
+1
-1
@@ -954,7 +954,7 @@ mod gap_fill_tests {
|
||||
|
||||
#[test]
|
||||
fn partial_yield_fills_gaps_keeps_framework() {
|
||||
// Oppenheimer-style: framework matched but only labeled 2 of 6 audios.
|
||||
// Partial-coverage case: framework matched but only labeled 2 of 6 audios.
|
||||
let mut framework = vec![
|
||||
label(StreamLabelType::Audio, 1, "eng", "Atmos"),
|
||||
label(StreamLabelType::Audio, 4, "eng", "Commentary"),
|
||||
|
||||
@@ -300,7 +300,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn assign_labels_numbers_commentary_behind_placeholders() {
|
||||
// Wicked: the FPL_MainFeature playlist lists three unlabelled main
|
||||
// Observed case: the FPL_MainFeature playlist lists three unlabelled main
|
||||
// audio tracks as `Audio Stream N` placeholders, then a lone
|
||||
// `eng_ACOM_` commentary at STN slot 4. The commentary must land on
|
||||
// audio #4, not collapse onto #1 (which would tag the main feature
|
||||
|
||||
+1
-2
@@ -10,8 +10,7 @@
|
||||
//! - English text → [`LabelPurpose`] (Commentary / Descriptive / etc.).
|
||||
//! - English text → [`LabelQualifier`] (SDH / Forced / Descriptive Service).
|
||||
//!
|
||||
//! Rules of engagement (carried over from
|
||||
//! `(internal)/memory/feedback_label_data_rules.md`):
|
||||
//! Rules of engagement:
|
||||
//!
|
||||
//! 1. Only map values we are 100% certain about — published codec
|
||||
//! names, well-known ISO 639-2 mappings, vendor-documented purpose
|
||||
|
||||
Reference in New Issue
Block a user