Skip to main content

matrix_sdk_test/
identifiers.rs

1//! Matrix identifiers.
2
3use std::{fmt, hash::Hash, sync::LazyLock};
4
5use indexmap::Equivalent;
6use ruma::{
7    DeviceId, OwnedDeviceId, OwnedRoomAliasId, OwnedRoomId, OwnedRoomOrAliasId, OwnedUserId,
8    RoomAliasId, RoomId, RoomOrAliasId, UserId,
9    events::direct::{DirectUserIdentifier, OwnedDirectUserIdentifier},
10    owned_device_id, owned_room_alias_id, owned_room_id, owned_user_id,
11};
12use serde::Serialize;
13
14/// A Matrix user.
15///
16/// This can be converted to the following types with `.into()`:
17///
18/// - `&'static UserId`
19/// - `OwnedUserId`
20/// - `&'static DirectUserIdentifier`
21/// - `OwnedDirectUserIdentifier`
22///
23/// It implements `PartialEq` with all the ID types above, as well as with
24/// `serde_json::Value` to use with the `assert_eq!` macro.
25///
26/// It implements `Serialize` and `Into<String>` to use it with the `json!`
27/// macro.
28///
29/// It implements `Hash` and `Equivalent<OwnedUserId>` as well to be able to use
30/// it with methods like `IndexMap::get()` or `IndexMap::contains_key()`.
31///
32/// It can also be converted to a borrowed string with `.as_str()` to use it
33/// with methods like `HashMap::get()` or `HashSet::contains()`.
34#[derive(Debug, Clone, Copy)]
35pub enum User {
36    /// `@alice:server.name`
37    Alice,
38    /// `@bob:other.server`
39    Bob,
40    /// `@carol:other.server`
41    Carol,
42    /// The default user ID used when building a `Client` for tests,
43    /// `@example:localhost`.
44    Default,
45    /// `@ella:localhost`
46    Ella,
47}
48
49/// Alice's user ID.
50static ALICE_USER_ID: LazyLock<OwnedUserId> =
51    LazyLock::new(|| owned_user_id!("@alice:server.name"));
52/// Bob's user ID.
53static BOB_USER_ID: LazyLock<OwnedUserId> = LazyLock::new(|| owned_user_id!("@bob:other.server"));
54/// Carol's user ID.
55static CAROL_USER_ID: LazyLock<OwnedUserId> =
56    LazyLock::new(|| owned_user_id!("@carol:other.server"));
57/// Default user ID.
58static DEFAULT_USER_ID: LazyLock<OwnedUserId> =
59    LazyLock::new(|| owned_user_id!("@example:localhost"));
60/// Ella's user ID.
61static ELLA_USER_ID: LazyLock<OwnedUserId> = LazyLock::new(|| owned_user_id!("@ella:localhost"));
62
63impl User {
64    /// The user's ID.
65    ///
66    /// This unconventional return type allows to either clone the owned ID or
67    /// dereference it.
68    fn id(&self) -> &'static OwnedUserId {
69        match self {
70            User::Alice => &ALICE_USER_ID,
71            User::Bob => &BOB_USER_ID,
72            User::Carol => &CAROL_USER_ID,
73            User::Default => &DEFAULT_USER_ID,
74            User::Ella => &ELLA_USER_ID,
75        }
76    }
77
78    /// The user's ID as a `&str`.
79    pub fn as_str(&self) -> &'static str {
80        self.id().as_str()
81    }
82}
83
84impl From<User> for OwnedUserId {
85    fn from(user: User) -> Self {
86        user.id().clone()
87    }
88}
89
90impl From<User> for &'static UserId {
91    fn from(user: User) -> Self {
92        user.id()
93    }
94}
95
96impl From<User> for OwnedDirectUserIdentifier {
97    fn from(user: User) -> Self {
98        user.id().clone().into()
99    }
100}
101
102impl From<User> for &'static DirectUserIdentifier {
103    fn from(user: User) -> Self {
104        <&UserId>::from(user).into()
105    }
106}
107
108impl From<User> for String {
109    fn from(user: User) -> Self {
110        user.id().as_str().to_owned()
111    }
112}
113
114impl PartialEq<OwnedUserId> for User {
115    fn eq(&self, other: &OwnedUserId) -> bool {
116        self.id().eq(other)
117    }
118}
119
120impl PartialEq<User> for OwnedUserId {
121    fn eq(&self, other: &User) -> bool {
122        self.eq(other.id())
123    }
124}
125
126impl PartialEq<&OwnedUserId> for User {
127    fn eq(&self, other: &&OwnedUserId) -> bool {
128        self.id().eq(*other)
129    }
130}
131
132impl PartialEq<User> for &OwnedUserId {
133    fn eq(&self, other: &User) -> bool {
134        (*self).eq(other.id())
135    }
136}
137
138impl PartialEq<&UserId> for User {
139    fn eq(&self, other: &&UserId) -> bool {
140        self.id().eq(other)
141    }
142}
143
144impl PartialEq<User> for &UserId {
145    fn eq(&self, other: &User) -> bool {
146        self.eq(other.id())
147    }
148}
149
150impl PartialEq<serde_json::Value> for User {
151    fn eq(&self, other: &serde_json::Value) -> bool {
152        self.id().as_str().eq(other)
153    }
154}
155
156impl PartialEq<User> for serde_json::Value {
157    fn eq(&self, other: &User) -> bool {
158        self.eq(other.id().as_str())
159    }
160}
161
162impl Equivalent<OwnedUserId> for User {
163    fn equivalent(&self, key: &OwnedUserId) -> bool {
164        key.eq(self.id())
165    }
166}
167
168impl Hash for User {
169    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
170        self.id().hash(state);
171    }
172}
173
174impl Serialize for User {
175    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
176    where
177        S: serde::Serializer,
178    {
179        self.id().serialize(serializer)
180    }
181}
182
183impl fmt::Display for User {
184    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185        self.id().fmt(f)
186    }
187}
188
189/// A Matrix test room.
190///
191/// This can be converted to the following types with `.into()`:
192///
193/// - `&'static RoomId`
194/// - `OwnedRoomId`
195/// - `&'static RoomOrAliasId`
196/// - `OwnedRoomOrAliasId`
197///
198/// It implements `PartialEq` with all the ID types above, as well as with
199/// `serde_json::Value` to use with the `assert_eq!` macro.
200///
201/// It implements `Serialize` and `Into<String>` to use it with the `json!`
202/// macro.
203///
204/// It implements `Hash` and `Equivalent<OwnedRoomId>` as well to be able to use
205/// it with methods like `IndexMap::get()` or `IndexMap::contains_key()`.
206///
207/// It can also be converted to a borrowed string with `.as_str()` to use it
208/// with methods like `HashMap::get()` or `HashSet::contains()`.
209#[derive(Debug, Default, Clone, Copy)]
210pub enum TestRoom {
211    /// The default room ID, `!SVkFJHzfwvuaIEawgC:localhost`.
212    #[default]
213    Default,
214
215    /// A room with an ID using the format introduced in room version 12,
216    /// `!2n76rSaCoTdcb1-zm9dcLm0laKJnuPyE80mopRnYgmg`.
217    V12,
218
219    /// Another room ID, `!another_room:homeserver.localhost`.
220    Other,
221
222    /// An ID for an invited room, `!invited:matrix.local`.
223    Invited,
224
225    /// An ID for a room that was left, `!left:matrix.local`.
226    Left,
227}
228
229/// Default room ID.
230static DEFAULT_ROOM_ID: LazyLock<OwnedRoomId> =
231    LazyLock::new(|| crate::DEFAULT_TEST_ROOM_ID.to_owned());
232/// V12 room ID.
233static V12_ROOM_ID: LazyLock<OwnedRoomId> =
234    LazyLock::new(|| owned_room_id!("!2n76rSaCoTdcb1-zm9dcLm0laKJnuPyE80mopRnYgmg"));
235/// Another room ID.
236static OTHER_ROOM_ID: LazyLock<OwnedRoomId> =
237    LazyLock::new(|| owned_room_id!("!another_room:homeserver.localhost"));
238/// Invited room ID.
239static INVITED_ROOM_ID: LazyLock<OwnedRoomId> =
240    LazyLock::new(|| owned_room_id!("!invited:matrix.local"));
241/// Left room ID.
242static LEFT_ROOM_ID: LazyLock<OwnedRoomId> = LazyLock::new(|| owned_room_id!("!left:matrix.local"));
243
244impl TestRoom {
245    /// The room's ID.
246    ///
247    /// This unconventional return type allows to either clone the owned ID or
248    /// dereference it.
249    fn id(&self) -> &'static OwnedRoomId {
250        match self {
251            Self::Default => &DEFAULT_ROOM_ID,
252            Self::V12 => &V12_ROOM_ID,
253            Self::Other => &OTHER_ROOM_ID,
254            Self::Invited => &INVITED_ROOM_ID,
255            Self::Left => &LEFT_ROOM_ID,
256        }
257    }
258
259    /// The room's ID as a `&str`.
260    pub fn as_str(&self) -> &'static str {
261        self.id().as_str()
262    }
263}
264
265impl From<TestRoom> for OwnedRoomId {
266    fn from(room: TestRoom) -> Self {
267        room.id().clone()
268    }
269}
270
271impl From<TestRoom> for &'static RoomId {
272    fn from(room: TestRoom) -> Self {
273        room.id()
274    }
275}
276
277impl From<TestRoom> for OwnedRoomOrAliasId {
278    fn from(room: TestRoom) -> Self {
279        room.id().clone().into()
280    }
281}
282
283impl From<TestRoom> for &'static RoomOrAliasId {
284    fn from(room: TestRoom) -> Self {
285        <&RoomId>::from(room).into()
286    }
287}
288
289impl From<TestRoom> for String {
290    fn from(room: TestRoom) -> Self {
291        room.as_str().to_owned()
292    }
293}
294
295impl PartialEq<OwnedRoomId> for TestRoom {
296    fn eq(&self, other: &OwnedRoomId) -> bool {
297        self.id().eq(other)
298    }
299}
300
301impl PartialEq<TestRoom> for OwnedRoomId {
302    fn eq(&self, other: &TestRoom) -> bool {
303        self.eq(other.id())
304    }
305}
306
307impl PartialEq<&OwnedRoomId> for TestRoom {
308    fn eq(&self, other: &&OwnedRoomId) -> bool {
309        self.id().eq(*other)
310    }
311}
312
313impl PartialEq<TestRoom> for &OwnedRoomId {
314    fn eq(&self, other: &TestRoom) -> bool {
315        (*self).eq(other.id())
316    }
317}
318
319impl PartialEq<&RoomId> for TestRoom {
320    fn eq(&self, other: &&RoomId) -> bool {
321        self.id().eq(other)
322    }
323}
324
325impl PartialEq<TestRoom> for &RoomId {
326    fn eq(&self, other: &TestRoom) -> bool {
327        self.eq(other.id())
328    }
329}
330
331impl PartialEq<serde_json::Value> for TestRoom {
332    fn eq(&self, other: &serde_json::Value) -> bool {
333        self.as_str().eq(other)
334    }
335}
336
337impl PartialEq<TestRoom> for serde_json::Value {
338    fn eq(&self, other: &TestRoom) -> bool {
339        self.eq(other.as_str())
340    }
341}
342
343impl Equivalent<OwnedRoomId> for TestRoom {
344    fn equivalent(&self, key: &OwnedRoomId) -> bool {
345        key.eq(self.id())
346    }
347}
348
349impl Hash for TestRoom {
350    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
351        self.id().hash(state);
352    }
353}
354
355impl Serialize for TestRoom {
356    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
357    where
358        S: serde::Serializer,
359    {
360        self.id().serialize(serializer)
361    }
362}
363
364impl fmt::Display for TestRoom {
365    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
366        self.id().fmt(f)
367    }
368}
369
370/// A Matrix test room alias.
371///
372/// This can be converted to the following types with `.into()`:
373///
374/// - `&'static RoomAliasId`
375/// - `OwnedRoomAliasId`
376/// - `&'static RoomOrAliasId`
377/// - `OwnedRoomOrAliasId`
378///
379/// It implements `PartialEq` with all the ID types above, as well as with
380/// `serde_json::Value` to use with the `assert_eq!` macro.
381///
382/// It implements `Serialize` and `Into<String>` to use it with the `json!`
383/// macro.
384///
385/// It implements `Hash` and `Equivalent<OwnedRoomAliasId>` as well to be able
386/// to use it with methods like `IndexMap::get()` or `IndexMap::contains_key()`.
387///
388/// It can also be converted to a borrowed string with `.as_str()` to use it
389/// with methods like `HashMap::get()` or `HashSet::contains()`.
390#[derive(Debug, Clone, Copy)]
391pub enum TestRoomAlias {
392    /// A canonical room alias, `#canonical:localhost`.
393    Canonical,
394
395    /// An alternate room alias, `#alt_alias:localhost`.
396    Alt,
397}
398
399/// Canonical room alias.
400static CANONICAL_ROOM_ALIAS: LazyLock<OwnedRoomAliasId> =
401    LazyLock::new(|| owned_room_alias_id!("#canonical:localhost"));
402/// Alternate room alias.
403static ALT_ROOM_ALIAS: LazyLock<OwnedRoomAliasId> =
404    LazyLock::new(|| owned_room_alias_id!("#alt_alias:localhost"));
405
406impl TestRoomAlias {
407    /// The room's alias.
408    ///
409    /// This unconventional return type allows to either clone the owned ID or
410    /// dereference it.
411    fn id(&self) -> &'static OwnedRoomAliasId {
412        match self {
413            Self::Canonical => &CANONICAL_ROOM_ALIAS,
414            Self::Alt => &ALT_ROOM_ALIAS,
415        }
416    }
417
418    /// The room's alias as a `&str`.
419    pub fn as_str(&self) -> &'static str {
420        self.id().as_str()
421    }
422}
423
424impl From<TestRoomAlias> for OwnedRoomAliasId {
425    fn from(alias: TestRoomAlias) -> Self {
426        alias.id().clone()
427    }
428}
429
430impl From<TestRoomAlias> for &'static RoomAliasId {
431    fn from(alias: TestRoomAlias) -> Self {
432        alias.id()
433    }
434}
435
436impl From<TestRoomAlias> for OwnedRoomOrAliasId {
437    fn from(alias: TestRoomAlias) -> Self {
438        alias.id().clone().into()
439    }
440}
441
442impl From<TestRoomAlias> for &'static RoomOrAliasId {
443    fn from(alias: TestRoomAlias) -> Self {
444        <&RoomAliasId>::from(alias).into()
445    }
446}
447
448impl From<TestRoomAlias> for String {
449    fn from(alias: TestRoomAlias) -> Self {
450        alias.as_str().to_owned()
451    }
452}
453
454impl PartialEq<OwnedRoomAliasId> for TestRoomAlias {
455    fn eq(&self, other: &OwnedRoomAliasId) -> bool {
456        self.id().eq(other)
457    }
458}
459
460impl PartialEq<TestRoomAlias> for OwnedRoomAliasId {
461    fn eq(&self, other: &TestRoomAlias) -> bool {
462        self.eq(other.id())
463    }
464}
465
466impl PartialEq<&OwnedRoomAliasId> for TestRoomAlias {
467    fn eq(&self, other: &&OwnedRoomAliasId) -> bool {
468        self.id().eq(*other)
469    }
470}
471
472impl PartialEq<TestRoomAlias> for &OwnedRoomAliasId {
473    fn eq(&self, other: &TestRoomAlias) -> bool {
474        (*self).eq(other.id())
475    }
476}
477
478impl PartialEq<&RoomAliasId> for TestRoomAlias {
479    fn eq(&self, other: &&RoomAliasId) -> bool {
480        self.id().eq(other)
481    }
482}
483
484impl PartialEq<TestRoomAlias> for &RoomAliasId {
485    fn eq(&self, other: &TestRoomAlias) -> bool {
486        self.eq(other.id())
487    }
488}
489
490impl PartialEq<serde_json::Value> for TestRoomAlias {
491    fn eq(&self, other: &serde_json::Value) -> bool {
492        self.as_str().eq(other)
493    }
494}
495
496impl PartialEq<TestRoomAlias> for serde_json::Value {
497    fn eq(&self, other: &TestRoomAlias) -> bool {
498        self.eq(other.as_str())
499    }
500}
501
502impl Equivalent<OwnedRoomAliasId> for TestRoomAlias {
503    fn equivalent(&self, key: &OwnedRoomAliasId) -> bool {
504        key.eq(self.id())
505    }
506}
507
508impl Hash for TestRoomAlias {
509    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
510        self.id().hash(state);
511    }
512}
513
514impl Serialize for TestRoomAlias {
515    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
516    where
517        S: serde::Serializer,
518    {
519        self.id().serialize(serializer)
520    }
521}
522
523impl fmt::Display for TestRoomAlias {
524    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525        self.id().fmt(f)
526    }
527}
528
529/// A Matrix test device.
530///
531/// This can be converted to the following types with `.into()`:
532///
533/// - `&'static DeviceId`
534/// - `OwnedDeviceId`
535///
536/// It implements `PartialEq` with all the ID types above, as well as with
537/// `serde_json::Value` to use with the `assert_eq!` macro.
538///
539/// It implements `Serialize` and `Into<String>` to use it with the `json!`
540/// macro.
541///
542/// It implements `Hash` and `Equivalent<OwnedDeviceId>` as well to be able to
543/// use it with methods like `IndexMap::get()` or `IndexMap::contains_key()`.
544///
545/// It can also be converted to a borrowed string with `.as_str()` to use it
546/// with methods like `HashMap::get()` or `HashSet::contains()`.
547#[derive(Debug, Default, Clone, Copy)]
548pub enum TestDevice {
549    /// The default device ID, `MYD3V1C31D`.
550    #[default]
551    Default,
552
553    /// The first alternative device ID, `JLAFKJWSCS`.
554    Alt1,
555
556    /// The second alternative device ID, `ILMLKASTES`.
557    Alt2,
558
559    /// The third alternative device ID, `WSKKLTJZCL`.
560    Alt3,
561}
562
563/// Default device ID.
564static DEFAULT_DEVICE_ID: LazyLock<OwnedDeviceId> =
565    LazyLock::new(|| owned_device_id!("MYD3V1C31D"));
566/// First alternative device ID.
567static ALT1_DEVICE_ID: LazyLock<OwnedDeviceId> = LazyLock::new(|| owned_device_id!("JLAFKJWSCS"));
568/// Second alternative device ID.
569static ALT2_DEVICE_ID: LazyLock<OwnedDeviceId> = LazyLock::new(|| owned_device_id!("ILMLKASTES"));
570/// Third alternative device ID.
571static ALT3_DEVICE_ID: LazyLock<OwnedDeviceId> = LazyLock::new(|| owned_device_id!("WSKKLTJZCL"));
572
573impl TestDevice {
574    /// The device's ID.
575    ///
576    /// This unconventional return type allows to either clone the owned ID or
577    /// dereference it.
578    fn id(&self) -> &'static OwnedDeviceId {
579        match self {
580            Self::Default => &DEFAULT_DEVICE_ID,
581            Self::Alt1 => &ALT1_DEVICE_ID,
582            Self::Alt2 => &ALT2_DEVICE_ID,
583            Self::Alt3 => &ALT3_DEVICE_ID,
584        }
585    }
586
587    /// The room's ID as a `&str`.
588    pub fn as_str(&self) -> &'static str {
589        self.id().as_str()
590    }
591}
592
593impl From<TestDevice> for OwnedDeviceId {
594    fn from(device: TestDevice) -> Self {
595        device.id().clone()
596    }
597}
598
599impl From<TestDevice> for &'static DeviceId {
600    fn from(device: TestDevice) -> Self {
601        device.id()
602    }
603}
604
605impl From<TestDevice> for String {
606    fn from(device: TestDevice) -> Self {
607        device.as_str().to_owned()
608    }
609}
610
611impl PartialEq<OwnedDeviceId> for TestDevice {
612    fn eq(&self, other: &OwnedDeviceId) -> bool {
613        self.id().eq(other)
614    }
615}
616
617impl PartialEq<TestDevice> for OwnedDeviceId {
618    fn eq(&self, other: &TestDevice) -> bool {
619        self.eq(other.id())
620    }
621}
622
623impl PartialEq<&OwnedDeviceId> for TestDevice {
624    fn eq(&self, other: &&OwnedDeviceId) -> bool {
625        self.id().eq(*other)
626    }
627}
628
629impl PartialEq<TestDevice> for &OwnedDeviceId {
630    fn eq(&self, other: &TestDevice) -> bool {
631        (*self).eq(other.id())
632    }
633}
634
635impl PartialEq<&DeviceId> for TestDevice {
636    fn eq(&self, other: &&DeviceId) -> bool {
637        self.id().eq(other)
638    }
639}
640
641impl PartialEq<TestDevice> for &DeviceId {
642    fn eq(&self, other: &TestDevice) -> bool {
643        self.eq(other.id())
644    }
645}
646
647impl PartialEq<serde_json::Value> for TestDevice {
648    fn eq(&self, other: &serde_json::Value) -> bool {
649        self.as_str().eq(other)
650    }
651}
652
653impl PartialEq<TestDevice> for serde_json::Value {
654    fn eq(&self, other: &TestDevice) -> bool {
655        self.eq(other.as_str())
656    }
657}
658
659impl Equivalent<OwnedDeviceId> for TestDevice {
660    fn equivalent(&self, key: &OwnedDeviceId) -> bool {
661        key.eq(self.id())
662    }
663}
664
665impl Hash for TestDevice {
666    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
667        self.id().hash(state);
668    }
669}
670
671impl Serialize for TestDevice {
672    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
673    where
674        S: serde::Serializer,
675    {
676        self.id().serialize(serializer)
677    }
678}
679
680impl fmt::Display for TestDevice {
681    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
682        self.id().fmt(f)
683    }
684}