Skip to main content

ruma_common/identifiers/
direct_user_identifier.rs

1use ruma_macros::IdDst;
2
3use super::{IdParseError, OwnedUserId, UserId};
4
5/// An user identifier, it can be a [`UserId`] or a third-party identifier
6/// like an email or a phone number.
7///
8/// There is no validation on this type, any string is allowed,
9/// but you can use `as_user_id` or `into_user_id` to try to get an [`UserId`].
10#[repr(transparent)]
11#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, IdDst)]
12#[ruma_id(smallvec_inline_bytes = 40)]
13pub struct DirectUserIdentifier(str);
14
15impl DirectUserIdentifier {
16    /// Get this `DirectUserIdentifier` as an [`UserId`] if it is one.
17    pub fn as_user_id(&self) -> Option<&UserId> {
18        self.as_str().try_into().ok()
19    }
20}
21
22impl OwnedDirectUserIdentifier {
23    /// Get this `OwnedDirectUserIdentifier` as an [`UserId`] if it is one.
24    pub fn as_user_id(&self) -> Option<&UserId> {
25        self.as_str().try_into().ok()
26    }
27
28    /// Get this `OwnedDirectUserIdentifier` as an [`OwnedUserId`] if it is one.
29    pub fn into_user_id(self) -> Option<OwnedUserId> {
30        self.try_into().ok()
31    }
32}
33
34impl TryFrom<OwnedDirectUserIdentifier> for OwnedUserId {
35    type Error = IdParseError;
36
37    fn try_from(value: OwnedDirectUserIdentifier) -> Result<Self, Self::Error> {
38        ruma_identifiers_validation::user_id::validate(value.as_str())?;
39        Ok(unsafe { Self::from_inner_unchecked(value.into_inner()) })
40    }
41}
42
43impl TryFrom<&OwnedDirectUserIdentifier> for OwnedUserId {
44    type Error = IdParseError;
45
46    fn try_from(value: &OwnedDirectUserIdentifier) -> Result<Self, Self::Error> {
47        ruma_identifiers_validation::user_id::validate(value.as_str())?;
48        Ok(unsafe { Self::from_inner_unchecked(value.clone().into_inner()) })
49    }
50}
51
52impl TryFrom<&DirectUserIdentifier> for OwnedUserId {
53    type Error = IdParseError;
54
55    fn try_from(value: &DirectUserIdentifier) -> Result<Self, Self::Error> {
56        value.as_str().try_into()
57    }
58}
59
60impl<'a> TryFrom<&'a DirectUserIdentifier> for &'a UserId {
61    type Error = IdParseError;
62
63    fn try_from(value: &'a DirectUserIdentifier) -> Result<Self, Self::Error> {
64        value.as_str().try_into()
65    }
66}
67
68impl From<OwnedUserId> for OwnedDirectUserIdentifier {
69    fn from(value: OwnedUserId) -> Self {
70        unsafe { Self::from_inner_unchecked(value.into_inner()) }
71    }
72}
73
74impl From<&OwnedUserId> for OwnedDirectUserIdentifier {
75    fn from(value: &OwnedUserId) -> Self {
76        unsafe { Self::from_inner_unchecked(value.clone().into_inner()) }
77    }
78}
79
80impl From<&UserId> for OwnedDirectUserIdentifier {
81    fn from(value: &UserId) -> Self {
82        Self::from_str_unchecked(value.as_str())
83    }
84}
85
86impl<'a> From<&'a UserId> for &'a DirectUserIdentifier {
87    fn from(value: &'a UserId) -> Self {
88        DirectUserIdentifier::from_borrowed_unchecked(value.as_str())
89    }
90}
91
92impl PartialEq<&UserId> for &DirectUserIdentifier {
93    fn eq(&self, other: &&UserId) -> bool {
94        self.as_str().eq(other.as_str())
95    }
96}
97
98impl PartialEq<&DirectUserIdentifier> for &UserId {
99    fn eq(&self, other: &&DirectUserIdentifier) -> bool {
100        other.as_str().eq(self.as_str())
101    }
102}
103
104impl PartialEq<OwnedUserId> for &DirectUserIdentifier {
105    fn eq(&self, other: &OwnedUserId) -> bool {
106        self.as_str().eq(other.as_str())
107    }
108}
109
110impl PartialEq<&DirectUserIdentifier> for OwnedUserId {
111    fn eq(&self, other: &&DirectUserIdentifier) -> bool {
112        other.as_str().eq(self.as_str())
113    }
114}
115
116impl PartialEq<&UserId> for OwnedDirectUserIdentifier {
117    fn eq(&self, other: &&UserId) -> bool {
118        self.as_str().eq(other.as_str())
119    }
120}
121
122impl PartialEq<OwnedDirectUserIdentifier> for &UserId {
123    fn eq(&self, other: &OwnedDirectUserIdentifier) -> bool {
124        other.as_str().eq(self.as_str())
125    }
126}
127
128impl PartialEq<OwnedUserId> for OwnedDirectUserIdentifier {
129    fn eq(&self, other: &OwnedUserId) -> bool {
130        self.as_str().eq(other.as_str())
131    }
132}
133
134impl PartialEq<OwnedDirectUserIdentifier> for OwnedUserId {
135    fn eq(&self, other: &OwnedDirectUserIdentifier) -> bool {
136        other.as_str().eq(self.as_str())
137    }
138}
139
140#[cfg(test)]
141mod tests {
142    use serde_json::{from_value as from_json_value, to_value as to_json_value};
143
144    use super::{DirectUserIdentifier, OwnedDirectUserIdentifier};
145    use crate::{OwnedUserId, user_id};
146
147    #[test]
148    fn user_id_conversion() {
149        let alice_direct_uid = <&DirectUserIdentifier>::from("@alice:ruma.io");
150        let alice_owned_user_id: OwnedUserId = alice_direct_uid
151            .to_owned()
152            .try_into()
153            .expect("@alice:ruma.io should be convertible into a Matrix user ID");
154        assert_eq!(alice_direct_uid, alice_owned_user_id);
155
156        let alice_direct_uid_mail = <&DirectUserIdentifier>::from("alice@ruma.io");
157        OwnedUserId::try_from(alice_direct_uid_mail.to_owned())
158            .expect_err("alice@ruma.io should not be convertible into a Matrix user ID");
159
160        let alice_user_id = user_id!("@alice:ruma.io");
161        let alice_direct_uid_mail: &DirectUserIdentifier = alice_user_id.into();
162        assert_eq!(alice_direct_uid_mail, alice_user_id);
163        assert_eq!(alice_direct_uid_mail, alice_user_id.to_owned());
164        assert_eq!(alice_user_id, alice_direct_uid_mail);
165        assert_eq!(alice_user_id.to_owned(), alice_direct_uid_mail);
166
167        let alice_user_id = user_id!("@alice:ruma.io");
168        let alice_direct_uid_mail: OwnedDirectUserIdentifier = alice_user_id.into();
169        assert_eq!(alice_direct_uid_mail, alice_user_id);
170        assert_eq!(alice_direct_uid_mail, alice_user_id.to_owned());
171        assert_eq!(alice_user_id, alice_direct_uid_mail);
172        assert_eq!(alice_user_id.to_owned(), alice_direct_uid_mail);
173
174        let alice_user_id = user_id!("@alice:ruma.io");
175        let alice_user_id_json = to_json_value(alice_user_id).unwrap();
176        let alice_direct_uid_mail: OwnedDirectUserIdentifier =
177            from_json_value(alice_user_id_json).unwrap();
178        assert_eq!(alice_user_id, alice_direct_uid_mail);
179    }
180}