file_system/fundamentals/
flags.rs

1use core::fmt::Debug;
2
3use super::Permission;
4
5/// The mode of a file.
6///
7/// The mode is stored in a 8-bit integer, with the following layout:
8///
9/// | Read | Write |
10/// |------|-------|
11/// | 0    | 1     |
12///
13/// # Example
14///
15/// ```rust
16/// use file_system::Mode_type;
17///
18/// let mode = Mode_type::new(true, false);
19///
20/// assert_eq!(mode.get_read(), true);
21/// assert_eq!(mode.get_write(), false);
22///
23/// let mode = Mode_type::new(false, true);
24///
25/// assert_eq!(mode.get_read(), false);
26/// assert_eq!(mode.get_write(), true);
27///
28/// let mode = Mode_type::new(true, true);
29///
30/// assert_eq!(mode.get_read(), true);
31/// assert_eq!(mode.get_write(), true);
32/// ```
33#[derive(PartialEq, Eq, Clone, Copy)]
34#[repr(transparent)]
35pub struct Mode(u8);
36
37impl Mode {
38    pub const READ_BIT: u8 = 1 << 0;
39    pub const WRITE_BIT: u8 = 1 << 1;
40
41    pub const SIZE: u8 = 2;
42
43    pub const READ_ONLY: Self = Self::new(true, false);
44    pub const WRITE_ONLY: Self = Self::new(false, true);
45    pub const READ_WRITE: Self = Self::new(true, true);
46
47    pub const fn new(read: bool, write: bool) -> Self {
48        Self(0).set_read(read).set_write(write)
49    }
50
51    pub const fn set_bit(mut self, mask: u8, value: bool) -> Self {
52        if value {
53            self.0 |= mask;
54        } else {
55            self.0 &= !mask;
56        }
57        self
58    }
59
60    pub const fn set_read(self, value: bool) -> Self {
61        self.set_bit(Self::READ_BIT, value)
62    }
63
64    pub const fn set_write(self, value: bool) -> Self {
65        self.set_bit(Self::WRITE_BIT, value)
66    }
67
68    pub const fn get_bit(&self, mask: u8) -> bool {
69        self.0 & mask != 0
70    }
71
72    pub const fn get_read(&self) -> bool {
73        self.get_bit(Self::READ_BIT)
74    }
75
76    pub const fn get_write(&self) -> bool {
77        self.get_bit(Self::WRITE_BIT)
78    }
79
80    pub const fn from_u8(value: u8) -> Self {
81        Self(value)
82    }
83
84    pub const fn as_u8(&self) -> u8 {
85        self.0
86    }
87}
88
89impl Debug for Mode {
90    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91        formatter
92            .debug_struct("Mode_type")
93            .field("Read", &self.get_read())
94            .field("Write", &self.get_write())
95            .finish()
96    }
97}
98
99/// The type of opening a file.
100///
101/// The type is stored in a 8-bit integer, with the following layout:
102///
103/// | Create | Create exclusive | Truncate | Directory |
104/// |--------|------------------|----------|-----------|
105/// | 0      | 1                | 2        | 3         |
106///
107/// # Example
108///
109/// ```rust
110/// use file_system::Open_type;
111///
112/// let open = Open_type::new(true, true, false);
113///
114/// assert_eq!(open.get_create(), true);
115/// assert_eq!(open.get_exclusive(), true);
116/// assert_eq!(open.get_truncate(), false);
117/// ```
118#[derive(PartialEq, Eq, Clone, Copy)]
119#[repr(transparent)]
120pub struct Open(u8);
121
122impl Open {
123    pub const CREATE_MASK: u8 = 1 << 0;
124    pub const EXCLUSIVE_MASK: u8 = 1 << 1;
125    pub const TRUNCATE_MASK: u8 = 1 << 2;
126
127    pub const SIZE: u8 = 3;
128
129    pub const NONE: Self = Self::new(false, false, false);
130
131    pub const CREATE: Self = Self::new(true, false, false);
132    pub const CREATE_ONLY: Self = Self::new(true, true, false);
133    pub const TRUNCATE: Self = Self::new(false, false, true);
134
135    pub const fn new(create: bool, create_only: bool, truncate: bool) -> Self {
136        Self(0)
137            .set_create(create)
138            .set_exclusive(create_only)
139            .set_truncate(truncate)
140    }
141
142    pub const fn get_bit(&self, mask: u8) -> bool {
143        self.0 & mask != 0
144    }
145
146    pub const fn set_bit(mut self, mask: u8, value: bool) -> Self {
147        if value {
148            self.0 |= mask;
149        } else {
150            self.0 &= !mask;
151        }
152        self
153    }
154
155    pub const fn get_create(&self) -> bool {
156        self.get_bit(Self::CREATE_MASK)
157    }
158
159    pub const fn set_create(self, value: bool) -> Self {
160        self.set_bit(Self::CREATE_MASK, value)
161    }
162
163    pub const fn get_exclusive(&self) -> bool {
164        self.get_bit(Self::EXCLUSIVE_MASK)
165    }
166
167    pub const fn set_exclusive(self, value: bool) -> Self {
168        self.set_bit(Self::EXCLUSIVE_MASK, value)
169    }
170
171    pub const fn get_truncate(&self) -> bool {
172        self.get_bit(Self::TRUNCATE_MASK)
173    }
174
175    pub const fn set_truncate(self, value: bool) -> Self {
176        self.set_bit(Self::TRUNCATE_MASK, value)
177    }
178
179    pub const fn from_u8(value: u8) -> Self {
180        Self(value)
181    }
182}
183
184impl Default for Open {
185    fn default() -> Self {
186        Self::NONE
187    }
188}
189
190impl Debug for Open {
191    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
192        formatter
193            .debug_struct("Open_type")
194            .field("Create", &self.get_create())
195            .field("Create_only", &self.get_exclusive())
196            .field("Truncate", &self.get_truncate())
197            .finish()
198    }
199}
200
201/// The status of a file.
202///
203/// The status is stored in a 8-bit integer, with the following layout:
204///
205/// | Append | Non-blocking | Synchronous | Synchronous data only |
206///  -------------------------------------------------------------
207/// | 0      | 1            | 2           | 3                     |
208///
209/// # Example
210///
211/// ```rust
212/// use file_system::Status_type;
213///
214/// let status = Status_type::new(true, false, true, false);
215///
216/// assert_eq!(status.get_append(), true);
217/// assert_eq!(status.get_non_blocking(), false);
218/// assert_eq!(status.get_synchronous(), true);
219/// assert_eq!(status.get_synchronous_data_only(), false);
220/// ```
221#[derive(PartialEq, Eq, Clone, Copy)]
222#[repr(transparent)]
223pub struct Status(u8);
224
225impl Status {
226    pub const APPEND_BIT: u8 = 1 << 0;
227    pub const NON_BLOCKING_BIT: u8 = 1 << 1;
228    pub const SYNCHRONOUS_BIT: u8 = 1 << 2;
229    pub const SYNCHRONOUS_DATA_ONLY_BIT: u8 = 1 << 3;
230
231    pub const SIZE: u8 = 4;
232
233    pub const NON_BLOCKING: Self = Self::new(false, true, false, false);
234
235    pub const NONE: Self = Self::new(false, false, false, false);
236
237    pub const fn new(
238        append: bool,
239        non_blocking: bool,
240        synchronous: bool,
241        synchronous_data_only: bool,
242    ) -> Self {
243        Self(0)
244            .set_append(append)
245            .set_non_blocking(non_blocking)
246            .set_synchronous(synchronous)
247            .set_synchronous_data_only(synchronous_data_only)
248    }
249
250    const fn set_bit(mut self, mask: u8, value: bool) -> Self {
251        if value {
252            self.0 |= mask;
253        } else {
254            self.0 &= !mask;
255        }
256        self
257    }
258
259    const fn get_bit(&self, mask: u8) -> bool {
260        self.0 & mask != 0
261    }
262
263    pub const fn set_non_blocking(self, value: bool) -> Self {
264        self.set_bit(Self::NON_BLOCKING_BIT, value)
265    }
266
267    pub fn get_non_blocking(&self) -> bool {
268        self.get_bit(Self::NON_BLOCKING_BIT)
269    }
270
271    pub const fn set_append(self, value: bool) -> Self {
272        self.set_bit(Self::APPEND_BIT, value)
273    }
274
275    pub const fn get_append(&self) -> bool {
276        self.get_bit(Self::APPEND_BIT)
277    }
278
279    pub const fn set_synchronous(self, value: bool) -> Self {
280        self.set_bit(Self::SYNCHRONOUS_BIT, value)
281    }
282
283    pub const fn get_synchronous(&self) -> bool {
284        self.get_bit(Self::SYNCHRONOUS_BIT)
285    }
286
287    pub const fn set_synchronous_data_only(self, value: bool) -> Self {
288        self.set_bit(Self::SYNCHRONOUS_DATA_ONLY_BIT, value)
289    }
290
291    pub const fn get_synchronous_data_only(&self) -> bool {
292        self.get_bit(Self::SYNCHRONOUS_DATA_ONLY_BIT)
293    }
294
295    pub const fn from_u8(value: u8) -> Self {
296        Self(value)
297    }
298}
299
300impl Debug for Status {
301    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
302        formatter
303            .debug_struct("Status_type")
304            .field("Append", &self.get_append())
305            .field("Non_blocking", &self.get_non_blocking())
306            .field("Synchronous", &self.get_bit(Self::SYNCHRONOUS_BIT))
307            .field(
308                "Synchronous_data_only",
309                &self.get_bit(Self::SYNCHRONOUS_DATA_ONLY_BIT),
310            )
311            .finish()
312    }
313}
314
315impl Default for Status {
316    fn default() -> Self {
317        Self::NONE
318    }
319}
320
321/// All the flags that can be set for a file.
322///
323/// The flags are stored in a 16-bit integer, with the following layout:
324///
325/// | Mode | Open | Status |
326/// |------|------|--------|
327/// | 0-1  | 2-5  | 6-9    |
328///
329/// # Example
330///
331/// ```rust
332/// use file_system::{Flags_type, Mode_type, Open_type, Status_type};
333///     
334/// let flags = Flags_type::new(Mode_type::Read_write, Some(Open_type::Create_only), Some(Status_type::Non_blocking));
335///
336/// assert_eq!(flags.get_mode(), Mode_type::Read_write);
337/// assert_eq!(flags.get_open(), Open_type::Create_only);
338/// assert_eq!(flags.get_status(), Status_type::Non_blocking);
339/// ```
340#[derive(PartialEq, Eq, Clone, Copy)]
341#[repr(transparent)]
342pub struct Flags(u16);
343
344impl Debug for Flags {
345    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
346        formatter
347            .debug_struct("Flags_type")
348            .field("Mode", &self.get_mode())
349            .field("Open", &self.get_open())
350            .field("Status", &self.get_status())
351            .finish()
352    }
353}
354
355impl Flags {
356    const MODE_POSITION: u8 = 0;
357    const OPEN_POSITION: u8 = Mode::SIZE;
358    const STATUS_POSITION: u8 = Open::SIZE + Self::OPEN_POSITION;
359
360    const OPEN_MASK: u16 = (1 << Open::SIZE) - 1;
361    const STATUS_MASK: u16 = (1 << Status::SIZE) - 1;
362    const MODE_MASK: u16 = (1 << Mode::SIZE) - 1;
363
364    pub const fn new(mode: Mode, open: Option<Open>, status: Option<Status>) -> Self {
365        let open = if let Some(open_val) = open {
366            open_val
367        } else {
368            Open::NONE
369        };
370        let status = if let Some(status_val) = status {
371            status_val
372        } else {
373            Status::NONE
374        };
375
376        let mut flags: u16 = 0;
377        flags |= (mode.0 as u16) << Self::MODE_POSITION;
378        flags |= (open.0 as u16) << Self::OPEN_POSITION;
379        flags |= (status.0 as u16) << Self::STATUS_POSITION;
380        Self(flags)
381    }
382
383    pub const fn get_mode(&self) -> Mode {
384        Mode(((self.0 >> Self::MODE_POSITION) & Self::MODE_MASK) as u8)
385    }
386
387    pub const fn get_open(&self) -> Open {
388        Open(((self.0 >> Self::OPEN_POSITION) & Self::OPEN_MASK) as u8)
389    }
390
391    pub const fn get_status(&self) -> Status {
392        Status(((self.0 >> Self::STATUS_POSITION) & Self::STATUS_MASK) as u8)
393    }
394
395    pub const fn set_mode(mut self, mode: Mode) -> Self {
396        self.0 &= !(Self::MODE_MASK << Self::MODE_POSITION);
397        self.0 |= (mode.0 as u16) << Self::MODE_POSITION;
398        self
399    }
400
401    pub const fn set_open(mut self, open: Open) -> Self {
402        self.0 &= !(Self::OPEN_MASK << Self::OPEN_POSITION);
403        self.0 |= (open.0 as u16) << Self::OPEN_POSITION;
404        self
405    }
406
407    pub const fn set_status(mut self, status: Status) -> Self {
408        self.0 &= !(Self::STATUS_MASK << Self::STATUS_POSITION);
409        self.0 |= (status.0 as u16) << Self::STATUS_POSITION;
410        self
411    }
412
413    pub fn is_permission_granted(&self, permission: &Permission) -> bool {
414        let mode = self.get_mode();
415
416        (permission.get_read() && mode.get_read()) // Read permission
417            || (permission.get_write() && (mode.get_write() || self.get_status().get_append()))
418        // Write permission
419    }
420}
421
422impl From<Mode> for Flags {
423    fn from(mode: Mode) -> Self {
424        Self::new(mode, None, None)
425    }
426}
427
428impl From<Flags> for u16 {
429    fn from(flags: Flags) -> Self {
430        flags.0
431    }
432}
433
434#[cfg(test)]
435mod tests {
436    use super::*;
437
438    #[test]
439    fn test_mode_type_new() {
440        let read_only = Mode::new(true, false);
441        assert!(read_only.get_read());
442        assert!(!read_only.get_write());
443
444        let write_only = Mode::new(false, true);
445        assert!(!write_only.get_read());
446        assert!(write_only.get_write());
447
448        let read_write = Mode::new(true, true);
449        assert!(read_write.get_read());
450        assert!(read_write.get_write());
451    }
452
453    #[test]
454    fn test_mode_type_set_get() {
455        let mut mode = Mode(0);
456        mode = mode.set_read(true);
457        assert!(mode.get_read());
458        assert!(!mode.get_write());
459
460        mode = mode.set_write(true);
461        assert!(mode.get_read());
462        assert!(mode.get_write());
463
464        mode = mode.set_read(false);
465        assert!(!mode.get_read());
466        assert!(mode.get_write());
467    }
468
469    #[test]
470    fn test_open_type_new() {
471        let open = Open::new(true, false, true);
472        assert!(open.get_create());
473        assert!(!open.get_exclusive());
474        assert!(open.get_truncate());
475    }
476
477    #[test]
478    fn test_open_type_set_get() {
479        let mut open = Open(0);
480        open = open.set_create(true);
481        assert!(open.get_create());
482        assert!(!open.get_exclusive());
483
484        open = open.set_exclusive(true);
485        assert!(open.get_create());
486        assert!(open.get_exclusive());
487
488        open = open.set_truncate(true);
489        assert!(open.get_truncate());
490    }
491
492    #[test]
493    fn test_status_type_new() {
494        let status = Status::new(true, false, true, false);
495        assert!(status.get_append());
496        assert!(!status.get_non_blocking());
497        assert!(status.get_synchronous());
498        assert!(!status.get_synchronous_data_only());
499    }
500
501    #[test]
502    fn test_status_type_set_get() {
503        let mut status = Status(0);
504        status = status.set_append(true);
505        assert!(status.get_append());
506        assert!(!status.get_non_blocking());
507
508        status = status.set_non_blocking(true);
509        assert!(status.get_non_blocking());
510
511        status = status.set_synchronous(true);
512        assert!(status.get_synchronous());
513
514        status = status.set_synchronous_data_only(true);
515        assert!(status.get_synchronous_data_only());
516    }
517
518    #[test]
519    fn test_flags_type_new() {
520        let mode = Mode::READ_WRITE;
521        let open = Open::new(true, false, true);
522        let status = Status::new(true, false, true, false);
523
524        let flags = Flags::new(mode, Some(open), Some(status));
525        assert_eq!(flags.get_mode(), mode);
526        assert_eq!(flags.get_open(), open);
527        assert_eq!(flags.get_status(), status);
528    }
529
530    #[test]
531    fn test_flags_type_set_get() {
532        let flags = Flags::new(Mode::READ_ONLY, None, None);
533
534        let new_mode = Mode::WRITE_ONLY;
535        let flags = flags.set_mode(new_mode);
536        assert_eq!(flags.get_mode(), new_mode);
537
538        let new_open = Open::new(true, true, false);
539        let flags = flags.set_open(new_open);
540        assert_eq!(flags.get_open(), new_open);
541
542        let new_status = Status::new(false, true, false, true);
543        let flags = flags.set_status(new_status);
544        assert_eq!(flags.get_status(), new_status);
545    }
546
547    #[test]
548    fn test_flags_type_is_permission_granted() {
549        let mode = Mode::READ_WRITE;
550        let status = Status::new(true, false, false, false);
551        let flags = Flags::new(mode, None, Some(status));
552
553        assert!(flags.is_permission_granted(&Permission::READ_ONLY));
554        assert!(flags.is_permission_granted(&Permission::WRITE_ONLY));
555        assert!(flags.is_permission_granted(&Permission::READ_WRITE));
556    }
557
558    #[test]
559    fn test_flags_type_from_mode_type() {
560        let mode = Mode::READ_WRITE;
561        let flags: Flags = mode.into();
562        assert_eq!(flags.get_mode(), mode);
563    }
564
565    #[test]
566    fn test_flags_type_into_u16() {
567        let mode = Mode::READ_WRITE;
568        let flags = Flags::new(mode, None, None);
569        let flags_u16: u16 = flags.into();
570        assert_eq!(flags_u16, flags.0);
571    }
572}