cosmwasm_std/results/
events.rs1use crate::__internal::forward_ref_partial_eq;
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4
5use crate::prelude::*;
6
7#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)]
16#[non_exhaustive]
17pub struct Event {
18 #[serde(rename = "type")]
20 pub ty: String,
21 pub attributes: Vec<Attribute>,
27}
28
29forward_ref_partial_eq!(Event, Event);
30
31impl Event {
32 pub fn new(ty: impl Into<String>) -> Self {
34 Event {
35 ty: ty.into(),
36 attributes: Vec::with_capacity(10),
37 }
38 }
39
40 pub fn add_attribute(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
42 self.attributes.push(Attribute {
43 key: key.into(),
44 value: value.into(),
45 });
46 self
47 }
48
49 pub fn add_attributes<A: Into<Attribute>>(
54 mut self,
55 attrs: impl IntoIterator<Item = A>,
56 ) -> Self {
57 self.attributes.extend(attrs.into_iter().map(A::into));
58 self
59 }
60}
61
62#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, JsonSchema)]
64pub struct Attribute {
65 pub key: String,
66 pub value: String,
67}
68
69forward_ref_partial_eq!(Attribute, Attribute);
70
71impl Attribute {
72 pub fn new(key: impl Into<String>, value: impl Into<String>) -> Self {
74 let key = key.into();
75
76 #[cfg(debug_assertions)]
77 if key.starts_with('_') {
78 panic!(
79 "attribute key `{key}` is invalid - keys starting with an underscore are reserved"
80 );
81 }
82
83 Self {
84 key,
85 value: value.into(),
86 }
87 }
88}
89
90impl<K: Into<String>, V: Into<String>> From<(K, V)> for Attribute {
91 fn from((k, v): (K, V)) -> Self {
92 Attribute::new(k, v)
93 }
94}
95
96impl<K: AsRef<str>, V: AsRef<str>> PartialEq<(K, V)> for Attribute {
97 fn eq(&self, (k, v): &(K, V)) -> bool {
98 (self.key.as_str(), self.value.as_str()) == (k.as_ref(), v.as_ref())
99 }
100}
101
102impl<K: AsRef<str>, V: AsRef<str>> PartialEq<Attribute> for (K, V) {
103 fn eq(&self, attr: &Attribute) -> bool {
104 attr == self
105 }
106}
107
108impl<K: AsRef<str>, V: AsRef<str>> PartialEq<(K, V)> for &Attribute {
109 fn eq(&self, (k, v): &(K, V)) -> bool {
110 (self.key.as_str(), self.value.as_str()) == (k.as_ref(), v.as_ref())
111 }
112}
113
114impl<K: AsRef<str>, V: AsRef<str>> PartialEq<&Attribute> for (K, V) {
115 fn eq(&self, attr: &&Attribute) -> bool {
116 attr == self
117 }
118}
119
120#[inline]
122pub fn attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
123 Attribute::new(key, value)
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129 use crate::Uint128;
130
131 #[test]
132 fn event_construction() {
133 let event_direct = Event {
134 ty: "test".to_string(),
135 attributes: vec![attr("foo", "bar"), attr("bar", "baz")],
136 };
137 let event_builder = Event::new("test").add_attributes(vec![("foo", "bar"), ("bar", "baz")]);
138
139 assert_eq!(event_direct, event_builder);
140 }
141
142 #[test]
143 #[should_panic]
144 fn attribute_new_reserved_key_panicks() {
145 Attribute::new("_invalid", "value");
146 }
147
148 #[test]
149 #[should_panic]
150 fn attribute_new_reserved_key_panicks2() {
151 Attribute::new("_", "value");
152 }
153
154 #[test]
155 fn attr_works_for_different_types() {
156 let expected = ("foo", "42");
157
158 assert_eq!(attr("foo", "42"), expected);
159 assert_eq!(attr("foo", "42"), expected);
160 assert_eq!(attr("foo", "42"), expected);
161 assert_eq!(attr("foo", Uint128::new(42)), expected);
162 }
163}