use std::{
cmp::Ordering,
hash::{Hash, Hasher},
marker::PhantomData,
str::FromStr,
};
use ruma_macros::IdZst;
use super::{crypto_algorithms::SigningKeyAlgorithm, DeviceId, KeyName};
#[repr(transparent)]
#[derive(IdZst)]
#[ruma_id(validate = ruma_identifiers_validation::key_id::validate)]
pub struct KeyId<A, K: ?Sized>(PhantomData<(A, K)>, str);
impl<A, K: ?Sized> KeyId<A, K> {
pub fn from_parts(algorithm: A, key_name: &K) -> OwnedKeyId<A, K>
where
A: AsRef<str>,
K: AsRef<str>,
{
let algorithm = algorithm.as_ref();
let key_name = key_name.as_ref();
let mut res = String::with_capacity(algorithm.len() + 1 + key_name.len());
res.push_str(algorithm);
res.push(':');
res.push_str(key_name);
Self::from_borrowed(&res).to_owned()
}
pub fn algorithm(&self) -> A
where
A: FromStr,
{
A::from_str(&self.as_str()[..self.colon_idx()]).unwrap_or_else(|_| unreachable!())
}
pub fn key_name<'a>(&'a self) -> &'a K
where
&'a K: From<&'a str>,
{
self.as_str()[self.colon_idx() + 1..].into()
}
fn colon_idx(&self) -> usize {
self.as_str().find(':').unwrap()
}
}
pub type SigningKeyId<K> = KeyId<SigningKeyAlgorithm, K>;
pub type OwnedSigningKeyId<K> = OwnedKeyId<SigningKeyAlgorithm, K>;
pub type ServerSigningKeyId = SigningKeyId<KeyName>;
pub type OwnedServerSigningKeyId = OwnedSigningKeyId<KeyName>;
pub type DeviceSigningKeyId = SigningKeyId<DeviceId>;
pub type OwnedDeviceSigningKeyId = OwnedSigningKeyId<DeviceId>;
impl<A, K: ?Sized> PartialEq for KeyId<A, K> {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}
}
impl<A, K: ?Sized> Eq for KeyId<A, K> {}
impl<A, K: ?Sized> PartialOrd for KeyId<A, K> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<A, K: ?Sized> Ord for KeyId<A, K> {
fn cmp(&self, other: &Self) -> Ordering {
Ord::cmp(self.as_str(), other.as_str())
}
}
impl<A, K: ?Sized> Hash for KeyId<A, K> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}