file_system/fundamentals/
attributes.rs

1use crate::{Inode, Kind, Permissions, Size, Time};
2use core::fmt::Debug;
3use shared::flags;
4use users::{GroupIdentifier, UserIdentifier};
5
6flags! {
7    /// Flags for file creation.
8    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/// File attributes.
24///
25/// The attributes are metadata associated with the file that stores:
26/// - The file type.
27/// - The file creation time.
28/// - The file modification time.
29/// - The file access time.
30/// - The file permissions.
31/// - The file owner.
32/// - The file group.
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct Attributes {
35    /// The file inode.
36    inode: Inode,
37    /// The file type.
38    kind: Kind,
39    /// Size
40    size: Size,
41    /// Links
42    links: Size,
43    /// The file status change time.
44    status: Time,
45    /// The file modification time.
46    modification: Time,
47    /// The file access time.
48    access: Time,
49    /// The file creation time.
50    creation: Time,
51    /// The file permissions.
52    permissions: Permissions,
53    /// The file owner.
54    user: UserIdentifier,
55    /// The file group.
56    group: GroupIdentifier,
57    /// Mask
58    mask: AttributeFlags,
59}
60
61/// Macro to generate getter, mutable getter, and setter methods for Attributes fields
62macro_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}