alloy_sol_types/types/event/
topic.rs
1use crate::{abi::token::WordToken, sol_data::*, SolType};
2use alloc::vec::Vec;
3use alloy_primitives::keccak256;
4
5pub trait EventTopic: SolType {
20 fn topic_preimage_length(rust: &Self::RustType) -> usize;
28
29 fn encode_topic_preimage(rust: &Self::RustType, out: &mut Vec<u8>);
36
37 fn encode_topic(rust: &Self::RustType) -> WordToken;
46}
47
48macro_rules! word_impl {
50 () => {
51 #[inline]
52 fn topic_preimage_length(_: &Self::RustType) -> usize {
53 32
54 }
55
56 #[inline]
57 fn encode_topic_preimage(rust: &Self::RustType, out: &mut Vec<u8>) {
58 out.extend($crate::private::SolTypeValue::<Self>::stv_to_tokens(rust).0);
59 }
60
61 #[inline]
62 fn encode_topic(rust: &Self::RustType) -> WordToken {
63 $crate::private::SolTypeValue::<Self>::stv_to_tokens(rust)
64 }
65 };
66}
67
68impl EventTopic for Address {
69 word_impl!();
70}
71
72impl EventTopic for Function {
73 word_impl!();
74}
75
76impl EventTopic for Bool {
77 word_impl!();
78}
79
80impl<const BITS: usize> EventTopic for Int<BITS>
81where
82 IntBitCount<BITS>: SupportedInt,
83{
84 word_impl!();
85}
86
87impl<const BITS: usize> EventTopic for Uint<BITS>
88where
89 IntBitCount<BITS>: SupportedInt,
90{
91 word_impl!();
92}
93
94impl<const N: usize> EventTopic for FixedBytes<N>
95where
96 ByteCount<N>: SupportedFixedBytes,
97{
98 word_impl!();
99}
100
101macro_rules! bytes_impl {
103 () => {
104 #[inline]
105 fn topic_preimage_length(rust: &Self::RustType) -> usize {
106 crate::utils::next_multiple_of_32(rust.len())
107 }
108
109 #[inline]
110 fn encode_topic_preimage(rust: &Self::RustType, out: &mut Vec<u8>) {
111 encode_topic_bytes(rust.as_ref(), out);
112 }
113
114 #[inline]
115 fn encode_topic(rust: &Self::RustType) -> WordToken {
116 WordToken(keccak256(rust))
117 }
118 };
119}
120
121impl EventTopic for String {
122 bytes_impl!();
123}
124
125impl EventTopic for Bytes {
126 bytes_impl!();
127}
128
129macro_rules! array_impl {
131 ($ty:ident) => {
132 #[inline]
133 fn topic_preimage_length(rust: &Self::RustType) -> usize {
134 rust.iter().map($ty::topic_preimage_length).sum()
135 }
136
137 #[inline]
138 fn encode_topic_preimage(rust: &Self::RustType, out: &mut Vec<u8>) {
139 out.reserve(Self::topic_preimage_length(rust));
140 for t in rust {
141 $ty::encode_topic_preimage(t, out);
142 }
143 }
144
145 #[inline]
146 fn encode_topic(rust: &Self::RustType) -> WordToken {
147 let mut out = Vec::new();
148 Self::encode_topic_preimage(rust, &mut out);
149 WordToken(keccak256(out))
150 }
151 };
152}
153
154impl<T: EventTopic> EventTopic for Array<T> {
155 array_impl!(T);
156}
157
158impl<T: EventTopic, const N: usize> EventTopic for FixedArray<T, N> {
159 array_impl!(T);
160}
161
162macro_rules! tuple_impls {
163 ($count:literal $($ty:ident),+) => {
164 #[allow(non_snake_case)]
165 impl<$($ty: EventTopic,)+> EventTopic for ($($ty,)+) {
166 #[inline]
167 fn topic_preimage_length(rust: &Self::RustType) -> usize {
168 let ($($ty,)+) = rust;
169 0usize $( + <$ty>::topic_preimage_length($ty) )+
170 }
171
172 #[inline]
173 fn encode_topic_preimage(rust: &Self::RustType, out: &mut Vec<u8>) {
174 let b @ ($($ty,)+) = rust;
175 out.reserve(Self::topic_preimage_length(b));
176 $(
177 <$ty>::encode_topic_preimage($ty, out);
178 )+
179 }
180
181 #[inline]
182 fn encode_topic(rust: &Self::RustType) -> WordToken {
183 let mut out = Vec::new();
184 Self::encode_topic_preimage(rust, &mut out);
185 WordToken(keccak256(out))
186 }
187 }
188 };
189}
190
191impl EventTopic for () {
192 #[inline]
193 fn topic_preimage_length(_: &Self::RustType) -> usize {
194 0
195 }
196
197 #[inline]
198 fn encode_topic_preimage(_: &Self::RustType, _: &mut Vec<u8>) {}
199
200 #[inline]
201 fn encode_topic(_: &Self::RustType) -> WordToken {
202 WordToken::default()
203 }
204}
205
206all_the_tuples!(tuple_impls);
207
208fn encode_topic_bytes(sl: &[u8], out: &mut Vec<u8>) {
209 let padding = 32 - sl.len() % 32;
210 out.reserve(sl.len() + padding);
211 out.extend_from_slice(sl);
212 out.extend(core::iter::repeat(0).take(padding));
213}