pyo3_stub_gen_derive/gen_stub/
pyclass_enum.rs1use proc_macro2::TokenStream as TokenStream2;
2use quote::{quote, ToTokens, TokenStreamExt};
3use syn::{parse_quote, Error, ItemEnum, Result, Type};
4
5use super::{extract_documents, parse_pyo3_attrs, util::quote_option, Attr, StubType};
6
7pub struct PyEnumInfo {
8 pyclass_name: String,
9 enum_type: Type,
10 module: Option<String>,
11 variants: Vec<(String, String)>,
12 doc: String,
13}
14
15impl From<&PyEnumInfo> for StubType {
16 fn from(info: &PyEnumInfo) -> Self {
17 let PyEnumInfo {
18 pyclass_name,
19 module,
20 enum_type,
21 ..
22 } = info;
23 Self {
24 ty: enum_type.clone(),
25 name: pyclass_name.clone(),
26 module: module.clone(),
27 }
28 }
29}
30
31impl TryFrom<ItemEnum> for PyEnumInfo {
32 type Error = Error;
33 fn try_from(
34 ItemEnum {
35 variants,
36 attrs,
37 ident,
38 ..
39 }: ItemEnum,
40 ) -> Result<Self> {
41 let doc = extract_documents(&attrs).join("\n");
42 let mut pyclass_name = None;
43 let mut module = None;
44 let mut renaming_rule = None;
45 for attr in parse_pyo3_attrs(&attrs)? {
46 match attr {
47 Attr::Name(name) => pyclass_name = Some(name),
48 Attr::Module(name) => module = Some(name),
49 Attr::RenameAll(name) => renaming_rule = Some(name),
50 _ => {}
51 }
52 }
53 let struct_type = parse_quote!(#ident);
54 let pyclass_name = pyclass_name.unwrap_or_else(|| ident.to_string());
55 let variants = variants
56 .into_iter()
57 .map(|var| -> Result<(String, String)> {
58 let mut var_name = None;
59 for attr in parse_pyo3_attrs(&var.attrs)? {
60 if let Attr::Name(name) = attr {
61 var_name = Some(name);
62 }
63 }
64 let mut var_name = var_name.unwrap_or_else(|| var.ident.to_string());
65 if let Some(renaming_rule) = renaming_rule {
66 var_name = renaming_rule.apply(&var_name);
67 }
68 let var_doc = extract_documents(&var.attrs).join("\n");
69 Ok((var_name, var_doc))
70 })
71 .collect::<Result<Vec<(String, String)>>>()?;
72 Ok(Self {
73 doc,
74 enum_type: struct_type,
75 pyclass_name,
76 module,
77 variants,
78 })
79 }
80}
81
82impl ToTokens for PyEnumInfo {
83 fn to_tokens(&self, tokens: &mut TokenStream2) {
84 let Self {
85 pyclass_name,
86 enum_type,
87 variants,
88 doc,
89 module,
90 } = self;
91 let module = quote_option(module);
92 let variants: Vec<_> = variants
93 .iter()
94 .map(|(name, doc)| quote! {(#name,#doc)})
95 .collect();
96 tokens.append_all(quote! {
97 ::pyo3_stub_gen::type_info::PyEnumInfo {
98 pyclass_name: #pyclass_name,
99 enum_id: std::any::TypeId::of::<#enum_type>,
100 variants: &[ #(#variants),* ],
101 module: #module,
102 doc: #doc,
103 }
104 })
105 }
106}