diplomat_core/ast/
enums.rs1use serde::Serialize;
2
3use super::docs::Docs;
4use super::{AttrInheritContext, Attrs, Ident, Method};
5use quote::ToTokens;
6
7#[derive(Clone, Serialize, Debug, Hash, PartialEq, Eq)]
9#[non_exhaustive]
10pub struct Enum {
11 pub name: Ident,
12 pub docs: Docs,
13 pub variants: Vec<(Ident, isize, Docs, Attrs)>,
15 pub methods: Vec<Method>,
16 pub attrs: Attrs,
17}
18
19impl Enum {
20 pub fn new(enm: &syn::ItemEnum, parent_attrs: &Attrs) -> Enum {
22 let mut last_discriminant = -1;
23 if !enm.generics.params.is_empty() {
24 panic!("Enums cannot have generic parameters");
29 }
30
31 let mut attrs = parent_attrs.clone();
32 attrs.add_attrs(&enm.attrs);
33 let variant_parent_attrs = attrs.attrs_for_inheritance(AttrInheritContext::Variant);
34
35 Enum {
36 name: (&enm.ident).into(),
37 docs: Docs::from_attrs(&enm.attrs),
38 variants: enm
39 .variants
40 .iter()
41 .map(|v| {
42 let new_discriminant = v
43 .discriminant
44 .as_ref()
45 .map(|d| {
46 let lit: Result<syn::Lit, _> = syn::parse2(d.1.to_token_stream());
49 if let Ok(syn::Lit::Int(ref lit_int)) = lit {
50 lit_int.base10_parse::<isize>().unwrap()
51 } else {
52 panic!("Expected a discriminant to be a constant integer");
53 }
54 })
55 .unwrap_or_else(|| last_discriminant + 1);
56
57 last_discriminant = new_discriminant;
58 let mut v_attrs = variant_parent_attrs.clone();
59 v_attrs.add_attrs(&v.attrs);
60 (
61 (&v.ident).into(),
62 new_discriminant,
63 Docs::from_attrs(&v.attrs),
64 v_attrs,
65 )
66 })
67 .collect(),
68 methods: vec![],
69 attrs,
70 }
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use insta::{self, Settings};
77
78 use syn;
79
80 use super::Enum;
81
82 #[test]
83 fn simple_enum() {
84 let mut settings = Settings::new();
85 settings.set_sort_maps(true);
86
87 settings.bind(|| {
88 insta::assert_yaml_snapshot!(Enum::new(
89 &syn::parse_quote! {
90 #[diplomat::rust_link(foo::Bar, Enum)]
92 enum MyLocalEnum {
93 Abc,
94 Def
96 }
97 },
98 &Default::default()
99 ));
100 });
101 }
102
103 #[test]
104 fn enum_with_discr() {
105 let mut settings = Settings::new();
106 settings.set_sort_maps(true);
107
108 settings.bind(|| {
109 insta::assert_yaml_snapshot!(Enum::new(
110 &syn::parse_quote! {
111 #[diplomat::rust_link(foo::Bar, Enum)]
113 enum DiscriminantedEnum {
114 Abc = -1,
115 Def = 0,
116 Ghi = 1,
117 Jkl = 2,
118 }
119 },
120 &Default::default()
121 ));
122 });
123 }
124}