mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-13 22:22:31 +00:00
Misc: Add decode_err!
macro to cleanup FileDecodingError
creation
This commit is contained in:
parent
ddffb169f7
commit
899f4e4664
23 changed files with 142 additions and 290 deletions
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::traits::SeekStreamLen;
|
use crate::traits::SeekStreamLen;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
@ -25,9 +25,7 @@ where
|
||||||
if size < 32 {
|
if size < 32 {
|
||||||
// If the size is < 32, something went wrong during encoding
|
// If the size is < 32, something went wrong during encoding
|
||||||
// The size includes the footer and all items
|
// The size includes the footer and all items
|
||||||
return Err(
|
decode_err!(@BAIL APE, "APE tag has an invalid size (< 32)");
|
||||||
FileDecodingError::new(FileType::APE, "APE tag has an invalid size (< 32)").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ape")]
|
#[cfg(feature = "ape")]
|
||||||
|
@ -53,11 +51,7 @@ where
|
||||||
|
|
||||||
#[allow(unstable_name_collisions)]
|
#[allow(unstable_name_collisions)]
|
||||||
if u64::from(size) > data.stream_len()? {
|
if u64::from(size) > data.stream_len()? {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "APE tag has an invalid size (> file size)");
|
||||||
FileType::APE,
|
|
||||||
"APE tag has an invalid size (> file size)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ApeHeader {
|
Ok(ApeHeader {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
@ -81,7 +81,7 @@ where
|
||||||
{
|
{
|
||||||
let version = data
|
let version = data
|
||||||
.read_u16::<LittleEndian>()
|
.read_u16::<LittleEndian>()
|
||||||
.map_err(|_| FileDecodingError::new(FileType::APE, "Unable to read APE tag version"))?;
|
.map_err(|_| decode_err!(APE, "Unable to read APE tag version"))?;
|
||||||
|
|
||||||
// Property reading differs between versions
|
// Property reading differs between versions
|
||||||
if version >= 3980 {
|
if version >= 3980 {
|
||||||
|
@ -103,9 +103,9 @@ where
|
||||||
// First read the file descriptor
|
// First read the file descriptor
|
||||||
let mut descriptor = [0; 46];
|
let mut descriptor = [0; 46];
|
||||||
data.read_exact(&mut descriptor).map_err(|_| {
|
data.read_exact(&mut descriptor).map_err(|_| {
|
||||||
FileDecodingError::new(
|
decode_err!(
|
||||||
FileType::APE,
|
APE,
|
||||||
"Not enough data left in reader to finish file descriptor",
|
"Not enough data left in reader to finish file descriptor"
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
@ -122,12 +122,8 @@ where
|
||||||
|
|
||||||
// Move on to the header
|
// Move on to the header
|
||||||
let mut header = [0; 24];
|
let mut header = [0; 24];
|
||||||
data.read_exact(&mut header).map_err(|_| {
|
data.read_exact(&mut header)
|
||||||
FileDecodingError::new(
|
.map_err(|_| decode_err!(APE, "Not enough data left in reader to finish MAC header"))?;
|
||||||
FileType::APE,
|
|
||||||
"Not enough data left in reader to finish MAC header",
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Skip the first 4 bytes of the header
|
// Skip the first 4 bytes of the header
|
||||||
// Compression type (2)
|
// Compression type (2)
|
||||||
|
@ -139,7 +135,7 @@ where
|
||||||
let total_frames = header_read.read_u32::<LittleEndian>()?;
|
let total_frames = header_read.read_u32::<LittleEndian>()?;
|
||||||
|
|
||||||
if total_frames == 0 {
|
if total_frames == 0 {
|
||||||
return Err(FileDecodingError::new(FileType::APE, "File contains no frames").into());
|
decode_err!(@BAIL APE, "File contains no frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
let bits_per_sample = header_read.read_u16::<LittleEndian>()?;
|
let bits_per_sample = header_read.read_u16::<LittleEndian>()?;
|
||||||
|
@ -147,11 +143,7 @@ where
|
||||||
let channels = header_read.read_u16::<LittleEndian>()?;
|
let channels = header_read.read_u16::<LittleEndian>()?;
|
||||||
|
|
||||||
if !(1..=32).contains(&channels) {
|
if !(1..=32).contains(&channels) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "File has an invalid channel count (must be between 1 and 32 inclusive)");
|
||||||
FileType::APE,
|
|
||||||
"File has an invalid channel count (must be between 1 and 32 inclusive)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_rate = header_read.read_u32::<LittleEndian>()?;
|
let sample_rate = header_read.read_u32::<LittleEndian>()?;
|
||||||
|
@ -187,12 +179,8 @@ where
|
||||||
{
|
{
|
||||||
// Versions < 3980 don't have a descriptor
|
// Versions < 3980 don't have a descriptor
|
||||||
let mut header = [0; 26];
|
let mut header = [0; 26];
|
||||||
data.read_exact(&mut header).map_err(|_| {
|
data.read_exact(&mut header)
|
||||||
FileDecodingError::new(
|
.map_err(|_| decode_err!(APE, "Not enough data left in reader to finish MAC header"))?;
|
||||||
FileType::APE,
|
|
||||||
"Not enough data left in reader to finish MAC header",
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// We don't need all the header data, so just make 2 slices
|
// We don't need all the header data, so just make 2 slices
|
||||||
let header_first = &mut &header[..8];
|
let header_first = &mut &header[..8];
|
||||||
|
@ -223,11 +211,7 @@ where
|
||||||
let channels = header_first.read_u16::<LittleEndian>()?;
|
let channels = header_first.read_u16::<LittleEndian>()?;
|
||||||
|
|
||||||
if !(1..=32).contains(&channels) {
|
if !(1..=32).contains(&channels) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "File has an invalid channel count (must be between 1 and 32 inclusive)");
|
||||||
FileType::APE,
|
|
||||||
"File has an invalid channel count (must be between 1 and 32 inclusive)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_rate = header_first.read_u32::<LittleEndian>()?;
|
let sample_rate = header_first.read_u32::<LittleEndian>()?;
|
||||||
|
@ -236,7 +220,7 @@ where
|
||||||
let total_frames = header_second.read_u32::<LittleEndian>()?;
|
let total_frames = header_second.read_u32::<LittleEndian>()?;
|
||||||
|
|
||||||
if total_frames == 0 {
|
if total_frames == 0 {
|
||||||
return Err(FileDecodingError::new(FileType::APE, "File contains no frames").into());
|
decode_err!(@BAIL APE, "File contains no frames");
|
||||||
}
|
}
|
||||||
|
|
||||||
let final_frame_blocks = data.read_u32::<LittleEndian>()?;
|
let final_frame_blocks = data.read_u32::<LittleEndian>()?;
|
||||||
|
|
|
@ -3,13 +3,13 @@ use super::header::read_ape_header;
|
||||||
#[cfg(feature = "ape")]
|
#[cfg(feature = "ape")]
|
||||||
use super::tag::{read::read_ape_tag, ApeTag};
|
use super::tag::{read::read_ape_tag, ApeTag};
|
||||||
use super::{ApeFile, ApeProperties};
|
use super::{ApeFile, ApeProperties};
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
#[cfg(feature = "id3v1")]
|
#[cfg(feature = "id3v1")]
|
||||||
use crate::id3::v1::tag::ID3v1Tag;
|
use crate::id3::v1::tag::ID3v1Tag;
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
use crate::id3::v2::{read::parse_id3v2, tag::ID3v2Tag};
|
use crate::id3::v2::{read::parse_id3v2, tag::ID3v2Tag};
|
||||||
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, ID3FindResults};
|
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2, ID3FindResults};
|
||||||
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -69,16 +69,14 @@ where
|
||||||
// Get the remaining part of the ape tag
|
// Get the remaining part of the ape tag
|
||||||
let mut remaining = [0; 4];
|
let mut remaining = [0; 4];
|
||||||
data.read_exact(&mut remaining).map_err(|_| {
|
data.read_exact(&mut remaining).map_err(|_| {
|
||||||
FileDecodingError::new(
|
decode_err!(
|
||||||
FileType::APE,
|
APE,
|
||||||
"Found partial APE tag, but there isn't enough data left in the reader",
|
"Found partial APE tag, but there isn't enough data left in the reader"
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if &remaining[..4] != b"AGEX" {
|
if &remaining[..4] != b"AGEX" {
|
||||||
return Err(
|
decode_err!(@BAIL APE, "Found incomplete APE tag");
|
||||||
FileDecodingError::new(FileType::APE, "Found incomplete APE tag").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ape_header = read_ape_header(data, false)?;
|
let ape_header = read_ape_header(data, false)?;
|
||||||
|
@ -94,12 +92,7 @@ where
|
||||||
data.seek(SeekFrom::Current(ape_header.size as i64))?;
|
data.seek(SeekFrom::Current(ape_header.size as i64))?;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "Invalid data found while reading header, expected any of [\"MAC \", \"APETAGEX\", \"ID3\"]")
|
||||||
FileType::APE,
|
|
||||||
"Invalid data found while reading header, expected any of [\"MAC \", \
|
|
||||||
\"APETAGEX\", \"ID3\"]",
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::ape::constants::INVALID_KEYS;
|
use crate::ape::constants::INVALID_KEYS;
|
||||||
use crate::error::{FileDecodingError, LoftyError, Result};
|
use crate::error::{LoftyError, Result};
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::tag::item::{ItemValue, ItemValueRef, TagItem};
|
use crate::tag::item::{ItemValue, ItemValueRef, TagItem};
|
||||||
use crate::tag::TagType;
|
use crate::tag::TagType;
|
||||||
|
|
||||||
|
@ -28,27 +28,15 @@ impl ApeItem {
|
||||||
/// * `key` contains invalid characters (must be in the range 0x20 to 0x7E, inclusive)
|
/// * `key` contains invalid characters (must be in the range 0x20 to 0x7E, inclusive)
|
||||||
pub fn new(key: String, value: ItemValue) -> Result<Self> {
|
pub fn new(key: String, value: ItemValue) -> Result<Self> {
|
||||||
if INVALID_KEYS.contains(&&*key.to_uppercase()) {
|
if INVALID_KEYS.contains(&&*key.to_uppercase()) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "APE tag item contains an illegal key");
|
||||||
FileType::APE,
|
|
||||||
"APE tag item contains an illegal key",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(2..=255).contains(&key.len()) {
|
if !(2..=255).contains(&key.len()) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "APE tag item key has an invalid length (< 2 || > 255)");
|
||||||
FileType::APE,
|
|
||||||
"APE tag item key has an invalid length (< 2 || > 255)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if key.chars().any(|c| !(0x20..=0x7E).contains(&(c as u32))) {
|
if key.chars().any(|c| !(0x20..=0x7E).contains(&(c as u32))) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "APE tag item key contains invalid characters");
|
||||||
FileType::APE,
|
|
||||||
"APE tag item key contains invalid characters",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -86,12 +74,7 @@ impl TryFrom<TagItem> for ApeItem {
|
||||||
value
|
value
|
||||||
.item_key
|
.item_key
|
||||||
.map_key(TagType::APE, false)
|
.map_key(TagType::APE, false)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| decode_err!(APE, "Attempted to convert an unsupported item key"))?
|
||||||
FileDecodingError::new(
|
|
||||||
FileType::APE,
|
|
||||||
"Attempted to convert an unsupported item key",
|
|
||||||
)
|
|
||||||
})?
|
|
||||||
.to_string(),
|
.to_string(),
|
||||||
value.item_value,
|
value.item_value,
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,9 +2,8 @@ use super::item::ApeItem;
|
||||||
use super::ApeTag;
|
use super::ApeTag;
|
||||||
use crate::ape::constants::INVALID_KEYS;
|
use crate::ape::constants::INVALID_KEYS;
|
||||||
use crate::ape::header::ApeHeader;
|
use crate::ape::header::ApeHeader;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::{decode_err, err, try_vec};
|
||||||
use crate::macros::{err, try_vec};
|
|
||||||
use crate::tag::item::ItemValue;
|
use crate::tag::item::ItemValue;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
@ -39,16 +38,11 @@ where
|
||||||
key_char = data.read_u8()?;
|
key_char = data.read_u8()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = String::from_utf8(key).map_err(|_| {
|
let key = String::from_utf8(key)
|
||||||
FileDecodingError::new(FileType::APE, "APE tag item contains a non UTF-8 key")
|
.map_err(|_| decode_err!(APE, "APE tag item contains a non UTF-8 key"))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
if INVALID_KEYS.contains(&&*key.to_uppercase()) {
|
if INVALID_KEYS.contains(&&*key.to_uppercase()) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "APE tag item contains an illegal key");
|
||||||
FileType::APE,
|
|
||||||
"APE tag item contains an illegal key",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let read_only = (flags & 1) == 1;
|
let read_only = (flags & 1) == 1;
|
||||||
|
@ -64,25 +58,13 @@ where
|
||||||
|
|
||||||
let parsed_value = match item_type {
|
let parsed_value = match item_type {
|
||||||
0 => ItemValue::Text(String::from_utf8(value).map_err(|_| {
|
0 => ItemValue::Text(String::from_utf8(value).map_err(|_| {
|
||||||
FileDecodingError::new(
|
decode_err!(APE, "Failed to convert text item into a UTF-8 string")
|
||||||
FileType::APE,
|
|
||||||
"Failed to convert text item into a UTF-8 string",
|
|
||||||
)
|
|
||||||
})?),
|
})?),
|
||||||
1 => ItemValue::Binary(value),
|
1 => ItemValue::Binary(value),
|
||||||
2 => ItemValue::Locator(String::from_utf8(value).map_err(|_| {
|
2 => ItemValue::Locator(String::from_utf8(value).map_err(|_| {
|
||||||
FileDecodingError::new(
|
decode_err!(APE, "Failed to convert locator item into a UTF-8 string")
|
||||||
FileType::APE,
|
|
||||||
"Failed to convert locator item into a UTF-8 string",
|
|
||||||
)
|
|
||||||
})?),
|
})?),
|
||||||
_ => {
|
_ => decode_err!(@BAIL APE, "APE tag item contains an invalid item type"),
|
||||||
return Err(FileDecodingError::new(
|
|
||||||
FileType::APE,
|
|
||||||
"APE tag item contains an invalid item type",
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut item = ApeItem::new(key, parsed_value)?;
|
let mut item = ApeItem::new(key, parsed_value)?;
|
||||||
|
|
|
@ -3,10 +3,10 @@ use super::read::read_ape_tag;
|
||||||
use super::ApeTagRef;
|
use super::ApeTagRef;
|
||||||
use crate::ape::constants::APE_PREAMBLE;
|
use crate::ape::constants::APE_PREAMBLE;
|
||||||
use crate::ape::header::read_ape_header;
|
use crate::ape::header::read_ape_header;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::file::FileType;
|
||||||
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
|
use crate::id3::{find_id3v1, find_id3v2, find_lyrics3v2};
|
||||||
use crate::macros::err;
|
use crate::macros::{decode_err, err};
|
||||||
use crate::probe::Probe;
|
use crate::probe::Probe;
|
||||||
use crate::tag::item::ItemValueRef;
|
use crate::tag::item::ItemValueRef;
|
||||||
|
|
||||||
|
@ -97,11 +97,7 @@ where
|
||||||
if let Some(start) = start.checked_sub(size as usize) {
|
if let Some(start) = start.checked_sub(size as usize) {
|
||||||
ape_tag_location = Some(start..start + size as usize);
|
ape_tag_location = Some(start..start + size as usize);
|
||||||
} else {
|
} else {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL APE, "File has a tag with an invalid size");
|
||||||
FileType::APE,
|
|
||||||
"File has a tag with an invalid size",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use super::block::Block;
|
use super::block::Block;
|
||||||
use super::FlacFile;
|
use super::FlacFile;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
use crate::id3::v2::read::parse_id3v2;
|
use crate::id3::v2::read::parse_id3v2;
|
||||||
use crate::id3::{find_id3v2, ID3FindResults};
|
use crate::id3::{find_id3v2, ID3FindResults};
|
||||||
|
use crate::macros::decode_err;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
#[cfg(feature = "vorbis_comments")]
|
#[cfg(feature = "vorbis_comments")]
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -22,19 +22,13 @@ where
|
||||||
data.read_exact(&mut marker)?;
|
data.read_exact(&mut marker)?;
|
||||||
|
|
||||||
if &marker != b"fLaC" {
|
if &marker != b"fLaC" {
|
||||||
return Err(
|
decode_err!(@BAIL FLAC, "File missing \"fLaC\" stream marker");
|
||||||
FileDecodingError::new(FileType::FLAC, "File missing \"fLaC\" stream marker").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let block = Block::read(data)?;
|
let block = Block::read(data)?;
|
||||||
|
|
||||||
if block.ty != 0 {
|
if block.ty != 0 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL FLAC, "File missing mandatory STREAMINFO block");
|
||||||
FileType::FLAC,
|
|
||||||
"File missing mandatory STREAMINFO block",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(block)
|
Ok(block)
|
||||||
|
@ -67,11 +61,7 @@ where
|
||||||
let stream_info_len = (stream_info.end - stream_info.start) as u32;
|
let stream_info_len = (stream_info.end - stream_info.start) as u32;
|
||||||
|
|
||||||
if stream_info_len < 18 {
|
if stream_info_len < 18 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL FLAC, "File has an invalid STREAMINFO block size (< 18)");
|
||||||
FileType::FLAC,
|
|
||||||
"File has an invalid STREAMINFO block size (< 18)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut last_block = stream_info.last;
|
let mut last_block = stream_info.last;
|
||||||
|
@ -88,11 +78,7 @@ where
|
||||||
last_block = block.last;
|
last_block = block.last;
|
||||||
|
|
||||||
if block.content.is_empty() && (block.ty != 1 && block.ty != 3) {
|
if block.content.is_empty() && (block.ty != 1 && block.ty != 3) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL FLAC, "Encountered a zero-sized metadata block");
|
||||||
FileType::FLAC,
|
|
||||||
"Encountered a zero-sized metadata block",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match block.ty {
|
match block.ty {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -15,7 +15,7 @@ pub(super) fn read_properties(
|
||||||
let channels = comm.read_u16::<BigEndian>()? as u8;
|
let channels = comm.read_u16::<BigEndian>()? as u8;
|
||||||
|
|
||||||
if channels == 0 {
|
if channels == 0 {
|
||||||
return Err(FileDecodingError::new(FileType::AIFF, "File contains 0 channels").into());
|
decode_err!(@BAIL AIFF, "File contains 0 channels");
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_frames = comm.read_u32::<BigEndian>()?;
|
let sample_frames = comm.read_u32::<BigEndian>()?;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
#[cfg(feature = "aiff_text_chunks")]
|
#[cfg(feature = "aiff_text_chunks")]
|
||||||
use super::tag::{AIFFTextChunks, Comment};
|
use super::tag::{AIFFTextChunks, Comment};
|
||||||
use super::AiffFile;
|
use super::AiffFile;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
use crate::id3::v2::tag::ID3v2Tag;
|
use crate::id3::v2::tag::ID3v2Tag;
|
||||||
use crate::iff::chunk::Chunks;
|
use crate::iff::chunk::Chunks;
|
||||||
use crate::macros::err;
|
use crate::macros::{decode_err, err};
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
@ -63,11 +62,7 @@ where
|
||||||
b"ID3 " | b"id3 " => id3v2_tag = Some(chunks.id3_chunk(data)?),
|
b"ID3 " | b"id3 " => id3v2_tag = Some(chunks.id3_chunk(data)?),
|
||||||
b"COMM" if read_properties && comm.is_none() => {
|
b"COMM" if read_properties && comm.is_none() => {
|
||||||
if chunks.size < 18 {
|
if chunks.size < 18 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL AIFF, "File has an invalid \"COMM\" chunk size (< 18)");
|
||||||
FileType::AIFF,
|
|
||||||
"File has an invalid \"COMM\" chunk size (< 18)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
comm = Some(chunks.content(data)?);
|
comm = Some(chunks.content(data)?);
|
||||||
|
@ -139,11 +134,7 @@ where
|
||||||
match comm {
|
match comm {
|
||||||
Some(comm) => {
|
Some(comm) => {
|
||||||
if stream_len == 0 {
|
if stream_len == 0 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL AIFF, "File does not contain a \"SSND\" chunk");
|
||||||
FileType::AIFF,
|
|
||||||
"File does not contain a \"SSND\" chunk",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = super::properties::read_properties(
|
properties = super::properties::read_properties(
|
||||||
|
@ -152,13 +143,7 @@ where
|
||||||
data.stream_position()?,
|
data.stream_position()?,
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
None => {
|
None => decode_err!(@BAIL AIFF, "File does not contain a \"COMM\" chunk"),
|
||||||
return Err(FileDecodingError::new(
|
|
||||||
FileType::AIFF,
|
|
||||||
"File does not contain a \"COMM\" chunk",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
properties = FileProperties::default();
|
properties = FileProperties::default();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -98,7 +98,7 @@ pub(super) fn read_properties(
|
||||||
let channels = fmt.read_u16::<LittleEndian>()? as u8;
|
let channels = fmt.read_u16::<LittleEndian>()? as u8;
|
||||||
|
|
||||||
if channels == 0 {
|
if channels == 0 {
|
||||||
return Err(FileDecodingError::new(FileType::WAV, "File contains 0 channels").into());
|
decode_err!(@BAIL WAV, "File contains 0 channels");
|
||||||
}
|
}
|
||||||
|
|
||||||
let sample_rate = fmt.read_u32::<LittleEndian>()?;
|
let sample_rate = fmt.read_u32::<LittleEndian>()?;
|
||||||
|
@ -117,11 +117,7 @@ pub(super) fn read_properties(
|
||||||
|
|
||||||
if format_tag == EXTENSIBLE {
|
if format_tag == EXTENSIBLE {
|
||||||
if fmt.len() + 16 < 40 {
|
if fmt.len() + 16 < 40 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WAV, "Extensible format identified, invalid \"fmt \" chunk size found (< 40)");
|
||||||
FileType::WAV,
|
|
||||||
"Extensible format identified, invalid \"fmt \" chunk size found (< 40)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cbSize (Size of extra format information) (2)
|
// cbSize (Size of extra format information) (2)
|
||||||
|
@ -140,11 +136,7 @@ pub(super) fn read_properties(
|
||||||
let non_pcm = format_tag != PCM && format_tag != IEEE_FLOAT;
|
let non_pcm = format_tag != PCM && format_tag != IEEE_FLOAT;
|
||||||
|
|
||||||
if non_pcm && total_samples == 0 {
|
if non_pcm && total_samples == 0 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WAV, "Non-PCM format identified, no \"fact\" chunk found");
|
||||||
FileType::WAV,
|
|
||||||
"Non-PCM format identified, no \"fact\" chunk found",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if bits_per_sample > 0 {
|
if bits_per_sample > 0 {
|
||||||
|
|
|
@ -2,11 +2,11 @@ use super::properties::WavProperties;
|
||||||
#[cfg(feature = "riff_info_list")]
|
#[cfg(feature = "riff_info_list")]
|
||||||
use super::tag::RIFFInfoList;
|
use super::tag::RIFFInfoList;
|
||||||
use super::WavFile;
|
use super::WavFile;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
use crate::id3::v2::tag::ID3v2Tag;
|
use crate::id3::v2::tag::ID3v2Tag;
|
||||||
use crate::iff::chunk::Chunks;
|
use crate::iff::chunk::Chunks;
|
||||||
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -20,15 +20,11 @@ where
|
||||||
data.read_exact(&mut id)?;
|
data.read_exact(&mut id)?;
|
||||||
|
|
||||||
if &id[..4] != b"RIFF" {
|
if &id[..4] != b"RIFF" {
|
||||||
return Err(
|
decode_err!(@BAIL WAV, "WAV file doesn't contain a RIFF chunk");
|
||||||
FileDecodingError::new(FileType::WAV, "WAV file doesn't contain a RIFF chunk").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if &id[8..] != b"WAVE" {
|
if &id[8..] != b"WAVE" {
|
||||||
return Err(
|
decode_err!(@BAIL WAV, "Found RIFF file, format is not WAVE");
|
||||||
FileDecodingError::new(FileType::WAV, "Found RIFF file, format is not WAVE").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -103,19 +99,11 @@ where
|
||||||
|
|
||||||
let properties = if read_properties {
|
let properties = if read_properties {
|
||||||
if fmt.len() < 16 {
|
if fmt.len() < 16 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WAV, "File does not contain a valid \"fmt \" chunk");
|
||||||
FileType::WAV,
|
|
||||||
"File does not contain a valid \"fmt \" chunk",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if stream_len == 0 {
|
if stream_len == 0 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WAV, "File does not contain a \"data\" chunk");
|
||||||
FileType::WAV,
|
|
||||||
"File does not contain a \"data\" chunk",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let file_length = data.stream_position()?;
|
let file_length = data.stream_position()?;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use super::RIFFInfoList;
|
use super::RIFFInfoList;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
use crate::iff::chunk::Chunks;
|
use crate::iff::chunk::Chunks;
|
||||||
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek};
|
use std::io::{Read, Seek};
|
||||||
|
|
||||||
|
@ -17,23 +17,18 @@ where
|
||||||
R: Read + Seek,
|
R: Read + Seek,
|
||||||
{
|
{
|
||||||
while data.stream_position()? != end && chunks.next(data).is_ok() {
|
while data.stream_position()? != end && chunks.next(data).is_ok() {
|
||||||
let key_str = String::from_utf8(chunks.fourcc.to_vec()).map_err(|_| {
|
let key_str = String::from_utf8(chunks.fourcc.to_vec())
|
||||||
FileDecodingError::new(FileType::WAV, "Non UTF-8 item key found in RIFF INFO")
|
.map_err(|_| decode_err!(WAV, "Non UTF-8 item key found in RIFF INFO"))?;
|
||||||
})?;
|
|
||||||
|
|
||||||
if !verify_key(&key_str) {
|
if !verify_key(&key_str) {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WAV, "RIFF INFO item key contains invalid characters");
|
||||||
FileType::WAV,
|
|
||||||
"RIFF INFO item key contains invalid characters",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tag.items.push((
|
tag.items.push((
|
||||||
key_str,
|
key_str,
|
||||||
chunks.read_cstring(data).map_err(|_| {
|
chunks
|
||||||
FileDecodingError::new(FileType::WAV, "Failed to read RIFF INFO item value")
|
.read_cstring(data)
|
||||||
})?,
|
.map_err(|_| decode_err!(WAV, "Failed to read RIFF INFO item value"))?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,4 +40,32 @@ macro_rules! err {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use {err, try_vec};
|
// Shorthand for FileDecodingError::new(FileType::Foo, "Message")
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
//
|
||||||
|
// - decode_err!(Variant, Message)
|
||||||
|
// - decode_err!(Message)
|
||||||
|
//
|
||||||
|
// or bail:
|
||||||
|
//
|
||||||
|
// - decode_err!(@BAIL Variant, Message)
|
||||||
|
// - decode_err!(@BAIL Message)
|
||||||
|
macro_rules! decode_err {
|
||||||
|
($file_ty:ident, $reason:literal) => {
|
||||||
|
Into::<crate::error::LoftyError>::into(crate::error::FileDecodingError::new(
|
||||||
|
crate::file::FileType::$file_ty,
|
||||||
|
$reason,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
($reason:literal) => {
|
||||||
|
Into::<crate::error::LoftyError>::into(crate::error::FileDecodingError::from_description(
|
||||||
|
$reason,
|
||||||
|
))
|
||||||
|
};
|
||||||
|
(@BAIL $($file_ty:ident,)? $reason:literal) => {
|
||||||
|
return Err(decode_err!($($file_ty,)? $reason))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use {decode_err, err, try_vec};
|
||||||
|
|
|
@ -6,8 +6,8 @@ use super::{
|
||||||
ilst::{read::parse_ilst, Ilst},
|
ilst::{read::parse_ilst, Ilst},
|
||||||
read::{meta_is_full, AtomReader},
|
read::{meta_is_full, AtomReader},
|
||||||
};
|
};
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek};
|
use std::io::{Read, Seek};
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ impl Moov {
|
||||||
if let Some(moov) = moov {
|
if let Some(moov) = moov {
|
||||||
Ok(moov)
|
Ok(moov)
|
||||||
} else {
|
} else {
|
||||||
Err(FileDecodingError::new(FileType::MP4, "No \"moov\" atom found").into())
|
decode_err!(@BAIL MP4, "No \"moov\" atom found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use super::atom_info::{AtomIdent, AtomInfo};
|
use super::atom_info::{AtomIdent, AtomInfo};
|
||||||
use super::read::{nested_atom, skip_unneeded, AtomReader};
|
use super::read::{nested_atom, skip_unneeded, AtomReader};
|
||||||
use super::trak::Trak;
|
use super::trak::Trak;
|
||||||
use crate::error::{FileDecodingError, LoftyError, Result};
|
use crate::error::{LoftyError, Result};
|
||||||
use crate::file::FileType;
|
use crate::macros::{decode_err, err, try_vec};
|
||||||
use crate::macros::{err, try_vec};
|
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::io::{Cursor, Read, Seek, SeekFrom};
|
use std::io::{Cursor, Read, Seek, SeekFrom};
|
||||||
|
@ -135,11 +134,7 @@ impl TryFrom<u8> for AudioObjectType {
|
||||||
44 => Ok(Self::LowDelayMpegSurround),
|
44 => Ok(Self::LowDelayMpegSurround),
|
||||||
45 => Ok(Self::SpatialAudioObjectCodingDialogueEnhancement),
|
45 => Ok(Self::SpatialAudioObjectCodingDialogueEnhancement),
|
||||||
46 => Ok(Self::AudioSync),
|
46 => Ok(Self::AudioSync),
|
||||||
_ => Err(FileDecodingError::new(
|
_ => decode_err!(@BAIL MP4, "Encountered an invalid audio object type"),
|
||||||
FileType::MP4,
|
|
||||||
"Encountered an invalid audio object type",
|
|
||||||
)
|
|
||||||
.into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,7 +271,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if !audio_track {
|
if !audio_track {
|
||||||
return Err(FileDecodingError::new(FileType::MP4, "File contains no audio tracks").into());
|
decode_err!(@BAIL MP4, "File contains no audio tracks");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mdhd = match mdhd {
|
let mdhd = match mdhd {
|
||||||
|
@ -657,7 +652,7 @@ where
|
||||||
skip_unneeded(reader, atom.extended, atom.len)?;
|
skip_unneeded(reader, atom.extended, atom.len)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(FileDecodingError::new(FileType::MP4, "Failed to find \"mdat\" atom").into())
|
decode_err!(@BAIL MP4, "Failed to find \"mdat\" atom");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Descriptor {
|
struct Descriptor {
|
||||||
|
|
|
@ -2,9 +2,8 @@ use super::atom_info::{AtomIdent, AtomInfo};
|
||||||
use super::moov::Moov;
|
use super::moov::Moov;
|
||||||
use super::properties::Mp4Properties;
|
use super::properties::Mp4Properties;
|
||||||
use super::Mp4File;
|
use super::Mp4File;
|
||||||
use crate::error::{ErrorKind, FileDecodingError, LoftyError, Result};
|
use crate::error::{ErrorKind, LoftyError, Result};
|
||||||
use crate::file::FileType;
|
use crate::macros::{decode_err, err};
|
||||||
use crate::macros::err;
|
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -136,7 +135,7 @@ where
|
||||||
// size + identifier + major brand
|
// size + identifier + major brand
|
||||||
// There *should* be more, but this is all we need from it
|
// There *should* be more, but this is all we need from it
|
||||||
if atom.len < 12 {
|
if atom.len < 12 {
|
||||||
return Err(FileDecodingError::new(FileType::MP4, "\"ftyp\" atom too short").into());
|
decode_err!(@BAIL MP4, "\"ftyp\" atom too short");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut major_brand = vec![0; 4];
|
let mut major_brand = vec![0; 4];
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::constants::{BITRATES, PADDING_SIZES, SAMPLES, SAMPLE_RATES, SIDE_INFORMATION_SIZES};
|
use super::constants::{BITRATES, PADDING_SIZES, SAMPLES, SAMPLE_RATES, SIDE_INFORMATION_SIZES};
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -307,11 +307,7 @@ impl XingHeader {
|
||||||
match &header {
|
match &header {
|
||||||
b"Xing" | b"Info" => {
|
b"Xing" | b"Info" => {
|
||||||
if reader_len < 16 {
|
if reader_len < 16 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL MPEG, "Xing header has an invalid size (< 16)");
|
||||||
FileType::MPEG,
|
|
||||||
"Xing header has an invalid size (< 16)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut flags = [0; 4];
|
let mut flags = [0; 4];
|
||||||
|
@ -334,11 +330,7 @@ impl XingHeader {
|
||||||
},
|
},
|
||||||
b"VBRI" => {
|
b"VBRI" => {
|
||||||
if reader_len < 32 {
|
if reader_len < 32 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL MPEG, "VBRI header has an invalid size (< 32)");
|
||||||
FileType::MPEG,
|
|
||||||
"VBRI header has an invalid size (< 32)",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip 6 bytes
|
// Skip 6 bytes
|
||||||
|
|
|
@ -4,13 +4,12 @@ use crate::ape::constants::APE_PREAMBLE;
|
||||||
use crate::ape::header::read_ape_header;
|
use crate::ape::header::read_ape_header;
|
||||||
#[cfg(feature = "ape")]
|
#[cfg(feature = "ape")]
|
||||||
use crate::ape::tag::read::read_ape_tag;
|
use crate::ape::tag::read::read_ape_tag;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
|
||||||
#[cfg(feature = "id3v2")]
|
#[cfg(feature = "id3v2")]
|
||||||
use crate::id3::v2::read::parse_id3v2;
|
use crate::id3::v2::read::parse_id3v2;
|
||||||
use crate::id3::v2::read_id3v2_header;
|
use crate::id3::v2::read_id3v2_header;
|
||||||
use crate::id3::{find_id3v1, find_lyrics3v2, ID3FindResults};
|
use crate::id3::{find_id3v1, find_lyrics3v2, ID3FindResults};
|
||||||
use crate::macros::err;
|
use crate::macros::{decode_err, err};
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
|
@ -138,18 +137,12 @@ where
|
||||||
if read_properties {
|
if read_properties {
|
||||||
let first_frame_header = match first_frame_header {
|
let first_frame_header = match first_frame_header {
|
||||||
Some(header) => header,
|
Some(header) => header,
|
||||||
None => {
|
// The search for sync bits was unsuccessful
|
||||||
// The search for sync bits was unsuccessful
|
None => decode_err!(@BAIL MPEG, "File contains an invalid frame"),
|
||||||
return Err(FileDecodingError::new(
|
|
||||||
FileType::MPEG,
|
|
||||||
"File contains an invalid frame",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if first_frame_header.sample_rate == 0 {
|
if first_frame_header.sample_rate == 0 {
|
||||||
return Err(FileDecodingError::new(FileType::MPEG, "Sample rate is 0").into());
|
decode_err!(@BAIL MPEG, "Sample rate is 0");
|
||||||
}
|
}
|
||||||
|
|
||||||
let first_frame_offset = first_frame_offset;
|
let first_frame_offset = first_frame_offset;
|
||||||
|
|
|
@ -9,8 +9,8 @@ pub(crate) mod read;
|
||||||
pub(crate) mod speex;
|
pub(crate) mod speex;
|
||||||
pub(crate) mod vorbis;
|
pub(crate) mod vorbis;
|
||||||
|
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
|
|
||||||
use std::io::{Read, Seek};
|
use std::io::{Read, Seek};
|
||||||
|
|
||||||
|
@ -38,9 +38,7 @@ pub(self) fn verify_signature(page: &Page, sig: &[u8]) -> Result<()> {
|
||||||
let sig_len = sig.len();
|
let sig_len = sig.len();
|
||||||
|
|
||||||
if page.content().len() < sig_len || &page.content()[..sig_len] != sig {
|
if page.content().len() < sig_len || &page.content()[..sig_len] != sig {
|
||||||
return Err(
|
decode_err!(@BAIL Vorbis, "File missing magic signature");
|
||||||
FileDecodingError::new(FileType::Vorbis, "File missing magic signature").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::find_last_page;
|
use super::find_last_page;
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
@ -100,11 +100,7 @@ where
|
||||||
if (channel_mapping_family == 0 && properties.channels > 2)
|
if (channel_mapping_family == 0 && properties.channels > 2)
|
||||||
|| (channel_mapping_family == 1 && properties.channels > 8)
|
|| (channel_mapping_family == 1 && properties.channels > 8)
|
||||||
{
|
{
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL Opus, "Invalid channel count for mapping family");
|
||||||
FileType::Opus,
|
|
||||||
"Invalid channel count for mapping family",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Subtract the identification and metadata packet length from the total
|
// Subtract the identification and metadata packet length from the total
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use super::tag::VorbisComments;
|
use super::tag::VorbisComments;
|
||||||
use super::verify_signature;
|
use super::verify_signature;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::macros::err;
|
use crate::macros::{decode_err, err};
|
||||||
#[cfg(feature = "vorbis_comments")]
|
#[cfg(feature = "vorbis_comments")]
|
||||||
use crate::picture::Picture;
|
use crate::picture::Picture;
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ pub(crate) fn read_comments<R>(data: &mut R, mut len: u64, tag: &mut VorbisComme
|
||||||
where
|
where
|
||||||
R: Read,
|
R: Read,
|
||||||
{
|
{
|
||||||
use crate::error::FileDecodingError;
|
|
||||||
use crate::macros::try_vec;
|
use crate::macros::try_vec;
|
||||||
|
|
||||||
let vendor_len = data.read_u32::<LittleEndian>()?;
|
let vendor_len = data.read_u32::<LittleEndian>()?;
|
||||||
|
@ -50,12 +49,7 @@ where
|
||||||
|
|
||||||
match String::from_utf16(&s) {
|
match String::from_utf16(&s) {
|
||||||
Ok(vendor) => vendor,
|
Ok(vendor) => vendor,
|
||||||
Err(_) => {
|
Err(_) => decode_err!(@BAIL "OGG: File has an invalid vendor string"),
|
||||||
return Err(FileDecodingError::from_description(
|
|
||||||
"OGG: File has an invalid vendor string",
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::decode_err;
|
||||||
use crate::ogg::find_last_page;
|
use crate::ogg::find_last_page;
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ where
|
||||||
let first_page_abgp = first_page.abgp;
|
let first_page_abgp = first_page.abgp;
|
||||||
|
|
||||||
if first_page.content().len() < 80 {
|
if first_page.content().len() < 80 {
|
||||||
return Err(FileDecodingError::new(FileType::Speex, "Header packet too small").into());
|
decode_err!(@BAIL Speex, "Header packet too small");
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut properties = SpeexProperties::default();
|
let mut properties = SpeexProperties::default();
|
||||||
|
@ -117,11 +117,7 @@ where
|
||||||
let channels = first_page_content.read_u32::<LittleEndian>()?;
|
let channels = first_page_content.read_u32::<LittleEndian>()?;
|
||||||
|
|
||||||
if channels != 1 && channels != 2 {
|
if channels != 1 && channels != 2 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL Speex, "Found invalid channel count, must be mono or stereo");
|
||||||
FileType::Speex,
|
|
||||||
"Found invalid channel count, must be mono or stereo",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.channels = channels as u8;
|
properties.channels = channels as u8;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::error::{FileDecodingError, Result};
|
use crate::error::Result;
|
||||||
use crate::file::FileType;
|
use crate::macros::{decode_err, err, try_vec};
|
||||||
use crate::macros::{err, try_vec};
|
|
||||||
use crate::properties::FileProperties;
|
use crate::properties::FileProperties;
|
||||||
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
@ -210,9 +209,7 @@ where
|
||||||
|
|
||||||
let block_size = reader.read_u32::<LittleEndian>()?;
|
let block_size = reader.read_u32::<LittleEndian>()?;
|
||||||
if !(24..=WV_BLOCK_MAX_SIZE).contains(&block_size) {
|
if !(24..=WV_BLOCK_MAX_SIZE).contains(&block_size) {
|
||||||
return Err(
|
decode_err!(@BAIL WavPack, "WavPack block has an invalid size");
|
||||||
FileDecodingError::new(FileType::WavPack, "WavPack block has an invalid size").into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let version = reader.read_u16::<LittleEndian>()?;
|
let version = reader.read_u16::<LittleEndian>()?;
|
||||||
|
@ -267,11 +264,7 @@ where
|
||||||
},
|
},
|
||||||
ID_DSD => {
|
ID_DSD => {
|
||||||
if size <= 1 {
|
if size <= 1 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WavPack, "Encountered an invalid DSD block size");
|
||||||
FileType::WavPack,
|
|
||||||
"Encountered an invalid DSD block size",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let rate_multiplier = u32::from(reader.read_u8()?);
|
let rate_multiplier = u32::from(reader.read_u8()?);
|
||||||
|
@ -285,11 +278,7 @@ where
|
||||||
},
|
},
|
||||||
ID_MULTICHANNEL => {
|
ID_MULTICHANNEL => {
|
||||||
if size <= 1 {
|
if size <= 1 {
|
||||||
return Err(FileDecodingError::new(
|
decode_err!(@BAIL WavPack, "Unable to extract channel information");
|
||||||
FileType::WavPack,
|
|
||||||
"Unable to extract channel information",
|
|
||||||
)
|
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.channels = reader.read_u8()?;
|
properties.channels = reader.read_u8()?;
|
||||||
|
@ -300,13 +289,7 @@ where
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
4 | 5 => {},
|
4 | 5 => {},
|
||||||
_ => {
|
_ => decode_err!(@BAIL WavPack, "Encountered invalid channel info size"),
|
||||||
return Err(FileDecodingError::new(
|
|
||||||
FileType::WavPack,
|
|
||||||
"Encountered invalid channel info size",
|
|
||||||
)
|
|
||||||
.into())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.seek(SeekFrom::Current(1))?;
|
reader.seek(SeekFrom::Current(1))?;
|
||||||
|
|
Loading…
Reference in a new issue