1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use super::{
    int_repr_ext::IntReprExt, to_ident::ToIdent, StringExt, TokenStreamPair,
    TypeDefinitionExtensions,
};
use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::LitInt;
use witx::{EnumDatatype, Id};

impl TypeDefinitionExtensions for EnumDatatype {
    fn get_type_definitions(&self, ident: &Id, docs: TokenStream) -> TokenStreamPair {
        let repr = self.repr.to_type();

        let ident_native = ident.to_ident_native(None);

        let variants_native = self.variants.iter().enumerate().map(|(i, v)| {
            let docs = v.docs.as_docs();
            let ident = v.name.to_ident_native(Some(ident.as_str()));
            let value = LitInt::new(&format!("{}", i), Span::call_site());

            quote! {
                #docs
                pub const #ident: #ident_native = #value;
            }
        });

        let native = quote! {
            #docs
            pub type #ident_native = #repr;

            #( #variants_native )*
        };

        let variants = self.variants.iter().map(|v| {
            let docs = v.docs.as_docs();

            let ident = v.name.to_ident();

            quote! {
                #docs
                #ident
            }
        });

        let variants_back = self.variants.iter().map(|v| {
            let variant_ident = v.name.to_ident();
            let variant_ident_native = v.name.to_ident_native(Some(ident.as_str()));

            quote! {
                self::native::#variant_ident_native => Ok(Self::#variant_ident),
            }
        });
        let ident = ident.to_ident();

        let mapped = quote! {
            #docs
            #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
            #[non_exhaustive]
            pub enum #ident {
                #( #variants ),*
            }

            impl witx_gen::WasiValue for #ident {
                type NativeType = self::native::#ident_native;

                fn from_native(native: Self::NativeType) -> std::result::Result<Self, witx_gen::WasiValueError<Self>> {
                    match native {
                        #( #variants_back )*
                        _ => Err(witx_gen::WasiValueError::from_native(native)),
                    }
                }

                fn to_native(self) -> Self::NativeType {
                    self as #repr
                }
            }
        };

        TokenStreamPair::from_streams(native, mapped)
    }

    fn has_rust_value(&self) -> bool {
        true
    }
}