alloy_rlp_derive/
utils.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::{
4    parse_quote, Attribute, DataStruct, Error, Field, GenericParam, Generics, Meta, Result, Type,
5    TypePath,
6};
7
8pub(crate) const EMPTY_STRING_CODE: u8 = 0x80;
9
10pub(crate) fn parse_struct<'a>(
11    ast: &'a syn::DeriveInput,
12    derive_attr: &str,
13) -> Result<&'a DataStruct> {
14    if let syn::Data::Struct(s) = &ast.data {
15        Ok(s)
16    } else {
17        Err(Error::new_spanned(
18            ast,
19            format!("#[derive({derive_attr})] is only defined for structs."),
20        ))
21    }
22}
23
24pub(crate) fn attributes_include(attrs: &[Attribute], attr_name: &str) -> bool {
25    for attr in attrs {
26        if attr.path().is_ident("rlp") {
27            if let Meta::List(meta) = &attr.meta {
28                let mut is_attr = false;
29                let _ = meta.parse_nested_meta(|meta| {
30                    is_attr = meta.path.is_ident(attr_name);
31                    Ok(())
32                });
33                if is_attr {
34                    return true;
35                }
36            }
37        }
38    }
39    false
40}
41
42pub(crate) fn is_optional(field: &Field) -> bool {
43    if let Type::Path(TypePath { qself, path }) = &field.ty {
44        qself.is_none()
45            && path.leading_colon.is_none()
46            && path.segments.len() == 1
47            && path.segments.first().unwrap().ident == "Option"
48    } else {
49        false
50    }
51}
52
53pub(crate) fn field_ident(index: usize, field: &syn::Field) -> TokenStream {
54    field.ident.as_ref().map_or_else(
55        || {
56            let index = syn::Index::from(index);
57            quote! { #index }
58        },
59        |ident| quote! { #ident },
60    )
61}
62
63pub(crate) fn make_generics(generics: &Generics, trait_name: TokenStream) -> Generics {
64    let mut generics = generics.clone();
65    generics.make_where_clause();
66    let mut where_clause = generics.where_clause.take().unwrap();
67
68    for generic in &generics.params {
69        if let GenericParam::Type(ty) = &generic {
70            let t = &ty.ident;
71            let pred = parse_quote!(#t: #trait_name);
72            where_clause.predicates.push(pred);
73        }
74    }
75    generics.where_clause = Some(where_clause);
76    generics
77}