ruma_identifiers/
key_id.rs

1use std::{
2    cmp::Ordering,
3    convert::TryFrom,
4    fmt,
5    hash::{Hash, Hasher},
6    marker::PhantomData,
7    rc::Rc,
8    str::FromStr,
9    sync::Arc,
10};
11
12use crate::{crypto_algorithms::SigningKeyAlgorithm, DeviceId, KeyName};
13
14/// A key algorithm and key name delimited by a colon.
15#[repr(transparent)]
16pub struct KeyId<A, K: ?Sized>(PhantomData<(A, K)>, str);
17
18impl<A, K: ?Sized> KeyId<A, K> {
19    /// Creates a new `KeyId` from an algorithm and key name.
20    pub fn from_parts(algorithm: A, key_name: &K) -> Box<Self>
21    where
22        A: AsRef<str>,
23        K: AsRef<str>,
24    {
25        let algorithm = algorithm.as_ref();
26        let key_name = key_name.as_ref();
27
28        let mut res = String::with_capacity(algorithm.len() + 1 + key_name.len());
29        res.push_str(algorithm);
30        res.push(':');
31        res.push_str(key_name);
32
33        Self::from_owned(res.into())
34    }
35
36    /// Returns key algorithm of the key ID.
37    pub fn algorithm(&self) -> A
38    where
39        A: FromStr,
40    {
41        A::from_str(&self.as_str()[..self.colon_idx()]).unwrap_or_else(|_| unreachable!())
42    }
43
44    /// Returns the key name of the key ID.
45    pub fn key_name<'a>(&'a self) -> &'a K
46    where
47        &'a K: From<&'a str>,
48    {
49        self.as_str()[self.colon_idx() + 1..].into()
50    }
51
52    /// Creates a string slice from this `KeyId`.
53    pub fn as_str(&self) -> &str {
54        &self.1
55    }
56
57    /// Creates a byte slice from this `KeyId`.
58    pub fn as_bytes(&self) -> &[u8] {
59        self.1.as_bytes()
60    }
61
62    fn from_borrowed(s: &str) -> &Self {
63        unsafe { std::mem::transmute(s) }
64    }
65
66    fn from_owned(s: Box<str>) -> Box<Self> {
67        unsafe { Box::from_raw(Box::into_raw(s) as _) }
68    }
69
70    fn into_owned(self: Box<Self>) -> Box<str> {
71        unsafe { Box::from_raw(Box::into_raw(self) as _) }
72    }
73
74    fn colon_idx(&self) -> usize {
75        self.as_str().find(':').unwrap()
76    }
77}
78
79/// Algorithm + key name for signing keys.
80pub type SigningKeyId<K> = KeyId<SigningKeyAlgorithm, K>;
81
82/// Algorithm + key name for homeserver signing keys.
83pub type ServerSigningKeyId = SigningKeyId<KeyName>;
84
85/// Algorithm + key name for device keys.
86pub type DeviceSigningKeyId = SigningKeyId<DeviceId>;
87
88impl<A, K: ?Sized> Clone for Box<KeyId<A, K>> {
89    fn clone(&self) -> Self {
90        (**self).to_owned()
91    }
92}
93
94impl<A, K: ?Sized> ToOwned for KeyId<A, K> {
95    type Owned = Box<KeyId<A, K>>;
96
97    fn to_owned(&self) -> Self::Owned {
98        Self::from_owned(self.1.into())
99    }
100}
101
102impl<A, K: ?Sized> From<&KeyId<A, K>> for Box<KeyId<A, K>> {
103    fn from(id: &KeyId<A, K>) -> Self {
104        id.to_owned()
105    }
106}
107
108impl<A, K: ?Sized> AsRef<str> for Box<KeyId<A, K>> {
109    fn as_ref(&self) -> &str {
110        self.as_str()
111    }
112}
113
114impl<A, K: ?Sized> From<&KeyId<A, K>> for Rc<KeyId<A, K>> {
115    fn from(s: &KeyId<A, K>) -> Rc<KeyId<A, K>> {
116        let rc = Rc::<str>::from(s.as_str());
117        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const KeyId<A, K>) }
118    }
119}
120
121impl<A, K: ?Sized> From<&KeyId<A, K>> for Arc<KeyId<A, K>> {
122    fn from(s: &KeyId<A, K>) -> Arc<KeyId<A, K>> {
123        let arc = Arc::<str>::from(s.as_str());
124        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const KeyId<A, K>) }
125    }
126}
127
128impl<A, K: ?Sized> PartialEq<KeyId<A, K>> for Box<KeyId<A, K>> {
129    fn eq(&self, other: &KeyId<A, K>) -> bool {
130        self.as_str() == other.as_str()
131    }
132}
133
134impl<A, K: ?Sized> PartialEq<&'_ KeyId<A, K>> for Box<KeyId<A, K>> {
135    fn eq(&self, other: &&KeyId<A, K>) -> bool {
136        self.as_str() == other.as_str()
137    }
138}
139
140impl<A, K: ?Sized> PartialEq<Box<KeyId<A, K>>> for KeyId<A, K> {
141    fn eq(&self, other: &Box<KeyId<A, K>>) -> bool {
142        self.as_str() == other.as_str()
143    }
144}
145
146impl<A, K: ?Sized> PartialEq<Box<KeyId<A, K>>> for &'_ KeyId<A, K> {
147    fn eq(&self, other: &Box<KeyId<A, K>>) -> bool {
148        self.as_str() == other.as_str()
149    }
150}
151
152impl<A, K: ?Sized> AsRef<str> for KeyId<A, K> {
153    fn as_ref(&self) -> &str {
154        self.as_str()
155    }
156}
157
158impl<A, K: ?Sized> fmt::Display for KeyId<A, K> {
159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160        self.as_str().fmt(f)
161    }
162}
163
164impl<A, K: ?Sized> fmt::Debug for KeyId<A, K> {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        self.as_str().fmt(f)
167    }
168}
169
170impl<A, K: ?Sized> PartialEq for KeyId<A, K> {
171    fn eq(&self, other: &Self) -> bool {
172        self.as_str() == other.as_str()
173    }
174}
175
176impl<A, K: ?Sized> Eq for KeyId<A, K> {}
177
178impl<A, K: ?Sized> PartialOrd for KeyId<A, K> {
179    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
180        PartialOrd::partial_cmp(self.as_str(), other.as_str())
181    }
182}
183
184impl<A, K: ?Sized> Ord for KeyId<A, K> {
185    fn cmp(&self, other: &Self) -> Ordering {
186        Ord::cmp(self.as_str(), other.as_str())
187    }
188}
189
190impl<A, K: ?Sized> Hash for KeyId<A, K> {
191    fn hash<H: Hasher>(&self, state: &mut H) {
192        self.as_str().hash(state);
193    }
194}
195#[cfg(feature = "serde")]
196impl<A, K: ?Sized> serde::Serialize for KeyId<A, K> {
197    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
198    where
199        S: serde::Serializer,
200    {
201        serializer.serialize_str(self.as_str())
202    }
203}
204
205impl<A, K: ?Sized> From<Box<KeyId<A, K>>> for String {
206    fn from(id: Box<KeyId<A, K>>) -> Self {
207        id.into_owned().into()
208    }
209}
210
211#[cfg(feature = "serde")]
212impl<'de, A, K: ?Sized> serde::Deserialize<'de> for Box<KeyId<A, K>> {
213    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
214    where
215        D: serde::Deserializer<'de>,
216    {
217        use serde::de::Error;
218        let s = String::deserialize(deserializer)?;
219        match try_from(s) {
220            Ok(o) => Ok(o),
221            Err(e) => Err(D::Error::custom(e)),
222        }
223    }
224}
225
226fn try_from<S, A, K: ?Sized>(s: S) -> Result<Box<KeyId<A, K>>, crate::Error>
227where
228    S: AsRef<str> + Into<Box<str>>,
229{
230    ruma_identifiers_validation::key_id::validate(s.as_ref())?;
231    Ok(KeyId::from_owned(s.into()))
232}
233
234impl<'a, A, K: ?Sized> TryFrom<&'a str> for &'a KeyId<A, K> {
235    type Error = crate::Error;
236
237    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
238        (ruma_identifiers_validation::key_id::validate)(s)?;
239        Ok(KeyId::from_borrowed(s))
240    }
241}
242
243impl<A, K: ?Sized> FromStr for Box<KeyId<A, K>> {
244    type Err = crate::Error;
245
246    fn from_str(s: &str) -> Result<Self, Self::Err> {
247        try_from(s)
248    }
249}
250
251impl<A, K: ?Sized> TryFrom<&str> for Box<KeyId<A, K>> {
252    type Error = crate::Error;
253
254    fn try_from(s: &str) -> Result<Self, Self::Error> {
255        try_from(s)
256    }
257}
258
259impl<A, K: ?Sized> TryFrom<String> for Box<KeyId<A, K>> {
260    type Error = crate::Error;
261
262    fn try_from(s: String) -> Result<Self, Self::Error> {
263        try_from(s)
264    }
265}
266
267#[rustfmt::skip]
268partial_eq_string!(KeyId<A, K> [A, K]);