From 86782436f23168057842c12ceafd687bc33d0081 Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Fri, 26 Apr 2024 10:45:13 -0400 Subject: [PATCH] io: Impl `Length` for mutable refs --- CHANGELOG.md | 6 ++- lofty/src/iff/wav/tag/write.rs | 2 +- lofty/src/mp4/ilst/mod.rs | 2 +- lofty/src/util/io.rs | 67 ++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 251a4072c..8e2df6d04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added +- **Length**: `impl Truncate for &mut T` ([PR](https://github.com/Serial-ATA/lofty-rs/pull/387)) + ## [0.19.1] - 2024-04-26 ### Added @@ -726,7 +729,8 @@ See [ogg_pager's changelog](ogg_pager/CHANGELOG.md). ### Removed - `ErrorKind::BadExtension` -[Unreleased]: https://github.com/Serial-ATA/lofty-rs/compare/0.19.1...HEAD +[Unreleased]: https://github.com/Serial-ATA/lofty-rs/compare/0.19.2...HEAD +[0.19.2]: https://github.com/Serial-ATA/lofty-rs/compare/0.19.1...0.19.2 [0.19.1]: https://github.com/Serial-ATA/lofty-rs/compare/0.19.0...0.19.1 [0.19.0]: https://github.com/Serial-ATA/lofty-rs/compare/0.18.2...0.19.0 [0.18.2]: https://github.com/Serial-ATA/lofty-rs/compare/0.18.1...0.18.2 diff --git a/lofty/src/iff/wav/tag/write.rs b/lofty/src/iff/wav/tag/write.rs index 732c76d00..d3e2d4004 100644 --- a/lofty/src/iff/wav/tag/write.rs +++ b/lofty/src/iff/wav/tag/write.rs @@ -124,7 +124,7 @@ pub(super) fn create_riff_info( bytes.extend(terminator); } - let packet_size = bytes.len() - 4; + let packet_size = Vec::len(bytes) - 4; if packet_size > u32::MAX as usize { err!(TooMuchData); diff --git a/lofty/src/mp4/ilst/mod.rs b/lofty/src/mp4/ilst/mod.rs index ff2c97bad..682d0ab1c 100644 --- a/lofty/src/mp4/ilst/mod.rs +++ b/lofty/src/mp4/ilst/mod.rs @@ -599,7 +599,7 @@ impl SplitTag for Ilst { ItemValue::Text(text) }, // We have to special case track/disc numbers since they are stored together - AtomData::Unknown { code: 0, data } if data.len() >= 6 => { + AtomData::Unknown { code: 0, data } if Vec::len(data) >= 6 => { if let AtomIdent::Fourcc(ref fourcc) = ident { match fourcc { b"trkn" => { diff --git a/lofty/src/util/io.rs b/lofty/src/util/io.rs index a45a98a73..90efda101 100644 --- a/lofty/src/util/io.rs +++ b/lofty/src/util/io.rs @@ -29,6 +29,17 @@ impl SeekStreamLen for T where T: Seek {} /// /// Take great care in implementing this for downstream types, as Lofty will assume that the /// container has the new length specified. If this assumption were to be broken, files **will** become corrupted. +/// +/// # Examples +/// +/// ```rust +/// use lofty::io::Truncate; +/// +/// let mut data = vec![1, 2, 3, 4, 5]; +/// data.truncate(3); +/// +/// assert_eq!(data, vec![1, 2, 3]); +/// ``` pub trait Truncate { /// The error type of the truncation operation type Error: Into; @@ -107,6 +118,15 @@ where /// /// Take great care in implementing this for downstream types, as Lofty will assume that the /// container has the exact length specified. If this assumption were to be broken, files **may** become corrupted. +/// +/// # Examples +/// +/// ```rust +/// use lofty::io::Length; +/// +/// let data = vec![1, 2, 3, 4, 5]; +/// assert_eq!(data.len(), 5); +/// ``` pub trait Length { /// The error type of the length operation type Error: Into; @@ -176,6 +196,17 @@ where } } +impl Length for &mut T +where + T: Length, +{ + type Error = ::Error; + + fn len(&self) -> Result { + Length::len(*self) + } +} + /// Provides a set of methods to read and write to a file-like object /// /// This is a combination of the [`Read`], [`Write`], [`Seek`], [`Truncate`], and [`Length`] traits. @@ -284,4 +315,40 @@ mod tests { let current_file_contents = reader.into_inner(); assert_eq!(current_file_contents, test_asset_contents()); } + + #[test] + fn io_save_using_references() { + struct File { + buf: Vec, + } + + let mut f = File { + buf: std::fs::read(TEST_ASSET).unwrap(), + }; + + // Same test as above, but using references instead of owned values + let mut file = file(); + alter_tag(&mut file); + + { + let mut reader = Cursor::new(&mut f.buf); + file.save_to(&mut reader, WriteOptions::new().preferred_padding(0)) + .expect("Failed to save to vec"); + } + + { + let mut reader = Cursor::new(&f.buf[..]); + file = MpegFile::read_from(&mut reader, ParseOptions::new()).unwrap(); + revert_tag(&mut file); + } + + { + let mut reader = Cursor::new(&mut f.buf); + file.save_to(&mut reader, WriteOptions::new().preferred_padding(0)) + .expect("Failed to save to vec"); + } + + let current_file_contents = f.buf; + assert_eq!(current_file_contents, test_asset_contents()); + } }