mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2025-03-04 14:57:17 +00:00
RIFF cleanup
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
2a3e54ba25
commit
d403b11783
1 changed files with 43 additions and 44 deletions
|
@ -6,26 +6,28 @@ use std::fs::File;
|
|||
use std::io::{Cursor, Read, Seek, SeekFrom, Write};
|
||||
|
||||
// Used to determine the RIFF metadata format
|
||||
pub const LIST_ID: &[u8; 4] = b"LIST";
|
||||
pub const LIST_ID: &[u8] = b"LIST";
|
||||
|
||||
// FourCC
|
||||
|
||||
// Standard
|
||||
pub const IART: [u8; 4] = [73, 65, 82, 84];
|
||||
pub const ICMT: [u8; 4] = [73, 67, 77, 84];
|
||||
pub const ICRD: [u8; 4] = [73, 67, 82, 68];
|
||||
pub const INAM: [u8; 4] = [73, 78, 65, 77];
|
||||
pub const IPRD: [u8; 4] = [73, 80, 82, 68]; // Represents album title
|
||||
pub const IART: &[u8] = &[73, 65, 82, 84];
|
||||
pub const ICMT: &[u8] = &[73, 67, 77, 84];
|
||||
pub const ICRD: &[u8] = &[73, 67, 82, 68];
|
||||
pub const INAM: &[u8] = &[73, 78, 65, 77];
|
||||
pub const IPRD: &[u8] = &[73, 80, 82, 68]; // Represents album title
|
||||
|
||||
// Non-standard
|
||||
pub const ITRK: [u8; 4] = [73, 84, 82, 75]; // Can represent track number
|
||||
pub const IPRT: [u8; 4] = [73, 80, 82, 84]; // Can also represent track number
|
||||
pub const IFRM: [u8; 4] = [73, 70, 82, 77]; // Can represent total tracks
|
||||
pub const ITRK: &[u8] = &[73, 84, 82, 75]; // Can represent track number
|
||||
pub const IPRT: &[u8] = &[73, 80, 82, 84]; // Can also represent track number
|
||||
pub const IFRM: &[u8] = &[73, 70, 82, 77]; // Can represent total tracks
|
||||
|
||||
// Very non-standard
|
||||
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 const ALBU: &[u8] = &[65, 76, 66, 85]; // Can album artist OR album title
|
||||
pub const TRAC: &[u8] = &[84, 82, 65, 67]; // Can represent track number OR total tracks
|
||||
pub const DISC: &[u8] = &[68, 73, 83, 67]; // Can represent disc number OR total discs
|
||||
|
||||
pub const NULL_CHAR: char = '\0';
|
||||
|
||||
pub(crate) fn read_from<T>(data: &mut T) -> Result<Option<HashMap<String, String>>>
|
||||
where
|
||||
|
@ -37,20 +39,19 @@ where
|
|||
|
||||
find_info_list(data)?;
|
||||
|
||||
let mut info_list_size = [0; 4];
|
||||
data.read_exact(&mut info_list_size)?;
|
||||
let info_list_size = data.read_u32::<LittleEndian>()?;
|
||||
|
||||
let mut info_list = vec![0; u32::from_le_bytes(info_list_size) as usize];
|
||||
let mut info_list = vec![0; 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);
|
||||
cursor.seek(SeekFrom::Start(4))?; // Skip the chunk ID
|
||||
|
||||
let chunk_len = info_list.len();
|
||||
let mut metadata: HashMap<String, String> = HashMap::with_capacity(chunk_len as usize);
|
||||
let mut metadata: HashMap<String, String> = HashMap::new();
|
||||
|
||||
let mut reading = true;
|
||||
|
||||
#[allow(clippy::cast_lossless)]
|
||||
while reading {
|
||||
if let (Ok(fourcc), Ok(size)) = (
|
||||
cursor.read_u32::<LittleEndian>(),
|
||||
|
@ -61,25 +62,21 @@ where
|
|||
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());
|
||||
let _ = metadata.insert(key, val.trim_matches(NULL_CHAR).to_string());
|
||||
},
|
||||
Err(_) => {
|
||||
return Err(LoftyError::InvalidData(
|
||||
"RIFF file contains non UTF-8 strings",
|
||||
))
|
||||
},
|
||||
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 {
|
||||
if cursor.position() >= info_list_size as u64 {
|
||||
reading = false
|
||||
}
|
||||
} else {
|
||||
|
@ -98,7 +95,7 @@ where
|
|||
let mut chunk_name = [0; 4];
|
||||
data.read_exact(&mut chunk_name)?;
|
||||
|
||||
if &chunk_name == LIST_ID {
|
||||
if chunk_name == LIST_ID {
|
||||
data.seek(SeekFrom::Current(4))?;
|
||||
|
||||
let mut list_type = [0; 4];
|
||||
|
@ -133,23 +130,19 @@ where
|
|||
|
||||
fn create_key(fourcc: &[u8]) -> Option<String> {
|
||||
match fourcc {
|
||||
fcc if fcc == IART => Some("Artist".to_string()),
|
||||
fcc if fcc == ICMT => Some("Comment".to_string()),
|
||||
fcc if fcc == ICRD => Some("Date".to_string()),
|
||||
fcc if fcc == INAM => Some("Title".to_string()),
|
||||
fcc if fcc == IPRD => Some("Album".to_string()),
|
||||
|
||||
// Non-standard
|
||||
fcc if fcc == ITRK || fcc == IPRT => Some("TrackNumber".to_string()),
|
||||
fcc if fcc == IFRM => Some("TrackTotal".to_string()),
|
||||
fcc if fcc == ALBU => Some("Album".to_string()),
|
||||
fcc if fcc == TRAC => Some("TrackNumber".to_string()),
|
||||
fcc if fcc == DISC => Some("DiscNumber".to_string()),
|
||||
IART => Some("Artist".to_string()),
|
||||
ICMT => Some("Comment".to_string()),
|
||||
ICRD => Some("Date".to_string()),
|
||||
INAM => Some("Title".to_string()),
|
||||
IPRD | ALBU => Some("Album".to_string()),
|
||||
ITRK | IPRT | TRAC => Some("TrackNumber".to_string()),
|
||||
IFRM => Some("TrackTotal".to_string()),
|
||||
DISC => Some("DiscNumber".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn key_to_fourcc(key: &str) -> Option<[u8; 4]> {
|
||||
pub fn key_to_fourcc(key: &str) -> Option<&[u8]> {
|
||||
match key {
|
||||
"Artist" => Some(IART),
|
||||
"Comment" => Some(ICMT),
|
||||
|
@ -186,7 +179,13 @@ pub(crate) fn write_to(data: &mut File, metadata: HashMap<String, String>) -> Re
|
|||
}
|
||||
}
|
||||
|
||||
let size = ((packet.len() - 4) as u32).to_le_bytes();
|
||||
let packet_size = packet.len() - 4;
|
||||
|
||||
if packet_size > u32::MAX as usize {
|
||||
return Err(LoftyError::TooMuchData);
|
||||
}
|
||||
|
||||
let size = (packet_size as u32).to_le_bytes();
|
||||
|
||||
#[allow(clippy::needless_range_loop)]
|
||||
for i in 0..4 {
|
||||
|
|
Loading…
Add table
Reference in a new issue