1use serde::{Deserialize, Serialize};
2
3use crate::prelude::*;
4
5#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Hash)]
16pub struct Event {
17 #[serde(rename = "type", default)]
22 pub kind: String,
23
24 pub attributes: Vec<EventAttribute>,
26}
27
28#[derive(Clone, PartialEq, Eq, Debug, Deserialize, Serialize, Hash)]
41#[serde(untagged)]
42pub enum EventAttribute {
43 V037(v0_37::EventAttribute),
45
46 V034(v0_34::EventAttribute),
48}
49
50impl EventAttribute {
51 pub fn key_str(&self) -> Result<&str, crate::Error> {
54 match self {
55 EventAttribute::V034(attr) => {
56 core::str::from_utf8(&attr.key).map_err(|e| crate::Error::parse(e.to_string()))
57 },
58 EventAttribute::V037(attr) => Ok(&attr.key),
59 }
60 }
61
62 pub fn key_bytes(&self) -> &[u8] {
64 match self {
65 EventAttribute::V034(attr) => &attr.key,
66 EventAttribute::V037(attr) => attr.key.as_bytes(),
67 }
68 }
69
70 pub fn value_str(&self) -> Result<&str, crate::Error> {
73 match self {
74 EventAttribute::V034(attr) => {
75 core::str::from_utf8(&attr.value).map_err(|e| crate::Error::parse(e.to_string()))
76 },
77 EventAttribute::V037(attr) => Ok(&attr.value),
78 }
79 }
80
81 pub fn value_bytes(&self) -> &[u8] {
84 match self {
85 EventAttribute::V034(attr) => &attr.value,
86 EventAttribute::V037(attr) => attr.value.as_bytes(),
87 }
88 }
89
90 pub fn index(&self) -> bool {
92 match self {
93 EventAttribute::V034(attr) => attr.index,
94 EventAttribute::V037(attr) => attr.index,
95 }
96 }
97
98 pub fn set_index(&mut self, index: bool) {
100 match self {
101 EventAttribute::V034(attr) => attr.index = index,
102 EventAttribute::V037(attr) => attr.index = index,
103 }
104 }
105}
106
107impl Event {
108 pub fn new<K, I>(kind: K, attributes: I) -> Self
126 where
127 K: Into<String>,
128 I: IntoIterator,
129 I::Item: Into<EventAttribute>,
130 {
131 Self {
132 kind: kind.into(),
133 attributes: attributes.into_iter().map(Into::into).collect(),
134 }
135 }
136
137 pub fn eq_ignoring_index(&self, other: &Self) -> bool {
139 self.kind == other.kind
140 && self.attributes.len() == other.attributes.len()
143 && self
144 .attributes
145 .iter()
146 .zip(other.attributes.iter())
147 .all(|(a, b)| a.eq_ignoring_index(b))
148 }
149
150 pub fn hash_ignoring_index<H: core::hash::Hasher>(&self, state: &mut H) {
152 use core::hash::Hash;
153 self.kind.hash(state);
154 state.write_usize(self.attributes.len());
157 for attr in &self.attributes {
158 attr.hash_ignoring_index(state);
159 }
160 }
161}
162
163pub trait TypedEvent
183where
184 Self: TryFrom<Event>,
185 Event: From<Self>,
186{
187 fn into_event(self) -> Event {
189 self.into()
190 }
191}
192
193impl EventAttribute {
194 pub fn eq_ignoring_index(&self, other: &Self) -> bool {
196 match (self, other) {
197 (EventAttribute::V034(a), EventAttribute::V034(b)) => {
198 a.key == b.key && a.value == b.value
199 },
200 (EventAttribute::V037(a), EventAttribute::V037(b)) => {
201 a.key == b.key && a.value == b.value
202 },
203 _ => false,
205 }
206 }
207
208 pub fn hash_ignoring_index<H: core::hash::Hasher>(&self, state: &mut H) {
210 use core::hash::Hash;
211 match self {
213 EventAttribute::V034(attr) => {
214 (&attr.key, &attr.value).hash(state);
215 },
216 EventAttribute::V037(attr) => {
217 (&attr.key, &attr.value).hash(state);
218 },
219 }
220 }
221}
222
223impl<K: Into<String>, V: Into<String>> From<(K, V, bool)> for EventAttribute {
224 fn from((key, value, index): (K, V, bool)) -> Self {
225 Self::V037(v0_37::EventAttribute {
226 key: key.into(),
227 value: value.into(),
228 index,
229 })
230 }
231}
232
233#[allow(missing_docs)]
238pub trait EventAttributeIndexExt: private::Sealed {
239 type Key;
240 type Value;
241
242 fn index(self) -> (Self::Key, Self::Value, bool);
244 fn no_index(self) -> (Self::Key, Self::Value, bool);
246}
247
248impl<K: Into<String>, V: Into<String>> EventAttributeIndexExt for (K, V) {
249 type Key = K;
250 type Value = V;
251 fn index(self) -> (K, V, bool) {
252 let (key, value) = self;
253 (key, value, true)
254 }
255 fn no_index(self) -> (K, V, bool) {
256 let (key, value) = self;
257 (key, value, false)
258 }
259}
260
261mod private {
262 use crate::prelude::*;
263
264 pub trait Sealed {}
265
266 impl<K: Into<String>, V: Into<String>> Sealed for (K, V) {}
267}
268
269impl<K: Into<String>, V: Into<String>> From<(K, V)> for EventAttribute {
270 fn from((key, value): (K, V)) -> Self {
271 (key, value, false).into()
272 }
273}
274
275pub mod v0_34 {
280 use super::Event;
281 use crate::prelude::*;
282 use crate::serializers;
283
284 use serde::{Deserialize, Serialize};
285 use tendermint_proto::v0_34::abci as pb;
286 use tendermint_proto::Protobuf;
287
288 #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)]
295 pub struct EventAttribute {
296 #[serde(with = "serializers::bytes::base64string")]
298 pub key: Vec<u8>,
299
300 #[serde(with = "serializers::bytes::base64string")]
302 pub value: Vec<u8>,
303
304 pub index: bool,
308 }
309
310 impl From<EventAttribute> for pb::EventAttribute {
311 fn from(event: EventAttribute) -> Self {
312 Self {
313 key: event.key.into(),
314 value: event.value.into(),
315 index: event.index,
316 }
317 }
318 }
319
320 impl TryFrom<pb::EventAttribute> for EventAttribute {
321 type Error = crate::Error;
322
323 fn try_from(event: pb::EventAttribute) -> Result<Self, Self::Error> {
324 Ok(Self {
325 key: event.value.to_vec(),
326 value: event.value.to_vec(),
327 index: event.index,
328 })
329 }
330 }
331
332 impl Protobuf<pb::EventAttribute> for EventAttribute {}
333
334 impl From<Event> for pb::Event {
335 fn from(event: Event) -> Self {
336 Self {
337 r#type: event.kind,
338 attributes: event
339 .attributes
340 .into_iter()
341 .filter_map(|t| {
342 let super::EventAttribute::V034(ea) = t else {
343 return None;
344 };
345 Some(ea.into())
346 })
347 .collect(),
348 }
349 }
350 }
351
352 impl TryFrom<pb::Event> for Event {
353 type Error = crate::Error;
354
355 fn try_from(event: pb::Event) -> Result<Self, Self::Error> {
356 Ok(Self {
357 kind: event.r#type,
358 attributes: event
359 .attributes
360 .into_iter()
361 .map(TryInto::try_into)
362 .collect::<Result<Vec<EventAttribute>, _>>()?
363 .into_iter()
364 .map(super::EventAttribute::V034)
365 .collect(),
366 })
367 }
368 }
369
370 impl Protobuf<pb::Event> for Event {}
371}
372
373pub mod v0_37 {
374 use super::Event;
375 use crate::prelude::*;
376 use crate::serializers;
377
378 use serde::{Deserialize, Serialize};
379 use tendermint_proto::v0_37::abci as pb;
380 use tendermint_proto::Protobuf;
381
382 #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize, Hash)]
389 pub struct EventAttribute {
390 #[serde(with = "serializers::allow_null")]
392 pub key: String,
393
394 #[serde(with = "serializers::allow_null")]
396 pub value: String,
397
398 pub index: bool,
402 }
403
404 impl From<EventAttribute> for pb::EventAttribute {
405 fn from(event: EventAttribute) -> Self {
406 Self {
407 key: event.key,
408 value: event.value,
409 index: event.index,
410 }
411 }
412 }
413
414 impl TryFrom<pb::EventAttribute> for EventAttribute {
415 type Error = crate::Error;
416
417 fn try_from(event: pb::EventAttribute) -> Result<Self, Self::Error> {
418 Ok(Self {
419 key: event.key,
420 value: event.value,
421 index: event.index,
422 })
423 }
424 }
425
426 impl Protobuf<pb::EventAttribute> for EventAttribute {}
427
428 impl From<Event> for pb::Event {
429 fn from(event: Event) -> Self {
430 Self {
431 r#type: event.kind,
432 attributes: event
433 .attributes
434 .into_iter()
435 .filter_map(|t| {
436 let super::EventAttribute::V037(ea) = t else {
437 return None;
438 };
439 Some(ea.into())
440 })
441 .collect(),
442 }
443 }
444 }
445
446 impl TryFrom<pb::Event> for Event {
447 type Error = crate::Error;
448
449 fn try_from(event: pb::Event) -> Result<Self, Self::Error> {
450 Ok(Self {
451 kind: event.r#type,
452 attributes: event
453 .attributes
454 .into_iter()
455 .map(TryInto::try_into)
456 .collect::<Result<Vec<EventAttribute>, _>>()?
457 .into_iter()
458 .map(super::EventAttribute::V037)
459 .collect(),
460 })
461 }
462 }
463
464 impl Protobuf<pb::Event> for Event {}
465}
466
467mod v0_38 {
468 use super::Event;
469 use crate::prelude::*;
470
471 use tendermint_proto::v0_38::abci as pb;
472 use tendermint_proto::Protobuf;
473
474 pub use super::v0_37::EventAttribute;
475
476 impl From<EventAttribute> for pb::EventAttribute {
477 fn from(event: EventAttribute) -> Self {
478 Self {
479 key: event.key,
480 value: event.value,
481 index: event.index,
482 }
483 }
484 }
485
486 impl TryFrom<pb::EventAttribute> for EventAttribute {
487 type Error = crate::Error;
488
489 fn try_from(event: pb::EventAttribute) -> Result<Self, Self::Error> {
490 Ok(Self {
491 key: event.key,
492 value: event.value,
493 index: event.index,
494 })
495 }
496 }
497
498 impl Protobuf<pb::EventAttribute> for EventAttribute {}
499
500 impl From<Event> for pb::Event {
501 fn from(event: Event) -> Self {
502 Self {
503 r#type: event.kind,
504 attributes: event
505 .attributes
506 .into_iter()
507 .filter_map(|t| {
508 let super::EventAttribute::V037(ea) = t else {
509 return None;
510 };
511 Some(ea.into())
512 })
513 .collect(),
514 }
515 }
516 }
517
518 impl TryFrom<pb::Event> for Event {
519 type Error = crate::Error;
520
521 fn try_from(event: pb::Event) -> Result<Self, Self::Error> {
522 Ok(Self {
523 kind: event.r#type,
524 attributes: event
525 .attributes
526 .into_iter()
527 .map(TryInto::try_into)
528 .collect::<Result<Vec<EventAttribute>, _>>()?
529 .into_iter()
530 .map(super::EventAttribute::V037)
531 .collect(),
532 })
533 }
534 }
535
536 impl Protobuf<pb::Event> for Event {}
537}
538
539#[cfg(test)]
540#[allow(clippy::bool_assert_comparison)]
541#[allow(clippy::redundant_clone)]
542mod tests {
543
544 use serde::Deserialize;
545
546 use super::*;
547
548 #[test]
549 fn event_eq_ignoring_index_ignores_index() {
550 let event_a = Event::new("test", [("foo", "bar").index()]);
551 let event_b = Event::new("test", [("foo", "bar").no_index()]);
552 let event_c = Event::new("test", [("foo", "baz").index()]);
553
554 assert_eq!(event_a.eq_ignoring_index(&event_b), true);
555 assert_eq!(event_a.eq_ignoring_index(&event_c), false);
556 }
557
558 #[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
559 struct Payload {
560 x: u32,
561 y: u32,
562 }
563
564 #[derive(Clone, Debug, PartialEq, Eq)]
565 struct MyEvent {
566 a: Payload,
567 b: Payload,
568 }
569
570 impl From<MyEvent> for Event {
571 fn from(event: MyEvent) -> Self {
572 Event::new(
573 "my_event",
574 vec![
575 ("a", serde_json::to_string(&event.a).unwrap()).index(),
576 ("b", serde_json::to_string(&event.b).unwrap()).index(),
577 ],
578 )
579 }
580 }
581
582 impl TryFrom<Event> for MyEvent {
583 type Error = (); fn try_from(event: Event) -> Result<Self, Self::Error> {
586 if event.kind != "my_event" {
587 return Err(());
588 }
589
590 let a = event
591 .attributes
592 .iter()
593 .find(|attr| attr.key_bytes() == b"a")
594 .ok_or(())
595 .and_then(|attr| serde_json::from_slice(attr.value_bytes()).map_err(|_| ()))?;
596 let b = event
597 .attributes
598 .iter()
599 .find(|attr| attr.key_bytes() == b"b")
600 .ok_or(())
601 .and_then(|attr| serde_json::from_slice(attr.value_bytes()).map_err(|_| ()))?;
602
603 Ok(MyEvent { a, b })
604 }
605 }
606
607 impl TypedEvent for MyEvent {}
608
609 #[test]
610 fn exercise_typed_event() {
611 let t = MyEvent {
612 a: Payload { x: 1, y: 2 },
613 b: Payload { x: 3, y: 4 },
614 };
615
616 let e1 = Event::from(t.clone());
617 let e2 = {
619 let mut e = e1.clone();
620 e.attributes[0].set_index(false);
621 e.attributes[1].set_index(false);
622 e
623 };
624
625 assert_eq!(e1.eq_ignoring_index(&e2), true);
630 assert_eq!(MyEvent::try_from(e1.clone()), Ok(t.clone()));
631 assert_eq!(MyEvent::try_from(e2.clone()), Ok(t.clone()));
632
633 assert_eq!(
636 Event::from(MyEvent::try_from(e1.clone()).unwrap()).eq_ignoring_index(&e1),
637 true
638 );
639 assert_eq!(
640 Event::from(MyEvent::try_from(e2.clone()).unwrap()).eq_ignoring_index(&e2),
641 true
642 );
643 }
644}