wiggle: use bitflags to generate flags
more consistient with the rest of the ecosystem.
This commit is contained in:
@@ -27,102 +27,31 @@ pub(super) fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDataty
|
|||||||
}
|
}
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[repr(transparent)]
|
#rt::bitflags::bitflags! {
|
||||||
#[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)]
|
pub struct #ident: #repr {
|
||||||
pub struct #ident(#repr);
|
#(const #names_ = #values_;)*
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::std::fmt::Display for #ident {
|
impl ::std::fmt::Display for #ident {
|
||||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||||
let mut first = true;
|
f.write_str(stringify!(#ident))?;
|
||||||
#(
|
f.write_str("(")?;
|
||||||
if self.0 & #values_ == #values_ {
|
::std::fmt::Debug::fmt(self, f)?;
|
||||||
if !first {
|
f.write_str(" (0x")?;
|
||||||
f.write_str("|")?;
|
::std::fmt::LowerHex::fmt(&self.bits, f)?;
|
||||||
}
|
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))?;
|
|
||||||
Ok(())
|
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 {
|
impl ::std::convert::TryFrom<#repr> for #ident {
|
||||||
type Error = #rt::GuestError;
|
type Error = #rt::GuestError;
|
||||||
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
|
fn try_from(value: #repr) -> Result<Self, #rt::GuestError> {
|
||||||
if #repr::from(!#ident::all()) & value != 0 {
|
if #repr::from(!#ident::all()) & value != 0 {
|
||||||
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
|
Err(#rt::GuestError::InvalidFlagValue(stringify!(#ident)))
|
||||||
} else {
|
} 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 {
|
impl From<#ident> for #repr {
|
||||||
fn from(e: #ident) -> #repr {
|
fn from(e: #ident) -> #repr {
|
||||||
e.0
|
e.bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,11 +103,11 @@ proptest! {
|
|||||||
#[test]
|
#[test]
|
||||||
fn flags_fmt() {
|
fn flags_fmt() {
|
||||||
let empty = format!("{}", types::CarConfig::empty());
|
let empty = format!("{}", types::CarConfig::empty());
|
||||||
assert_eq!(empty, "empty (0x0)");
|
assert_eq!(empty, "CarConfig((empty) (0x0))");
|
||||||
let one_flag = format!("{}", types::CarConfig::AWD);
|
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);
|
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());
|
let all = format!("{}", types::CarConfig::all());
|
||||||
assert_eq!(all, "automatic|awd|suv (0x7)");
|
assert_eq!(all, "CarConfig(AUTOMATIC | AWD | SUV (0x7))");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user