From 2a3e54ba25f194a97e23433eb349ae62a1020c3f Mon Sep 17 00:00:00 2001 From: Serial <69764315+Serial-ATA@users.noreply.github.com> Date: Tue, 6 Jul 2021 11:29:00 -0400 Subject: [PATCH] Remove riff as a dependency Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com> --- Cargo.lock | 7 -- Cargo.toml | 4 +- README.md | 1 - src/components/logic/riff.rs | 209 ++++++++++++++++++----------------- 4 files changed, 107 insertions(+), 114 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ab11d65..0163bee7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -327,7 +327,6 @@ dependencies = [ "metaflac", "mp4ameta", "ogg_pager", - "riff", "thiserror", ] @@ -531,12 +530,6 @@ version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" -[[package]] -name = "riff" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9b1a3d5f46d53f4a3478e2be4a5a5ce5108ea58b100dcd139830eae7f79a3a1" - [[package]] name = "rustc_version" version = "0.2.3" diff --git a/Cargo.toml b/Cargo.toml index 0f728d49..81893366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,6 @@ categories = ["accessibility", "multimedia::audio"] [dependencies] # Ape ape = {version = "0.3.0", optional = true, git = "https://github.com/rossnomann/rust-ape"} -# Riff -riff = {version = "1.0.1", optional = true} # Id3 id3 = {version = "0.6.4", optional = true} # De/Encoding filepath = { version = "0.1.1", optional = true } # wav/aiff only supports paths for some reason @@ -40,7 +38,7 @@ format-opus = ["ogg_pager"] format-vorbis = ["ogg_pager"] format-ape = ["ape"] format-id3 = ["id3", "filepath"] -format-riff = ["riff"] +format-riff = [] format-ogg = ["format-flac", "format-opus", "format-vorbis"] all_tags = ["format-ogg", "format-mp4", "format-id3", "format-riff", "format-ape"] diff --git a/README.md b/README.md index f1c8482f..07bc7c9e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ All these great projects helped make this crate possible. (*Sorted alphabeticall * [**id3**](https://github.com/polyfloyd/rust-id3) * [**metaflac**](https://github.com/jameshurst/rust-metaflac) * [**mp4ameta**](https://github.com/Saecki/rust-mp4ameta) -* [**riff**](https://github.com/frabert/riff) ## License diff --git a/src/components/logic/riff.rs b/src/components/logic/riff.rs index 52ae6dab..89c4ab88 100644 --- a/src/components/logic/riff.rs +++ b/src/components/logic/riff.rs @@ -1,7 +1,6 @@ use crate::{LoftyError, Result}; use byteorder::{LittleEndian, ReadBytesExt}; -use std::borrow::BorrowMut; use std::collections::HashMap; use std::fs::File; use std::io::{Cursor, Read, Seek, SeekFrom, Write}; @@ -28,86 +27,108 @@ pub const ALBU: [u8; 4] = [65, 76, 66, 85]; // Can album artist OR album title pub const TRAC: [u8; 4] = [84, 82, 65, 67]; // Can represent track number OR total tracks pub const DISC: [u8; 4] = [68, 73, 83, 67]; // Can represent disc number OR total discs -pub(crate) fn read_from(mut data: T) -> Result>> +pub(crate) fn read_from(data: &mut T) -> Result>> where T: Read + Seek, { - let chunk = riff::Chunk::read(&mut data, 0)?; + verify_riff(data)?; - let mut lists: Vec = Vec::new(); + data.seek(SeekFrom::Current(8))?; - for child in chunk.iter(&mut data) { - let chunk_id = child.id(); + find_info_list(data)?; - if &chunk_id.value == LIST_ID { - lists.push(child) + let mut info_list_size = [0; 4]; + data.read_exact(&mut info_list_size)?; + + let mut info_list = vec![0; u32::from_le_bytes(info_list_size) as usize]; + data.read_exact(&mut info_list)?; + + info_list.drain(0..4); // Get rid of the chunk ID + let mut cursor = Cursor::new(&*info_list); + + let chunk_len = info_list.len(); + let mut metadata: HashMap = HashMap::with_capacity(chunk_len as usize); + + let mut reading = true; + + while reading { + if let (Ok(fourcc), Ok(size)) = ( + cursor.read_u32::(), + cursor.read_u32::(), + ) { + match create_key(&fourcc.to_le_bytes()) { + Some(key) => { + let mut buf = vec![0; size as usize]; + cursor.read_exact(&mut buf)?; + + // Just skip any values that can't be converted + match std::string::String::from_utf8(buf) { + Ok(val) => { + let _ = + metadata.insert(key, val.trim_matches(char::from(0)).to_string()); + }, + Err(_) => continue, + } + }, + #[allow(clippy::cast_lossless)] + None => cursor.set_position(cursor.position() + size as u64), + } + + // Skip null byte + if size as usize % 2 != 0 { + cursor.set_position(cursor.position() + 1) + } + + if cursor.position() >= cursor.get_ref().len() as u64 { + reading = false + } + } else { + reading = false } } - return if lists.is_empty() { - Err(LoftyError::Riff("This file doesn't contain a LIST chunk")) - } else { - let mut info: Option = None; + Ok(Some(metadata)) +} - for child in lists { - if &child.read_type(&mut data)?.value == b"INFO" { - info = Some(child); - break; - } - } +fn find_info_list(data: &mut T) -> Result<()> +where + T: Read + Seek, +{ + loop { + let mut chunk_name = [0; 4]; + data.read_exact(&mut chunk_name)?; - if let Some(list) = info { - let mut content = list.read_contents(&mut data)?; + if &chunk_name == LIST_ID { + data.seek(SeekFrom::Current(4))?; - content.drain(0..4); // Get rid of the chunk ID - let mut cursor = Cursor::new(&*content); + let mut list_type = [0; 4]; + data.read_exact(&mut list_type)?; - let chunk_len = list.len(); - let mut metadata: HashMap = HashMap::with_capacity(chunk_len as usize); - - let mut reading = true; - - while reading { - if let (Ok(fourcc), Ok(size)) = ( - cursor.read_u32::(), - cursor.read_u32::(), - ) { - match create_key(&fourcc.to_le_bytes()) { - Some(key) => { - let mut buf = vec![0; size as usize]; - cursor.read_exact(&mut buf)?; - - // Just skip any values that can't be converted - match std::string::String::from_utf8(buf) { - Ok(val) => { - let _ = metadata - .insert(key, val.trim_matches(char::from(0)).to_string()); - }, - Err(_) => continue, - } - }, - #[allow(clippy::cast_lossless)] - None => cursor.set_position(cursor.position() + size as u64), - } - - // Skip null byte - if size as usize % 2 != 0 { - cursor.set_position(cursor.position() + 1) - } - - if cursor.position() >= cursor.get_ref().len() as u64 { - reading = false - } - } else { - reading = false - } + if &list_type == b"INFO" { + data.seek(SeekFrom::Current(-8))?; + return Ok(()); } - Ok(Some(metadata)) - } else { - Err(LoftyError::Riff("This file doesn't contain an INFO chunk")) + data.seek(SeekFrom::Current(-8))?; } - }; + + let size = data.read_u32::()?; + data.seek(SeekFrom::Current(i64::from(size)))?; + } +} + +fn verify_riff(data: &mut T) -> Result<()> +where + T: Read + Seek, +{ + let mut id = [0; 4]; + data.read_exact(&mut id)?; + + if &id != b"RIFF" { + return Err(LoftyError::Riff("RIFF file doesn't contain a RIFF chunk")); + } + + Ok(()) } fn create_key(fourcc: &[u8]) -> Option { @@ -146,10 +167,8 @@ pub fn key_to_fourcc(key: &str) -> Option<[u8; 4]> { pub(crate) fn write_to(data: &mut File, metadata: HashMap) -> Result<()> { let mut packet = Vec::new(); - packet.extend(riff::LIST_ID.value.iter()); - - let fourcc = "INFO"; - packet.extend(fourcc.as_bytes().iter()); + packet.extend(LIST_ID.iter()); + packet.extend(b"INFO".iter()); for (k, v) in metadata { if let Some(fcc) = key_to_fourcc(&*k) { @@ -167,53 +186,37 @@ pub(crate) fn write_to(data: &mut File, metadata: HashMap) -> Re } } - let mut file_bytes = Vec::new(); - std::io::copy(data.borrow_mut(), &mut file_bytes)?; - - let len = (packet.len() - 4) as u32; - let size = len.to_le_bytes(); + let size = ((packet.len() - 4) as u32).to_le_bytes(); #[allow(clippy::needless_range_loop)] for i in 0..4 { packet.insert(i + 4, size[i]); } - let mut file = Cursor::new(file_bytes); + verify_riff(data)?; - let chunk = riff::Chunk::read(&mut file, 0)?; + data.seek(SeekFrom::Current(8))?; - let (mut list_pos, mut list_len): (Option, Option) = (None, None); + find_info_list(data)?; - if chunk.id() != riff::RIFF_ID { - return Err(LoftyError::Riff("This file does not contain a RIFF chunk")); - } + let info_list_size = data.read_u32::()? as usize; + data.seek(SeekFrom::Current(-8))?; - for child in chunk.iter(&mut file) { - if child.id() == riff::LIST_ID { - list_pos = Some(child.offset() as u32); - list_len = Some(child.len()); - } - } + let info_list_start = data.seek(SeekFrom::Current(0))? as usize; + let info_list_end = info_list_start + 8 + info_list_size; - file.seek(SeekFrom::Start(0))?; + data.seek(SeekFrom::Start(0))?; + let mut file_bytes = Vec::new(); + data.read_to_end(&mut file_bytes)?; - let mut content = Vec::new(); - std::io::copy(&mut file, &mut content)?; + let _ = file_bytes.splice(info_list_start..info_list_end, packet); - if let (Some(list_pos), Some(list_len)) = (list_pos, list_len) { - let list_end = (list_pos + list_len) as usize; + let total_size = (file_bytes.len() - 8) as u32; + let _ = file_bytes.splice(4..8, total_size.to_le_bytes().to_vec()); - let _ = content.splice(list_pos as usize..list_end, packet); + data.seek(SeekFrom::Start(0))?; + data.set_len(0)?; + data.write_all(&*file_bytes)?; - let total_size = (content.len() - 8) as u32; - let _ = content.splice(4..8, total_size.to_le_bytes().to_vec()); - - data.seek(SeekFrom::Start(0))?; - data.set_len(0)?; - data.write_all(&*content)?; - - Ok(()) - } else { - Err(LoftyError::Riff("This file does not contain an INFO chunk")) - } + Ok(()) }