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}