1 use darling::{ast, FromDeriveInput, FromVariant};
2 
3 #[derive(Debug, FromDeriveInput)]
4 #[darling(attributes(from_variants), supports(enum_any))]
5 pub struct Container {
6     // The second type parameter can be anything that implements FromField, since
7     // FromDeriveInput will produce an error if given a struct.
8     data: ast::Data<Variant, ()>,
9 }
10 
11 #[derive(Default, Debug, FromVariant)]
12 #[darling(default, attributes(from_variants), supports(newtype, unit))]
13 pub struct Variant {
14     into: Option<bool>,
15     skip: Option<bool>,
16 }
17 
18 #[derive(Debug, FromDeriveInput)]
19 #[darling(attributes(from_struct), supports(struct_named))]
20 pub struct StructContainer {
21     // The second type parameter can be anything that implements FromVariant, since
22     // FromDeriveInput will produce an error if given an enum.
23     data: ast::Data<(), syn::Field>,
24 }
25 
26 mod source {
27     use syn::{parse_quote, DeriveInput};
28 
newtype_enum() -> DeriveInput29     pub fn newtype_enum() -> DeriveInput {
30         parse_quote! {
31             enum Hello {
32                 World(bool),
33                 String(String),
34             }
35         }
36     }
37 
named_field_enum() -> DeriveInput38     pub fn named_field_enum() -> DeriveInput {
39         parse_quote! {
40             enum Hello {
41                 Foo(u16),
42                 World {
43                     name: String
44                 },
45             }
46         }
47     }
48 
empty_enum() -> DeriveInput49     pub fn empty_enum() -> DeriveInput {
50         parse_quote! {
51             enum Hello {}
52         }
53     }
54 
named_struct() -> DeriveInput55     pub fn named_struct() -> DeriveInput {
56         parse_quote! {
57             struct Hello {
58                 world: bool,
59             }
60         }
61     }
62 
tuple_struct() -> DeriveInput63     pub fn tuple_struct() -> DeriveInput {
64         parse_quote! { struct Hello(String, bool); }
65     }
66 }
67 
68 #[test]
enum_newtype_or_unit()69 fn enum_newtype_or_unit() {
70     // Should pass
71     let container = Container::from_derive_input(&source::newtype_enum()).unwrap();
72     assert!(container.data.is_enum());
73 
74     // Should error
75     Container::from_derive_input(&source::named_field_enum()).unwrap_err();
76     Container::from_derive_input(&source::named_struct()).unwrap_err();
77 }
78 
79 #[test]
struct_named()80 fn struct_named() {
81     // Should pass
82     let container = StructContainer::from_derive_input(&source::named_struct()).unwrap();
83     assert!(container.data.is_struct());
84 
85     // Should fail
86     StructContainer::from_derive_input(&source::tuple_struct()).unwrap_err();
87     StructContainer::from_derive_input(&source::named_field_enum()).unwrap_err();
88     StructContainer::from_derive_input(&source::newtype_enum()).unwrap_err();
89     StructContainer::from_derive_input(&source::empty_enum()).unwrap_err();
90 }
91