1use core::{ops, str::FromStr};
10
11use ethereum_types::H256;
12use serde::{de::Visitor, Deserialize};
13#[cfg(feature = "serde")]
14use serde::{Serialize, Serializer};
15
16#[cfg(not(feature = "std"))]
17use crate::no_std_prelude::*;
18use crate::{Error, Hash, Token};
19
20#[derive(Debug, PartialEq, Default)]
22pub struct RawTopicFilter {
23 pub topic0: Topic<Token>,
25 pub topic1: Topic<Token>,
27 pub topic2: Topic<Token>,
29}
30
31#[derive(Debug, PartialEq, Eq, Default, Clone, Hash)]
33pub struct TopicFilter {
34 pub topic0: Topic<Hash>,
36 pub topic1: Topic<Hash>,
38 pub topic2: Topic<Hash>,
40 pub topic3: Topic<Hash>,
42}
43
44#[cfg(feature = "serde")]
45impl Serialize for TopicFilter {
46 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47 where
48 S: Serializer,
49 {
50 let mut data = vec![];
51
52 if self.topic0.need_serialize() {
53 data.push(&self.topic0)
54 }
55
56 if self.topic1.need_serialize() {
57 data.push(&self.topic1)
58 }
59
60 if self.topic2.need_serialize() {
61 data.push(&self.topic2)
62 }
63
64 if self.topic3.need_serialize() {
65 data.push(&self.topic3)
66 }
67
68 data.serialize(serializer)
69 }
70}
71
72#[cfg(feature = "serde")]
73impl<'de> Deserialize<'de> for TopicFilter {
74 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
75 where
76 D: serde::Deserializer<'de>,
77 {
78 let topics = Vec::<Topic<Hash>>::deserialize(deserializer)?;
79
80 if topics.len() > 4 || topics.is_empty() {
81 return Err(Error::Other("Topics > 4 or Topics == 0".into()))
82 .map_err(serde::de::Error::custom);
83 } else {
84 let none = Topic::<Hash>::Any;
85 let topic0 = topics[0].clone();
86
87 let topic1 = topics.get(1).unwrap_or(&none).clone();
88
89 let topic2 = topics.get(2).unwrap_or(&none).clone();
90
91 let topic3 = topics.get(3).unwrap_or(&none).clone();
92
93 Ok(TopicFilter {
94 topic0,
95 topic1,
96 topic2,
97 topic3,
98 })
99 }
100 }
101}
102
103#[derive(Debug, PartialEq, Eq, Clone, Hash)]
105pub enum Topic<T> {
106 None,
108 Any,
110 OneOf(Vec<T>),
112 This(T),
114}
115
116impl<T> Topic<T> {
117 pub fn map<F, O>(self, f: F) -> Topic<O>
119 where
120 F: Fn(T) -> O,
121 {
122 match self {
123 Topic::None => Topic::None,
124 Topic::Any => Topic::Any,
125 Topic::OneOf(topics) => Topic::OneOf(topics.into_iter().map(f).collect()),
126 Topic::This(topic) => Topic::This(f(topic)),
127 }
128 }
129
130 pub fn is_any(&self) -> bool {
132 match *self {
133 Topic::Any => true,
134 Topic::None | Topic::This(_) | Topic::OneOf(_) => false,
135 }
136 }
137 pub fn need_serialize(&self) -> bool {
139 match *self {
140 Topic::None => false,
141 _ => true,
142 }
143 }
144}
145
146impl<T> Default for Topic<T> {
147 fn default() -> Self {
148 Topic::None
149 }
150}
151
152impl<T> From<Option<T>> for Topic<T> {
153 fn from(o: Option<T>) -> Self {
154 match o {
155 Some(topic) => Topic::This(topic),
156 None => Topic::Any,
157 }
158 }
159}
160
161impl<T> From<T> for Topic<T> {
162 fn from(topic: T) -> Self {
163 Topic::This(topic)
164 }
165}
166
167impl<T> From<Vec<T>> for Topic<T> {
168 fn from(topics: Vec<T>) -> Self {
169 Topic::OneOf(topics)
170 }
171}
172
173impl<T> From<Topic<T>> for Vec<T> {
174 fn from(topic: Topic<T>) -> Self {
175 match topic {
176 Topic::None => vec![],
177 Topic::Any => vec![],
178 Topic::This(topic) => vec![topic],
179 Topic::OneOf(topics) => topics,
180 }
181 }
182}
183
184#[cfg(feature = "serde")]
185impl Serialize for Topic<Hash> {
186 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187 where
188 S: Serializer,
189 {
190 match *self {
191 Topic::Any | Topic::None => Option::<()>::None.serialize(serializer),
192 Topic::OneOf(ref vec) => vec.serialize(serializer),
193 Topic::This(ref hash) => hash.serialize(serializer),
194 }
195 }
196}
197
198#[cfg(feature = "serde")]
199impl<'de> Deserialize<'de> for Topic<Hash> {
200 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
201 where
202 D: serde::Deserializer<'de>,
203 {
204 struct TopicVisitor;
205
206 impl<'de> Visitor<'de> for TopicVisitor {
207 type Value = Topic<Hash>;
208 fn expecting(&self, formatter: &mut alloc::fmt::Formatter) -> alloc::fmt::Result {
209 write!(formatter, "Expect null/h256/[h256]")
210 }
211
212 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
213 where
214 E: serde::de::Error,
215 {
216 let topic = H256::from_str(v).map_err(serde::de::Error::custom)?;
217
218 Ok(Topic::This(topic))
219 }
220
221 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
222 where
223 A: serde::de::SeqAccess<'de>,
224 {
225 let mut topics = vec![];
226
227 while let Some(el) = seq.next_element::<&str>()? {
228 let topic = H256::from_str(el).map_err(serde::de::Error::custom)?;
229
230 topics.push(topic);
231 }
232
233 Ok(Topic::OneOf(topics))
234 }
235
236 fn visit_none<E>(self) -> Result<Self::Value, E>
237 where
238 E: serde::de::Error,
239 {
240 Ok(Topic::Any)
241 }
242
243 fn visit_unit<E>(self) -> Result<Self::Value, E>
244 where
245 E: serde::de::Error,
246 {
247 Ok(Topic::Any)
248 }
249 }
250
251 deserializer.deserialize_any(TopicVisitor {})
252 }
253}
254
255impl<T> ops::Index<usize> for Topic<T> {
256 type Output = T;
257
258 fn index(&self, index: usize) -> &Self::Output {
259 match *self {
260 Topic::Any | Topic::None => panic!("Topic unavailable"),
261 Topic::This(ref topic) => {
262 if index != 0 {
263 panic!("Topic unavailable");
264 }
265 topic
266 }
267 Topic::OneOf(ref topics) => topics.index(index),
268 }
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use super::Topic;
275 #[cfg(feature = "serde")]
276 use super::TopicFilter;
277 #[cfg(not(feature = "std"))]
278 use crate::no_std_prelude::*;
279 #[cfg(feature = "serde")]
280 use crate::Hash;
281
282 #[cfg(feature = "serde")]
283 fn hash(s: &'static str) -> Hash {
284 s.parse().unwrap()
285 }
286
287 #[cfg(feature = "serde")]
288 #[test]
289 fn test_topic_filter_serialization() {
290 let expected = r#"["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",null,["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b","0x0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"],null]"#;
291
292 let topic = TopicFilter {
293 topic0: Topic::This(hash(
294 "000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b",
295 )),
296 topic1: Topic::Any,
297 topic2: Topic::OneOf(vec![
298 hash("000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
299 hash("0000000000000000000000000aff3454fce5edbc8cca8697c15331677e6ebccc"),
300 ]),
301 topic3: Topic::Any,
302 };
303
304 let topic_str = serde_json::to_string(&topic).unwrap();
305
306 assert_eq!(expected, &topic_str);
307
308 let expected_topic: TopicFilter = serde_json::from_str(&topic_str).unwrap();
309
310 assert_eq!(expected_topic, topic);
311 }
312
313 #[test]
314 fn test_topic_from() {
315 assert_eq!(Topic::Any as Topic<u64>, None.into());
316 assert_eq!(Topic::This(10u64), 10u64.into());
317 assert_eq!(Topic::OneOf(vec![10u64, 20]), vec![10u64, 20].into());
318 }
319
320 #[test]
321 fn test_topic_into_vec() {
322 let expected: Vec<u64> = vec![];
323 let is: Vec<u64> = (Topic::Any as Topic<u64>).into();
324 assert_eq!(expected, is);
325 let expected: Vec<u64> = vec![10];
326 let is: Vec<u64> = Topic::This(10u64).into();
327 assert_eq!(expected, is);
328 let expected: Vec<u64> = vec![10, 20];
329 let is: Vec<u64> = Topic::OneOf(vec![10u64, 20]).into();
330 assert_eq!(expected, is);
331 }
332
333 #[test]
334 fn test_topic_is_any() {
335 assert!((Topic::Any as Topic<u8>).is_any());
336 assert!(!Topic::OneOf(vec![10u64, 20]).is_any());
337 assert!(!Topic::This(10u64).is_any());
338 }
339
340 #[test]
341 fn test_topic_index() {
342 assert_eq!(Topic::OneOf(vec![10u64, 20])[0], 10);
343 assert_eq!(Topic::OneOf(vec![10u64, 20])[1], 20);
344 assert_eq!(Topic::This(10u64)[0], 10);
345 }
346
347 #[test]
348 #[should_panic(expected = "Topic unavailable")]
349 fn test_topic_index_panic() {
350 let _ = (Topic::Any as Topic<u8>)[0];
351 }
352
353 #[test]
354 #[should_panic(expected = "Topic unavailable")]
355 fn test_topic_index_panic2() {
356 assert_eq!(Topic::This(10u64)[1], 10);
357 }
358}