commonlibsse_ng_proc_macro_common/
enum_parser.rs1use proc_macro2::TokenStream;
2use quote::{ToTokens as _, quote};
3use syn::{Attribute, Expr, Lit, Meta};
4
5pub(crate) fn parse_discriminant(expr: &Expr) -> syn::Result<i64> {
7 match expr {
8 Expr::Lit(lit) => {
9 match &lit.lit {
10 Lit::Int(int) => int.base10_parse::<i64>(),
11 Lit::Byte(byte) => Ok(byte.value() as i64), _ => Err(syn::Error::new_spanned(
13 lit,
14 format!("Failed to parse as integer: {}", lit.to_token_stream()),
15 )),
16 }
17 }
18 Expr::Binary(binary) => {
19 let left = parse_discriminant(&binary.left)?;
20 let right = parse_discriminant(&binary.right)?;
21
22 match binary.op {
23 syn::BinOp::Add(_) => Ok(left + right), syn::BinOp::Sub(_) => Ok(left - right), syn::BinOp::Mul(_) => Ok(left * right), syn::BinOp::Div(_) => {
27 if right == 0 {
28 Err(syn::Error::new_spanned(
29 binary,
30 "Division by zero is not allowed".to_string(),
31 ))
32 } else {
33 Ok(left / right) }
35 }
36 syn::BinOp::Rem(_) => {
37 if right == 0 {
38 Err(syn::Error::new_spanned(
39 binary,
40 "Modulo by zero is not allowed".to_string(),
41 ))
42 } else {
43 Ok(left % right) }
45 }
46 syn::BinOp::Shl(_) => Ok(left << right), syn::BinOp::Shr(_) => Ok(left >> right), syn::BinOp::BitAnd(_) => Ok(left & right), syn::BinOp::BitOr(_) => Ok(left | right), syn::BinOp::BitXor(_) => Ok(left ^ right), _ => Err(syn::Error::new_spanned(
52 binary,
53 format!("Unsupported operator: {}", binary.to_token_stream()),
54 )),
55 }
56 }
57 unknown => Err(syn::Error::new_spanned(
58 unknown,
59 format!("Unsupported expression type: {}", unknown.to_token_stream()),
60 )),
61 }
62}
63
64pub(crate) fn select_bitflags_type(repr_attr: &Attribute) -> syn::Result<TokenStream> {
66 let mut repr = quote! { usize };
67 if let Meta::List(meta) = &repr_attr.meta {
68 meta.parse_nested_meta(|nested_meta| {
69 let path = &nested_meta.path;
70
71 if path.is_ident("u32") {
72 repr = quote! { u32 };
73 } else if path.is_ident("i32") {
74 repr = quote! { i32 };
75 } else if path.is_ident("u64") {
76 repr = quote! { u64 };
77 } else if path.is_ident("i64") {
78 repr = quote! { i64 };
79 } else if path.is_ident("u8") {
80 repr = quote! { u8 };
81 } else if path.is_ident("i8") {
82 repr = quote! { i8 };
83 } else if path.is_ident("u16") {
84 repr = quote! { u16 };
85 } else if path.is_ident("i16") {
86 repr = quote! { i16 };
87 } else if path.is_ident("usize") {
88 repr = quote! { usize };
89 } else if path.is_ident("isize") {
90 repr = quote! { isize };
91 } else if path.is_ident("C") {
92 repr = quote! { i32 }; } else {
94 return Err(syn::Error::new_spanned(
95 path,
96 format!(
97 "Unsupported repr type: {}",
98 path.get_ident().map(|i| i.to_string()).unwrap_or_default()
99 ),
100 ));
101 }
102
103 Ok(())
104 })?;
105 }
106
107 Ok(repr)
108}
109
110pub(crate) fn filter_default_attr(attrs: &[Attribute]) -> (Vec<&Attribute>, bool) {
111 let mut not_default = false;
112 let v = attrs
113 .iter()
114 .filter(|attr| {
115 not_default =
117 if let Meta::Path(path) = &attr.meta { !path.is_ident("default") } else { true };
118 not_default
119 })
120 .collect();
121
122 (v, not_default)
123}
124
125pub(crate) fn filter_repr_default_attr(
126 attrs: &[Attribute],
127) -> (Vec<TokenStream>, Option<&Attribute>) {
128 let mut others_attr = vec![];
129 let mut repr_attr = None;
130
131 for attr in attrs {
132 let path = attr.meta.path();
134
135 if path.is_ident("repr") {
136 repr_attr = Some(attr);
137 continue;
138 }
139
140 if path.is_ident("derive") {
141 let mut derived = vec![];
142 if let Meta::List(meta) = &attr.meta {
143 let _ = meta.parse_nested_meta(|nested_meta| {
144 let path = nested_meta.path;
145 if !path.is_ident("Default") {
146 derived.push(path);
147 };
148 Ok(())
149 });
150 }
151 others_attr.push(quote! { #[derive(#(#derived,)*)] });
152 continue;
153 }
154
155 others_attr.push(attr.to_token_stream());
156 }
157
158 (others_attr, repr_attr)
159}