diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a7314d..d630afa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ +## [0.5.2](https://github.com/Blobfolio/cdtoc/releases/tag/v0.5.2) - 2024-11-07 + +### Changed + +* Add (more) inline hints +* Add `Formatter` width/fill/align/etc. support for `AccurateRip`, `Cddb`, `ShaB64` +* Improve docs, test coverage + + + ## [0.5.1](https://github.com/Blobfolio/cdtoc/releases/tag/v0.5.1) - 2024-10-10 ### Changed diff --git a/CREDITS.md b/CREDITS.md index cef37d1..296d1b4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -1,19 +1,34 @@ # Project Dependencies Package: cdtoc - Version: 0.5.1 - Generated: 2024-10-11 03:12:14 UTC + Version: 0.5.2 + Generated: 2024-11-08 06:38:45 UTC -| Package | Version | Author(s) | License | -| ---- | ---- | ---- | ---- | -| [block-buffer](https://github.com/RustCrypto/utils) | 0.10.4 | RustCrypto Developers | Apache-2.0 or MIT | -| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:alex@alexcrichton.com) | Apache-2.0 or MIT | -| [crypto-common](https://github.com/RustCrypto/traits) | 0.1.6 | RustCrypto Developers | Apache-2.0 or MIT | -| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.4 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | -| [digest](https://github.com/RustCrypto/traits) | 0.10.7 | RustCrypto Developers | Apache-2.0 or MIT | -| [faster-hex](https://github.com/NervosFoundation/faster-hex) | 0.10.0 | [zhangsoledad](mailto:787953403@qq.com) | MIT | -| [generic-array](https://github.com/fizyk20/generic-array.git) | 0.14.7 | [Bartłomiej Kamiński](mailto:fizyk20@gmail.com) and [Aaron Trent](mailto:novacrazy@gmail.com) | MIT | -| [itoa](https://github.com/dtolnay/itoa) | 1.0.11 | [David Tolnay](mailto:dtolnay@gmail.com) | Apache-2.0 or MIT | -| [serde](https://github.com/serde-rs/serde) | 1.0.210 | [Erick Tryzelaar](mailto:erick.tryzelaar@gmail.com) and [David Tolnay](mailto:dtolnay@gmail.com) | Apache-2.0 or MIT | -| [sha1](https://github.com/RustCrypto/hashes) | 0.10.6 | RustCrypto Developers | Apache-2.0 or MIT | -| [trimothy](https://github.com/Blobfolio/trimothy) | 0.3.1 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | -| [typenum](https://github.com/paholg/typenum) | 1.17.0 | [Paho Lurie-Gregg](mailto:paho@paholg.com) and [Andre Bogus](mailto:bogusandre@gmail.com) | Apache-2.0 or MIT | +| Package | Version | Author(s) | License | Context | +| ---- | ---- | ---- | ---- | ---- | +| [dactyl](https://github.com/Blobfolio/dactyl) | 0.7.4 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | | +| [faster-hex](https://github.com/NervosFoundation/faster-hex) | 0.10.0 | [zhangsoledad](mailto:787953403@qq.com) | MIT | | +| [trimothy](https://github.com/Blobfolio/trimothy) | 0.3.1 | [Blobfolio, LLC.](mailto:hello@blobfolio.com) | WTFPL | | +| [block-buffer](https://github.com/RustCrypto/utils) | 0.10.4 | RustCrypto Developers | MIT OR Apache-2.0 | optional | +| [byteorder](https://github.com/BurntSushi/byteorder) | 1.5.0 | [Andrew Gallant](mailto:jamslam@gmail.com) | Unlicense OR MIT | target-specific | +| [cc](https://github.com/rust-lang/cc-rs) | 1.1.36 | [Alex Crichton](mailto:alex@alexcrichton.com) | MIT OR Apache-2.0 | optional, build, target-specific | +| [cfg-if](https://github.com/alexcrichton/cfg-if) | 1.0.0 | [Alex Crichton](mailto:alex@alexcrichton.com) | MIT OR Apache-2.0 | optional | +| [cpufeatures](https://github.com/RustCrypto/utils) | 0.2.14 | RustCrypto Developers | MIT OR Apache-2.0 | optional, target-specific | +| [crypto-common](https://github.com/RustCrypto/traits) | 0.1.6 | RustCrypto Developers | MIT OR Apache-2.0 | optional | +| [digest](https://github.com/RustCrypto/traits) | 0.10.7 | RustCrypto Developers | MIT OR Apache-2.0 | optional | +| [generic-array](https://github.com/fizyk20/generic-array.git) | 0.14.7 | [Bartłomiej Kamiński](mailto:fizyk20@gmail.com) and [Aaron Trent](mailto:novacrazy@gmail.com) | MIT | optional | +| [hash32](https://github.com/japaric/hash32) | 0.3.1 | [Jorge Aparicio](mailto:jorge@japaric.io) | MIT OR Apache-2.0 | target-specific | +| [heapless](https://github.com/rust-embedded/heapless) | 0.8.0 | [Jorge Aparicio](mailto:jorge@japaric.io), [Per Lindgren](mailto:per.lindgren@ltu.se), and [Emil Fresk](mailto:emil.fresk@gmail.com) | MIT OR Apache-2.0 | target-specific | +| [itoa](https://github.com/dtolnay/itoa) | 1.0.11 | [David Tolnay](mailto:dtolnay@gmail.com) | MIT OR Apache-2.0 | optional | +| [libc](https://github.com/rust-lang/libc) | 0.2.162 | The Rust Project Developers | MIT OR Apache-2.0 | optional, target-specific | +| [proc-macro2](https://github.com/dtolnay/proc-macro2) | 1.0.89 | [David Tolnay](mailto:dtolnay@gmail.com) and [Alex Crichton](mailto:alex@alexcrichton.com) | MIT OR Apache-2.0 | optional, build, target-specific | +| [quote](https://github.com/dtolnay/quote) | 1.0.37 | [David Tolnay](mailto:dtolnay@gmail.com) | MIT OR Apache-2.0 | optional, build, target-specific | +| [serde](https://github.com/serde-rs/serde) | 1.0.214 | [Erick Tryzelaar](mailto:erick.tryzelaar@gmail.com) and [David Tolnay](mailto:dtolnay@gmail.com) | MIT OR Apache-2.0 | optional | +| [serde_derive](https://github.com/serde-rs/serde) | 1.0.214 | [Erick Tryzelaar](mailto:erick.tryzelaar@gmail.com) and [David Tolnay](mailto:dtolnay@gmail.com) | MIT OR Apache-2.0 | optional | +| [sha1](https://github.com/RustCrypto/hashes) | 0.10.6 | RustCrypto Developers | MIT OR Apache-2.0 | optional | +| [sha1-asm](https://github.com/RustCrypto/asm-hashes) | 0.5.3 | RustCrypto Developers | MIT | optional, target-specific | +| [shlex](https://github.com/comex/rust-shlex) | 1.3.0 | [comex](mailto:comexk@gmail.com), [Fenhl](mailto:fenhl@fenhl.net), [Adrian Taylor](mailto:adetaylor@chromium.org), [Alex Touchet](mailto:alextouchet@outlook.com), [Daniel Parks](mailto:dp+git@oxidized.org), and [Garrett Berg](mailto:googberg@gmail.com) | MIT OR Apache-2.0 | optional, build, target-specific | +| [stable_deref_trait](https://github.com/storyyeller/stable_deref_trait) | 1.2.0 | [Robert Grosse](mailto:n210241048576@gmail.com) | MIT OR Apache-2.0 | target-specific | +| [syn](https://github.com/dtolnay/syn) | 2.0.87 | [David Tolnay](mailto:dtolnay@gmail.com) | MIT OR Apache-2.0 | optional, build, target-specific | +| [typenum](https://github.com/paholg/typenum) | 1.17.0 | [Paho Lurie-Gregg](mailto:paho@paholg.com) and [Andre Bogus](mailto:bogusandre@gmail.com) | MIT OR Apache-2.0 | optional | +| [unicode-ident](https://github.com/dtolnay/unicode-ident) | 1.0.13 | [David Tolnay](mailto:dtolnay@gmail.com) | (MIT OR Apache-2.0) AND Unicode-DFS-2016 | optional, build, target-specific | +| [version_check](https://github.com/SergioBenitez/version_check) | 0.9.5 | [Sergio Benitez](mailto:sb@sergio.bz) | MIT OR Apache-2.0 | optional, build | diff --git a/Cargo.toml b/Cargo.toml index 60a4272..53d7ed8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "cdtoc" -version = "0.5.1" -authors = ["Blobfolio, LLC. "] +version = "0.5.2" +authors = ["Josh Stoik "] edition = "2021" rust-version = "1.81" description = "Parser and tools for CDTOC metadata tags." @@ -19,9 +19,6 @@ exclude = [ [package.metadata.bashman] name = "CDTOC" -bash-dir = "./" -man-dir = "./" -credits-dir = "./" [package.metadata.docs.rs] rustc-args = ["--cfg", "docsrs"] diff --git a/README.md b/README.md index d9fd0c0..2617c70 100644 --- a/README.md +++ b/README.md @@ -72,25 +72,3 @@ The disc ID helpers require additional dependencies, so if you aren't using them version = "0.5.*" default-features = false ``` - - - -## License - -Copyright © 2024 [Blobfolio, LLC](https://blobfolio.com) <hello@blobfolio.com> - -This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - Version 2, December 2004 - - Copyright (C) 2004 Sam Hocevar - - Everyone is permitted to copy and distribute verbatim or modified - copies of this license document, and changing it is allowed as long - as the name is changed. - - DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. You just DO WHAT THE FUCK YOU WANT TO. diff --git a/src/accuraterip.rs b/src/accuraterip.rs index 8dd55f4..888e4cb 100644 --- a/src/accuraterip.rs +++ b/src/accuraterip.rs @@ -70,16 +70,19 @@ const DRIVE_OFFSET_OFFSET_RNG: Range = -2940..2941; pub struct AccurateRip([u8; 13]); impl AsRef<[u8]> for AccurateRip { + #[inline] fn as_ref(&self) -> &[u8] { &self.0 } } impl From for [u8; 13] { + #[inline] fn from(src: AccurateRip) -> Self { src.0 } } impl fmt::Display for AccurateRip { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.pretty_print()) + f.pad(&self.pretty_print()) } } @@ -412,6 +415,10 @@ impl AccurateRip { /// toc.accuraterip_id().pretty_print(), /// "013-0015deca-00d9b921-9a0a6e0d", /// ); + /// assert_eq!( + /// toc.accuraterip_id().to_string(), + /// "013-0015deca-00d9b921-9a0a6e0d", + /// ); /// ``` pub fn pretty_print(&self) -> String { let mut out: Vec = vec![ @@ -545,6 +552,7 @@ mod tests { let toc = Toc::from_cdtoc(t).expect("Invalid TOC"); let ar_id = toc.accuraterip_id(); assert_eq!(ar_id.to_string(), id); + assert_eq!(ar_id.pretty_print(), id); // Test decoding three ways. assert_eq!(AccurateRip::decode(id), Ok(ar_id)); diff --git a/src/cddb.rs b/src/cddb.rs index 7acd7b7..903544e 100644 --- a/src/cddb.rs +++ b/src/cddb.rs @@ -53,7 +53,7 @@ impl fmt::Display for Cddb { faster_hex::hex_encode_fallback(self.0.to_be_bytes().as_slice(), &mut buf); std::str::from_utf8(buf.as_slice()) .map_err(|_| fmt::Error) - .and_then(|s| f.write_str(s)) + .and_then(|s| f.pad(s)) } } @@ -64,10 +64,12 @@ impl FromStr for Cddb { } impl hash::Hash for Cddb { + #[inline] fn hash(&self, state: &mut H) { state.write_u32(self.0); } } impl PartialEq for Cddb { + #[inline] fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } diff --git a/src/ctdb.rs b/src/ctdb.rs index dc6ccaf..2658afb 100644 --- a/src/ctdb.rs +++ b/src/ctdb.rs @@ -260,6 +260,7 @@ mod tests { let toc = Toc::from_cdtoc(t).expect("Invalid TOC"); let ctdb_id = toc.ctdb_id(); assert_eq!(ctdb_id.to_string(), id); + assert_eq!(ctdb_id.pretty_print(), id); assert_eq!(toc.ctdb_checksum_url(), lookup); // Test decoding three ways. diff --git a/src/error.rs b/src/error.rs index 65cc4fc..9b4c84f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -101,26 +101,26 @@ pub enum TocError { impl fmt::Display for TocError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::CDDASampleCount => f.write_str("Invalid CDDA sample count."), - Self::CDTOCChars => f.write_str("Invalid character(s), expecting only 0-9, A-F, +, and (rarely) X."), - Self::Checksums => f.write_str("Unable to parse checksums."), - Self::Format(kind) => write!(f, "This operation can't be applied to {kind} discs."), - Self::LeadinSize => f.write_str("Leadin must be at least 150."), - Self::NoAudio => f.write_str("At least one audio track is required."), - Self::NoChecksums => f.write_str("No checksums were present."), - Self::SectorCount(expected, found) => write!(f, "Expected {expected} audio sectors, found {found}."), - Self::SectorOrder => f.write_str("Sectors are incorrectly ordered or overlap."), - Self::SectorSize => f.write_str("Sector sizes may not exceed four bytes (u32)."), - Self::TrackCount => f.write_str("The number of audio tracks must be between 1..=99."), - - #[cfg(feature = "accuraterip")] Self::AccurateRipDecode => f.write_str("Invalid AccurateRip ID string."), - #[cfg(feature = "accuraterip")] Self::DriveOffsetDecode => f.write_str("Unable to parse drive offsets."), - #[cfg(feature = "accuraterip")] Self::NoDriveOffsets => f.write_str("No drive offsets were found."), - - #[cfg(feature = "cddb")] Self::CddbDecode => f.write_str("Invalid CDDB ID string."), - #[cfg(feature = "sha1")] Self::ShaB64Decode => f.write_str("Invalid sha/base64 ID string."), - } + f.write_str(match self { + Self::CDDASampleCount => "Invalid CDDA sample count.", + Self::CDTOCChars => "Invalid character(s), expecting only 0-9, A-F, +, and (rarely) X.", + Self::Checksums => "Unable to parse checksums.", + Self::Format(kind) => return write!(f, "This operation can't be applied to {kind} discs."), + Self::LeadinSize => "Leadin must be at least 150.", + Self::NoAudio => "At least one audio track is required.", + Self::NoChecksums => "No checksums were present.", + Self::SectorCount(expected, found) => return write!(f, "Expected {expected} audio sectors, found {found}."), + Self::SectorOrder => "Sectors are incorrectly ordered or overlap.", + Self::SectorSize => "Sector sizes may not exceed four bytes (u32).", + Self::TrackCount => "The number of audio tracks must be between 1..=99.", + + #[cfg(feature = "accuraterip")] Self::AccurateRipDecode => "Invalid AccurateRip ID string.", + #[cfg(feature = "accuraterip")] Self::DriveOffsetDecode => "Unable to parse drive offsets.", + #[cfg(feature = "accuraterip")] Self::NoDriveOffsets => "No drive offsets were found.", + + #[cfg(feature = "cddb")] Self::CddbDecode => "Invalid CDDB ID string.", + #[cfg(feature = "sha1")] Self::ShaB64Decode => "Invalid sha/base64 ID string.", + }) } } diff --git a/src/lib.rs b/src/lib.rs index ed34cf0..86a4c65 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -979,9 +979,8 @@ pub enum TocKind { } impl fmt::Display for TocKind { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad(self.as_str()) } } impl TocKind { diff --git a/src/musicbrainz.rs b/src/musicbrainz.rs index 4f445f1..deaf489 100644 --- a/src/musicbrainz.rs +++ b/src/musicbrainz.rs @@ -37,6 +37,10 @@ impl Toc { /// toc.musicbrainz_id().to_string(), /// "nljDXdC8B_pDwbdY1vZJvdrAZI4-", /// ); + /// assert_eq!( + /// toc.musicbrainz_id().pretty_print(), + /// "nljDXdC8B_pDwbdY1vZJvdrAZI4-", + /// ); /// ``` pub fn musicbrainz_id(&self) -> ShaB64 { use sha1::Digest; @@ -133,6 +137,7 @@ mod tests { let toc = Toc::from_cdtoc(t).expect("Invalid TOC"); let mb_id = toc.musicbrainz_id(); assert_eq!(mb_id.to_string(), id); + assert_eq!(mb_id.pretty_print(), id); // Test decoding three ways. assert_eq!(ShaB64::decode(id), Ok(mb_id)); diff --git a/src/serde.rs b/src/serde.rs index 47c610e..9805fa6 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -64,6 +64,7 @@ macro_rules! serialize_with { ($ty:ty, $fn:ident) => ( #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl Serialize for $ty { + #[inline] fn serialize(&self, serializer: S) -> Result where S: ser::Serializer { self.$fn().serialize(serializer) } } @@ -86,6 +87,7 @@ serialize_with!(Toc, to_string); #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl<'de> Deserialize<'de> for Duration { + #[inline] fn deserialize(deserializer: D) -> Result where D: de::Deserializer<'de> { u64::deserialize(deserializer).map(Self::from) @@ -94,6 +96,7 @@ impl<'de> Deserialize<'de> for Duration { #[cfg_attr(docsrs, doc(cfg(feature = "serde")))] impl Serialize for Duration { + #[inline] fn serialize(&self, serializer: S) -> Result where S: ser::Serializer { self.0.serialize(serializer) } } diff --git a/src/shab64.rs b/src/shab64.rs index 87ccd2e..541b172 100644 --- a/src/shab64.rs +++ b/src/shab64.rs @@ -30,12 +30,14 @@ use std::{ pub struct ShaB64([u8; 20]); impl fmt::Display for ShaB64 { + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.pretty_print()) + f.pad(&self.pretty_print()) } } impl From for ShaB64 { + #[inline] fn from(src: Sha1) -> Self { Self(<[u8; 20]>::from(src.finalize())) } } diff --git a/src/time.rs b/src/time.rs index 5654d5b..de378a9 100644 --- a/src/time.rs +++ b/src/time.rs @@ -82,17 +82,20 @@ pub struct Duration(pub(crate) u64); impl Add for Duration where u64: From { type Output = Self; + #[inline] fn add(self, other: T) -> Self { Self(self.0 + u64::from(other)) } } impl AddAssign for Duration where u64: From { + #[inline] fn add_assign(&mut self, other: T) { self.0 += u64::from(other); } } impl Div for Duration where u64: From { type Output = Self; + #[inline] fn div(self, other: T) -> Self { let other = u64::from(other); if other == 0 { Self(0) } @@ -102,6 +105,7 @@ where u64: From { impl DivAssign for Duration where u64: From { + #[inline] fn div_assign(&mut self, other: T) { let other = u64::from(other); if other == 0 { self.0 = 0; } @@ -113,6 +117,7 @@ impl Eq for Duration {} impl fmt::Display for Duration { #[expect(clippy::many_single_char_names, reason = "Consistency is preferred.")] + #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (d, h, m, s, frames) = self.dhmsf(); if d == 0 { @@ -125,56 +130,65 @@ impl fmt::Display for Duration { } impl From for Duration { + #[inline] fn from(src: u32) -> Self { Self(src.into()) } } impl From for Duration { + #[inline] fn from(src: u64) -> Self { Self(src) } } impl From for Duration { + #[inline] fn from(src: usize) -> Self { Self(src as u64) } } impl From for u64 { + #[inline] fn from(src: Duration) -> Self { src.0 } } impl hash::Hash for Duration { + #[inline] fn hash(&self, state: &mut H) { state.write_u64(self.0); } } impl PartialEq for Duration { + #[inline] fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } impl Mul for Duration where u64: From { type Output = Self; + #[inline] fn mul(self, other: T) -> Self { Self(self.0 * u64::from(other)) } } impl MulAssign for Duration where u64: From { + #[inline] fn mul_assign(&mut self, other: T) { self.0 *= u64::from(other); } } impl Sub for Duration where u64: From { type Output = Self; + #[inline] fn sub(self, other: T) -> Self { Self(self.0.saturating_sub(u64::from(other))) } } impl SubAssign for Duration where u64: From { + #[inline] fn sub_assign(&mut self, other: T) { self.0 = self.0.saturating_sub(u64::from(other)); } } impl Sum for Duration { + #[inline] fn sum(iter: I) -> Self - where I: Iterator { - iter.fold(Self::default(), |a, b| a + b) - } + where I: Iterator { iter.fold(Self::default(), |a, b| a + b) } } impl Duration { diff --git a/src/track.rs b/src/track.rs index ed5de93..552719a 100644 --- a/src/track.rs +++ b/src/track.rs @@ -284,6 +284,7 @@ impl Iterator for Tracks<'_> { Some(Track { num, pos, from, to }) } + #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) @@ -291,9 +292,8 @@ impl Iterator for Tracks<'_> { } impl ExactSizeIterator for Tracks<'_> { - fn len(&self) -> usize { - self.tracks.len().saturating_sub(self.pos) - } + #[inline] + fn len(&self) -> usize { self.tracks.len().saturating_sub(self.pos) } } impl<'a> Tracks<'a> {