file_system/fundamentals/
attributes.rs1use crate::{Inode, Kind, Permissions, Size, Time};
2use core::fmt::Debug;
3use shared::flags;
4use users::{GroupIdentifier, UserIdentifier};
5
6flags! {
7 pub enum AttributeFlags: u16 {
9 Inode,
10 Kind,
11 Size,
12 Links,
13 CreationTime,
14 ModificationTime,
15 AccessTime,
16 StatusTime,
17 Permissions,
18 User,
19 Group,
20 }
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct Attributes {
35 inode: Inode,
37 kind: Kind,
39 size: Size,
41 links: Size,
43 status: Time,
45 modification: Time,
47 access: Time,
49 creation: Time,
51 permissions: Permissions,
53 user: UserIdentifier,
55 group: GroupIdentifier,
57 mask: AttributeFlags,
59}
60
61macro_rules! generate_attribute_accessors {
63 ($getter:ident, $mutable_getter:ident, $setter:ident, $field:ident, $field_type:ty, $mask_flag:expr) => {
64 pub fn $getter(&self) -> Option<&$field_type> {
65 Self::get(&self.$field, self.mask, $mask_flag)
66 }
67
68 pub fn $mutable_getter(&mut self) -> Option<&mut $field_type> {
69 Self::get_mutable(&mut self.$field, self.mask, $mask_flag)
70 }
71
72 pub fn $setter(mut self, $field: $field_type) -> Self {
73 self.mask = self.mask.insert($mask_flag);
74 self.$field = $field;
75
76 self
77 }
78 };
79}
80
81impl Default for Attributes {
82 fn default() -> Self {
83 Self::new()
84 }
85}
86
87impl Attributes {
88 pub const fn new() -> Self {
89 Attributes {
90 inode: 0,
91 kind: Kind::File,
92 size: 0,
93 links: 0,
94 creation: Time::new(0),
95 status: Time::new(0),
96 modification: Time::new(0),
97 access: Time::new(0),
98 permissions: Permissions::NONE,
99 user: UserIdentifier::ROOT,
100 group: GroupIdentifier::ROOT,
101 mask: AttributeFlags::None,
102 }
103 }
104
105 fn get<T>(field: &T, instance_mask: AttributeFlags, field_mask: AttributeFlags) -> Option<&T> {
106 if instance_mask.contains(field_mask) {
107 Some(field)
108 } else {
109 None
110 }
111 }
112
113 fn get_mutable<T>(
114 field: &mut T,
115 instance_mask: AttributeFlags,
116 field_mask: AttributeFlags,
117 ) -> Option<&mut T> {
118 if instance_mask.contains(field_mask) {
119 Some(field)
120 } else {
121 None
122 }
123 }
124
125 pub fn get_mask(&self) -> AttributeFlags {
126 self.mask
127 }
128
129 pub fn set_mask(mut self, mask: AttributeFlags) -> Self {
130 self.mask = mask;
131 self
132 }
133
134 generate_attribute_accessors!(
135 get_inode,
136 get_mutable_inode,
137 set_inode,
138 inode,
139 Inode,
140 AttributeFlags::Inode
141 );
142 generate_attribute_accessors!(
143 get_size,
144 get_mutable_size,
145 set_size,
146 size,
147 Size,
148 AttributeFlags::Size
149 );
150 generate_attribute_accessors!(
151 get_kind,
152 get_mutable_kind,
153 set_kind,
154 kind,
155 Kind,
156 AttributeFlags::Kind
157 );
158 generate_attribute_accessors!(
159 get_permissions,
160 get_mutable_permissions,
161 set_permissions,
162 permissions,
163 Permissions,
164 AttributeFlags::Permissions
165 );
166 generate_attribute_accessors!(
167 get_user,
168 get_mutable_user,
169 set_user,
170 user,
171 UserIdentifier,
172 AttributeFlags::User
173 );
174 generate_attribute_accessors!(
175 get_group,
176 get_mutable_group,
177 set_group,
178 group,
179 GroupIdentifier,
180 AttributeFlags::Group
181 );
182 generate_attribute_accessors!(
183 get_creation,
184 get_mutable_creation,
185 set_creation,
186 creation,
187 Time,
188 AttributeFlags::CreationTime
189 );
190 generate_attribute_accessors!(
191 get_modification,
192 get_mutable_modification,
193 set_modification,
194 modification,
195 Time,
196 AttributeFlags::ModificationTime
197 );
198 generate_attribute_accessors!(
199 get_access,
200 get_mutable_access,
201 set_access,
202 access,
203 Time,
204 AttributeFlags::AccessTime
205 );
206 generate_attribute_accessors!(
207 get_status,
208 get_mutable_status,
209 set_status,
210 status,
211 Time,
212 AttributeFlags::StatusTime
213 );
214 generate_attribute_accessors!(
215 get_links,
216 get_mutable_links,
217 set_links,
218 links,
219 Size,
220 AttributeFlags::Links
221 );
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227 extern crate std;
228
229 #[test]
230 fn test_attributes_new() {
231 let attrs = Attributes::new();
232 assert_eq!(attrs.inode, 0);
233 assert_eq!(attrs.kind, Kind::File);
234 assert_eq!(attrs.size, 0);
235 assert_eq!(attrs.links, 0);
236 assert_eq!(attrs.permissions, Permissions::NONE);
237 assert_eq!(attrs.user, UserIdentifier::ROOT);
238 assert_eq!(attrs.group, GroupIdentifier::ROOT);
239 assert_eq!(attrs.mask, AttributeFlags::None);
240 }
241
242 #[test]
243 fn test_attributes_default() {
244 let attrs = Attributes::default();
245 assert_eq!(attrs, Attributes::new());
246 }
247
248 #[test]
249 fn test_attributes_set_and_get_inode() {
250 let attrs = Attributes::new().set_inode(42);
251 assert_eq!(attrs.get_inode(), Some(&42));
252 assert!(attrs.mask.contains(AttributeFlags::Inode));
253 }
254
255 #[test]
256 fn test_attributes_set_and_get_size() {
257 let attrs = Attributes::new().set_size(1024);
258 assert_eq!(attrs.get_size(), Some(&1024));
259 assert!(attrs.mask.contains(AttributeFlags::Size));
260 }
261
262 #[test]
263 fn test_attributes_set_and_get_kind() {
264 let attrs = Attributes::new().set_kind(Kind::Directory);
265 assert_eq!(attrs.get_kind(), Some(&Kind::Directory));
266 assert!(attrs.mask.contains(AttributeFlags::Kind));
267 }
268
269 #[test]
270 fn test_attributes_set_and_get_permissions() {
271 let perms = Permissions::USER_READ_WRITE;
272 let attrs = Attributes::new().set_permissions(perms);
273 assert_eq!(attrs.get_permissions(), Some(&perms));
274 assert!(attrs.mask.contains(AttributeFlags::Permissions));
275 }
276
277 #[test]
278 fn test_attributes_set_and_get_user() {
279 let user = UserIdentifier::new(1000);
280 let attrs = Attributes::new().set_user(user);
281 assert_eq!(attrs.get_user(), Some(&user));
282 assert!(attrs.mask.contains(AttributeFlags::User));
283 }
284
285 #[test]
286 fn test_attributes_set_and_get_group() {
287 let group = GroupIdentifier::new(1000);
288 let attrs = Attributes::new().set_group(group);
289 assert_eq!(attrs.get_group(), Some(&group));
290 assert!(attrs.mask.contains(AttributeFlags::Group));
291 }
292
293 #[test]
294 fn test_attributes_set_and_get_creation_time() {
295 let time = Time::new(123456);
296 let attrs = Attributes::new().set_creation(time);
297 assert_eq!(attrs.get_creation(), Some(&time));
298 assert!(attrs.mask.contains(AttributeFlags::CreationTime));
299 }
300
301 #[test]
302 fn test_attributes_set_and_get_modification_time() {
303 let time = Time::new(123456);
304 let attrs = Attributes::new().set_modification(time);
305 assert_eq!(attrs.get_modification(), Some(&time));
306 assert!(attrs.mask.contains(AttributeFlags::ModificationTime));
307 }
308
309 #[test]
310 fn test_attributes_set_and_get_access_time() {
311 let time = Time::new(123456);
312 let attrs = Attributes::new().set_access(time);
313 assert_eq!(attrs.get_access(), Some(&time));
314 assert!(attrs.mask.contains(AttributeFlags::AccessTime));
315 }
316
317 #[test]
318 fn test_attributes_set_and_get_status_time() {
319 let time = Time::new(123456);
320 let attrs = Attributes::new().set_status(time);
321 assert_eq!(attrs.get_status(), Some(&time));
322 assert!(attrs.mask.contains(AttributeFlags::StatusTime));
323 }
324
325 #[test]
326 fn test_attributes_set_and_get_links() {
327 let attrs = Attributes::new().set_links(5);
328 assert_eq!(attrs.get_links(), Some(&5));
329 assert!(attrs.mask.contains(AttributeFlags::Links));
330 }
331
332 #[test]
333 fn test_attributes_get_returns_none_when_not_set() {
334 let attrs = Attributes::new();
335 assert_eq!(attrs.get_inode(), None);
336 assert_eq!(attrs.get_size(), None);
337 assert_eq!(attrs.get_kind(), None);
338 assert_eq!(attrs.get_permissions(), None);
339 assert_eq!(attrs.get_user(), None);
340 assert_eq!(attrs.get_group(), None);
341 assert_eq!(attrs.get_creation(), None);
342 assert_eq!(attrs.get_modification(), None);
343 assert_eq!(attrs.get_access(), None);
344 assert_eq!(attrs.get_status(), None);
345 assert_eq!(attrs.get_links(), None);
346 }
347
348 #[test]
349 fn test_attributes_mutable_getter() {
350 let mut attrs = Attributes::new().set_inode(42);
351
352 if let Some(inode) = attrs.get_mutable_inode() {
353 *inode = 100;
354 }
355
356 assert_eq!(attrs.get_inode(), Some(&100));
357 }
358
359 #[test]
360 fn test_attributes_mutable_getter_returns_none() {
361 let mut attrs = Attributes::new();
362 assert!(attrs.get_mutable_inode().is_none());
363 }
364
365 #[test]
366 fn test_attributes_set_mask() {
367 let mask = AttributeFlags::Inode | AttributeFlags::Size;
368 let attrs = Attributes::new().set_mask(mask);
369 assert_eq!(attrs.get_mask(), mask);
370 }
371
372 #[test]
373 fn test_attributes_chaining_setters() {
374 let attrs = Attributes::new()
375 .set_inode(42)
376 .set_size(1024)
377 .set_kind(Kind::Directory)
378 .set_permissions(Permissions::USER_FULL);
379
380 assert_eq!(attrs.get_inode(), Some(&42));
381 assert_eq!(attrs.get_size(), Some(&1024));
382 assert_eq!(attrs.get_kind(), Some(&Kind::Directory));
383 assert_eq!(attrs.get_permissions(), Some(&Permissions::USER_FULL));
384
385 assert!(attrs.mask.contains(AttributeFlags::Inode));
386 assert!(attrs.mask.contains(AttributeFlags::Size));
387 assert!(attrs.mask.contains(AttributeFlags::Kind));
388 assert!(attrs.mask.contains(AttributeFlags::Permissions));
389 }
390
391 #[test]
392 fn test_attributes_clone() {
393 let attrs1 = Attributes::new().set_inode(42).set_size(1024);
394 let attrs2 = attrs1.clone();
395
396 assert_eq!(attrs1, attrs2);
397 assert_eq!(attrs2.get_inode(), Some(&42));
398 assert_eq!(attrs2.get_size(), Some(&1024));
399 }
400
401 #[test]
402 fn test_attributes_partial_eq() {
403 let attrs1 = Attributes::new().set_inode(42);
404 let attrs2 = Attributes::new().set_inode(42);
405 let attrs3 = Attributes::new().set_inode(43);
406
407 assert_eq!(attrs1, attrs2);
408 assert_ne!(attrs1, attrs3);
409 }
410}