file_system/fundamentals/
type.rs1use core::fmt::Display;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
30#[repr(u8)]
31pub enum Kind {
32 File,
34 Directory,
36 BlockDevice,
38 CharacterDevice,
40 Pipe,
42 Socket,
44 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 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 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 use core::mem::size_of;
136
137 assert_eq!(size_of::<Kind>(), 1);
139 }
140
141 #[test]
142 fn test_type_discriminants() {
143 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 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 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 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 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}