1use bitfield_struct::bitfield;
4
5#[bitfield(u32, debug = false, new = false)]
15#[derive(PartialEq)]
16pub struct IoFlags {
17 #[bits(1)]
18 data_or_constant: bool,
19 #[bits(1)]
20 array_or_variable: bool,
21 #[bits(1)]
22 absolute_or_relative: bool,
23 #[bits(1)]
24 no_wrap_or_wrap: bool,
25 #[bits(1)]
26 linear_or_nonlinear: bool,
27 #[bits(1)]
28 preferred_or_no_preferred: bool,
29 #[bits(1)]
30 no_null_position_or_null_state: bool,
31 #[bits(1)]
33 non_volatile_or_volatile: bool,
34 #[bits(1)]
35 bitfield_or_buffered: bool,
36 #[bits(23)]
37 _reserved: u32,
38}
39
40impl IoFlags {
41 const fn new() -> Self {
42 Self(0)
43 }
44
45 pub const fn data() -> Self {
47 Self::new()
48 }
49
50 pub const fn constant() -> Self {
52 Self::new().with_data_or_constant(true)
53 }
54
55 pub const fn is_constant(self) -> bool {
57 self.data_or_constant()
58 }
59 pub const fn is_data(self) -> bool {
61 !self.is_constant()
62 }
63
64 pub const fn variable(self) -> Self {
68 self.with_array_or_variable(true)
69 }
70
71 pub const fn is_variable(self) -> bool {
73 self.array_or_variable()
74 }
75 pub const fn is_array(self) -> bool {
77 !self.is_variable()
78 }
79
80 pub const fn relative(self) -> Self {
84 self.with_absolute_or_relative(true)
85 }
86
87 pub const fn is_relative(self) -> bool {
89 self.absolute_or_relative()
90 }
91 pub const fn is_absolute(self) -> bool {
93 !self.is_relative()
94 }
95
96 pub const fn wrap(self) -> Self {
100 self.with_no_wrap_or_wrap(true)
101 }
102
103 pub const fn wraps(self) -> bool {
105 self.no_wrap_or_wrap()
106 }
107
108 pub const fn non_linear(self) -> Self {
112 self.with_linear_or_nonlinear(true)
113 }
114
115 pub const fn is_linear(self) -> bool {
117 !self.linear_or_nonlinear()
118 }
119
120 pub const fn no_preferred_state(self) -> Self {
128 self.with_preferred_or_no_preferred(true)
129 }
130
131 pub const fn has_preferred_state(self) -> bool {
133 !self.preferred_or_no_preferred()
134 }
135
136 pub const fn null_state(self) -> Self {
143 self.with_no_null_position_or_null_state(true)
144 }
145
146 pub const fn has_null_state(self) -> bool {
148 !self.no_null_position_or_null_state()
149 }
150
151 pub const fn volatile(self) -> Self {
159 self.with_non_volatile_or_volatile(true)
160 }
161
162 pub const fn is_volatile(self) -> bool {
164 self.non_volatile_or_volatile()
165 }
166
167 pub const fn buffered(self) -> Self {
174 self.with_bitfield_or_buffered(true)
175 }
176
177 pub const fn is_buffered(self) -> bool {
179 self.bitfield_or_buffered()
180 }
181 pub const fn is_bitfield(self) -> bool {
183 !self.is_buffered()
184 }
185}
186
187pub mod ioflags {
192 use super::IoFlags;
193
194 pub const DATA_VARIABLE_ABSOLUTE: IoFlags = IoFlags::data().variable();
198
199 pub const CONSTANT: IoFlags = IoFlags::constant();
203
204 pub const ARRAY: IoFlags = IoFlags::data();
208}
209
210#[derive(Clone, Copy, PartialEq)]
212pub struct InputFlags(pub IoFlags);
213
214impl InputFlags {
215 pub fn from_unchecked(flags: IoFlags) -> Self {
217 Self(flags)
218 }
219}
220
221#[derive(Clone, Copy, PartialEq)]
223pub struct OutputFeatureFlags(pub IoFlags);
224
225impl From<IoFlags> for OutputFeatureFlags {
226 fn from(flags: IoFlags) -> Self {
230 Self(flags)
231 }
232}
233
234#[cfg(feature = "std")]
235mod std_impls {
236 use super::*;
237
238 use std::fmt::{self, Debug};
239
240 fn debug_flags(is_input: bool, flags: IoFlags, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 if flags.data_or_constant() {
242 f.write_str("Constant ")?;
243 } else {
244 f.write_str("Data ")?;
245 }
246 if flags.array_or_variable() {
247 f.write_str("Variable ")?;
248 } else {
249 f.write_str("Array ")?;
250 }
251 if flags.absolute_or_relative() {
252 f.write_str("Relative ")?;
253 } else {
254 f.write_str("Absolute ")?;
255 }
256 if flags.no_wrap_or_wrap() {
257 f.write_str("Wrap ")?;
258 } else {
259 f.write_str("No-Wrap ")?;
260 }
261 if flags.linear_or_nonlinear() {
262 f.write_str("Non-Linear ")?;
263 } else {
264 f.write_str("Linear ")?;
265 }
266 if flags.preferred_or_no_preferred() {
267 f.write_str("No-Preferred ")?;
268 } else {
269 f.write_str("Preferred-State ")?;
270 }
271 if flags.no_null_position_or_null_state() {
272 f.write_str("Null-State ")?
273 } else {
274 f.write_str("No-Null-Position ")?;
275 }
276
277 if flags.non_volatile_or_volatile() {
279 f.write_str("Volatile ")?;
280 } else {
281 if !is_input {
282 f.write_str("Non-Volatile ")?;
283 }
284 }
285
286 if flags.bitfield_or_buffered() {
287 f.write_str("Buffered-Bytes")?;
288 } else {
289 f.write_str("Bit-Field")?;
290 }
291 Ok(())
292 }
293
294 impl Debug for InputFlags {
295 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296 debug_flags(true, self.0, f)
297 }
298 }
299
300 impl Debug for OutputFeatureFlags {
301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302 debug_flags(false, self.0, f)
303 }
304 }
305}
306
307#[cfg(test)]
308mod tests {
309 use super::*;
310
311 #[test]
312 fn test_ioflags() {
313 const DATA: IoFlags = IoFlags::data();
314 const CONSTANT: IoFlags = IoFlags::constant();
315
316 assert!(DATA.is_data());
317 assert!(!DATA.is_constant());
318 assert!(!CONSTANT.is_data());
319 assert!(CONSTANT.is_constant());
320
321 assert!(DATA.is_array());
322 assert!(!DATA.is_variable());
323 assert!(!DATA.variable().is_array());
324 assert!(DATA.variable().is_variable());
325
326 assert!(DATA.is_absolute());
327 assert!(!DATA.is_relative());
328 assert!(!DATA.relative().is_absolute());
329 assert!(DATA.relative().is_relative());
330
331 assert!(!DATA.wraps());
332 assert!(DATA.wrap().wraps());
333
334 assert!(DATA.is_linear());
335 assert!(!DATA.non_linear().is_linear());
336
337 assert!(DATA.has_preferred_state());
338 assert!(!DATA.no_preferred_state().has_preferred_state());
339
340 assert!(DATA.has_null_state());
341 assert!(!DATA.null_state().has_null_state());
342
343 assert!(!DATA.is_volatile());
344 assert!(DATA.volatile().is_volatile());
345
346 assert!(DATA.is_bitfield());
347 assert!(!DATA.is_buffered());
348 assert!(!DATA.buffered().is_bitfield());
349 assert!(DATA.buffered().is_buffered());
350 }
351}