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