use std::path::PathBuf;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ArchiveError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Unsupported archive format: {0}")]
UnsupportedFormat(String),
#[error("Invalid {format} archive header")]
InvalidHeader {
format: String,
},
#[error("Corrupted {format} entry '{entry_name}': {reason}")]
CorruptedEntry {
format: String,
entry_name: String,
reason: String,
},
#[error("Entry index mismatch: {0}")]
IndexMismatch(String),
#[error("CRC mismatch for '{entry}': expected {expected:#010x}, got {actual:#010x}")]
CrcMismatch {
entry: String,
expected: u32,
actual: u32,
},
#[error("Decompression failed for '{entry}': {reason}")]
DecompressionFailed {
entry: String,
reason: String,
},
#[error("Unsupported compression method '{method}' in {format} archive")]
UnsupportedMethod {
format: String,
method: String,
},
#[error("Archive '{path}' is encrypted and requires a password")]
PasswordRequired {
path: PathBuf,
},
#[error("Entry '{entry}' in {format} archive is encrypted and requires a password")]
EncryptionRequired {
entry: String,
format: String,
},
#[error("Invalid password for '{entry}' in {format} archive")]
InvalidPassword {
entry: String,
format: String,
},
#[error("{library} error: {message}")]
ExternalLibrary {
library: String,
message: String,
},
}
pub type Result<T> = std::result::Result<T, ArchiveError>;
impl<T: std::io::Read> From<delharc::decode::LhaDecodeError<T>> for ArchiveError {
fn from(err: delharc::decode::LhaDecodeError<T>) -> Self {
ArchiveError::ExternalLibrary {
library: "delharc".to_string(),
message: format!("{:?}", err),
}
}
}
impl From<delharc::LhaError<std::io::Error>> for ArchiveError {
fn from(err: delharc::LhaError<std::io::Error>) -> Self {
ArchiveError::ExternalLibrary {
library: "delharc".to_string(),
message: format!("{:?}", err),
}
}
}
impl From<ArchiveError> for std::io::Error {
fn from(err: ArchiveError) -> Self {
match err {
ArchiveError::Io(io_err) => io_err,
other => std::io::Error::other(other.to_string()),
}
}
}
impl ArchiveError {
pub fn io_error(message: impl Into<String>) -> Self {
Self::Io(std::io::Error::other(message.into()))
}
pub fn unsupported_format(path: impl Into<String>) -> Self {
Self::UnsupportedFormat(path.into())
}
pub fn invalid_header(format: impl Into<String>) -> Self {
Self::InvalidHeader { format: format.into() }
}
pub fn corrupted_entry(format: impl Into<String>, reason: impl Into<String>) -> Self {
Self::CorruptedEntry {
format: format.into(),
entry_name: String::new(),
reason: reason.into(),
}
}
pub fn corrupted_entry_named(format: impl Into<String>, entry_name: impl Into<String>, reason: impl Into<String>) -> Self {
Self::CorruptedEntry {
format: format.into(),
entry_name: entry_name.into(),
reason: reason.into(),
}
}
pub fn crc_mismatch(entry: impl Into<String>, expected: u32, actual: u32) -> Self {
Self::CrcMismatch {
entry: entry.into(),
expected,
actual,
}
}
pub fn decompression_failed(entry: impl Into<String>, reason: impl Into<String>) -> Self {
Self::DecompressionFailed {
entry: entry.into(),
reason: reason.into(),
}
}
pub fn unsupported_method(format: impl Into<String>, method: impl Into<String>) -> Self {
Self::UnsupportedMethod {
format: format.into(),
method: method.into(),
}
}
pub fn external_library(library: impl Into<String>, message: impl Into<String>) -> Self {
Self::ExternalLibrary {
library: library.into(),
message: message.into(),
}
}
pub fn encryption_required(entry: impl Into<String>, format: impl Into<String>) -> Self {
Self::EncryptionRequired {
entry: entry.into(),
format: format.into(),
}
}
pub fn invalid_password(entry: impl Into<String>, format: impl Into<String>) -> Self {
Self::InvalidPassword {
entry: entry.into(),
format: format.into(),
}
}
}