enum_tools/parser/
values.rs1use crate::feature::sorted::FeatureSorted;
2use crate::parser::error::Error;
3use proc_macro2::Span;
4use proc_macro_error::{abort, emit_error};
5use std::collections::HashMap;
6use syn::spanned::Spanned;
7use syn::{Data, Expr, ExprLit, ExprUnary, Fields, Ident, Lit, Meta, MetaNameValue, UnOp};
8
9pub(crate) fn parse_values(
10 span: Span,
11 data: Data,
12 sorted: FeatureSorted,
13) -> Vec<(i64, (Ident, String))> {
14 if let Data::Enum(data) = data {
15 let mut values = HashMap::new();
16 let mut last = -1i64;
17 let mut last_name = None;
18
19 for mut v in data.variants {
20 let span = v.span();
21 if !matches!(v.fields, Fields::Unit) {
22 emit_error!(span, Error::OnlyUnitField);
23 }
24 let mut name = v.ident.to_string();
25 for a in v.attrs {
26 if a.path().is_ident("enum_tools") {
27 if let Meta::List(meta_list) = &a.meta {
28 let nested = meta_list
29 .parse_args()
30 .unwrap_or_else(|e| abort!(meta_list, Error::MetaParseError(e)));
31 if let Meta::NameValue(MetaNameValue {
32 path,
33 value:
34 Expr::Lit(ExprLit {
35 lit: Lit::Str(lit_str),
36 ..
37 }),
38 ..
39 }) = nested
40 {
41 if !path.is_ident("rename") {
42 emit_error!(a, Error::UnsupportedAttributeType);
43 } else {
44 name = lit_str.value();
45 }
46 } else {
47 emit_error!(a, Error::UnsupportedAttributeType);
48 }
49 } else {
50 emit_error!(a, Error::UnsupportedAttributeType);
51 }
52 }
53 }
54 if sorted.name {
55 if let Some(last_name) = last_name {
56 if last_name >= name {
57 emit_error!(span, Error::FieldsNotNameSorted);
58 }
59 }
60 last_name = Some(name.clone());
61 }
62 if let Some((_, d)) = v.discriminant.take() {
63 let mut negate = false;
65 let mut num = &d;
66 if let Expr::Unary(ExprUnary { attrs, op, expr }) = &d {
67 if attrs.is_empty() {
68 if let UnOp::Neg(_) = op {
69 num = expr;
70 negate = true;
71 }
72 }
73 }
74
75 if let Expr::Lit(ExprLit {
76 lit: Lit::Int(i), ..
77 }) = num
78 {
79 if let Ok(mut i) = i.base10_parse::<i64>() {
80 if negate {
81 i = -i;
82 }
83 if sorted.value && !values.is_empty() && i < last {
84 emit_error!(span, Error::FieldsNotValueSorted);
85 }
86 if values.insert(i, (v.ident, name)).is_some() {
87 emit_error!(span, Error::DuplicateValue);
88 }
89 last = i;
90 } else {
91 emit_error!(span, Error::NoI64);
92 }
93 } else {
94 emit_error!(span, Error::NotInteger);
95 }
96 } else {
97 if last == i64::MAX {
98 emit_error!(span, Error::I64Overflow);
99 }
100 last = last.wrapping_add(1);
101 if values.insert(last, (v.ident, name)).is_some() {
102 emit_error!(span, Error::DuplicateValue);
103 }
104 }
105 }
106
107 let mut values = values
108 .iter()
109 .map(|(k, v)| (*k, v.clone()))
110 .collect::<Vec<_>>();
111 values.sort_by_key(|v| v.0);
112
113 if values.is_empty() {
114 abort!(span, Error::NoVariantsFound);
115 }
116
117 values
118 } else {
119 abort!(span, Error::NoEnum);
120 }
121}