mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 14:12:31 +00:00
Only read RIFF INFO LISTs instead of all LISTs
Signed-off-by: Serial <69764315+Serial-ATA@users.noreply.github.com>
This commit is contained in:
parent
c285b36629
commit
028afaa9ee
2 changed files with 67 additions and 56 deletions
|
@ -17,7 +17,7 @@ ape = {version = "0.3.0", optional = true}
|
||||||
# Wav
|
# Wav
|
||||||
riff = {version = "1.0.1", optional = true}
|
riff = {version = "1.0.1", optional = true}
|
||||||
# Mp3
|
# Mp3
|
||||||
id3 = {version = "0.6.3", optional = true} # De/Encoding
|
id3 = {version = "0.6.4", optional = true} # De/Encoding
|
||||||
mp3-duration = {version = "0.1.10", optional = true} # Duration
|
mp3-duration = {version = "0.1.10", optional = true} # Duration
|
||||||
# Ogg
|
# Ogg
|
||||||
lewton = {version = "0.10.2", optional = true} # Decoding
|
lewton = {version = "0.10.2", optional = true} # Decoding
|
||||||
|
|
|
@ -11,72 +11,83 @@ where
|
||||||
{
|
{
|
||||||
let chunk = riff::Chunk::read(&mut data, 0)?;
|
let chunk = riff::Chunk::read(&mut data, 0)?;
|
||||||
|
|
||||||
let mut list: Option<riff::Chunk> = None;
|
let mut lists: Vec<riff::Chunk> = Vec::new();
|
||||||
|
|
||||||
for child in chunk.iter(&mut data) {
|
for child in chunk.iter(&mut data) {
|
||||||
let chunk_id = child.id();
|
let chunk_id = child.id();
|
||||||
let value_upper = std::str::from_utf8(&chunk_id.value)?.to_uppercase();
|
|
||||||
let value_bytes = value_upper.as_bytes();
|
|
||||||
|
|
||||||
if value_bytes == LIST_ID {
|
if &chunk_id.value == LIST_ID {
|
||||||
// TODO: actually check for the INFO id rather than any LIST
|
lists.push(child)
|
||||||
list = Some(child);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return if let Some(list) = list {
|
return if lists.is_empty() {
|
||||||
let mut content = list.read_contents(&mut data)?;
|
Err(Error::Wav(
|
||||||
|
"This file doesn't contain a LIST chunk".to_string(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
let mut info: Option<riff::Chunk> = None;
|
||||||
|
|
||||||
content.drain(0..4); // Get rid of the chunk ID
|
for child in lists {
|
||||||
let mut cursor = Cursor::new(&*content);
|
if &child.read_type(&mut data)?.value == b"INFO" {
|
||||||
|
info = Some(child);
|
||||||
let chunk_len = list.len();
|
break;
|
||||||
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_wav_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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(metadata))
|
if let Some(list) = info {
|
||||||
} else {
|
let mut content = list.read_contents(&mut data)?;
|
||||||
Err(Error::Wav(
|
|
||||||
"This file doesn't contain an INFO chunk".to_string(),
|
content.drain(0..4); // Get rid of the chunk ID
|
||||||
))
|
let mut cursor = Cursor::new(&*content);
|
||||||
|
|
||||||
|
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_wav_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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(metadata))
|
||||||
|
} else {
|
||||||
|
Err(Error::Wav(
|
||||||
|
"This file doesn't contain an INFO chunk".to_string(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue