use bitfield_struct::bitfield;
#[bitfield(u32, debug = false, new = false)]
#[derive(PartialEq)]
pub struct IoFlags {
#[bits(1)]
data_or_constant: bool,
#[bits(1)]
array_or_variable: bool,
#[bits(1)]
absolute_or_relative: bool,
#[bits(1)]
no_wrap_or_wrap: bool,
#[bits(1)]
linear_or_nonlinear: bool,
#[bits(1)]
preferred_or_no_preferred: bool,
#[bits(1)]
no_null_position_or_null_state: bool,
#[bits(1)]
non_volatile_or_volatile: bool,
#[bits(1)]
bitfield_or_buffered: bool,
#[bits(23)]
_reserved: u32,
}
impl IoFlags {
const fn new() -> Self {
Self(0)
}
pub const fn data() -> Self {
Self::new()
}
pub const fn constant() -> Self {
Self::new().with_data_or_constant(true)
}
pub const fn is_constant(self) -> bool {
self.data_or_constant()
}
pub const fn is_data(self) -> bool {
!self.is_constant()
}
pub const fn variable(self) -> Self {
self.with_array_or_variable(true)
}
pub const fn is_variable(self) -> bool {
self.array_or_variable()
}
pub const fn is_array(self) -> bool {
!self.is_variable()
}
pub const fn relative(self) -> Self {
self.with_absolute_or_relative(true)
}
pub const fn is_relative(self) -> bool {
self.absolute_or_relative()
}
pub const fn is_absolute(self) -> bool {
!self.is_relative()
}
pub const fn wrap(self) -> Self {
self.with_no_wrap_or_wrap(true)
}
pub const fn wraps(self) -> bool {
self.no_wrap_or_wrap()
}
pub const fn non_linear(self) -> Self {
self.with_linear_or_nonlinear(true)
}
pub const fn is_linear(self) -> bool {
!self.linear_or_nonlinear()
}
pub const fn no_preferred_state(self) -> Self {
self.with_preferred_or_no_preferred(true)
}
pub const fn has_preferred_state(self) -> bool {
!self.preferred_or_no_preferred()
}
pub const fn null_state(self) -> Self {
self.with_no_null_position_or_null_state(true)
}
pub const fn has_null_state(self) -> bool {
!self.no_null_position_or_null_state()
}
pub const fn volatile(self) -> Self {
self.with_non_volatile_or_volatile(true)
}
pub const fn is_volatile(self) -> bool {
self.non_volatile_or_volatile()
}
pub const fn buffered(self) -> Self {
self.with_bitfield_or_buffered(true)
}
pub const fn is_buffered(self) -> bool {
self.bitfield_or_buffered()
}
pub const fn is_bitfield(self) -> bool {
!self.is_buffered()
}
}
pub mod ioflags {
use super::IoFlags;
pub const DATA_VARIABLE_ABSOLUTE: IoFlags = IoFlags::data().variable();
pub const CONSTANT: IoFlags = IoFlags::constant();
pub const ARRAY: IoFlags = IoFlags::data();
}
#[derive(Clone, Copy, PartialEq)]
pub struct InputFlags(pub IoFlags);
impl core::ops::Deref for InputFlags {
type Target = IoFlags;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl InputFlags {
pub fn from_unchecked(flags: IoFlags) -> Self {
Self(flags)
}
#[doc(hidden)]
#[deprecated = "`InputFlags` should not use the volatile bit"]
pub fn is_volatile(&self) -> bool {
self.0.is_volatile()
}
}
#[derive(Clone, Copy, PartialEq)]
pub struct OutputFeatureFlags(pub IoFlags);
impl core::ops::Deref for OutputFeatureFlags {
type Target = IoFlags;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<IoFlags> for OutputFeatureFlags {
fn from(flags: IoFlags) -> Self {
Self(flags)
}
}
#[cfg(feature = "std")]
mod std_impls {
use super::*;
use std::fmt::{self, Debug};
fn debug_flags(is_input: bool, flags: IoFlags, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if flags.data_or_constant() {
f.write_str("Constant ")?;
} else {
f.write_str("Data ")?;
}
if flags.array_or_variable() {
f.write_str("Variable ")?;
} else {
f.write_str("Array ")?;
}
if flags.absolute_or_relative() {
f.write_str("Relative ")?;
} else {
f.write_str("Absolute ")?;
}
if flags.no_wrap_or_wrap() {
f.write_str("Wrap ")?;
} else {
f.write_str("No-Wrap ")?;
}
if flags.linear_or_nonlinear() {
f.write_str("Non-Linear ")?;
} else {
f.write_str("Linear ")?;
}
if flags.preferred_or_no_preferred() {
f.write_str("No-Preferred ")?;
} else {
f.write_str("Preferred-State ")?;
}
if flags.no_null_position_or_null_state() {
f.write_str("Null-State ")?
} else {
f.write_str("No-Null-Position ")?;
}
if flags.non_volatile_or_volatile() {
f.write_str("Volatile ")?;
} else {
if !is_input {
f.write_str("Non-Volatile ")?;
}
}
if flags.bitfield_or_buffered() {
f.write_str("Buffered-Bytes")?;
} else {
f.write_str("Bit-Field")?;
}
Ok(())
}
impl Debug for InputFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_flags(true, self.0, f)
}
}
impl Debug for OutputFeatureFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
debug_flags(false, self.0, f)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ioflags() {
const DATA: IoFlags = IoFlags::data();
const CONSTANT: IoFlags = IoFlags::constant();
assert!(DATA.is_data());
assert!(!DATA.is_constant());
assert!(!CONSTANT.is_data());
assert!(CONSTANT.is_constant());
assert!(DATA.is_array());
assert!(!DATA.is_variable());
assert!(!DATA.variable().is_array());
assert!(DATA.variable().is_variable());
assert!(DATA.is_absolute());
assert!(!DATA.is_relative());
assert!(!DATA.relative().is_absolute());
assert!(DATA.relative().is_relative());
assert!(!DATA.wraps());
assert!(DATA.wrap().wraps());
assert!(DATA.is_linear());
assert!(!DATA.non_linear().is_linear());
assert!(DATA.has_preferred_state());
assert!(!DATA.no_preferred_state().has_preferred_state());
assert!(DATA.has_null_state());
assert!(!DATA.null_state().has_null_state());
assert!(!DATA.is_volatile());
assert!(DATA.volatile().is_volatile());
assert!(DATA.is_bitfield());
assert!(!DATA.is_buffered());
assert!(!DATA.buffered().is_bitfield());
assert!(DATA.buffered().is_buffered());
}
}