unarc_rs/
error.rs

1//! Error types for unarc-rs
2//!
3//! This module provides a unified error type for all archive operations.
4
5use std::path::PathBuf;
6use thiserror::Error;
7
8/// Error type for archive operations
9#[derive(Debug, Error)]
10pub enum ArchiveError {
11    /// IO error during archive operations
12    #[error("IO error: {0}")]
13    Io(#[from] std::io::Error),
14
15    /// Unsupported archive format
16    #[error("Unsupported archive format: {0}")]
17    UnsupportedFormat(String),
18
19    /// Invalid archive header
20    #[error("Invalid {format} archive header")]
21    InvalidHeader {
22        /// Archive format name (e.g., "ARC", "ARJ", "ZIP")
23        format: String,
24    },
25
26    /// Corrupted archive entry
27    #[error("Corrupted {format} entry '{entry_name}': {reason}")]
28    CorruptedEntry {
29        /// Archive format name
30        format: String,
31        /// Name of the corrupted entry
32        entry_name: String,
33        /// Reason for corruption
34        reason: String,
35    },
36
37    /// Entry index mismatch
38    #[error("Entry index mismatch: {0}")]
39    IndexMismatch(String),
40
41    /// CRC checksum mismatch
42    #[error("CRC mismatch for '{entry}': expected {expected:#010x}, got {actual:#010x}")]
43    CrcMismatch {
44        /// Name of the entry with CRC mismatch
45        entry: String,
46        /// Expected CRC value
47        expected: u32,
48        /// Actual calculated CRC value
49        actual: u32,
50    },
51
52    /// Decompression failed
53    #[error("Decompression failed for '{entry}': {reason}")]
54    DecompressionFailed {
55        /// Name of the entry that failed to decompress
56        entry: String,
57        /// Reason for decompression failure
58        reason: String,
59    },
60
61    /// Unsupported compression method
62    #[error("Unsupported compression method '{method}' in {format} archive")]
63    UnsupportedMethod {
64        /// Archive format name
65        format: String,
66        /// Compression method name or identifier
67        method: String,
68    },
69
70    /// Password required but not provided
71    #[error("Archive '{path}' is encrypted and requires a password")]
72    PasswordRequired {
73        /// Path to the encrypted archive
74        path: PathBuf,
75    },
76
77    /// External library error (e.g., from zip, unrar, sevenz-rust2)
78    #[error("{library} error: {message}")]
79    ExternalLibrary {
80        /// Name of the external library
81        library: String,
82        /// Error message from the library
83        message: String,
84    },
85}
86
87/// Result type for archive operations
88pub type Result<T> = std::result::Result<T, ArchiveError>;
89
90// From implementations for external library errors
91
92impl<T: std::io::Read> From<delharc::decode::LhaDecodeError<T>> for ArchiveError {
93    fn from(err: delharc::decode::LhaDecodeError<T>) -> Self {
94        ArchiveError::ExternalLibrary {
95            library: "delharc".to_string(),
96            message: format!("{:?}", err),
97        }
98    }
99}
100
101impl From<delharc::LhaError<std::io::Error>> for ArchiveError {
102    fn from(err: delharc::LhaError<std::io::Error>) -> Self {
103        ArchiveError::ExternalLibrary {
104            library: "delharc".to_string(),
105            message: format!("{:?}", err),
106        }
107    }
108}
109
110// Allow converting ArchiveError to std::io::Error for compatibility
111impl From<ArchiveError> for std::io::Error {
112    fn from(err: ArchiveError) -> Self {
113        match err {
114            ArchiveError::Io(io_err) => io_err,
115            other => std::io::Error::other(other.to_string()),
116        }
117    }
118}
119
120impl ArchiveError {
121    /// Create an IO error from a string message
122    pub fn io_error(message: impl Into<String>) -> Self {
123        Self::Io(std::io::Error::other(message.into()))
124    }
125
126    /// Create an unsupported format error
127    pub fn unsupported_format(path: impl Into<String>) -> Self {
128        Self::UnsupportedFormat(path.into())
129    }
130
131    /// Create an invalid header error
132    pub fn invalid_header(format: impl Into<String>) -> Self {
133        Self::InvalidHeader {
134            format: format.into(),
135        }
136    }
137
138    /// Create a corrupted entry error
139    pub fn corrupted_entry(format: impl Into<String>, reason: impl Into<String>) -> Self {
140        Self::CorruptedEntry {
141            format: format.into(),
142            entry_name: String::new(),
143            reason: reason.into(),
144        }
145    }
146
147    /// Create a corrupted entry error with entry name
148    pub fn corrupted_entry_named(
149        format: impl Into<String>,
150        entry_name: impl Into<String>,
151        reason: impl Into<String>,
152    ) -> Self {
153        Self::CorruptedEntry {
154            format: format.into(),
155            entry_name: entry_name.into(),
156            reason: reason.into(),
157        }
158    }
159
160    /// Create a CRC mismatch error
161    pub fn crc_mismatch(entry: impl Into<String>, expected: u32, actual: u32) -> Self {
162        Self::CrcMismatch {
163            entry: entry.into(),
164            expected,
165            actual,
166        }
167    }
168
169    /// Create a decompression failed error
170    pub fn decompression_failed(entry: impl Into<String>, reason: impl Into<String>) -> Self {
171        Self::DecompressionFailed {
172            entry: entry.into(),
173            reason: reason.into(),
174        }
175    }
176
177    /// Create an unsupported method error
178    pub fn unsupported_method(format: impl Into<String>, method: impl Into<String>) -> Self {
179        Self::UnsupportedMethod {
180            format: format.into(),
181            method: method.into(),
182        }
183    }
184
185    /// Create an external library error
186    pub fn external_library(library: impl Into<String>, message: impl Into<String>) -> Self {
187        Self::ExternalLibrary {
188            library: library.into(),
189            message: message.into(),
190        }
191    }
192}