diff --git a/crates/generate/src/types.rs b/crates/generate/src/types.rs index d2f94353da..a089dad629 100644 --- a/crates/generate/src/types.rs +++ b/crates/generate/src/types.rs @@ -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 { @@ -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)] @@ -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 { @@ -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)] @@ -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> { diff --git a/tests/errno.witx b/tests/errno.witx index 5197c2c224..36ee67622e 100644 --- a/tests/errno.witx +++ b/tests/errno.witx @@ -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))