1mod from;
16mod into;
17
18use proc_macro::TokenStream;
19use proc_macro2::Ident;
20use syn::parse::{Parse, ParseStream};
21use syn::{Attribute, LitStr, Type, Variant};
22
23#[allow(clippy::duplicated_attributes)]
24#[proc_macro_derive(IntoValue, attributes(wit_transparent, unit_case, wit_field))]
25pub fn derive_into_value(input: TokenStream) -> TokenStream {
26 into::derive_into_value(input)
27}
28
29#[allow(clippy::duplicated_attributes)]
30#[proc_macro_derive(
31 FromValue,
32 attributes(wit_transparent, unit_case, wit_field, from_value)
33)]
34pub fn derive_from_value(input: TokenStream) -> TokenStream {
35 from::derive_from_value(input)
36}
37
38#[derive(Default)]
39struct WitField {
40 skip: bool,
41 rename: Option<LitStr>,
42 convert: Option<Type>,
43 convert_vec: Option<Type>,
44 convert_option: Option<Type>,
45}
46
47fn parse_wit_field_attribute(attr: &Attribute) -> WitField {
48 attr.parse_args_with(WitField::parse)
49 .expect("failed to parse wit_field attribute")
50}
51
52impl Parse for WitField {
53 fn parse(input: ParseStream) -> syn::Result<Self> {
54 let mut skip = false;
55 let mut rename = None;
56 let mut convert = None;
57 let mut convert_vec = None;
58 let mut convert_option = None;
59
60 while !input.is_empty() {
61 let ident: Ident = input.parse()?;
62 if ident == "skip" {
63 skip = true;
64 } else if ident == "rename" {
65 input.parse::<syn::Token![=]>()?;
66 rename = Some(input.parse()?);
67 } else if ident == "convert" {
68 input.parse::<syn::Token![=]>()?;
69 convert = Some(input.parse()?);
70 } else if ident == "convert_vec" {
71 input.parse::<syn::Token![=]>()?;
72 convert_vec = Some(input.parse()?);
73 } else if ident == "convert_option" {
74 input.parse::<syn::Token![=]>()?;
75 convert_option = Some(input.parse()?);
76 } else {
77 return Err(syn::Error::new(ident.span(), "unexpected attribute"));
78 }
79 }
80
81 Ok(WitField {
82 skip,
83 rename,
84 convert,
85 convert_vec,
86 convert_option,
87 })
88 }
89}
90
91fn is_unit_case(variant: &Variant) -> bool {
92 variant.fields.is_empty()
93 || variant
94 .attrs
95 .iter()
96 .any(|attr| attr.path().is_ident("unit_case"))
97}