scale_info_derive/
utils.rs1use proc_macro2::TokenStream;
20use quote::quote;
21use syn::{parse::Parse, spanned::Spanned, AttrStyle, Attribute, Lit, Meta, NestedMeta, Variant};
22
23pub fn variant_index(v: &Variant, i: usize) -> TokenStream {
26 let index = maybe_index(v);
28 index.map(|i| quote! { #i }).unwrap_or_else(|| {
30 v.discriminant
31 .as_ref()
32 .map(|(_, ref expr)| quote! { #expr })
33 .unwrap_or_else(|| quote! { #i })
34 })
35}
36
37pub fn maybe_index(variant: &Variant) -> Option<u8> {
40 let outer_attrs = variant
41 .attrs
42 .iter()
43 .filter(|attr| attr.style == AttrStyle::Outer);
44
45 codec_meta_item(outer_attrs, |meta| {
46 if let NestedMeta::Meta(Meta::NameValue(ref nv)) = meta {
47 if nv.path.is_ident("index") {
48 if let Lit::Int(ref v) = nv.lit {
49 let byte = v
50 .base10_parse::<u8>()
51 .expect("Internal error. `#[codec(index = …)]` attribute syntax must be checked in `parity-scale-codec`. This is a bug.");
52 return Some(byte);
53 }
54 }
55 }
56
57 None
58 })
59}
60
61pub fn is_compact(field: &syn::Field) -> bool {
63 let outer_attrs = field
64 .attrs
65 .iter()
66 .filter(|attr| attr.style == AttrStyle::Outer);
67 codec_meta_item(outer_attrs, |meta| {
68 if let NestedMeta::Meta(Meta::Path(ref path)) = meta {
69 if path.is_ident("compact") {
70 return Some(());
71 }
72 }
73
74 None
75 })
76 .is_some()
77}
78
79pub fn should_skip(attrs: &[Attribute]) -> bool {
81 codec_meta_item(attrs.iter(), |meta| {
82 if let NestedMeta::Meta(Meta::Path(ref path)) = meta {
83 if path.is_ident("skip") {
84 return Some(path.span());
85 }
86 }
87
88 None
89 })
90 .is_some()
91}
92
93fn codec_meta_item<'a, F, R, I, M>(itr: I, pred: F) -> Option<R>
94where
95 F: FnMut(M) -> Option<R> + Clone,
96 I: Iterator<Item = &'a Attribute>,
97 M: Parse,
98{
99 find_meta_item("codec", itr, pred)
100}
101
102fn find_meta_item<'a, F, R, I, M>(kind: &str, mut itr: I, mut pred: F) -> Option<R>
103where
104 F: FnMut(M) -> Option<R> + Clone,
105 I: Iterator<Item = &'a Attribute>,
106 M: Parse,
107{
108 itr.find_map(|attr| {
109 attr.path
110 .is_ident(kind)
111 .then(|| pred(attr.parse_args().ok()?))
112 .flatten()
113 })
114}