From 8189da1b0cc7f48fae2fcb2ea67e23aa23e0c79f Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Sat, 1 Aug 2026 14:24:47 -0700 Subject: [PATCH] Document why audio.rs's bit-packing | mutants are equivalent Every mutation-testing survivor in this file is a | with ^ flip inside a bitstream packer: BitReader::read's accumulate step, the push closures in dac3_box/dec3_box/ddts_box, and the multi-field extractions in parse_eac3 and parse_dts. All nine are the same shape: shift an accumulator left by exactly the width of the next field, then OR it in, so the two operands never share a set bit and | and ^ agree on every input. Confirmed by running cargo-mutants against just these nine mutations after the existing test suite (which already exercises each function's field values) - all nine still survive, as expected for a genuinely equivalent mutant. Recorded the reasoning once at BitReader::read so nobody spends time chasing it site by site. --- src/mux/mp4/audio.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/mux/mp4/audio.rs b/src/mux/mp4/audio.rs index fc7efdd..63909d9 100644 --- a/src/mux/mp4/audio.rs +++ b/src/mux/mp4/audio.rs @@ -44,6 +44,20 @@ impl<'a> BitReader<'a> { self.bit += n; } /// Read `n` bits (n ≤ 32). Returns 0 past end of data (callers pre-check len). + /// + /// The accumulate step below (`(v << 1) | bit`) is one instance of a + /// pattern repeated throughout this file — shift an accumulator left by + /// exactly the width of the next field, then OR in that field, mask-limited + /// to the same width (the `push` closures in `dac3_box`, `dec3_box` and + /// `ddts_box`; the multi-byte bit-field extractions in `parse_eac3` and + /// `parse_dts`). Because the shift always vacates precisely the bits the OR + /// then fills, and never more, the two operands never share a set bit — so + /// `|` and `^` agree on every input, always. Mutation testing flags each of + /// these `|` sites as a surviving `|`→`^` mutant; that is expected and is + /// not a coverage gap. Don't write tests chasing it and don't "fix" it by + /// switching to `^` — either spelling is correct and equally unenforceable + /// by a test, so `|` stays because it is the conventional way to write "set + /// these bits" in a bitstream packer. fn read(&mut self, n: usize) -> u32 { let mut v = 0u32; for _ in 0..n {