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