1use core::fmt::{self, Debug, Display};
4
5#[derive(Debug)]
7pub enum Error {
8 Io(hadris_io::Error),
10
11 InvalidMbrSignature {
13 found: [u8; 2],
15 },
16
17 InvalidGptSignature {
19 found: [u8; 8],
21 },
22
23 GptHeaderCrcMismatch {
25 expected: u32,
27 actual: u32,
29 },
30
31 GptEntriesCrcMismatch {
33 expected: u32,
35 actual: u32,
37 },
38
39 BackupHeaderIo {
41 lba: u64,
43 source: hadris_io::Error,
45 },
46
47 InvalidBackupGptSignature {
49 found: [u8; 8],
51 },
52
53 BackupGptHeaderCrcMismatch {
55 expected: u32,
57 actual: u32,
59 },
60
61 PartitionOverlap {
63 index1: usize,
65 index2: usize,
67 overlap_start: u64,
69 overlap_end: u64,
71 },
72
73 TooManyPartitions {
75 max: usize,
77 requested: usize,
79 },
80
81 PartitionOutOfBounds {
83 index: usize,
85 partition_end: u64,
87 disk_end: u64,
89 },
90
91 InvalidPartitionEntrySize {
93 size: u32,
95 },
96
97 InvalidBlockSize {
99 size: u32,
101 minimum: u32,
103 },
104
105 BackupHeaderMismatch,
107
108 NoProtectiveMbr,
110
111 InvalidHybridMbr {
113 reason: &'static str,
115 },
116
117 DiskTooSmall {
119 required: u64,
121 available: u64,
123 },
124
125 FeatureNotAvailable(&'static str),
127
128 MisalignedPartition {
130 lba: u64,
132 required_alignment: u64,
134 },
135}
136
137impl Display for Error {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 match self {
140 Self::Io(err) => write!(f, "I/O error: {err}"),
141 Self::InvalidMbrSignature { found } => {
142 write!(
143 f,
144 "invalid MBR signature: expected 0x55AA, found 0x{:02X}{:02X}",
145 found[0], found[1]
146 )
147 }
148 Self::InvalidGptSignature { found } => {
149 write!(
150 f,
151 "invalid GPT signature: expected 'EFI PART', found {found:?}"
152 )
153 }
154 Self::GptHeaderCrcMismatch { expected, actual } => {
155 write!(
156 f,
157 "GPT header CRC mismatch: expected 0x{expected:08X}, got 0x{actual:08X}"
158 )
159 }
160 Self::GptEntriesCrcMismatch { expected, actual } => {
161 write!(
162 f,
163 "GPT entries CRC mismatch: expected 0x{expected:08X}, got 0x{actual:08X}"
164 )
165 }
166 Self::InvalidBlockSize { size, minimum } => {
167 write!(f, "invalid block size {size}; minimum is {minimum} bytes")
168 }
169 Self::BackupHeaderIo { lba, source } => {
170 write!(f, "failed to read backup GPT header at LBA {lba}: {source}")
171 }
172 Self::InvalidBackupGptSignature { found } => {
173 write!(
174 f,
175 "invalid backup GPT signature: expected 'EFI PART', found {found:?}"
176 )
177 }
178 Self::BackupGptHeaderCrcMismatch { expected, actual } => {
179 write!(
180 f,
181 "backup GPT header CRC mismatch: expected 0x{expected:08X}, got 0x{actual:08X}"
182 )
183 }
184 Self::PartitionOverlap {
185 index1,
186 index2,
187 overlap_start,
188 overlap_end,
189 } => {
190 write!(
191 f,
192 "partitions {index1} and {index2} overlap (LBA {overlap_start}-{overlap_end})"
193 )
194 }
195 Self::TooManyPartitions { max, requested } => {
196 write!(
197 f,
198 "too many partitions: maximum is {max}, requested {requested}"
199 )
200 }
201 Self::PartitionOutOfBounds {
202 index,
203 partition_end,
204 disk_end,
205 } => {
206 write!(
207 f,
208 "partition {index} extends beyond disk (ends at LBA {partition_end}, disk ends at {disk_end})"
209 )
210 }
211 Self::InvalidPartitionEntrySize { size } => {
212 write!(
213 f,
214 "invalid partition entry size: {size} (must be 128 * 2^n)"
215 )
216 }
217 Self::BackupHeaderMismatch => {
218 write!(f, "backup GPT header does not match primary")
219 }
220 Self::NoProtectiveMbr => {
221 write!(f, "no protective MBR found on GPT disk")
222 }
223 Self::InvalidHybridMbr { reason } => {
224 write!(f, "invalid hybrid MBR: {reason}")
225 }
226 Self::DiskTooSmall {
227 required,
228 available,
229 } => {
230 write!(
231 f,
232 "disk too small: requires {required} sectors, only {available} available"
233 )
234 }
235 Self::FeatureNotAvailable(feature) => {
236 write!(f, "feature not available: {feature}")
237 }
238 Self::MisalignedPartition {
239 lba,
240 required_alignment,
241 } => {
242 write!(
243 f,
244 "partition at LBA {lba} is not aligned to {required_alignment} sectors"
245 )
246 }
247 }
248 }
249}
250
251impl<E: hadris_io::IoError> From<hadris_io::Error<E>> for Error {
252 fn from(err: hadris_io::Error<E>) -> Self {
253 Self::Io(err.erase())
254 }
255}
256
257#[cfg(all(feature = "write", any(feature = "sync", feature = "async")))]
258impl Error {
259 pub(crate) fn lba_offset_overflow() -> Self {
261 Self::Io(hadris_io::Error::new(
262 hadris_io::ErrorKind::InvalidInput,
263 "LBA value overflows byte offset",
264 ))
265 }
266}
267
268#[cfg(feature = "std")]
269impl std::error::Error for Error {
270 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
271 match self {
272 Self::Io(err) => Some(err),
273 Self::BackupHeaderIo { source, .. } => Some(source),
274 _ => None,
275 }
276 }
277}
278
279pub type Result<T> = core::result::Result<T, Error>;