borsh_derive/internals/attributes/
parsing.rs
1use std::{collections::BTreeMap, iter::FromIterator};
2
3use syn::{
4 meta::ParseNestedMeta, punctuated::Punctuated, token::Paren, Attribute, Expr, Lit, LitStr,
5 Token,
6};
7
8use super::Symbol;
9
10fn get_lit_str2(
11 attr_name: Symbol,
12 meta_item_name: Symbol,
13 meta: &ParseNestedMeta,
14) -> syn::Result<LitStr> {
15 let expr: Expr = meta.value()?.parse()?;
16 let mut value = &expr;
17 while let Expr::Group(e) = value {
18 value = &e.expr;
19 }
20 if let Expr::Lit(syn::ExprLit {
21 lit: Lit::Str(lit), ..
22 }) = value
23 {
24 Ok(lit.clone())
25 } else {
26 Err(syn::Error::new_spanned(
27 expr,
28 format!(
29 "expected borsh {} attribute to be a string: `{} = \"...\"`",
30 attr_name.0, meta_item_name.0
31 ),
32 ))
33 }
34}
35
36pub(super) fn parse_lit_into<T: syn::parse::Parse>(
37 attr_name: Symbol,
38 meta_item_name: Symbol,
39 meta: &ParseNestedMeta,
40) -> syn::Result<T> {
41 let string = get_lit_str2(attr_name, meta_item_name, meta)?;
42
43 match string.parse() {
44 Ok(expr) => Ok(expr),
45 Err(err) => Err(syn::Error::new_spanned(string, err)),
46 }
47}
48
49pub(super) fn parse_lit_into_vec<T: syn::parse::Parse>(
50 attr_name: Symbol,
51 meta_item_name: Symbol,
52 meta: &ParseNestedMeta,
53) -> syn::Result<Vec<T>> {
54 let string = get_lit_str2(attr_name, meta_item_name, meta)?;
55
56 match string.parse_with(Punctuated::<T, Token![,]>::parse_terminated) {
57 Ok(elements) => Ok(Vec::from_iter(elements)),
58 Err(err) => Err(syn::Error::new_spanned(string, err)),
59 }
60}
61
62fn get_nested_meta_logic<T, F>(
63 attr_name: Symbol,
64 meta: ParseNestedMeta,
65 map: &BTreeMap<Symbol, F>,
66 result: &mut BTreeMap<Symbol, T>,
67) -> syn::Result<()>
68where
69 F: Fn(Symbol, Symbol, &ParseNestedMeta) -> syn::Result<T>,
70{
71 let mut match_ = false;
72 for (symbol_key, func) in map.iter() {
73 if meta.path == *symbol_key {
74 let v = func(attr_name, *symbol_key, &meta)?;
75 result.insert(*symbol_key, v);
76 match_ = true;
77 }
78 }
79 if !match_ {
80 let keys_strs = map.keys().map(|symbol| symbol.1).collect::<Vec<_>>();
81 let keys_strs = keys_strs.join(", ");
82 return Err(meta.error(format_args!(
83 "malformed {0} attribute, expected `{0}({1})`",
84 attr_name.0, keys_strs
85 )));
86 }
87 Ok(())
88}
89
90pub(super) fn meta_get_by_symbol_keys<T, F>(
91 attr_name: Symbol,
92 meta: &ParseNestedMeta,
93 map: &BTreeMap<Symbol, F>,
94) -> syn::Result<BTreeMap<Symbol, T>>
95where
96 F: Fn(Symbol, Symbol, &ParseNestedMeta) -> syn::Result<T>,
97{
98 let mut result = BTreeMap::new();
99
100 let lookahead = meta.input.lookahead1();
101 if lookahead.peek(Paren) {
102 meta.parse_nested_meta(|meta| get_nested_meta_logic(attr_name, meta, map, &mut result))?;
103 } else {
104 return Err(lookahead.error());
105 }
106
107 Ok(result)
108}
109
110pub(super) fn attr_get_by_symbol_keys<T, F>(
111 attr_name: Symbol,
112 attr: &Attribute,
113 map: &BTreeMap<Symbol, F>,
114) -> syn::Result<BTreeMap<Symbol, T>>
115where
116 F: Fn(Symbol, Symbol, &ParseNestedMeta) -> syn::Result<T>,
117{
118 let mut result = BTreeMap::new();
119
120 attr.parse_nested_meta(|meta| get_nested_meta_logic(attr_name, meta, map, &mut result))?;
121
122 Ok(result)
123}