Skip to main content

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