wiggle_generate/types/
flags.rs1use crate::names;
2
3use proc_macro2::{Literal, TokenStream};
4use quote::quote;
5
6pub(super) fn define_flags(
7 name: &witx::Id,
8 repr: witx::IntRepr,
9 record: &witx::RecordDatatype,
10) -> TokenStream {
11 let ident = names::type_(&name);
12 let abi_repr = names::wasm_type(repr.into());
13 let repr = super::int_repr_tokens(repr);
14
15 let mut names_ = vec![];
16 let mut values_ = vec![];
17 for (i, member) in record.members.iter().enumerate() {
18 let name = names::flag_member(&member.name);
19 let value_token = Literal::usize_unsuffixed(1 << i);
20 names_.push(name);
21 values_.push(value_token);
22 }
23
24 quote! {
25 wiggle::bitflags::bitflags! {
26 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
27 pub struct #ident: #repr {
28 #(const #names_ = #values_;)*
29 }
30 }
31
32 impl ::std::fmt::Display for #ident {
33 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
34 f.write_str(stringify!(#ident))?;
35 f.write_str("(")?;
36 ::std::fmt::Debug::fmt(self, f)?;
37 f.write_str(" (0x")?;
38 ::std::fmt::LowerHex::fmt(&self.bits(), f)?;
39 f.write_str("))")?;
40 Ok(())
41 }
42 }
43
44 impl TryFrom<#repr> for #ident {
45 type Error = wiggle::GuestError;
46 #[inline]
47 fn try_from(value: #repr) -> Result<Self, wiggle::GuestError> {
48 #ident::from_bits(value)
49 .ok_or(wiggle::GuestError::InvalidFlagValue(stringify!(#ident)))
50 }
51 }
52
53 impl TryFrom<#abi_repr> for #ident {
54 type Error = wiggle::GuestError;
55 #[inline]
56 fn try_from(value: #abi_repr) -> Result<Self, wiggle::GuestError> {
57 #ident::try_from(#repr::try_from(value)?)
58 }
59 }
60
61 impl From<#ident> for #repr {
62 #[inline]
63 fn from(e: #ident) -> #repr {
64 e.bits()
65 }
66 }
67
68 impl wiggle::GuestType for #ident {
69 #[inline]
70 fn guest_size() -> u32 {
71 #repr::guest_size()
72 }
73
74 #[inline]
75 fn guest_align() -> usize {
76 #repr::guest_align()
77 }
78
79 fn read(mem: &wiggle::GuestMemory, location: wiggle::GuestPtr<#ident>) -> Result<#ident, wiggle::GuestError> {
80 use std::convert::TryFrom;
81 let reprval = #repr::read(mem, location.cast())?;
82 let value = #ident::try_from(reprval)?;
83 Ok(value)
84 }
85
86 fn write(mem: &mut wiggle::GuestMemory, location: wiggle::GuestPtr<#ident>, val: Self) -> Result<(), wiggle::GuestError> {
87 let val: #repr = #repr::from(val);
88 #repr::write(mem, location.cast(), val)
89 }
90 }
91 }
92}