io: Impl Length for mutable refs

This commit is contained in:
Serial 2024-04-26 10:45:13 -04:00
parent e0bea0c21a
commit 86782436f2
No known key found for this signature in database
GPG key ID: DA95198DC17C4568
4 changed files with 74 additions and 3 deletions

View file

@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- **Length**: `impl<T: Length> 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

View file

@ -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);

View file

@ -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" => {

View file

@ -29,6 +29,17 @@ impl<T> 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<LoftyError>;
@ -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<LoftyError>;
@ -176,6 +196,17 @@ where
}
}
impl<T> Length for &mut T
where
T: Length,
{
type Error = <T as Length>::Error;
fn len(&self) -> Result<u64, Self::Error> {
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<u8>,
}
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());
}
}