const_array_attrs/
sorted.rs1use proc_macro2::TokenStream;
2use syn:: {
3 ItemConst,
4 Expr, ExprArray,
5 Lit,
6 parse:: { self, Parse, ParseStream },
7};
8use quote:: { quote, ToTokens };
9
10pub struct SortedTable(ItemConst);
11
12impl Parse for SortedTable {
13 fn parse(input: ParseStream) -> parse::Result<Self> {
14 let mut item_const: ItemConst = input.parse()?;
15
16 match item_const.expr.as_mut() {
17 Expr::Array(ExprArray {
18 ref mut elems, ..
19 }) => {
20 let mut new_elems: Vec<Expr> = Vec::new();
21
22 while let Some(ex) = elems.pop() {
23 if let Err(i) = new_elems.binary_search_by(
24 |p| get_key(p).cmp(&get_key(ex.value()))
25 ) {
26 new_elems.insert(i, ex.into_value());
27 }
28 }
29 for ex in new_elems {
30 elems.push(ex);
31 }
32 },
33 _ => (),
34 }
35 Ok(Self(item_const))
36 }
37}
38
39impl ToTokens for SortedTable {
40 fn to_tokens(&self, tokens: &mut TokenStream) {
41 let item_const = &self.0;
42
43 tokens.extend(quote! { #item_const });
44 }
45}
46
47fn get_key(ex: &Expr) -> String {
48 use Expr::*;
49
50 match ex {
51 Tuple(tuple) => match tuple.elems.first() {
52 Some(Lit(expr)) => lit_to_string(&expr.lit),
53 _ => panic!(),
54 },
55 Lit(expr) => lit_to_string(&expr.lit),
56 _ => panic!(),
57 }
58}
59
60fn lit_to_string(lit: &Lit) -> String {
61 use Lit::*;
62 match lit {
63 Str(s) => s.value(),
64 ByteStr(s) => String::from_utf8(s.value()).unwrap(),
65 Byte(s) => s.value().to_string(),
66 Char(s) => s.value().into(),
67 Int(s) => s.base10_parse().unwrap(),
68 Float(s) => s.base10_parse().unwrap(),
69 Bool(s) => s.value().to_string(),
70 Verbatim(s) => s.to_string(),
71 }
72}