ion_proc/class/
property.rs1use proc_macro2::{Ident, TokenStream};
8use quote::{format_ident, quote};
9use syn::{ImplItemConst, Result, Type};
10
11use crate::attribute::ParseAttribute as _;
12use crate::attribute::name::Name;
13use crate::attribute::property::PropertyAttribute;
14use crate::utils::path_ends_with;
15
16#[derive(Clone, Debug)]
17pub(super) enum PropertyType {
18 Int32,
19 Double,
20 String,
21}
22
23#[derive(Clone)]
24pub(super) struct Property {
25 pub(super) ty: PropertyType,
26 pub(super) ident: Ident,
27 pub(super) names: Vec<Name>,
28}
29
30impl Property {
31 pub(super) fn from_const(r#const: &mut ImplItemConst) -> Result<Option<(Property, bool)>> {
32 let mut names = Vec::new();
33
34 let attribute = PropertyAttribute::from_attributes("ion", &mut r#const.attrs, ())?;
35
36 let PropertyAttribute { name, alias, skip, r#static } = attribute;
37 for alias in alias {
38 names.push(Name::String(alias));
39 }
40
41 r#const.attrs.clear();
42 if skip {
43 return Ok(None);
44 }
45
46 let ident = r#const.ident.clone();
47
48 match name {
49 Some(name) => names.insert(0, name),
50 None => names.insert(0, Name::from_string(ident.to_string(), ident.span())),
51 }
52
53 match &r#const.ty {
54 Type::Path(ty) => {
55 if path_ends_with(&ty.path, "i32") {
56 Ok(Some((Property { ty: PropertyType::Int32, ident, names }, r#static)))
57 } else if path_ends_with(&ty.path, "f64") {
58 Ok(Some((Property { ty: PropertyType::Double, ident, names }, r#static)))
59 } else {
60 Ok(None)
61 }
62 }
63 Type::Reference(re) => {
64 if let Type::Path(ty) = &*re.elem
65 && path_ends_with(&ty.path, "str")
66 {
67 return Ok(Some((Property { ty: PropertyType::String, ident, names }, r#static)));
68 }
69 Ok(None)
70 }
71 _ => Ok(None),
72 }
73 }
74
75 pub(super) fn to_specs(&self, ion: &TokenStream, class: &Ident) -> Vec<TokenStream> {
76 let ident = &self.ident;
77
78 self.names
79 .iter()
80 .map(|name| {
81 let mut function_ident = format_ident!("create_property_spec");
82
83 let (key, flags) = name.to_property_spec(ion, &mut function_ident);
84
85 function_ident = match self.ty {
86 PropertyType::Int32 => format_ident!("{}_int", function_ident),
87 PropertyType::Double => format_ident!("{}_double", function_ident),
88 PropertyType::String => format_ident!("{}_string", function_ident),
89 };
90
91 quote!(#ion::spec::#function_ident(#key, #class::#ident, #flags))
92 })
93 .collect()
94 }
95}