Remove riff as a dependency

Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
Serial 2021-07-06 11:29:00 -04:00
parent b0709c0e8f
commit 2a3e54ba25
4 changed files with 107 additions and 114 deletions

7
Cargo.lock generated
View file

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

View file

@ -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"]

View file

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

View file

@ -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<T>(mut data: T) -> Result<Option<HashMap<String, String>>>
pub(crate) fn read_from<T>(data: &mut T) -> Result<Option<HashMap<String, String>>>
where
T: Read + Seek,
{
let chunk = riff::Chunk::read(&mut data, 0)?;
verify_riff(data)?;
let mut lists: Vec<riff::Chunk> = 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<String, String> = HashMap::with_capacity(chunk_len as usize);
let mut reading = true;
while reading {
if let (Ok(fourcc), Ok(size)) = (
cursor.read_u32::<LittleEndian>(),
cursor.read_u32::<LittleEndian>(),
) {
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<riff::Chunk> = 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<T>(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<String, String> = HashMap::with_capacity(chunk_len as usize);
let mut reading = true;
while reading {
if let (Ok(fourcc), Ok(size)) = (
cursor.read_u32::<LittleEndian>(),
cursor.read_u32::<LittleEndian>(),
) {
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::<LittleEndian>()?;
data.seek(SeekFrom::Current(i64::from(size)))?;
}
}
fn verify_riff<T>(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<String> {
@ -146,10 +167,8 @@ pub fn key_to_fourcc(key: &str) -> Option<[u8; 4]> {
pub(crate) fn write_to(data: &mut File, metadata: HashMap<String, String>) -> 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<String, String>) -> 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<u32>, Option<u32>) = (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::<LittleEndian>()? 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(())
}