ruma_common/identifiers.rs
1//! Types for [Matrix](https://matrix.org/) identifiers for devices, events, keys, rooms, servers,
2//! users and URIs.
3
4// FIXME: Remove once lint doesn't trigger on std::convert::TryFrom in identifiers/macros.rs anymore
5#![allow(unused_qualifications)]
6
7#[doc(inline)]
8pub use ruma_identifiers_validation::{
9 ID_MAX_BYTES, KeyName,
10 error::{
11 Error as IdParseError, MatrixIdError, MatrixToError, MatrixUriError, MxcUriError,
12 VoipVersionIdError,
13 },
14};
15use serde::de::{self, Deserializer, Unexpected};
16
17#[doc(inline)]
18pub use self::{
19 base64_public_key::{Base64PublicKey, OwnedBase64PublicKey},
20 base64_public_key_or_device_id::{Base64PublicKeyOrDeviceId, OwnedBase64PublicKeyOrDeviceId},
21 client_secret::{ClientSecret, OwnedClientSecret},
22 crypto_algorithms::{
23 DeviceKeyAlgorithm, EventEncryptionAlgorithm, KeyDerivationAlgorithm, OneTimeKeyAlgorithm,
24 SigningKeyAlgorithm,
25 },
26 device_id::{DeviceId, OwnedDeviceId},
27 direct_user_identifier::{DirectUserIdentifier, OwnedDirectUserIdentifier},
28 event_id::{EventId, OwnedEventId},
29 key_id::{
30 AnyKeyName, CrossSigningKeyId, CrossSigningOrDeviceSigningKeyId, DeviceKeyId,
31 DeviceSigningKeyId, KeyAlgorithm, KeyId, OneTimeKeyId, OwnedCrossSigningKeyId,
32 OwnedCrossSigningOrDeviceSigningKeyId, OwnedDeviceKeyId, OwnedDeviceSigningKeyId,
33 OwnedKeyId, OwnedOneTimeKeyId, OwnedServerSigningKeyId, OwnedSigningKeyId,
34 ServerSigningKeyId, SigningKeyId,
35 },
36 matrix_uri::{MatrixToUri, MatrixUri},
37 mxc_uri::{MxcUri, OwnedMxcUri},
38 one_time_key_name::{OneTimeKeyName, OwnedOneTimeKeyName},
39 room_alias_id::{OwnedRoomAliasId, RoomAliasId},
40 room_id::{OwnedRoomId, RoomId},
41 room_or_alias_id::{OwnedRoomOrAliasId, RoomOrAliasId},
42 room_version_id::RoomVersionId,
43 server_name::{OwnedServerName, ServerName},
44 server_signing_key_version::{OwnedServerSigningKeyVersion, ServerSigningKeyVersion},
45 session_id::{OwnedSessionId, SessionId},
46 signatures::{
47 CrossSigningOrDeviceSignatures, DeviceSignatures, EntitySignatures, ServerSignatures,
48 Signatures,
49 },
50 space_child_order::{OwnedSpaceChildOrder, SpaceChildOrder},
51 transaction_id::{OwnedTransactionId, TransactionId},
52 user_id::{OwnedUserId, UserId},
53 voip_id::{OwnedVoipId, VoipId},
54 voip_version_id::VoipVersionId,
55};
56
57pub mod matrix_uri;
58pub mod user_id;
59
60mod base64_public_key;
61mod base64_public_key_or_device_id;
62mod client_secret;
63mod crypto_algorithms;
64mod device_id;
65mod direct_user_identifier;
66mod event_id;
67mod key_id;
68mod mxc_uri;
69mod one_time_key_name;
70mod room_alias_id;
71mod room_id;
72mod room_or_alias_id;
73mod room_version_id;
74mod server_name;
75mod server_signing_key_version;
76mod session_id;
77mod signatures;
78mod space_child_order;
79mod transaction_id;
80mod voip_id;
81mod voip_version_id;
82
83/// Generates a random identifier localpart.
84#[cfg(feature = "rand")]
85fn generate_localpart(length: usize) -> Box<str> {
86 use rand::RngExt as _;
87 rand::rng()
88 .sample_iter(&rand::distr::Alphanumeric)
89 .map(char::from)
90 .take(length)
91 .collect::<String>()
92 .into_boxed_str()
93}
94
95/// Find the localpart in the given identifier string.
96///
97/// This function expects the string to start with a sigil and the localpart to be the part between
98/// the sigil and the first colon. If there is no colon, the full string after the sigil is assumed
99/// to be the localpart.
100fn find_localpart(s: &str) -> &str {
101 let without_sigil = &s[1..];
102 without_sigil.find(':').map(|idx| &without_sigil[..idx]).unwrap_or(without_sigil)
103}
104
105/// Find the server name in the given identifier string and return it as a `&str`.
106///
107/// This function expects the server name to be the part of the string after the first colon.
108///
109/// Returns `None` if there is no colon in the string.
110fn find_server_name_str(s: &str) -> Option<&str> {
111 s.find(':').map(|idx| &s[idx + 1..])
112}
113
114/// Find the server name from the given identifier string an return it as a `ServerName`.
115///
116/// This function expects the server name to be the part of the string after the first colon, and
117/// that it was already validated.
118///
119/// Returns `None` if there is no colon in the string.
120fn find_server_name_unchecked(s: &str) -> Option<&ServerName> {
121 find_server_name_str(s).map(ServerName::from_borrowed_unchecked)
122}
123
124/// Deserializes any type of id using the provided `TryFrom` implementation.
125///
126/// This is a helper function to reduce the boilerplate of the `Deserialize` implementations.
127fn deserialize_id<'de, D, T>(deserializer: D, expected_str: &str) -> Result<T, D::Error>
128where
129 D: Deserializer<'de>,
130 T: for<'a> TryFrom<&'a str>,
131{
132 crate::serde::deserialize_cow_str(deserializer).and_then(|v| {
133 T::try_from(&v).map_err(|_| de::Error::invalid_value(Unexpected::Str(&v), &expected_str))
134 })
135}
136
137#[doc(hidden)]
138pub mod __private_macros {
139 pub use ruma_macros::{
140 base64_public_key, event_id, mxc_uri, room_alias_id, room_id, room_version_id, server_name,
141 server_signing_key_version, user_id,
142 };
143}
144
145/// Compile-time checked [`&'static Base64PublicKey`][Base64PublicKey] construction.
146#[macro_export]
147macro_rules! base64_public_key {
148 ($s:literal) => {
149 $crate::__private_macros::base64_public_key!($crate, $s)
150 };
151}
152
153/// Compile-time checked [`&'static Base64PublicKey`][Base64PublicKey] construction.
154///
155/// This is currently equivalent to [`base64_public_key!`]. However there is a plan to remove
156/// identifier DST types, so that other macro's return type will change while this macro is
157/// guaranteed to keep its return type. This macro allows to ease the transition for the expected
158/// change by allowing to migrate tests in advance.
159///
160/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
161/// identifier type removal.
162#[cfg(feature = "unstable-identifier-ref-macros")]
163#[macro_export]
164macro_rules! base64_public_key_ref {
165 ($s:literal) => {
166 $crate::base64_public_key!($s)
167 };
168}
169
170/// Compile-time checked [`OwnedBase64PublicKey`] construction.
171#[macro_export]
172macro_rules! owned_base64_public_key {
173 ($s:literal) => {
174 $crate::base64_public_key!($s).to_owned()
175 };
176}
177
178/// [`&'static DeviceId`][DeviceId] construction.
179#[macro_export]
180macro_rules! device_id {
181 ($s:expr) => {
182 <&$crate::DeviceId as ::std::convert::From<_>>::from($s)
183 };
184}
185
186/// [`&'static DeviceId`][DeviceId] construction.
187///
188/// This is currently equivalent to [`device_id!`]. However there is a plan to remove identifier DST
189/// types, so that other macro's return type will change while this macro is guaranteed to keep its
190/// return type. This macro allows to ease the transition for the expected change by allowing to
191/// migrate tests in advance.
192///
193/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
194/// identifier type removal.
195#[cfg(feature = "unstable-identifier-ref-macros")]
196#[macro_export]
197macro_rules! device_id_ref {
198 ($s:literal) => {
199 $crate::device_id!($s)
200 };
201}
202
203/// [`OwnedDeviceId`] construction.
204#[macro_export]
205macro_rules! owned_device_id {
206 ($s:expr) => {
207 <$crate::OwnedDeviceId as ::std::convert::From<_>>::from($s)
208 };
209}
210
211/// Compile-time checked [`&'static EventId`][EventId] construction.
212#[macro_export]
213macro_rules! event_id {
214 ($s:literal) => {
215 $crate::__private_macros::event_id!($crate, $s)
216 };
217}
218
219/// Compile-time checked [`&'static EventId`][EventId] construction.
220///
221/// This is currently equivalent to [`event_id!`]. However there is a plan to remove identifier DST
222/// types, so that other macro's return type will change while this macro is guaranteed to keep its
223/// return type. This macro allows to ease the transition for the expected change by allowing to
224/// migrate tests in advance.
225///
226/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
227/// identifier type removal.
228#[cfg(feature = "unstable-identifier-ref-macros")]
229#[macro_export]
230macro_rules! event_id_ref {
231 ($s:literal) => {
232 $crate::event_id!($s)
233 };
234}
235
236/// Compile-time checked [`OwnedEventId`] construction.
237#[macro_export]
238macro_rules! owned_event_id {
239 ($s:literal) => {
240 $crate::event_id!($s).to_owned()
241 };
242}
243
244/// Compile-time checked [`&'static MxcUri`][MxcUri] construction.
245#[macro_export]
246macro_rules! mxc_uri {
247 ($s:literal) => {
248 $crate::__private_macros::mxc_uri!($crate, $s)
249 };
250}
251
252/// Compile-time checked [`&'static MxcUri`][MxcUri] construction.
253///
254/// This is currently equivalent to [`mxc_uri!`]. However there is a plan to remove identifier DST
255/// types, so that other macro's return type will change while this macro is guaranteed to keep its
256/// return type. This macro allows to ease the transition for the expected change by allowing to
257/// migrate tests in advance.
258///
259/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
260/// identifier type removal.
261#[cfg(feature = "unstable-identifier-ref-macros")]
262#[macro_export]
263macro_rules! mxc_uri_ref {
264 ($s:literal) => {
265 $crate::mxc_uri!($s)
266 };
267}
268
269/// Compile-time checked [`OwnedMxcUri`] construction.
270#[macro_export]
271macro_rules! owned_mxc_uri {
272 ($s:literal) => {
273 $crate::mxc_uri!($s).to_owned()
274 };
275}
276
277/// Compile-time checked [`&'static RoomAliasId`][RoomAliasId] construction.
278#[macro_export]
279macro_rules! room_alias_id {
280 ($s:literal) => {
281 $crate::__private_macros::room_alias_id!($crate, $s)
282 };
283}
284
285/// Compile-time checked [`&'static RoomAliasId`][RoomAliasId] construction.
286///
287/// This is currently equivalent to [`room_alias_id!`]. However there is a plan to remove identifier
288/// DST types, so that other macro's return type will change while this macro is guaranteed to keep
289/// its return type. This macro allows to ease the transition for the expected change by allowing to
290/// migrate tests in advance.
291///
292/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
293/// identifier type removal.
294#[cfg(feature = "unstable-identifier-ref-macros")]
295#[macro_export]
296macro_rules! room_alias_id_ref {
297 ($s:literal) => {
298 $crate::room_alias_id!($s)
299 };
300}
301
302/// Compile-time checked [`OwnedRoomAliasId`] construction.
303#[macro_export]
304macro_rules! owned_room_alias_id {
305 ($s:literal) => {
306 $crate::room_alias_id!($s).to_owned()
307 };
308}
309
310/// Compile-time checked [`&'static RoomId`][RoomId] construction.
311#[macro_export]
312macro_rules! room_id {
313 ($s:literal) => {
314 $crate::__private_macros::room_id!($crate, $s)
315 };
316}
317
318/// Compile-time checked [`&'static RoomId`][RoomId] construction.
319///
320/// This is currently equivalent to [`room_id!`]. However there is a plan to remove identifier
321/// DST types, so that other macro's return type will change while this macro is guaranteed to keep
322/// its return type. This macro allows to ease the transition for the expected change by allowing to
323/// migrate tests in advance.
324///
325/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
326/// identifier type removal.
327#[cfg(feature = "unstable-identifier-ref-macros")]
328#[macro_export]
329macro_rules! room_id_ref {
330 ($s:literal) => {
331 $crate::room_id!($s)
332 };
333}
334
335/// Compile-time checked [`OwnedRoomId`] construction.
336#[macro_export]
337macro_rules! owned_room_id {
338 ($s:literal) => {
339 $crate::room_id!($s).to_owned()
340 };
341}
342
343/// Compile-time checked [`RoomVersionId`] construction.
344#[macro_export]
345macro_rules! room_version_id {
346 ($s:literal) => {
347 $crate::__private_macros::room_version_id!($crate, $s)
348 };
349}
350
351/// Compile-time checked [`&'static ServerName`][ServerName] construction.
352#[macro_export]
353macro_rules! server_name {
354 ($s:literal) => {
355 $crate::__private_macros::server_name!($crate, $s)
356 };
357}
358
359/// Compile-time checked [`&'static ServerName`][ServerName] construction.
360///
361/// This is currently equivalent to [`server_name!`]. However there is a plan to remove identifier
362/// DST types, so that other macro's return type will change while this macro is guaranteed to keep
363/// its return type. This macro allows to ease the transition for the expected change by allowing to
364/// migrate tests in advance.
365///
366/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
367/// identifier type removal.
368#[cfg(feature = "unstable-identifier-ref-macros")]
369#[macro_export]
370macro_rules! server_name_ref {
371 ($s:literal) => {
372 $crate::server_name!($s)
373 };
374}
375
376/// Compile-time checked [`OwnedServerName`] construction.
377#[macro_export]
378macro_rules! owned_server_name {
379 ($s:literal) => {
380 $crate::server_name!($s).to_owned()
381 };
382}
383
384/// Compile-time checked [`&'static ServerSigningKeyVersion`][ServerSigningKeyVersion] construction.
385#[macro_export]
386macro_rules! server_signing_key_version {
387 ($s:literal) => {
388 $crate::__private_macros::server_signing_key_version!($crate, $s)
389 };
390}
391
392/// Compile-time checked [`&'static ServerSigningKeyVersion`][ServerSigningKeyVersion] construction.
393///
394/// This is currently equivalent to [`server_signing_key_version!`]. However there is a plan to
395/// remove identifier DST types, so that other macro's return type will change while this macro is
396/// guaranteed to keep its return type. This macro allows to ease the transition for the expected
397/// change by allowing to migrate tests in advance.
398///
399/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
400/// identifier type removal.
401#[cfg(feature = "unstable-identifier-ref-macros")]
402#[macro_export]
403macro_rules! server_signing_key_version_ref {
404 ($s:literal) => {
405 $crate::server_signing_key_version!($s)
406 };
407}
408
409/// Compile-time checked [`OwnedServerSigningKeyVersion`] construction.
410#[macro_export]
411macro_rules! owned_server_signing_key_version {
412 ($s:literal) => {
413 $crate::server_signing_key_version!($s).to_owned()
414 };
415}
416
417/// Compile-time checked [`&'static SessionId`][SessionId] construction.
418#[macro_export]
419macro_rules! session_id {
420 ($s:literal) => {{
421 const SESSION_ID: &$crate::SessionId = match $crate::SessionId::_priv_const_new($s) {
422 Ok(id) => id,
423 Err(e) => panic!("{}", e),
424 };
425
426 SESSION_ID
427 }};
428}
429
430/// Compile-time checked [`&'static SessionId`][SessionId] construction.
431///
432/// This is currently equivalent to [`session_id!`]. However there is a plan to remove identifier
433/// DST types, so that other macro's return type will change while this macro is guaranteed to keep
434/// its return type. This macro allows to ease the transition for the expected change by allowing to
435/// migrate tests in advance.
436///
437/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
438/// identifier type removal.
439#[cfg(feature = "unstable-identifier-ref-macros")]
440#[macro_export]
441macro_rules! session_id_ref {
442 ($s:literal) => {
443 $crate::session_id!($s)
444 };
445}
446
447/// Compile-time checked [`OwnedSessionId`] construction.
448#[macro_export]
449macro_rules! owned_session_id {
450 ($s:literal) => {
451 $crate::session_id!($s).to_owned()
452 };
453}
454
455/// Compile-time checked [`&'static UserId`][UserId] construction.
456#[macro_export]
457macro_rules! user_id {
458 ($s:literal) => {
459 $crate::__private_macros::user_id!($crate, $s)
460 };
461}
462
463/// Compile-time checked [`&'static UserId`][UserId] construction.
464///
465/// This is currently equivalent to [`user_id!`]. However there is a plan to remove identifier
466/// DST types, so that other macro's return type will change while this macro is guaranteed to keep
467/// its return type. This macro allows to ease the transition for the expected change by allowing to
468/// migrate tests in advance.
469///
470/// This is behind an unstable cargo feature because it is likely to be removed soon after the DST
471/// identifier type removal.
472#[cfg(feature = "unstable-identifier-ref-macros")]
473#[macro_export]
474macro_rules! user_id_ref {
475 ($s:literal) => {
476 $crate::user_id!($s)
477 };
478}
479
480/// Compile-time checked [`OwnedUserId`] construction.
481#[macro_export]
482macro_rules! owned_user_id {
483 ($s:literal) => {
484 $crate::user_id!($s).to_owned()
485 };
486}