file_system/fundamentals/
flags.rs1use core::fmt::Debug;
2
3use shared::flags;
4
5use super::Permission;
6
7flags! {
8 pub enum AccessFlags: u8 {
10 Read,
12 Write,
14 }
15}
16
17impl AccessFlags {
18 pub const READ_WRITE: Self = Self::None.insert(Self::Read).insert(Self::Write);
19
20 pub const fn into_permission(&self) -> Permission {
21 let mut permission = Permission::None;
22
23 if self.contains(AccessFlags::Read) {
24 permission = permission.insert(Permission::Read);
25 }
26
27 if self.contains(AccessFlags::Write) {
28 permission = permission.insert(Permission::Write);
29 }
30
31 permission
32 }
33}
34
35flags! {
36 pub enum CreateFlags: u8 {
38 Create,
40 Exclusive,
42 Truncate,
44 }
45}
46
47impl CreateFlags {
48 pub const CREATE_TRUNCATE: Self = Self::Create.insert(Self::Truncate);
49 pub const CREATE_EXCLUSIVE: Self = Self::Create.insert(Self::Exclusive);
50}
51
52flags! {
53 pub enum StateFlags: u8 {
55 Append,
57 NonBlocking,
59 Synchronous,
61 SynchronousDataOnly,
63 }
64}
65
66#[derive(PartialEq, Eq, Clone, Copy)]
86#[repr(transparent)]
87pub struct Flags(u16);
88
89impl Debug for Flags {
90 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
91 formatter
92 .debug_struct("Flags")
93 .field("Access", &self.get_access())
94 .field("Create", &self.get_create())
95 .field("State", &self.get_state())
96 .finish()
97 }
98}
99
100impl Flags {
101 const MODE_POSITION: u8 = 0;
102 const OPEN_POSITION: u8 = AccessFlags::bits_used();
103 const STATUS_POSITION: u8 = CreateFlags::bits_used() + Self::OPEN_POSITION;
104
105 const OPEN_MASK: u16 = (1 << CreateFlags::bits_used()) - 1;
106 const STATUS_MASK: u16 = (1 << StateFlags::bits_used()) - 1;
107 const MODE_MASK: u16 = (1 << AccessFlags::bits_used()) - 1;
108
109 pub const fn new(
110 mode: AccessFlags,
111 open: Option<CreateFlags>,
112 status: Option<StateFlags>,
113 ) -> Self {
114 let open = if let Some(open_val) = open {
115 open_val
116 } else {
117 CreateFlags::None
118 };
119 let status = if let Some(status_val) = status {
120 status_val
121 } else {
122 StateFlags::None
123 };
124
125 let mut flags: u16 = 0;
126 flags |= (mode.0 as u16) << Self::MODE_POSITION;
127 flags |= (open.0 as u16) << Self::OPEN_POSITION;
128 flags |= (status.0 as u16) << Self::STATUS_POSITION;
129 Self(flags)
130 }
131
132 pub const fn get_access(&self) -> AccessFlags {
133 AccessFlags(((self.0 >> Self::MODE_POSITION) & Self::MODE_MASK) as u8)
134 }
135
136 pub const fn get_create(&self) -> CreateFlags {
137 CreateFlags(((self.0 >> Self::OPEN_POSITION) & Self::OPEN_MASK) as u8)
138 }
139
140 pub const fn get_state(&self) -> StateFlags {
141 StateFlags(((self.0 >> Self::STATUS_POSITION) & Self::STATUS_MASK) as u8)
142 }
143
144 pub const fn set_mode(mut self, mode: AccessFlags) -> Self {
145 self.0 &= !(Self::MODE_MASK << Self::MODE_POSITION);
146 self.0 |= (mode.0 as u16) << Self::MODE_POSITION;
147 self
148 }
149
150 pub const fn set_open(mut self, open: CreateFlags) -> Self {
151 self.0 &= !(Self::OPEN_MASK << Self::OPEN_POSITION);
152 self.0 |= (open.0 as u16) << Self::OPEN_POSITION;
153 self
154 }
155
156 pub const fn set_status(mut self, status: StateFlags) -> Self {
157 self.0 &= !(Self::STATUS_MASK << Self::STATUS_POSITION);
158 self.0 |= (status.0 as u16) << Self::STATUS_POSITION;
159 self
160 }
161
162 pub fn is_permission_granted(&self, permission: &Permission) -> bool {
163 let mode = self.get_access();
164
165 let read = permission.contains(Permission::Read) && mode.contains(AccessFlags::Read); let write = permission.contains(Permission::Write)
167 && (mode.contains(AccessFlags::Write) || self.get_state().contains(StateFlags::Append)); read || write
170 }
171
172 pub fn split(&self) -> (AccessFlags, CreateFlags, StateFlags) {
173 (self.get_access(), self.get_create(), self.get_state())
174 }
175}
176
177impl From<AccessFlags> for Flags {
178 fn from(mode: AccessFlags) -> Self {
179 Self::new(mode, None, None)
180 }
181}
182
183impl From<Flags> for u16 {
184 fn from(flags: Flags) -> Self {
185 flags.0
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn test_flags_type_set_get() {
195 let flags = Flags::new(AccessFlags::Read, None, None);
196
197 let new_mode = AccessFlags::Write;
198 let flags = flags.set_mode(new_mode);
199 assert_eq!(flags.get_access(), new_mode);
200
201 let new_open = CreateFlags::Exclusive | CreateFlags::Truncate;
202 let flags = flags.set_open(new_open);
203 assert_eq!(flags.get_create(), new_open);
204
205 let new_status = StateFlags::NonBlocking | StateFlags::SynchronousDataOnly;
206 let flags = flags.set_status(new_status);
207 assert_eq!(flags.get_state(), new_status);
208 }
209
210 #[test]
211 fn test_flags_type_is_permission_granted() {
212 let mode = AccessFlags::READ_WRITE;
213 let status = StateFlags::None;
214 let flags = Flags::new(mode, None, Some(status));
215
216 assert!(flags.is_permission_granted(&Permission::Read));
217 assert!(flags.is_permission_granted(&Permission::Write));
218 assert!(flags.is_permission_granted(&Permission::READ_WRITE));
219 }
220
221 #[test]
222 fn test_flags_type_from_mode_type() {
223 let mode = AccessFlags::READ_WRITE;
224 let flags: Flags = mode.into();
225 assert_eq!(flags.get_access(), mode);
226 }
227
228 #[test]
229 fn test_flags_type_into_u16() {
230 let mode = AccessFlags::READ_WRITE;
231 let flags = Flags::new(mode, None, None);
232 let flags_u16: u16 = flags.into();
233 assert_eq!(flags_u16, flags.0);
234 }
235}