mirror of
https://github.com/Serial-ATA/lofty-rs
synced 2024-12-14 14:42:33 +00:00
384 lines
10 KiB
Rust
384 lines
10 KiB
Rust
//! Contains the errors that can arise within Lofty
|
|
//!
|
|
//! The primary error is [`LoftyError`]. The type of error is determined by [`ErrorKind`],
|
|
//! which can be extended at any time.
|
|
|
|
use crate::file::FileType;
|
|
|
|
use std::collections::TryReserveError;
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
|
|
use ogg_pager::PageError;
|
|
|
|
/// Alias for `Result<T, LoftyError>`
|
|
pub type Result<T> = std::result::Result<T, LoftyError>;
|
|
|
|
#[derive(Debug)]
|
|
#[non_exhaustive]
|
|
/// The types of errors that can occur
|
|
pub enum ErrorKind {
|
|
// File format related errors
|
|
/// Unable to guess the format
|
|
UnknownFormat,
|
|
|
|
// File data related errors
|
|
/// Attempting to read/write an abnormally large amount of data
|
|
TooMuchData,
|
|
/// Errors that occur while decoding a file
|
|
FileDecoding(FileDecodingError),
|
|
/// Errors that occur while encoding a file
|
|
FileEncoding(FileEncodingError),
|
|
|
|
// Picture related errors
|
|
/// Provided an invalid picture
|
|
NotAPicture,
|
|
/// Attempted to write a picture that the format does not support
|
|
UnsupportedPicture,
|
|
|
|
// Tag related errors
|
|
/// Arises when writing a tag to a file type that doesn't support it
|
|
UnsupportedTag,
|
|
/// Arises when a tag is expected (Ex. found an "ID3 " chunk in a WAV file), but isn't found
|
|
FakeTag,
|
|
/// Errors that arise while decoding text
|
|
TextDecode(&'static str),
|
|
/// Errors that arise while reading/writing ID3v2 tags
|
|
Id3v2(Id3v2Error),
|
|
|
|
/// Arises when an atom contains invalid data
|
|
BadAtom(&'static str),
|
|
|
|
// Conversions for external errors
|
|
/// Errors that arise while parsing OGG pages
|
|
OggPage(ogg_pager::PageError),
|
|
/// Unable to convert bytes to a String
|
|
StringFromUtf8(std::string::FromUtf8Error),
|
|
/// Unable to convert bytes to a str
|
|
StrFromUtf8(std::str::Utf8Error),
|
|
/// Represents all cases of [`std::io::Error`].
|
|
Io(std::io::Error),
|
|
/// Failure to allocate enough memory
|
|
Alloc(TryReserveError),
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
#[non_exhaustive]
|
|
/// The types of errors that can occur while interacting with ID3v2 tags
|
|
pub enum Id3v2ErrorKind {
|
|
#[cfg(feature = "id3v2")]
|
|
/// Arises when an invalid picture format is parsed. Only applicable to [`Id3v2Version::V2`](crate::id3::v2::Id3v2Version::V2)
|
|
BadPictureFormat(String),
|
|
/// Arises when an invalid ID3v2 version is found
|
|
BadId3v2Version(u8, u8),
|
|
#[cfg(feature = "id3v2")]
|
|
/// Arises when a frame ID contains invalid characters (must be within `'A'..'Z'` or `'0'..'9'`)
|
|
BadFrameID,
|
|
#[cfg(feature = "id3v2")]
|
|
/// Arises when a frame doesn't have enough data
|
|
BadFrameLength,
|
|
#[cfg(feature = "id3v2")]
|
|
/// Arises when invalid data is encountered while reading an ID3v2 synchronized text frame
|
|
BadSyncText,
|
|
#[cfg(feature = "id3v2")]
|
|
/// Arises when attempting to write an invalid Frame (Bad `FrameID`/`FrameValue` pairing)
|
|
BadFrame(String, &'static str),
|
|
/// A catch-all for all remaining errors
|
|
///
|
|
/// NOTE: This will likely be deprecated in the future
|
|
Other(&'static str),
|
|
}
|
|
|
|
impl Display for Id3v2ErrorKind {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self {
|
|
Id3v2ErrorKind::BadId3v2Version(major, minor) => write!(
|
|
f,
|
|
"Found an invalid version (v{}.{}), expected any major revision in: (2, 3, 4)",
|
|
major, minor
|
|
),
|
|
#[cfg(feature = "id3v2")]
|
|
Id3v2ErrorKind::BadFrameID => write!(f, "Failed to parse a frame ID"),
|
|
#[cfg(feature = "id3v2")]
|
|
Id3v2ErrorKind::BadFrameLength => write!(
|
|
f,
|
|
"Frame isn't long enough to extract the necessary information"
|
|
),
|
|
#[cfg(feature = "id3v2")]
|
|
Id3v2ErrorKind::BadSyncText => write!(f, "Encountered invalid data in SYLT frame"),
|
|
#[cfg(feature = "id3v2")]
|
|
Id3v2ErrorKind::BadFrame(ref frame_id, frame_value) => write!(
|
|
f,
|
|
"Attempted to write an invalid frame. ID: \"{}\", Value: \"{}\"",
|
|
frame_id, frame_value
|
|
),
|
|
#[cfg(feature = "id3v2")]
|
|
Id3v2ErrorKind::BadPictureFormat(format) => {
|
|
write!(f, "Picture: Found unexpected format \"{}\"", format)
|
|
},
|
|
Id3v2ErrorKind::Other(message) => write!(f, "{}", message),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An error that arises while interacting with an ID3v2 tag
|
|
pub struct Id3v2Error {
|
|
kind: Id3v2ErrorKind,
|
|
}
|
|
|
|
impl Id3v2Error {
|
|
/// Create a new `Id3v2Error` from an [`Id3v2ErrorKind`]
|
|
pub fn new(kind: Id3v2ErrorKind) -> Self {
|
|
Self { kind }
|
|
}
|
|
|
|
/// Returns the [`Id3v2ErrorKind`]
|
|
pub fn kind(&self) -> Id3v2ErrorKind {
|
|
self.kind.clone()
|
|
}
|
|
}
|
|
|
|
impl Debug for Id3v2Error {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "ID3v2: {:?}", self.kind)
|
|
}
|
|
}
|
|
|
|
impl Display for Id3v2Error {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "ID3v2: {}", self.kind)
|
|
}
|
|
}
|
|
|
|
/// An error that arises while decoding a file
|
|
pub struct FileDecodingError {
|
|
format: Option<FileType>,
|
|
description: &'static str,
|
|
}
|
|
|
|
impl FileDecodingError {
|
|
/// Create a `FileDecodingError` from a [`FileType`] and description
|
|
pub fn new(format: FileType, description: &'static str) -> Self {
|
|
Self {
|
|
format: Some(format),
|
|
description,
|
|
}
|
|
}
|
|
|
|
/// Create a `FileDecodingError` without binding it to a [`FileType`]
|
|
pub fn from_description(description: &'static str) -> Self {
|
|
Self {
|
|
format: None,
|
|
description,
|
|
}
|
|
}
|
|
|
|
/// Returns the associated [`FileType`], if one exists
|
|
pub fn format(&self) -> Option<FileType> {
|
|
self.format
|
|
}
|
|
|
|
/// Returns the error description
|
|
pub fn description(&self) -> &str {
|
|
self.description
|
|
}
|
|
}
|
|
|
|
impl Debug for FileDecodingError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(format) = self.format {
|
|
write!(f, "{:?}: {:?}", format, self.description)
|
|
} else {
|
|
write!(f, "{:?}", self.description)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for FileDecodingError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(format) = self.format {
|
|
write!(f, "{:?}: {}", format, self.description)
|
|
} else {
|
|
write!(f, "{}", self.description)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// An error that arises while encoding a file
|
|
pub struct FileEncodingError {
|
|
format: Option<FileType>,
|
|
description: &'static str,
|
|
}
|
|
|
|
impl FileEncodingError {
|
|
/// Create a `FileEncodingError` from a [`FileType`] and description
|
|
pub fn new(format: FileType, description: &'static str) -> Self {
|
|
Self {
|
|
format: Some(format),
|
|
description,
|
|
}
|
|
}
|
|
|
|
/// Create a `FileEncodingError` without binding it to a [`FileType`]
|
|
pub fn from_description(description: &'static str) -> Self {
|
|
Self {
|
|
format: None,
|
|
description,
|
|
}
|
|
}
|
|
|
|
/// Returns the associated [`FileType`], if one exists
|
|
pub fn format(&self) -> Option<FileType> {
|
|
self.format
|
|
}
|
|
|
|
/// Returns the error description
|
|
pub fn description(&self) -> &str {
|
|
self.description
|
|
}
|
|
}
|
|
|
|
impl Debug for FileEncodingError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(format) = self.format {
|
|
write!(f, "{:?}: {:?}", format, self.description)
|
|
} else {
|
|
write!(f, "{:?}", self.description)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for FileEncodingError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
if let Some(format) = self.format {
|
|
write!(f, "{:?}: {:?}", format, self.description)
|
|
} else {
|
|
write!(f, "{}", self.description)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Errors that could occur within Lofty
|
|
pub struct LoftyError {
|
|
kind: ErrorKind,
|
|
}
|
|
|
|
impl LoftyError {
|
|
/// Create a `LoftyError` from an [`ErrorKind`]
|
|
pub fn new(kind: ErrorKind) -> Self {
|
|
Self { kind }
|
|
}
|
|
|
|
/// Returns the [`ErrorKind`]
|
|
pub fn kind(&self) -> &ErrorKind {
|
|
&self.kind
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for LoftyError {}
|
|
|
|
impl Debug for LoftyError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "{:?}", self.kind)
|
|
}
|
|
}
|
|
|
|
impl From<Id3v2Error> for LoftyError {
|
|
fn from(input: Id3v2Error) -> Self {
|
|
Self {
|
|
kind: ErrorKind::Id3v2(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<FileDecodingError> for LoftyError {
|
|
fn from(input: FileDecodingError) -> Self {
|
|
Self {
|
|
kind: ErrorKind::FileDecoding(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<FileEncodingError> for LoftyError {
|
|
fn from(input: FileEncodingError) -> Self {
|
|
Self {
|
|
kind: ErrorKind::FileEncoding(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<ogg_pager::PageError> for LoftyError {
|
|
fn from(input: PageError) -> Self {
|
|
Self {
|
|
kind: ErrorKind::OggPage(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for LoftyError {
|
|
fn from(input: std::io::Error) -> Self {
|
|
Self {
|
|
kind: ErrorKind::Io(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::string::FromUtf8Error> for LoftyError {
|
|
fn from(input: std::string::FromUtf8Error) -> Self {
|
|
Self {
|
|
kind: ErrorKind::StringFromUtf8(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::str::Utf8Error> for LoftyError {
|
|
fn from(input: std::str::Utf8Error) -> Self {
|
|
Self {
|
|
kind: ErrorKind::StrFromUtf8(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<std::collections::TryReserveError> for LoftyError {
|
|
fn from(input: TryReserveError) -> Self {
|
|
Self {
|
|
kind: ErrorKind::Alloc(input),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for LoftyError {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
match self.kind {
|
|
// Conversions
|
|
ErrorKind::OggPage(ref err) => write!(f, "{}", err),
|
|
ErrorKind::StringFromUtf8(ref err) => write!(f, "{}", err),
|
|
ErrorKind::StrFromUtf8(ref err) => write!(f, "{}", err),
|
|
ErrorKind::Io(ref err) => write!(f, "{}", err),
|
|
ErrorKind::Alloc(ref err) => write!(f, "{}", err),
|
|
|
|
ErrorKind::UnknownFormat => {
|
|
write!(f, "No format could be determined from the provided file")
|
|
},
|
|
ErrorKind::TooMuchData => write!(
|
|
f,
|
|
"An abnormally large amount of data was provided, and an overflow occurred"
|
|
),
|
|
ErrorKind::NotAPicture => write!(f, "Picture: Encountered invalid data"),
|
|
ErrorKind::UnsupportedPicture => {
|
|
write!(f, "Picture: attempted to write an unsupported picture")
|
|
},
|
|
ErrorKind::UnsupportedTag => write!(
|
|
f,
|
|
"Attempted to write a tag to a format that does not support it"
|
|
),
|
|
ErrorKind::FakeTag => write!(f, "Reading: Expected a tag, found invalid data"),
|
|
ErrorKind::TextDecode(message) => write!(f, "Text decoding: {}", message),
|
|
ErrorKind::Id3v2(ref id3v2_err) => write!(f, "{}", id3v2_err),
|
|
ErrorKind::BadAtom(message) => write!(f, "MP4 Atom: {}", message),
|
|
|
|
// Files
|
|
ErrorKind::FileDecoding(ref file_decode_err) => write!(f, "{}", file_decode_err),
|
|
ErrorKind::FileEncoding(ref file_encode_err) => write!(f, "{}", file_encode_err),
|
|
}
|
|
}
|
|
}
|