1use core::fmt;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[repr(u8)]
52pub enum PartitionKind {
53 Empty = 0x00,
55 Fat12 = 0x01,
57 Fat16Small = 0x04,
59 Extended = 0x05,
61 Fat16 = 0x06,
63 NtfsExfat = 0x07,
65 Fat32 = 0x0B,
67 Fat32Lba = 0x0C,
69 Fat16Lba = 0x0E,
71 ExtendedLba = 0x0F,
73 HiddenFat12 = 0x11,
75 HiddenFat16Small = 0x14,
77 HiddenFat16 = 0x16,
79 HiddenNtfsExfat = 0x17,
81 HiddenFat32 = 0x1B,
83 HiddenFat32Lba = 0x1C,
85 HiddenFat16Lba = 0x1E,
87 LinuxSwap = 0x82,
89 Linux = 0x83,
91 LinuxLvm = 0x8E,
93 GptProtective = 0xEE,
95 EfiSystem = 0xEF,
97 Xila = 0xDA,
99 Unknown(u8),
101}
102
103impl PartitionKind {
104 pub fn from_u8(value: u8) -> Self {
131 match value {
132 0x00 => PartitionKind::Empty,
133 0x01 => PartitionKind::Fat12,
134 0x04 => PartitionKind::Fat16Small,
135 0x05 => PartitionKind::Extended,
136 0x06 => PartitionKind::Fat16,
137 0x07 => PartitionKind::NtfsExfat,
138 0x0B => PartitionKind::Fat32,
139 0x0C => PartitionKind::Fat32Lba,
140 0x0E => PartitionKind::Fat16Lba,
141 0x0F => PartitionKind::ExtendedLba,
142 0x11 => PartitionKind::HiddenFat12,
143 0x14 => PartitionKind::HiddenFat16Small,
144 0x16 => PartitionKind::HiddenFat16,
145 0x17 => PartitionKind::HiddenNtfsExfat,
146 0x1B => PartitionKind::HiddenFat32,
147 0x1C => PartitionKind::HiddenFat32Lba,
148 0x1E => PartitionKind::HiddenFat16Lba,
149 0x82 => PartitionKind::LinuxSwap,
150 0x83 => PartitionKind::Linux,
151 0x8E => PartitionKind::LinuxLvm,
152 0xEE => PartitionKind::GptProtective,
153 0xEF => PartitionKind::EfiSystem,
154 0xDA => PartitionKind::Xila,
155 _ => PartitionKind::Unknown(value),
156 }
157 }
158
159 pub fn to_u8(&self) -> u8 {
161 match self {
162 PartitionKind::Empty => 0x00,
163 PartitionKind::Fat12 => 0x01,
164 PartitionKind::Fat16Small => 0x04,
165 PartitionKind::Extended => 0x05,
166 PartitionKind::Fat16 => 0x06,
167 PartitionKind::NtfsExfat => 0x07,
168 PartitionKind::Fat32 => 0x0B,
169 PartitionKind::Fat32Lba => 0x0C,
170 PartitionKind::Fat16Lba => 0x0E,
171 PartitionKind::ExtendedLba => 0x0F,
172 PartitionKind::HiddenFat12 => 0x11,
173 PartitionKind::HiddenFat16Small => 0x14,
174 PartitionKind::HiddenFat16 => 0x16,
175 PartitionKind::HiddenNtfsExfat => 0x17,
176 PartitionKind::HiddenFat32 => 0x1B,
177 PartitionKind::HiddenFat32Lba => 0x1C,
178 PartitionKind::HiddenFat16Lba => 0x1E,
179 PartitionKind::LinuxSwap => 0x82,
180 PartitionKind::Linux => 0x83,
181 PartitionKind::LinuxLvm => 0x8E,
182 PartitionKind::GptProtective => 0xEE,
183 PartitionKind::EfiSystem => 0xEF,
184 PartitionKind::Xila => 0xDA,
185 PartitionKind::Unknown(value) => *value,
186 }
187 }
188
189 pub fn get_name(&self) -> &'static str {
191 match self {
192 PartitionKind::Empty => "Empty",
193 PartitionKind::Fat12 => "FAT12",
194 PartitionKind::Fat16Small => "FAT16 <32M",
195 PartitionKind::Extended => "Extended",
196 PartitionKind::Fat16 => "FAT16",
197 PartitionKind::NtfsExfat => "NTFS/exFAT",
198 PartitionKind::Fat32 => "FAT32",
199 PartitionKind::Fat32Lba => "FAT32 LBA",
200 PartitionKind::Fat16Lba => "FAT16 LBA",
201 PartitionKind::ExtendedLba => "Extended LBA",
202 PartitionKind::HiddenFat12 => "Hidden FAT12",
203 PartitionKind::HiddenFat16Small => "Hidden FAT16 <32M",
204 PartitionKind::HiddenFat16 => "Hidden FAT16",
205 PartitionKind::HiddenNtfsExfat => "Hidden NTFS/exFAT",
206 PartitionKind::HiddenFat32 => "Hidden FAT32",
207 PartitionKind::HiddenFat32Lba => "Hidden FAT32 LBA",
208 PartitionKind::HiddenFat16Lba => "Hidden FAT16 LBA",
209 PartitionKind::LinuxSwap => "Linux swap",
210 PartitionKind::Linux => "Linux",
211 PartitionKind::LinuxLvm => "Linux LVM",
212 PartitionKind::GptProtective => "GPT protective",
213 PartitionKind::EfiSystem => "EFI System",
214 PartitionKind::Xila => "Xila",
215 PartitionKind::Unknown(_) => "Unknown",
216 }
217 }
218
219 pub fn is_fat(&self) -> bool {
221 matches!(
222 self,
223 PartitionKind::Fat12
224 | PartitionKind::Fat16Small
225 | PartitionKind::Fat16
226 | PartitionKind::Fat32
227 | PartitionKind::Fat32Lba
228 | PartitionKind::Fat16Lba
229 | PartitionKind::HiddenFat12
230 | PartitionKind::HiddenFat16Small
231 | PartitionKind::HiddenFat16
232 | PartitionKind::HiddenFat32
233 | PartitionKind::HiddenFat32Lba
234 | PartitionKind::HiddenFat16Lba
235 )
236 }
237
238 pub fn is_hidden(&self) -> bool {
240 matches!(
241 self,
242 PartitionKind::HiddenFat12
243 | PartitionKind::HiddenFat16Small
244 | PartitionKind::HiddenFat16
245 | PartitionKind::HiddenNtfsExfat
246 | PartitionKind::HiddenFat32
247 | PartitionKind::HiddenFat32Lba
248 | PartitionKind::HiddenFat16Lba
249 )
250 }
251
252 pub fn is_extended(&self) -> bool {
254 matches!(self, PartitionKind::Extended | PartitionKind::ExtendedLba)
255 }
256
257 pub fn is_linux(&self) -> bool {
259 matches!(
260 self,
261 PartitionKind::Linux | PartitionKind::LinuxSwap | PartitionKind::LinuxLvm
262 )
263 }
264}
265
266impl fmt::Display for PartitionKind {
267 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
268 match self {
269 PartitionKind::Unknown(value) => write!(formatter, "Unknown (0x{value:02X})"),
270 _ => write!(formatter, "{} (0x{:02X})", self.get_name(), self.to_u8()),
271 }
272 }
273}
274
275#[cfg(test)]
276mod tests {
277 use super::*;
278 use alloc::{format, vec};
279
280 #[test]
281 fn test_partition_type_from_u8() {
282 assert_eq!(PartitionKind::from_u8(0x00), PartitionKind::Empty);
283 assert_eq!(PartitionKind::from_u8(0x0C), PartitionKind::Fat32Lba);
284 assert_eq!(PartitionKind::from_u8(0x83), PartitionKind::Linux);
285 assert_eq!(PartitionKind::from_u8(0xEE), PartitionKind::GptProtective);
286 assert_eq!(PartitionKind::from_u8(0xFF), PartitionKind::Unknown(0xFF));
287 }
288
289 #[test]
290 fn test_partition_type_to_u8() {
291 assert_eq!(PartitionKind::Empty.to_u8(), 0x00);
292 assert_eq!(PartitionKind::Fat32Lba.to_u8(), 0x0C);
293 assert_eq!(PartitionKind::Linux.to_u8(), 0x83);
294 assert_eq!(PartitionKind::GptProtective.to_u8(), 0xEE);
295 assert_eq!(PartitionKind::Unknown(0xFF).to_u8(), 0xFF);
296 }
297
298 #[test]
299 fn test_partition_type_round_trip() {
300 let types = vec![
301 0x00, 0x01, 0x04, 0x05, 0x06, 0x07, 0x0B, 0x0C, 0x0E, 0x0F, 0x11, 0x14, 0x16, 0x17,
302 0x1B, 0x1C, 0x1E, 0x82, 0x83, 0x8E, 0xEE, 0xEF, 0xFF, 0x42, 0x99,
303 ];
304
305 for type_value in types {
306 let partition_type = PartitionKind::from_u8(type_value);
307 assert_eq!(partition_type.to_u8(), type_value);
308 }
309 }
310
311 #[test]
312 fn test_partition_type_properties() {
313 assert!(PartitionKind::Fat12.is_fat());
315 assert!(PartitionKind::Fat16.is_fat());
316 assert!(PartitionKind::Fat32.is_fat());
317 assert!(PartitionKind::Fat32Lba.is_fat());
318 assert!(PartitionKind::HiddenFat32.is_fat());
319 assert!(!PartitionKind::Linux.is_fat());
320 assert!(!PartitionKind::NtfsExfat.is_fat());
321
322 assert!(PartitionKind::HiddenFat12.is_hidden());
324 assert!(PartitionKind::HiddenFat32.is_hidden());
325 assert!(PartitionKind::HiddenNtfsExfat.is_hidden());
326 assert!(!PartitionKind::Fat32.is_hidden());
327 assert!(!PartitionKind::Linux.is_hidden());
328
329 assert!(PartitionKind::Extended.is_extended());
331 assert!(PartitionKind::ExtendedLba.is_extended());
332 assert!(!PartitionKind::Fat32.is_extended());
333 assert!(!PartitionKind::Linux.is_extended());
334
335 assert!(PartitionKind::Linux.is_linux());
337 assert!(PartitionKind::LinuxSwap.is_linux());
338 assert!(PartitionKind::LinuxLvm.is_linux());
339 assert!(!PartitionKind::Fat32.is_linux());
340 assert!(!PartitionKind::NtfsExfat.is_linux());
341 }
342
343 #[test]
344 fn test_partition_type_names() {
345 assert_eq!(PartitionKind::Empty.get_name(), "Empty");
346 assert_eq!(PartitionKind::Fat32Lba.get_name(), "FAT32 LBA");
347 assert_eq!(PartitionKind::Linux.get_name(), "Linux");
348 assert_eq!(PartitionKind::GptProtective.get_name(), "GPT protective");
349 assert_eq!(PartitionKind::Unknown(0x42).get_name(), "Unknown");
350 }
351
352 #[test]
353 fn test_partition_type_display() {
354 let fat32_variant = PartitionKind::Fat32Lba;
355 let display_string = format!("{fat32_variant}");
356 assert!(display_string.contains("FAT32 LBA"));
357 assert!(display_string.contains("0x0C"));
358
359 let unknown = PartitionKind::Unknown(0x42);
360 let unknown_string = format!("{unknown}");
361 assert!(unknown_string.contains("Unknown"));
362 assert!(unknown_string.contains("0x42"));
363 }
364}