alloy_sol_macro_expander/
utils.rs1use ast::Spanned;
2use proc_macro2::{Span, TokenStream};
3use quote::ToTokens;
4use sha3::{Digest, Keccak256};
5
6pub(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
84pub(crate) fn pme_compat(f: impl FnOnce() -> TokenStream) -> TokenStream {
86 pme_compat_result(|| Ok(f())).unwrap()
87}
88
89pub(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}