1use thiserror::Error;
2
3#[derive(Debug, Error)]
5pub enum Par2Error {
6 #[error("invalid magic sequence at offset {offset}")]
8 InvalidMagic { offset: u64 },
9
10 #[error("packet too short: expected at least {expected} bytes, got {actual}")]
11 PacketTooShort { expected: u64, actual: u64 },
12
13 #[error("packet length {length} not a multiple of 4")]
14 InvalidPacketLength { length: u64 },
15
16 #[error("packet hash mismatch at offset {offset}")]
17 PacketHashMismatch { offset: u64 },
18
19 #[error("invalid main packet: {reason}")]
20 InvalidMainPacket { reason: String },
21
22 #[error("invalid file description packet: {reason}")]
23 InvalidFileDescPacket { reason: String },
24
25 #[error("invalid IFSC packet: {reason}")]
26 InvalidIfscPacket { reason: String },
27
28 #[error("invalid recovery slice packet: {reason}")]
29 InvalidRecoveryPacket { reason: String },
30
31 #[error("invalid creator packet: {reason}")]
32 InvalidCreatorPacket { reason: String },
33
34 #[error("duplicate main packet with different recovery set ID")]
35 ConflictingRecoverySet,
36
37 #[error("no main packet found in PAR2 file set")]
38 NoMainPacket,
39
40 #[error("insufficient critical PAR2 data: {reason}")]
41 InsufficientCriticalData { reason: String },
42
43 #[error("PAR2 resource limit exceeded: {reason}")]
44 ResourceLimitExceeded { reason: String },
45
46 #[error("file not found: {filename}")]
48 FileNotFound { filename: String },
49
50 #[error("file {filename}: {damaged_slices} of {total_slices} slices damaged")]
51 FileDamaged {
52 filename: String,
53 damaged_slices: u32,
54 total_slices: u32,
55 },
56
57 #[error(
59 "insufficient recovery data: need {needed} blocks, have {available} (deficit: {deficit})"
60 )]
61 InsufficientRecoveryData {
62 needed: u32,
63 available: u32,
64 deficit: u32,
65 },
66
67 #[error("reed-solomon decode failed: {reason}")]
68 ReedSolomonError { reason: String },
69
70 #[error("repair target write failed for {filename} at offset {offset}: {source}")]
71 RepairWriteFailed {
72 filename: String,
73 offset: u64,
74 source: std::io::Error,
75 },
76
77 #[error("operation cancelled")]
79 Cancelled,
80
81 #[error("I/O error: {0}")]
83 Io(#[from] std::io::Error),
84
85 #[error("invalid PAR2 creation options: {reason}")]
87 InvalidCreationOptions { reason: String },
88
89 #[error("unsafe PAR2 source path {path}: {reason}")]
90 UnsafeCreationSource { path: String, reason: String },
91
92 #[error("source file changed while creating PAR2 data: {path}")]
93 CreationSourceChanged { path: String },
94
95 #[error("PAR2 output already exists: {path}")]
96 CreationOutputExists { path: String },
97
98 #[error("unsafe PAR2 output path {path}: {reason}")]
99 UnsafeCreationOutput { path: String, reason: String },
100
101 #[error("staged PAR2 output validation failed for {path}: {reason}")]
102 CreationValidation { path: String, reason: String },
103
104 #[error("Metal creation backend is unavailable: {reason}")]
105 MetalUnavailable { reason: String },
106
107 #[error("Metal creation failed after staging began: {reason}")]
108 MetalExecutionFailed { reason: String },
109}
110
111pub type Result<T> = std::result::Result<T, Par2Error>;