wiggle: use bitflags to generate flags

more consistient with the rest of the ecosystem.
This commit is contained in:
Pat Hickey
2021-01-11 18:20:57 -08:00
parent e2fb99af86
commit ed44a19e5e
2 changed files with 15 additions and 86 deletions

View File

@@ -27,102 +27,31 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
}
quote! {
#[repr(transparent)]
#[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)]
pub struct #ident(#repr);
impl #ident {
#(pub const #names_: #ident = #ident(#values_);)*
#[inline]
pub const fn empty() -> Self {
#ident(0)
}
#[inline]
pub const fn all() -> Self {
#ident(#(#values_)|*)
}
#[inline]
pub fn contains(&self, other: &#ident) -> bool {
!*self & *other == Self::empty()
#rt::bitflags::bitflags! {
pub struct #ident: #repr {
#(const #names_ = #values_;)*
}
}
impl ::std::fmt::Display for #ident {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
let mut first = true;
#(
if self.0 & #values_ == #values_ {
if !first {
f.write_str("|")?;
}
first = false;
f.write_fmt(format_args!("{}", stringify!(#names_).to_lowercase()))?;
}
)*
if first {
f.write_str("empty")?;
}
f.write_fmt(format_args!(" ({:#x})", self.0))?;
f.write_str(stringify!(#ident))?;
f.write_str("(")?;
::std::fmt::Debug::fmt(self, f)?;
f.write_str(" (0x")?;
::std::fmt::LowerHex::fmt(&self.bits, f)?;
f.write_str("))")?;
Ok(())
}
}
impl ::std::ops::BitAnd for #ident {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
#ident(self.0 & rhs.0)
}
}
impl ::std::ops::BitAndAssign for #ident {
fn bitand_assign(&mut self, rhs: Self) {
*self = *self & rhs
}
}
impl ::std::ops::BitOr for #ident {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
#ident(self.0 | rhs.0)
}
}
impl ::std::ops::BitOrAssign for #ident {
fn bitor_assign(&mut self, rhs: Self) {
*self = *self | rhs
}
}
impl ::std::ops::BitXor for #ident {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self::Output {
#ident(self.0 ^ rhs.0)
}
}
impl ::std::ops::BitXorAssign for #ident {
fn bitxor_assign(&mut self, rhs: Self) {
*self = *self ^ rhs
}
}
impl ::std::ops::Not for #ident {
type Output = Self;
fn not(self) -> Self::Output {
#ident(!self.0)
}
}
impl ::std::convert::TryFrom<#repr> for #ident {
type Error = #rt::GuestError;
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
if #repr::from(!#ident::all()) & value != 0 {
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
} else {
Ok(#ident(value))
Ok(#ident { bits: value })
}
}
}
@@ -136,7 +65,7 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
impl From<#ident> for #repr {
fn from(e: #ident) -> #repr {
e.0
e.bits
}
}

View File

@@ -103,11 +103,11 @@ proptest! {
#[test]
fn flags_fmt() {
let empty = format!("{}", types::CarConfig::empty());
assert_eq!(empty, "empty (0x0)");
assert_eq!(empty, "CarConfig((empty) (0x0))");
let one_flag = format!("{}", types::CarConfig::AWD);
assert_eq!(one_flag, "awd (0x2)");
assert_eq!(one_flag, "CarConfig(AWD (0x2))");
let two_flags = format!("{}", types::CarConfig::AUTOMATIC | types::CarConfig::SUV);
assert_eq!(two_flags, "automatic|suv (0x5)");
assert_eq!(two_flags, "CarConfig(AUTOMATIC | SUV (0x5))");
let all = format!("{}", types::CarConfig::all());
assert_eq!(all, "automatic|awd|suv (0x7)");
assert_eq!(all, "CarConfig(AUTOMATIC | AWD | SUV (0x7))");
}