ruma_common/identifiers/
event_id.rs1use ruma_macros::IdDst;
4
5use super::ServerName;
6
7#[repr(transparent)]
39#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, IdDst)]
40#[ruma_id(validate = ruma_identifiers_validation::event_id::validate)]
41pub struct EventId(str);
42
43impl EventId {
44 #[cfg(feature = "rand")]
50 #[allow(clippy::new_ret_no_self)]
51 pub fn new(server_name: &ServerName) -> OwnedEventId {
52 OwnedEventId::from_string_unchecked(format!(
53 "${}:{server_name}",
54 super::generate_localpart(18)
55 ))
56 }
57
58 pub fn localpart(&self) -> &str {
64 let idx = self.colon_idx().unwrap_or_else(|| self.as_str().len());
65 &self.as_str()[1..idx]
66 }
67
68 pub fn server_name(&self) -> Option<&ServerName> {
72 self.colon_idx().map(|idx| ServerName::from_borrowed_unchecked(&self.as_str()[idx + 1..]))
73 }
74
75 fn colon_idx(&self) -> Option<usize> {
76 self.as_str().find(':')
77 }
78}
79
80#[cfg(test)]
81mod tests {
82 use super::{EventId, OwnedEventId};
83 use crate::IdParseError;
84
85 #[test]
86 fn valid_original_event_id() {
87 assert_eq!(
88 <&EventId>::try_from("$39hvsi03hlne:example.com").expect("Failed to create EventId."),
89 "$39hvsi03hlne:example.com"
90 );
91 }
92
93 #[test]
94 fn valid_base64_event_id() {
95 assert_eq!(
96 <&EventId>::try_from("$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk")
97 .expect("Failed to create EventId."),
98 "$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk"
99 );
100 }
101
102 #[test]
103 fn valid_url_safe_base64_event_id() {
104 assert_eq!(
105 <&EventId>::try_from("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg")
106 .expect("Failed to create EventId."),
107 "$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg"
108 );
109 }
110
111 #[cfg(feature = "rand")]
112 #[test]
113 fn generate_random_valid_event_id() {
114 use crate::server_name;
115
116 let event_id = EventId::new(server_name!("example.com"));
117 let id_str = event_id.as_str();
118
119 assert!(id_str.starts_with('$'));
120 assert_eq!(id_str.len(), 31);
121 }
122
123 #[test]
124 fn serialize_valid_original_event_id() {
125 assert_eq!(
126 serde_json::to_string(
127 <&EventId>::try_from("$39hvsi03hlne:example.com")
128 .expect("Failed to create EventId.")
129 )
130 .expect("Failed to convert EventId to JSON."),
131 r#""$39hvsi03hlne:example.com""#
132 );
133 }
134
135 #[test]
136 fn serialize_valid_base64_event_id() {
137 assert_eq!(
138 serde_json::to_string(
139 <&EventId>::try_from("$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk")
140 .expect("Failed to create EventId.")
141 )
142 .expect("Failed to convert EventId to JSON."),
143 r#""$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk""#
144 );
145 }
146
147 #[test]
148 fn serialize_valid_url_safe_base64_event_id() {
149 assert_eq!(
150 serde_json::to_string(
151 <&EventId>::try_from("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg")
152 .expect("Failed to create EventId.")
153 )
154 .expect("Failed to convert EventId to JSON."),
155 r#""$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg""#
156 );
157 }
158
159 #[test]
160 fn deserialize_valid_original_event_id() {
161 assert_eq!(
162 serde_json::from_str::<OwnedEventId>(r#""$39hvsi03hlne:example.com""#)
163 .expect("Failed to convert JSON to EventId"),
164 <&EventId>::try_from("$39hvsi03hlne:example.com").expect("Failed to create EventId.")
165 );
166 }
167
168 #[test]
169 fn deserialize_valid_base64_event_id() {
170 assert_eq!(
171 serde_json::from_str::<OwnedEventId>(
172 r#""$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk""#
173 )
174 .expect("Failed to convert JSON to EventId"),
175 <&EventId>::try_from("$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk")
176 .expect("Failed to create EventId.")
177 );
178 }
179
180 #[test]
181 fn deserialize_valid_url_safe_base64_event_id() {
182 assert_eq!(
183 serde_json::from_str::<OwnedEventId>(
184 r#""$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg""#
185 )
186 .expect("Failed to convert JSON to EventId"),
187 <&EventId>::try_from("$Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg")
188 .expect("Failed to create EventId.")
189 );
190 }
191
192 #[test]
193 fn valid_original_event_id_with_explicit_standard_port() {
194 assert_eq!(
195 <&EventId>::try_from("$39hvsi03hlne:example.com:443")
196 .expect("Failed to create EventId."),
197 "$39hvsi03hlne:example.com:443"
198 );
199 }
200
201 #[test]
202 fn valid_original_event_id_with_non_standard_port() {
203 assert_eq!(
204 <&EventId>::try_from("$39hvsi03hlne:example.com:5000")
205 .expect("Failed to create EventId."),
206 "$39hvsi03hlne:example.com:5000"
207 );
208 }
209
210 #[test]
211 fn missing_original_event_id_sigil() {
212 assert_eq!(
213 <&EventId>::try_from("39hvsi03hlne:example.com").unwrap_err(),
214 IdParseError::MissingLeadingSigil
215 );
216 }
217
218 #[test]
219 fn missing_base64_event_id_sigil() {
220 assert_eq!(
221 <&EventId>::try_from("acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk").unwrap_err(),
222 IdParseError::MissingLeadingSigil
223 );
224 }
225
226 #[test]
227 fn missing_url_safe_base64_event_id_sigil() {
228 assert_eq!(
229 <&EventId>::try_from("Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg").unwrap_err(),
230 IdParseError::MissingLeadingSigil
231 );
232 }
233
234 #[test]
235 fn invalid_event_id_host() {
236 assert_eq!(
237 <&EventId>::try_from("$39hvsi03hlne:/").unwrap_err(),
238 IdParseError::InvalidServerName
239 );
240 }
241
242 #[test]
243 fn invalid_event_id_port() {
244 assert_eq!(
245 <&EventId>::try_from("$39hvsi03hlne:example.com:notaport").unwrap_err(),
246 IdParseError::InvalidServerName
247 );
248 }
249}