use thiserror::Error;
#[derive(Debug, Error)]
pub enum Par2Error {
#[error("invalid magic sequence at offset {offset}")]
InvalidMagic { offset: u64 },
#[error("packet too short: expected at least {expected} bytes, got {actual}")]
PacketTooShort { expected: u64, actual: u64 },
#[error("packet length {length} not a multiple of 4")]
InvalidPacketLength { length: u64 },
#[error("packet hash mismatch at offset {offset}")]
PacketHashMismatch { offset: u64 },
#[error("invalid main packet: {reason}")]
InvalidMainPacket { reason: String },
#[error("invalid file description packet: {reason}")]
InvalidFileDescPacket { reason: String },
#[error("invalid IFSC packet: {reason}")]
InvalidIfscPacket { reason: String },
#[error("invalid recovery slice packet: {reason}")]
InvalidRecoveryPacket { reason: String },
#[error("invalid creator packet: {reason}")]
InvalidCreatorPacket { reason: String },
#[error("duplicate main packet with different recovery set ID")]
ConflictingRecoverySet,
#[error("no main packet found in PAR2 file set")]
NoMainPacket,
#[error("insufficient critical PAR2 data: {reason}")]
InsufficientCriticalData { reason: String },
#[error("PAR2 resource limit exceeded: {reason}")]
ResourceLimitExceeded { reason: String },
#[error("file not found: {filename}")]
FileNotFound { filename: String },
#[error("file {filename}: {damaged_slices} of {total_slices} slices damaged")]
FileDamaged {
filename: String,
damaged_slices: u32,
total_slices: u32,
},
#[error(
"insufficient recovery data: need {needed} blocks, have {available} (deficit: {deficit})"
)]
InsufficientRecoveryData {
needed: u32,
available: u32,
deficit: u32,
},
#[error("reed-solomon decode failed: {reason}")]
ReedSolomonError { reason: String },
#[error("repair target write failed for {filename} at offset {offset}: {source}")]
RepairWriteFailed {
filename: String,
offset: u64,
source: std::io::Error,
},
#[error("operation cancelled")]
Cancelled,
#[error("I/O error: {0}")]
Io(#[from] std::io::Error),
#[error("invalid PAR2 creation options: {reason}")]
InvalidCreationOptions { reason: String },
#[error("unsafe PAR2 source path {path}: {reason}")]
UnsafeCreationSource { path: String, reason: String },
#[error("source file changed while creating PAR2 data: {path}")]
CreationSourceChanged { path: String },
#[error("PAR2 output already exists: {path}")]
CreationOutputExists { path: String },
#[error("unsafe PAR2 output path {path}: {reason}")]
UnsafeCreationOutput { path: String, reason: String },
#[error("staged PAR2 output validation failed for {path}: {reason}")]
CreationValidation { path: String, reason: String },
#[error("Metal creation backend is unavailable: {reason}")]
MetalUnavailable { reason: String },
#[error("Metal creation failed after staging began: {reason}")]
MetalExecutionFailed { reason: String },
}
pub type Result<T> = std::result::Result<T, Par2Error>;