Skip to main content

embedded_sdmmc/filesystem/
attributes.rs

1//! Attribute related code
2
3/// Indicates whether a directory entry is read-only, a directory, a volume
4/// label, etc.
5#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
6#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
7pub struct Attributes(pub(crate) u8);
8
9impl Attributes {
10    /// Indicates this file cannot be written.
11    pub const READ_ONLY: u8 = 0x01;
12    /// Indicates the file is hidden.
13    pub const HIDDEN: u8 = 0x02;
14    /// Indicates this is a system file.
15    pub const SYSTEM: u8 = 0x04;
16    /// Indicates this is a volume label.
17    pub const VOLUME: u8 = 0x08;
18    /// Indicates this is a directory.
19    pub const DIRECTORY: u8 = 0x10;
20    /// Indicates this file needs archiving (i.e. has been modified since last
21    /// archived).
22    pub const ARCHIVE: u8 = 0x20;
23    /// This set of flags indicates the file is actually a long file name
24    /// fragment.
25    pub const LFN: u8 = Self::READ_ONLY | Self::HIDDEN | Self::SYSTEM | Self::VOLUME;
26
27    /// Create a `Attributes` value from the `u8` stored in a FAT16/FAT32
28    /// Directory Entry.
29    pub(crate) fn create_from_fat(value: u8) -> Attributes {
30        Attributes(value)
31    }
32
33    pub(crate) fn set_archive(&mut self, flag: bool) {
34        let archive = if flag { 0x20 } else { 0x00 };
35        self.0 |= archive;
36    }
37
38    /// Does this file has the read-only attribute set?
39    pub fn is_read_only(self) -> bool {
40        (self.0 & Self::READ_ONLY) == Self::READ_ONLY
41    }
42
43    /// Does this file has the hidden attribute set?
44    pub fn is_hidden(self) -> bool {
45        (self.0 & Self::HIDDEN) == Self::HIDDEN
46    }
47
48    /// Does this file has the system attribute set?
49    pub fn is_system(self) -> bool {
50        (self.0 & Self::SYSTEM) == Self::SYSTEM
51    }
52
53    /// Does this file has the volume attribute set?
54    pub fn is_volume(self) -> bool {
55        (self.0 & Self::VOLUME) == Self::VOLUME
56    }
57
58    /// Does this entry point at a directory?
59    pub fn is_directory(self) -> bool {
60        (self.0 & Self::DIRECTORY) == Self::DIRECTORY
61    }
62
63    /// Does this need archiving?
64    pub fn is_archive(self) -> bool {
65        (self.0 & Self::ARCHIVE) == Self::ARCHIVE
66    }
67
68    /// Is this a long file name fragment?
69    pub fn is_lfn(self) -> bool {
70        (self.0 & Self::LFN) == Self::LFN
71    }
72}
73
74impl core::fmt::Debug for Attributes {
75    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
76        // Worst case is "DRHSVA"
77        let mut output = heapless::String::<7>::new();
78        if self.is_lfn() {
79            output.push_str("LFN").unwrap();
80        } else {
81            if self.is_directory() {
82                output.push_str("D").unwrap();
83            } else {
84                output.push_str("F").unwrap();
85            }
86            if self.is_read_only() {
87                output.push_str("R").unwrap();
88            }
89            if self.is_hidden() {
90                output.push_str("H").unwrap();
91            }
92            if self.is_system() {
93                output.push_str("S").unwrap();
94            }
95            if self.is_volume() {
96                output.push_str("V").unwrap();
97            }
98            if self.is_archive() {
99                output.push_str("A").unwrap();
100            }
101        }
102        f.pad(&output)
103    }
104}
105
106// ****************************************************************************
107//
108// End Of File
109//
110// ****************************************************************************