file_system/fundamentals/
type.rs

1//! File system object type definitions.
2//!
3//! This module provides the [`Type_type`] enumeration which categorizes different
4//! types of objects that can exist in a file system, such as regular files,
5//! directories, devices, and special file types.
6
7use core::fmt::Display;
8
9/// Enumeration of file system object types.
10///
11/// This enum represents the different types of objects that can exist in a file system.
12/// Each variant corresponds to a specific type of file system entity with its own
13/// characteristics and behaviors.
14///
15/// # Examples
16///
17/// ```rust
18/// use file_system::Type_type;
19///
20/// let file_type = Type_type::File;
21/// let dir_type = Type_type::Directory;
22///
23/// // Types can be compared
24/// assert_ne!(file_type, dir_type);
25///
26/// // Types can be displayed
27/// println!("Object type: {}", file_type); // Prints "Object type: File"
28/// ```
29#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
30#[repr(u8)]
31pub enum Kind {
32    /// Regular file containing data
33    File,
34    /// Directory containing other file system objects
35    Directory,
36    /// Block-oriented device (e.g., disk drives, storage devices)
37    BlockDevice,
38    /// Character-oriented device (e.g., terminals, serial ports)
39    CharacterDevice,
40    /// Named pipe (FIFO) for inter-process communication
41    Pipe,
42    /// Unix domain socket for inter-process communication
43    Socket,
44    /// Symbolic link pointing to another file system object
45    SymbolicLink,
46}
47
48impl Display for Kind {
49    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
50        let type_value = match self {
51            Kind::File => "File",
52            Kind::Directory => "Directory",
53            Kind::BlockDevice => "Block device",
54            Kind::CharacterDevice => "Character device",
55            Kind::Pipe => "Pipe",
56            Kind::Socket => "Socket",
57            Kind::SymbolicLink => "Symbolic link",
58        };
59
60        write!(f, "{type_value}")
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use alloc::format;
68
69    #[test]
70    fn test_type_variants() {
71        // Test that all variants can be created
72        let file = Kind::File;
73        let directory = Kind::Directory;
74        let block_device = Kind::BlockDevice;
75        let character_device = Kind::CharacterDevice;
76        let pipe = Kind::Pipe;
77        let socket = Kind::Socket;
78        let symbolic_link = Kind::SymbolicLink;
79
80        // Basic verification they're different
81        assert_ne!(file, directory);
82        assert_ne!(directory, block_device);
83        assert_ne!(block_device, character_device);
84        assert_ne!(character_device, pipe);
85        assert_ne!(pipe, socket);
86        assert_ne!(socket, symbolic_link);
87    }
88
89    #[test]
90    fn test_type_equality() {
91        let file1 = Kind::File;
92        let file2 = Kind::File;
93        let directory = Kind::Directory;
94
95        assert_eq!(file1, file2);
96        assert_ne!(file1, directory);
97    }
98
99    #[test]
100    fn test_type_clone_copy() {
101        let original = Kind::File;
102        let cloned = original;
103        let copied = original;
104
105        assert_eq!(original, cloned);
106        assert_eq!(original, copied);
107        assert_eq!(cloned, copied);
108    }
109
110    #[test]
111    fn test_type_debug() {
112        let file_type = Kind::File;
113        let debug_str = format!("{file_type:?}");
114        assert_eq!(debug_str, "File");
115
116        let directory_type = Kind::Directory;
117        let debug_str = format!("{directory_type:?}");
118        assert_eq!(debug_str, "Directory");
119    }
120
121    #[test]
122    fn test_type_display() {
123        assert_eq!(format!("{}", Kind::File), "File");
124        assert_eq!(format!("{}", Kind::Directory), "Directory");
125        assert_eq!(format!("{}", Kind::BlockDevice), "Block device");
126        assert_eq!(format!("{}", Kind::CharacterDevice), "Character device");
127        assert_eq!(format!("{}", Kind::Pipe), "Pipe");
128        assert_eq!(format!("{}", Kind::Socket), "Socket");
129        assert_eq!(format!("{}", Kind::SymbolicLink), "Symbolic link");
130    }
131
132    #[test]
133    fn test_type_repr() {
134        // Test that the enum has a specific memory representation
135        use core::mem::size_of;
136
137        // Should be 1 byte due to repr(u8)
138        assert_eq!(size_of::<Kind>(), 1);
139    }
140
141    #[test]
142    fn test_type_discriminants() {
143        // Test that different variants have different discriminants
144        let file = Kind::File as u8;
145        let directory = Kind::Directory as u8;
146        let block_device = Kind::BlockDevice as u8;
147        let character_device = Kind::CharacterDevice as u8;
148        let pipe = Kind::Pipe as u8;
149        let socket = Kind::Socket as u8;
150        let symbolic_link = Kind::SymbolicLink as u8;
151
152        // All should be different
153        let discriminants = [
154            file,
155            directory,
156            block_device,
157            character_device,
158            pipe,
159            socket,
160            symbolic_link,
161        ];
162
163        for i in 0..discriminants.len() {
164            for j in i + 1..discriminants.len() {
165                assert_ne!(
166                    discriminants[i], discriminants[j],
167                    "Discriminants {i} and {j} should be different"
168                );
169            }
170        }
171    }
172
173    #[test]
174    fn test_type_pattern_matching() {
175        let file_type = Kind::File;
176
177        let description = match file_type {
178            Kind::File => "regular file",
179            Kind::Directory => "directory",
180            Kind::BlockDevice => "block device",
181            Kind::CharacterDevice => "character device",
182            Kind::Pipe => "pipe",
183            Kind::Socket => "socket",
184            Kind::SymbolicLink => "symbolic link",
185        };
186
187        assert_eq!(description, "regular file");
188    }
189
190    #[test]
191    fn test_type_all_variants_pattern_matching() {
192        let types = [
193            Kind::File,
194            Kind::Directory,
195            Kind::BlockDevice,
196            Kind::CharacterDevice,
197            Kind::Pipe,
198            Kind::Socket,
199            Kind::SymbolicLink,
200        ];
201
202        for type_variant in types.iter() {
203            // Test that each variant can be matched
204            let _matched = match type_variant {
205                Kind::File => "file",
206                Kind::Directory => "directory",
207                Kind::BlockDevice => "block",
208                Kind::CharacterDevice => "char",
209                Kind::Pipe => "pipe",
210                Kind::Socket => "socket",
211                Kind::SymbolicLink => "symlink",
212            };
213        }
214    }
215
216    #[test]
217    fn test_type_in_collections() {
218        let types = [Kind::File, Kind::Directory, Kind::SymbolicLink];
219
220        assert_eq!(types.len(), 3);
221        assert_eq!(types[0], Kind::File);
222        assert_eq!(types[1], Kind::Directory);
223        assert_eq!(types[2], Kind::SymbolicLink);
224    }
225
226    #[test]
227    fn test_type_is_specific_type() {
228        // Helper functions that might be useful
229        fn is_file(t: Kind) -> bool {
230            matches!(t, Kind::File)
231        }
232
233        fn is_directory(t: Kind) -> bool {
234            matches!(t, Kind::Directory)
235        }
236
237        fn is_device(t: Kind) -> bool {
238            matches!(t, Kind::BlockDevice | Kind::CharacterDevice)
239        }
240
241        assert!(is_file(Kind::File));
242        assert!(!is_file(Kind::Directory));
243
244        assert!(is_directory(Kind::Directory));
245        assert!(!is_directory(Kind::File));
246
247        assert!(is_device(Kind::BlockDevice));
248        assert!(is_device(Kind::CharacterDevice));
249        assert!(!is_device(Kind::File));
250    }
251
252    #[test]
253    fn test_type_default_behavior() {
254        // Test that we can use Type_type in various contexts
255        let mut type_counts = alloc::collections::BTreeMap::new();
256
257        let types = [
258            Kind::File,
259            Kind::File,
260            Kind::Directory,
261            Kind::File,
262            Kind::SymbolicLink,
263        ];
264
265        for t in types.iter() {
266            *type_counts.entry(*t).or_insert(0) += 1;
267        }
268
269        assert_eq!(type_counts[&Kind::File], 3);
270        assert_eq!(type_counts[&Kind::Directory], 1);
271        assert_eq!(type_counts[&Kind::SymbolicLink], 1);
272    }
273}