Skip to main content

alloy_sol_macro_expander/
utils.rs

1use ast::Spanned;
2use proc_macro2::{Span, TokenStream};
3use quote::ToTokens;
4use sha3::{Digest, Keccak256};
5
6/// Simple interface to the [`keccak256`] hash function.
7///
8/// [`keccak256`]: https://en.wikipedia.org/wiki/SHA-3
9pub(crate) fn keccak256<T: AsRef<[u8]>>(bytes: T) -> [u8; 32] {
10    Keccak256::digest(bytes).into()
11}
12
13pub(crate) fn selector<T: AsRef<[u8]>>(bytes: T) -> ExprArray<u8> {
14    ExprArray::new(keccak256(bytes)[..4].to_vec())
15}
16
17pub(crate) fn event_selector<T: AsRef<[u8]>>(bytes: T) -> ExprArray<u8> {
18    ExprArray::new(keccak256(bytes).to_vec())
19}
20
21pub(crate) fn combine_errors(v: impl IntoIterator<Item = syn::Error>) -> syn::Result<()> {
22    match v.into_iter().reduce(|mut a, b| {
23        a.combine(b);
24        a
25    }) {
26        Some(e) => Err(e),
27        None => Ok(()),
28    }
29}
30
31#[derive(Clone, Debug)]
32pub(crate) struct ExprArray<T> {
33    pub(crate) array: Vec<T>,
34    pub(crate) span: Span,
35}
36
37impl<T: PartialOrd> PartialOrd for ExprArray<T> {
38    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
39        self.array.partial_cmp(&other.array)
40    }
41}
42
43impl<T: Ord> Ord for ExprArray<T> {
44    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
45        self.array.cmp(&other.array)
46    }
47}
48
49impl<T: PartialEq> PartialEq for ExprArray<T> {
50    fn eq(&self, other: &Self) -> bool {
51        self.array == other.array
52    }
53}
54
55impl<T: Eq> Eq for ExprArray<T> {}
56
57impl<T> Spanned for ExprArray<T> {
58    fn span(&self) -> Span {
59        self.span
60    }
61
62    fn set_span(&mut self, span: Span) {
63        self.span = span;
64    }
65}
66
67impl<T> ExprArray<T> {
68    fn new(array: Vec<T>) -> Self {
69        Self { array, span: Span::call_site() }
70    }
71}
72
73impl<T: ToTokens> ToTokens for ExprArray<T> {
74    fn to_tokens(&self, tokens: &mut TokenStream) {
75        syn::token::Bracket(self.span).surround(tokens, |tokens| {
76            for t in &self.array {
77                t.to_tokens(tokens);
78                syn::token::Comma(self.span).to_tokens(tokens);
79            }
80        });
81    }
82}
83
84/// Applies [`proc_macro_error3`] programmatically.
85pub(crate) fn pme_compat(f: impl FnOnce() -> TokenStream) -> TokenStream {
86    pme_compat_result(|| Ok(f())).unwrap()
87}
88
89/// Applies [`proc_macro_error3`] programmatically.
90pub(crate) fn pme_compat_result(
91    f: impl FnOnce() -> syn::Result<TokenStream>,
92) -> syn::Result<TokenStream> {
93    let mut r = None;
94    let e = proc_macro_error3::entry_point(
95        std::panic::AssertUnwindSafe(|| {
96            r = Some(f());
97            Default::default()
98        }),
99        false,
100    );
101    if let Some(r) = r {
102        if e.is_empty() || r.is_err() {
103            return r;
104        }
105    }
106    Ok(e.into())
107}