Skip to content

Commit

Permalink
Implement fmt::Display for enums, flags, and ints (bytecodealliance#18)
Browse files Browse the repository at this point in the history
* Implement fmt::Display for enums

`wasi_common` relies on `strerror` to nicely format error messages.
`strerror` is autoimplemented in `wig`. I thought it might be useful
to provide a Rust-idiomatic alternative which boils down to autoimplementing
`fmt::Display` for all enums.

* Implement fmt::Display for flags

* Implement fmt::Display for ints
  • Loading branch information
kubkon committed Feb 24, 2020
1 parent b7cd003 commit 6780650
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 9 deletions.
47 changes: 38 additions & 9 deletions crates/generate/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ fn define_int(names: &Names, name: &witx::Id, i: &witx::IntDatatype) -> TokenStr
#(#consts;)*
}

impl ::std::fmt::Display for #ident {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "{:?}", self)
}
}

impl ::std::convert::TryFrom<#repr> for #ident {
type Error = wiggle_runtime::GuestError;
fn try_from(value: #repr) -> Result<Self, wiggle_runtime::GuestError> {
Expand Down Expand Up @@ -153,6 +159,8 @@ fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> Toke
}
let all_values_token = Literal::u128_unsuffixed(all_values);

let ident_str = ident.to_string();

quote! {
#[repr(transparent)]
#[derive(Copy, Clone, Debug, ::std::hash::Hash, Eq, PartialEq)]
Expand All @@ -167,6 +175,12 @@ fn define_flags(names: &Names, name: &witx::Id, f: &witx::FlagsDatatype) -> Toke
}
}

impl ::std::fmt::Display for #ident {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "{}({:#b})", #ident_str, self.0)
}
}

impl ::std::ops::BitAnd for #ident {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Expand Down Expand Up @@ -286,15 +300,21 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
witx::IntRepr::U64 => witx::AtomType::I64,
});

let variant_names = e.variants.iter().map(|v| names.enum_variant(&v.name));
let tryfrom_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
let variant_name = names.enum_variant(&v.name);
quote!(#n => Ok(#ident::#variant_name))
});
let to_repr_cases = e.variants.iter().enumerate().map(|(n, v)| {
let variant_name = names.enum_variant(&v.name);
quote!(#ident::#variant_name => #n as #repr)
});
let mut variant_names = vec![];
let mut tryfrom_repr_cases = vec![];
let mut to_repr_cases = vec![];
let mut to_display = vec![];

for (n, variant) in e.variants.iter().enumerate() {
let variant_name = names.enum_variant(&variant.name);
let docs = variant.docs.trim();
let ident_str = ident.to_string();
let variant_str = variant_name.to_string();
tryfrom_repr_cases.push(quote!(#n => Ok(#ident::#variant_name)));
to_repr_cases.push(quote!(#ident::#variant_name => #n as #repr));
to_display.push(quote!(#ident::#variant_name => format!("{} ({}::{}({}))", #docs, #ident_str, #variant_str, #repr::from(*self))));
variant_names.push(variant_name);
}

quote! {
#[repr(#repr)]
Expand All @@ -303,6 +323,15 @@ fn define_enum(names: &Names, name: &witx::Id, e: &witx::EnumDatatype) -> TokenS
#(#variant_names),*
}

impl ::std::fmt::Display for #ident {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
let to_str = match self {
#(#to_display,)*
};
write!(f, "{}", to_str)
}
}

impl ::std::convert::TryFrom<#repr> for #ident {
type Error = wiggle_runtime::GuestError;
fn try_from(value: #repr) -> Result<#ident, wiggle_runtime::GuestError> {
Expand Down
5 changes: 5 additions & 0 deletions tests/errno.witx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
(typename $errno
(enum u32
;;; Success
$ok
;;; Invalid argument
$invalid_arg
;;; I really don't want to
$dont_want_to
;;; I am physically unable to
$physically_unable
;;; Well, that's a picket line alright!
$picket_line))

0 comments on commit 6780650

Please sign in to comment.