use core::{fmt, str};
use bitflag_attr::Flags;
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct ManualFlags(u32);
impl ManualFlags {
const FLAG1: Self = Self(1 << 9);
const FLAG2: Self = Self(1 << 12);
const FLAG3: Self = Self(1);
const FLAG4: Self = Self(Self::FLAG1.0 | Self::FLAG2.0);
}
impl Flags for ManualFlags {
const NAMED_FLAGS: &'static [(&'static str, Self)] = &[
("FLAG1", Self::FLAG1),
("FLAG2", Self::FLAG2),
("FLAG3", Self::FLAG3),
("FLAG4", Self::FLAG4),
];
const RESERVED_BITS: Self::Bits = 0;
type Bits = u32;
fn bits(&self) -> Self::Bits {
self.0
}
fn from_bits_retain(bits: Self::Bits) -> Self {
Self(bits)
}
}
impl str::FromStr for ManualFlags {
type Err = bitflag_attr::parser::ParseError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
bitflag_attr::parser::from_text(input)
}
}
impl fmt::Display for ManualFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
bitflag_attr::parser::to_writer(self, f)
}
}
impl fmt::Debug for ManualFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
struct HumanReadable<'a>(&'a ManualFlags);
impl fmt::Debug for HumanReadable<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.0.is_empty() {
write!(f, "{:#X}", self.0 .0)
} else {
bitflag_attr::parser::to_writer(self.0, f)
}
}
}
#[inline]
pub const fn octal_width() -> usize {
match u32::BITS as usize {
8 => 3,
16 => 6,
32 => 11,
64 => 22,
128 => 43,
x => x / 3 + x % 3,
}
}
f.debug_struct("ManualFlags")
.field("flags", &HumanReadable(self))
.field(
"bits",
&::core::format_args!("{:#0width$b}", self.0, width = 2 + u32::BITS as usize),
)
.field(
"octal",
&::core::format_args!("{:#0width$o}", self.0, width = 2 + const { octal_width() }),
)
.field(
"hex",
&::core::format_args!(
"{:#0width$X}",
self.0,
width = 2 + const { u32::BITS as usize / 4 }
),
)
.finish()
}
}
fn main() {
let mut flag = ManualFlags::FLAG1
.union(ManualFlags::FLAG2)
.union(ManualFlags::FLAG3);
flag.set(ManualFlags::from_bits_retain(1 << 5));
println!("Display: {}", flag);
println!("Debug: {:#?}", flag);
}