From d4818ad88e7050d79b4f2b8db4f70330c61dc2e0 Mon Sep 17 00:00:00 2001 From: Matt Jackson <1085847+MattJackson@users.noreply.github.com> Date: Tue, 21 Apr 2026 18:52:55 +0000 Subject: [PATCH] =?UTF-8?q?v0.11.15:=20lint=20cleanup=20=E2=80=94=20fmt=20?= =?UTF-8?q?+=20clippy=20clean?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 7 +++++++ Cargo.toml | 2 +- src/css/auth.rs | 3 ++- src/disc/mod.rs | 16 +++++++--------- src/drive/mod.rs | 8 +++++++- src/event.rs | 13 +++---------- src/ifo.rs | 4 +++- src/labels/mod.rs | 5 +++-- src/lib.rs | 2 +- src/mux/codec/mpeg2.rs | 2 +- src/mux/codec/truehd.rs | 21 +++++++++------------ src/mux/disc.rs | 9 +++++++-- src/mux/mkv.rs | 39 ++++++++++++++++++++++++++++----------- src/scsi/linux.rs | 5 ++--- src/sector.rs | 8 +++++++- src/verify.rs | 27 ++++++++++++++++++++------- 16 files changed, 108 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3af480..9070e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.11.15 (2026-04-21) + +### Lint cleanup +- Fix all `cargo fmt` and `cargo clippy -D warnings` across codebase. +- Remove unused imports (Codec, HdrFormat, ScanOptions, detect_max_batch_sectors, Extent). +- Fix CSS tuple pattern deref, collapsible if-statement, div_ceil reimplementation. + ## 0.11.14 (2026-04-21) ### Audit fixes: read recovery, verify, SCSI diff --git a/Cargo.toml b/Cargo.toml index db4ed76..3701dc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libfreemkv" -version = "0.11.14" +version = "0.11.15" edition = "2021" rust-version = "1.86" license = "AGPL-3.0-only" diff --git a/src/css/auth.rs b/src/css/auth.rs index 28cee83..b957892 100644 --- a/src/css/auth.rs +++ b/src/css/auth.rs @@ -348,7 +348,7 @@ fn read_disc_key(drive: &mut Drive, agid: u8, bus_key: &[u8; 5]) -> Result<[u8; let candidate = super::lfsr::decrypt_key(0x00, player_key, &enc); // Check if any previous candidate matches (same disc key from different entry/pk) - for &(ref prev, _, _) in &candidates { + for (prev, _, _) in &candidates { if *prev == candidate { return Ok(candidate); } @@ -391,6 +391,7 @@ fn read_raw_title_key(drive: &mut Drive, agid: u8, lba: u32) -> Result<[u8; 5]> Ok(key) } +#[allow(dead_code)] fn read_title_key( drive: &mut Drive, agid: u8, diff --git a/src/disc/mod.rs b/src/disc/mod.rs index 722949f..ba4cf6b 100644 --- a/src/disc/mod.rs +++ b/src/disc/mod.rs @@ -874,8 +874,8 @@ impl KeySource { /// Standard KEYDB.cfg search locations (compatible with libaacs). const KEYDB_SEARCH_PATHS: &[&str] = &[ - ".config/aacs/KEYDB.cfg", // libaacs standard path - ".config/freemkv/keydb.cfg", // freemkv download path + ".config/aacs/KEYDB.cfg", // libaacs standard path + ".config/freemkv/keydb.cfg", // freemkv download path ]; const KEYDB_SYSTEM_PATH: &str = "/etc/aacs/KEYDB.cfg"; @@ -938,9 +938,7 @@ pub struct DiscId { impl DiscId { /// Best available name: meta_title, then formatted volume_id. pub fn name(&self) -> &str { - self.meta_title - .as_deref() - .unwrap_or(&self.volume_id) + self.meta_title.as_deref().unwrap_or(&self.volume_id) } } @@ -1031,10 +1029,10 @@ impl Disc { { let lba = disc.titles[0].extents.iter().find_map(|ext| { let mut buf = vec![0u8; 2048]; - if session.read_sectors(ext.start_lba, 1, &mut buf).is_ok() { - if crate::css::is_scrambled(&buf) { - return Some(ext.start_lba); - } + if session.read_sectors(ext.start_lba, 1, &mut buf).is_ok() + && crate::css::is_scrambled(&buf) + { + return Some(ext.start_lba); } None }); diff --git a/src/drive/mod.rs b/src/drive/mod.rs index 0e3593f..69deb55 100644 --- a/src/drive/mod.rs +++ b/src/drive/mod.rs @@ -714,7 +714,13 @@ impl SectorReader for Drive { self.read(lba, count, buf, true) } - fn read_sectors_recover(&mut self, lba: u32, count: u16, buf: &mut [u8], recovery: bool) -> Result { + fn read_sectors_recover( + &mut self, + lba: u32, + count: u16, + buf: &mut [u8], + recovery: bool, + ) -> Result { self.read(lba, count, buf, recovery) } } diff --git a/src/event.rs b/src/event.rs index 6d652cb..cb947cd 100644 --- a/src/event.rs +++ b/src/event.rs @@ -81,20 +81,13 @@ pub enum EventKind { }, /// Binary search isolated and recovered a marginal sector. - SectorRecovered { - sector: u64, - }, + SectorRecovered { sector: u64 }, /// Sector unreadable, zero-filled (skip mode). - SectorSkipped { - sector: u64, - }, + SectorSkipped { sector: u64 }, /// Binary search activated — batch failed, isolating bad sector. - BinarySearch { - sector: u64, - batch_size: u16, - }, + BinarySearch { sector: u64, batch_size: u16 }, /// Operation complete. Complete { diff --git a/src/ifo.rs b/src/ifo.rs index 888aff4..2943a85 100644 --- a/src/ifo.rs +++ b/src/ifo.rs @@ -564,7 +564,9 @@ fn parse_pgc(data: &[u8], pgc_offset: usize, chapters: u16) -> Result } // Program map: each byte is the first cell number (1-based) for that program for p in 0..nr_of_programs { - if pgm_base + p >= data.len() { break; } + if pgm_base + p >= data.len() { + break; + } let first_cell = data[pgm_base + p] as usize; // Chapter time = sum of cell durations before this program's first cell let time: f64 = cell_durations[..first_cell.saturating_sub(1)].iter().sum(); diff --git a/src/labels/mod.rs b/src/labels/mod.rs index e86a515..5639bf7 100644 --- a/src/labels/mod.rs +++ b/src/labels/mod.rs @@ -142,7 +142,7 @@ pub fn apply(reader: &mut dyn SectorReader, udf: &UdfFs, titles: &mut [DiscTitle /// Runs after BD-J label extraction — fills gaps with codec + channel descriptions. /// This is the central place for all fallback label generation. pub fn fill_defaults(titles: &mut [crate::disc::DiscTitle]) { - use crate::disc::{Codec, HdrFormat, Stream}; + use crate::disc::Stream; for title in titles.iter_mut() { for stream in &mut title.streams { @@ -151,7 +151,8 @@ pub fn fill_defaults(titles: &mut [crate::disc::DiscTitle]) { a.label = generate_audio_label(&a.codec, &a.channels, a.secondary); } Stream::Video(v) if v.label.is_empty() => { - v.label = generate_video_label(&v.codec, v.resolution.pixels(), &v.hdr, v.secondary); + v.label = + generate_video_label(&v.codec, v.resolution.pixels(), &v.hdr, v.secondary); } Stream::Subtitle(s) if s.forced => { // Ensure forced subs are labeled even if BD-J didn't set a name diff --git a/src/lib.rs b/src/lib.rs index a1a281b..14ba094 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,9 +90,9 @@ pub(crate) mod platform; pub mod profile; pub mod scsi; pub mod sector; -pub mod verify; pub(crate) mod speed; pub(crate) mod udf; +pub mod verify; pub use drive::capture::{ capture_drive_data, mask_bytes, mask_string, CapturedFeature, DriveCapture, diff --git a/src/mux/codec/mpeg2.rs b/src/mux/codec/mpeg2.rs index c9db80b..a076b4b 100644 --- a/src/mux/codec/mpeg2.rs +++ b/src/mux/codec/mpeg2.rs @@ -153,7 +153,7 @@ impl CodecParser for Mpeg2Parser { bits += 64 * 8; } } - let total_bytes = 4 + ((bits + 7) / 8) as usize; + let total_bytes = 4 + bits.div_ceil(8) as usize; (sc + total_bytes).min(data.len()) } } diff --git a/src/mux/codec/truehd.rs b/src/mux/codec/truehd.rs index f807814..1fbd91e 100644 --- a/src/mux/codec/truehd.rs +++ b/src/mux/codec/truehd.rs @@ -50,30 +50,27 @@ impl TrueHdParser { 0 => { // 48 kHz static SIZES: [usize; 38] = [ - 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, - 160, 160, 192, 192, 224, 224, 256, 256, 320, 320, - 384, 384, 448, 448, 512, 512, 640, 640, 768, 768, - 896, 896, 1024, 1024, 1152, 1152, 1280, 1280, + 64, 64, 80, 80, 96, 96, 112, 112, 128, 128, 160, 160, 192, 192, 224, 224, 256, + 256, 320, 320, 384, 384, 448, 448, 512, 512, 640, 640, 768, 768, 896, 896, + 1024, 1024, 1152, 1152, 1280, 1280, ]; SIZES.get(frmsizecod).copied().unwrap_or(0) } 1 => { // 44.1 kHz static SIZES: [usize; 38] = [ - 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, - 174, 175, 208, 209, 243, 244, 278, 279, 348, 349, - 417, 418, 487, 488, 557, 558, 696, 697, 835, 836, - 975, 976, 1114, 1115, 1253, 1254, 1393, 1394, + 69, 70, 87, 88, 104, 105, 121, 122, 139, 140, 174, 175, 208, 209, 243, 244, + 278, 279, 348, 349, 417, 418, 487, 488, 557, 558, 696, 697, 835, 836, 975, 976, + 1114, 1115, 1253, 1254, 1393, 1394, ]; SIZES.get(frmsizecod).copied().unwrap_or(0) } 2 => { // 32 kHz static SIZES: [usize; 38] = [ - 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, - 240, 240, 288, 288, 336, 336, 384, 384, 480, 480, - 576, 576, 672, 672, 768, 768, 960, 960, 1152, 1152, - 1344, 1344, 1536, 1536, 1728, 1728, 1920, 1920, + 96, 96, 120, 120, 144, 144, 168, 168, 192, 192, 240, 240, 288, 288, 336, 336, + 384, 384, 480, 480, 576, 576, 672, 672, 768, 768, 960, 960, 1152, 1152, 1344, + 1344, 1536, 1536, 1728, 1728, 1920, 1920, ]; SIZES.get(frmsizecod).copied().unwrap_or(0) } diff --git a/src/mux/disc.rs b/src/mux/disc.rs index 4e2163d..10f31ba 100644 --- a/src/mux/disc.rs +++ b/src/mux/disc.rs @@ -5,7 +5,7 @@ //! //! Read-only. For disc→ISO (raw sector copy), use `Disc::copy()`. -use crate::disc::{detect_max_batch_sectors, Disc, DiscTitle, Extent, ScanOptions}; +use crate::disc::{Disc, DiscTitle, Extent}; use crate::event::{Event, EventKind}; use crate::sector::SectorReader; use std::io; @@ -171,7 +171,12 @@ impl DiscStream { let offset = self.buf_valid; if self .reader - .read_sectors_recover(lba, count, &mut self.read_buf[offset..offset + bytes], false) + .read_sectors_recover( + lba, + count, + &mut self.read_buf[offset..offset + bytes], + false, + ) .is_ok() { self.buf_valid += bytes; diff --git a/src/mux/mkv.rs b/src/mux/mkv.rs index 92ccaaa..caf7361 100644 --- a/src/mux/mkv.rs +++ b/src/mux/mkv.rs @@ -5,7 +5,9 @@ //! cues and seek head are finalized at the end. use super::ebml; -use crate::disc::{AudioStream, Chapter, Codec, ColorSpace, HdrFormat, SubtitleStream, VideoStream}; +use crate::disc::{ + AudioStream, Chapter, Codec, ColorSpace, HdrFormat, SubtitleStream, VideoStream, +}; use std::io::{self, Seek, SeekFrom, Write}; /// MKV track definition (built from disc stream metadata). @@ -24,10 +26,10 @@ pub struct MkvTrack { pub display_width: u32, // display aspect ratio width (0 = same as pixel) pub display_height: u32, // display aspect ratio height (0 = same as pixel) // HDR colour metadata - pub colour_matrix: u8, // MatrixCoefficients (9=bt2020nc) - pub colour_transfer: u8, // TransferCharacteristics (16=smpte2084/PQ) - pub colour_primaries: u8, // Primaries (9=bt2020) - pub colour_range: u8, // Range (1=tv/limited) + pub colour_matrix: u8, // MatrixCoefficients (9=bt2020nc) + pub colour_transfer: u8, // TransferCharacteristics (16=smpte2084/PQ) + pub colour_primaries: u8, // Primaries (9=bt2020) + pub colour_range: u8, // Range (1=tv/limited) // Audio-specific pub sample_rate: f64, pub channels: u8, @@ -52,7 +54,7 @@ impl MkvTrack { }; let (matrix, transfer, primaries, range) = match v.color_space { ColorSpace::Bt2020 => (9, 16, 9, 1), // bt2020nc, PQ, bt2020, limited - ColorSpace::Bt709 => (1, 1, 1, 1), // bt709 + ColorSpace::Bt709 => (1, 1, 1, 1), // bt709 ColorSpace::Unknown => (0, 0, 0, 0), }; // Override transfer for non-PQ HDR @@ -268,7 +270,11 @@ impl MkvMuxer { // DefaultDuration — frame duration in nanoseconds if track.default_duration_ns > 0 { - ebml::write_uint(&mut writer, ebml::DEFAULT_DURATION, track.default_duration_ns)?; + ebml::write_uint( + &mut writer, + ebml::DEFAULT_DURATION, + track.default_duration_ns, + )?; } // Video-specific @@ -278,13 +284,25 @@ impl MkvMuxer { ebml::write_uint(&mut writer, ebml::PIXEL_HEIGHT, track.pixel_height as u64)?; if track.display_width > 0 && track.display_height > 0 { ebml::write_uint(&mut writer, ebml::DISPLAY_WIDTH, track.display_width as u64)?; - ebml::write_uint(&mut writer, ebml::DISPLAY_HEIGHT, track.display_height as u64)?; + ebml::write_uint( + &mut writer, + ebml::DISPLAY_HEIGHT, + track.display_height as u64, + )?; } // Colour metadata (HDR) if track.colour_matrix > 0 || track.colour_transfer > 0 { let col_pos = ebml::start_master(&mut writer, ebml::COLOUR)?; - ebml::write_uint(&mut writer, ebml::MATRIX_COEFFICIENTS, track.colour_matrix as u64)?; - ebml::write_uint(&mut writer, ebml::TRANSFER_CHARACTERISTICS, track.colour_transfer as u64)?; + ebml::write_uint( + &mut writer, + ebml::MATRIX_COEFFICIENTS, + track.colour_matrix as u64, + )?; + ebml::write_uint( + &mut writer, + ebml::TRANSFER_CHARACTERISTICS, + track.colour_transfer as u64, + )?; ebml::write_uint(&mut writer, ebml::PRIMARIES, track.colour_primaries as u64)?; ebml::write_uint(&mut writer, ebml::RANGE, track.colour_range as u64)?; ebml::end_master(&mut writer, col_pos)?; @@ -845,4 +863,3 @@ mod tests { ); } } - diff --git a/src/scsi/linux.rs b/src/scsi/linux.rs index 1504f32..f099b75 100644 --- a/src/scsi/linux.rs +++ b/src/scsi/linux.rs @@ -246,7 +246,6 @@ impl SgIoTransport { device.to_path_buf() } - } impl Drop for SgIoTransport { @@ -335,8 +334,8 @@ impl ScsiTransport for SgIoTransport { // Wait for completion with enforceable timeout. // Retry on EINTR (signal interrupted poll) with remaining time. - let deadline = std::time::Instant::now() - + std::time::Duration::from_millis(timeout_ms as u64); + let deadline = + std::time::Instant::now() + std::time::Duration::from_millis(timeout_ms as u64); let pr = loop { let remaining = deadline .saturating_duration_since(std::time::Instant::now()) diff --git a/src/sector.rs b/src/sector.rs index 8f7f052..d024a71 100644 --- a/src/sector.rs +++ b/src/sector.rs @@ -16,7 +16,13 @@ pub trait SectorReader: Send { /// Read with explicit recovery flag. /// true = full retry/reset loop (for ripping). false = single attempt, fast fail (for verify). /// Default: delegates to read_sectors (recovery=true behavior). - fn read_sectors_recover(&mut self, lba: u32, count: u16, buf: &mut [u8], recovery: bool) -> Result { + fn read_sectors_recover( + &mut self, + lba: u32, + count: u16, + buf: &mut [u8], + recovery: bool, + ) -> Result { // Default ignores flag — file-backed readers don't have recovery let _ = recovery; self.read_sectors(lba, count, buf) diff --git a/src/verify.rs b/src/verify.rs index 5abe176..2081406 100644 --- a/src/verify.rs +++ b/src/verify.rs @@ -1,6 +1,6 @@ //! Disc sector verification — read every sector and classify health. -use crate::disc::{Chapter, DiscTitle, Extent}; +use crate::disc::{Chapter, DiscTitle}; use crate::sector::SectorReader; use std::time::Instant; @@ -55,7 +55,12 @@ impl VerifyResult { } /// Map a bad sector range to a chapter timestamp. - pub fn chapter_at_offset(chapters: &[Chapter], byte_offset: u64, duration_secs: f64, total_bytes: u64) -> Option<(usize, f64)> { + pub fn chapter_at_offset( + chapters: &[Chapter], + byte_offset: u64, + duration_secs: f64, + total_bytes: u64, + ) -> Option<(usize, f64)> { if total_bytes == 0 || chapters.is_empty() { return None; } @@ -150,7 +155,12 @@ pub fn verify_title( let s1 = Instant::now(); let first_ok = reader - .read_sectors_recover(sector_lba, 1, &mut buf[sector_offset..sector_offset + 2048], false) + .read_sectors_recover( + sector_lba, + 1, + &mut buf[sector_offset..sector_offset + 2048], + false, + ) .is_ok(); let s1_ms = s1.elapsed().as_millis(); @@ -164,7 +174,12 @@ pub fn verify_title( // Retry once more after brief pause std::thread::sleep(std::time::Duration::from_secs(2)); if reader - .read_sectors_recover(sector_lba, 1, &mut buf[sector_offset..sector_offset + 2048], false) + .read_sectors_recover( + sector_lba, + 1, + &mut buf[sector_offset..sector_offset + 2048], + false, + ) .is_ok() { recovered += 1; @@ -178,9 +193,7 @@ pub fn verify_title( if status != SectorStatus::Good { // Merge with previous range if contiguous and same status if let Some(last) = ranges.last_mut() { - if last.status == status - && last.start_lba + last.count == sector_lba - { + if last.status == status && last.start_lba + last.count == sector_lba { last.count += 1; } else { ranges.push(SectorRange {