file_system/partition/
type.rs

1//! Partition type definitions for MBR partition tables.
2//!
3//! This module provides the [`Partition_type_type`] enumeration which defines
4//! all standard partition types used in MBR partition tables. Each partition
5//! type corresponds to a specific file system or partition purpose.
6
7use core::fmt;
8
9/// MBR partition type enumeration with comprehensive type definitions.
10///
11/// This enum represents the partition type field in MBR partition entries.
12/// Each variant corresponds to a specific file system type or partition purpose
13/// as defined by the standard PC partition type IDs.
14///
15/// # Standard Partition Types
16///
17/// ## FAT File Systems
18/// - [`PartitionKind::Fat12`] - FAT12 file system (floppy disks, small partitions)
19/// - [`PartitionKind::Fat16`] - FAT16 file system
20/// - [`PartitionKind::Fat16Small`] - FAT16 for partitions < 32MB
21/// - [`PartitionKind::Fat32`] - FAT32 file system
22/// - [`PartitionKind::Fat32Lba`] - FAT32 with LBA addressing (recommended)
23///
24/// ## Extended Partitions
25/// - [`PartitionKind::Extended`] - Extended partition (CHS addressing)
26/// - [`PartitionKind::ExtendedLba`] - Extended partition (LBA addressing)
27///
28/// ## Linux File Systems
29/// - [`PartitionKind::Linux`] - Linux native partition (typically ext2/3/4)
30/// - [`PartitionKind::LinuxSwap`] - Linux swap partition
31/// - [`PartitionKind::LinuxLvm`] - Linux LVM (Logical Volume Manager)
32///
33/// ## Other File Systems
34/// - [`PartitionKind::NtfsExfat`] - NTFS or exFAT file system
35/// - [`PartitionKind::EfiSystem`] - EFI System Partition
36/// - [`PartitionKind::GptProtective`] - GPT protective partition
37///
38/// # Examples
39///
40/// ```rust
41/// use file_system::*;
42///
43/// let partition_type = Partition_type_type::Fat32_lba;
44/// assert!(partition_type.is_fat());
45/// assert!(!partition_type.is_extended());
46///
47/// let linux_type = Partition_type_type::From_u8(0x83);
48/// assert_eq!(linux_type, Partition_type_type::Linux);
49/// ```
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[repr(u8)]
52pub enum PartitionKind {
53    /// Empty/unused partition slot
54    Empty = 0x00,
55    /// FAT12 file system
56    Fat12 = 0x01,
57    /// FAT16 file system (small partitions < 32MB)
58    Fat16Small = 0x04,
59    /// Extended partition (CHS addressing)
60    Extended = 0x05,
61    /// FAT16 file system
62    Fat16 = 0x06,
63    /// NTFS or exFAT file system
64    NtfsExfat = 0x07,
65    /// FAT32 file system (CHS addressing)
66    Fat32 = 0x0B,
67    /// FAT32 file system (LBA addressing - recommended)
68    Fat32Lba = 0x0C,
69    /// FAT16 file system (LBA addressing)
70    Fat16Lba = 0x0E,
71    /// Extended partition (LBA addressing)
72    ExtendedLba = 0x0F,
73    /// Hidden FAT12 partition
74    HiddenFat12 = 0x11,
75    /// Hidden FAT16 partition (small)
76    HiddenFat16Small = 0x14,
77    /// Hidden FAT16 partition
78    HiddenFat16 = 0x16,
79    /// Hidden NTFS/exFAT partition
80    HiddenNtfsExfat = 0x17,
81    /// Hidden FAT32 partition
82    HiddenFat32 = 0x1B,
83    /// Hidden FAT32 partition (LBA addressing)
84    HiddenFat32Lba = 0x1C,
85    /// Hidden FAT16 partition (LBA addressing)
86    HiddenFat16Lba = 0x1E,
87    /// Linux swap partition
88    LinuxSwap = 0x82,
89    /// Linux native partition (typically ext2/3/4)
90    Linux = 0x83,
91    /// Linux LVM (Logical Volume Manager)
92    LinuxLvm = 0x8E,
93    /// GPT protective partition (indicates GPT, not MBR)
94    GptProtective = 0xEE,
95    /// EFI System Partition
96    EfiSystem = 0xEF,
97    /// Xila
98    Xila = 0xDA,
99    /// Unknown or custom partition type
100    Unknown(u8),
101}
102
103impl PartitionKind {
104    /// Create a partition type from a raw u8 value.
105    ///
106    /// This function maps standard partition type IDs to their corresponding
107    /// enum variants. Unknown types are wrapped in [`PartitionKind::Unknown`].
108    ///
109    /// # Arguments
110    ///
111    /// * `Value` - The raw partition type ID from the MBR partition entry
112    ///
113    /// # Returns
114    ///
115    /// The corresponding partition type enum variant.
116    ///
117    /// # Examples
118    ///
119    /// ```rust
120    /// use file_system::*;
121    ///
122    /// assert_eq!(Partition_type_type::From_u8(0x0C), Partition_type_type::Fat32_lba);
123    /// assert_eq!(Partition_type_type::From_u8(0x83), Partition_type_type::Linux);
124    ///
125    /// // Unknown types are preserved
126    /// if let Partition_type_type::Unknown(id) = Partition_type_type::From_u8(0xFF) {
127    ///     assert_eq!(id, 0xFF);
128    /// }
129    /// ```
130    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    /// Convert the partition type to its raw u8 value
160    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    /// Get the human-readable name of the partition type
190    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    /// Check if this partition type is a FAT filesystem
220    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    /// Check if this partition type is hidden
239    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    /// Check if this partition type is an extended partition
253    pub fn is_extended(&self) -> bool {
254        matches!(self, PartitionKind::Extended | PartitionKind::ExtendedLba)
255    }
256
257    /// Check if this partition type is Linux-related
258    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        // Test FAT detection
314        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        // Test hidden detection
323        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        // Test extended detection
330        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        // Test Linux detection
336        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}