identifiers: Make KeyId a DST
This commit is contained in:
parent
3ce578f384
commit
5852658da5
@ -34,7 +34,7 @@ pub struct ThirdPartySigned<'a> {
|
||||
pub token: &'a str,
|
||||
|
||||
/// A signatures object containing a signature of the entire signed object.
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
}
|
||||
|
||||
impl<'a> ThirdPartySigned<'a> {
|
||||
@ -44,7 +44,7 @@ impl<'a> ThirdPartySigned<'a> {
|
||||
sender: &'a UserId,
|
||||
mxid: &'a UserId,
|
||||
token: &'a str,
|
||||
signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
) -> Self {
|
||||
Self { sender, mxid, token, signatures }
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ pub struct RoomV1Pdu {
|
||||
pub hashes: EventHash,
|
||||
|
||||
/// Signatures for the PDU.
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
}
|
||||
|
||||
/// A 'persistent data unit' (event) for room versions 3 and beyond.
|
||||
@ -146,7 +146,7 @@ pub struct RoomV3Pdu {
|
||||
pub hashes: EventHash,
|
||||
|
||||
/// Signatures for the PDU.
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
}
|
||||
|
||||
/// Content hashes of a PDU.
|
||||
|
@ -178,7 +178,7 @@ pub struct SignedContent {
|
||||
|
||||
/// A single signature from the verifying server, in the format specified by the Signing Events
|
||||
/// section of the server-server API.
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
|
||||
/// The token property of the containing `third_party_invite` object.
|
||||
pub token: String,
|
||||
@ -188,7 +188,7 @@ impl SignedContent {
|
||||
/// Creates a new `SignedContent` with the given mxid, signature and token.
|
||||
pub fn new(
|
||||
mxid: Box<UserId>,
|
||||
signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
token: String,
|
||||
) -> Self {
|
||||
Self { mxid, signatures, token }
|
||||
@ -495,7 +495,7 @@ mod tests {
|
||||
&& mxid == "@alice:example.org"
|
||||
&& signatures == btreemap! {
|
||||
server_name!("magic.forest") => btreemap! {
|
||||
server_signing_key_id!("ed25519:3") => "foobar".to_owned()
|
||||
server_signing_key_id!("ed25519:3").to_owned() => "foobar".to_owned()
|
||||
}
|
||||
}
|
||||
&& token == "abc123"
|
||||
@ -580,7 +580,7 @@ mod tests {
|
||||
&& mxid == "@alice:example.org"
|
||||
&& signatures == btreemap! {
|
||||
server_name!("magic.forest") => btreemap! {
|
||||
server_signing_key_id!("ed25519:3") => "foobar".to_owned()
|
||||
server_signing_key_id!("ed25519:3").to_owned() => "foobar".to_owned()
|
||||
}
|
||||
}
|
||||
&& token == "abc123"
|
||||
@ -654,7 +654,7 @@ mod tests {
|
||||
&& mxid == "@alice:example.org"
|
||||
&& signatures == btreemap! {
|
||||
server_name!("magic.forest") => btreemap! {
|
||||
server_signing_key_id!("ed25519:3") => "foobar".to_owned()
|
||||
server_signing_key_id!("ed25519:3").to_owned() => "foobar".to_owned()
|
||||
}
|
||||
}
|
||||
&& token == "abc123"
|
||||
|
@ -18,7 +18,7 @@ fn serialize_pdu_as_v1() {
|
||||
let mut signatures = BTreeMap::new();
|
||||
let mut inner_signature = BTreeMap::new();
|
||||
inner_signature.insert(
|
||||
server_signing_key_id!("ed25519:key_version"),
|
||||
server_signing_key_id!("ed25519:key_version").to_owned(),
|
||||
"86BytesOfSignatureOfTheRedactedEvent".into(),
|
||||
);
|
||||
signatures.insert(server_name!("example.com"), inner_signature);
|
||||
@ -85,7 +85,7 @@ fn serialize_pdu_as_v3() {
|
||||
let mut signatures = BTreeMap::new();
|
||||
let mut inner_signature = BTreeMap::new();
|
||||
inner_signature.insert(
|
||||
server_signing_key_id!("ed25519:key_version"),
|
||||
server_signing_key_id!("ed25519:key_version").to_owned(),
|
||||
"86BytesOfSignatureOfTheRedactedEvent".into(),
|
||||
);
|
||||
signatures.insert(server_name!("example.com"), inner_signature);
|
||||
|
@ -54,15 +54,15 @@ pub struct ServerSigningKeys {
|
||||
pub server_name: Box<ServerName>,
|
||||
|
||||
/// Public keys of the homeserver for verifying digital signatures.
|
||||
pub verify_keys: BTreeMap<ServerSigningKeyId, VerifyKey>,
|
||||
pub verify_keys: BTreeMap<Box<ServerSigningKeyId>, VerifyKey>,
|
||||
|
||||
/// Public keys that the homeserver used to use and when it stopped using them.
|
||||
pub old_verify_keys: BTreeMap<ServerSigningKeyId, OldVerifyKey>,
|
||||
pub old_verify_keys: BTreeMap<Box<ServerSigningKeyId>, OldVerifyKey>,
|
||||
|
||||
/// Digital signatures of this object signed using the verify_keys.
|
||||
///
|
||||
/// Map of server name to keys by key ID.
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signatures: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
|
||||
/// Timestamp when the keys should be refreshed.
|
||||
///
|
||||
|
@ -28,7 +28,7 @@ ruma_api! {
|
||||
/// notary server must return an empty server_keys array in the response.
|
||||
///
|
||||
/// The notary server may return multiple keys regardless of the Key IDs given.
|
||||
pub server_keys: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>>,
|
||||
pub server_keys: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>>,
|
||||
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ ruma_api! {
|
||||
impl Request {
|
||||
/// Creates a new `Request` with the given query criteria.
|
||||
pub fn new(
|
||||
server_keys: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, QueryCriteria>>,
|
||||
server_keys: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>>,
|
||||
) -> Self {
|
||||
Self { server_keys }
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ pub struct ThirdPartyInvite {
|
||||
pub sender: Box<UserId>,
|
||||
|
||||
/// Signature from the identity server using a long-term private key.
|
||||
pub signed: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
pub signed: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
}
|
||||
|
||||
impl ThirdPartyInvite {
|
||||
@ -87,7 +87,7 @@ impl ThirdPartyInvite {
|
||||
mxid: Box<UserId>,
|
||||
room_id: Box<RoomId>,
|
||||
sender: Box<UserId>,
|
||||
signed: BTreeMap<Box<ServerName>, BTreeMap<ServerSigningKeyId, String>>,
|
||||
signed: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, String>>,
|
||||
) -> Self {
|
||||
Self { medium: Medium::Email, address, mxid, room_id, sender, signed }
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ pub fn server_signing_key_id(input: TokenStream) -> TokenStream {
|
||||
assert!(key_id::validate(&id.value()).is_ok(), "Invalid server_signing_key_id");
|
||||
|
||||
let output = quote! {
|
||||
<#dollar_crate::ServerSigningKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
|
||||
<&#dollar_crate::ServerSigningKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap()
|
||||
};
|
||||
|
||||
output.into()
|
||||
|
@ -16,8 +16,6 @@ pub mod server_name;
|
||||
pub mod session_id;
|
||||
pub mod user_id;
|
||||
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
pub use error::Error;
|
||||
|
||||
/// All identifiers must be 255 bytes or less.
|
||||
@ -36,13 +34,12 @@ fn validate_id(id: &str, valid_sigils: &[char]) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks an identifier that contains a localpart and hostname for validity,
|
||||
/// and returns the index of the colon that separates the two.
|
||||
fn parse_id(id: &str, valid_sigils: &[char]) -> Result<NonZeroU8, Error> {
|
||||
/// Checks an identifier that contains a localpart and hostname for validity.
|
||||
fn parse_id(id: &str, valid_sigils: &[char]) -> Result<usize, Error> {
|
||||
validate_id(id, valid_sigils)?;
|
||||
let colon_idx = id.find(':').ok_or(Error::MissingDelimiter)?;
|
||||
server_name::validate(&id[colon_idx + 1..])?;
|
||||
Ok(NonZeroU8::new(colon_idx as u8).unwrap())
|
||||
Ok(colon_idx)
|
||||
}
|
||||
|
||||
/// Checks an identifier that contains a localpart and hostname for validity.
|
||||
|
@ -1,13 +1,11 @@
|
||||
use std::num::NonZeroU8;
|
||||
|
||||
use crate::{parse_id, Error};
|
||||
|
||||
pub fn validate(s: &str) -> Result<(NonZeroU8, bool), Error> {
|
||||
pub fn validate(s: &str) -> Result<(), Error> {
|
||||
let colon_idx = parse_id(s, &['@'])?;
|
||||
let localpart = &s[1..colon_idx.get() as usize];
|
||||
let is_historical = localpart_is_fully_conforming(localpart)?;
|
||||
let localpart = &s[1..colon_idx];
|
||||
let _ = localpart_is_fully_conforming(localpart)?;
|
||||
|
||||
Ok((colon_idx, is_historical))
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check whether the given user id localpart is valid and fully conforming
|
||||
|
@ -1,25 +1,21 @@
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
convert::{TryFrom, TryInto},
|
||||
convert::TryFrom,
|
||||
fmt,
|
||||
hash::{Hash, Hasher},
|
||||
marker::PhantomData,
|
||||
num::NonZeroU8,
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use crate::{crypto_algorithms::SigningKeyAlgorithm, DeviceId, KeyName};
|
||||
|
||||
/// A key algorithm and key name delimited by a colon
|
||||
pub struct KeyId<A, K: ?Sized> {
|
||||
full_id: Box<str>,
|
||||
colon_idx: NonZeroU8,
|
||||
_phantom: PhantomData<(A, K)>,
|
||||
}
|
||||
/// A key algorithm and key name delimited by a colon.
|
||||
#[repr(transparent)]
|
||||
pub struct KeyId<A, K: ?Sized>(PhantomData<(A, K)>, str);
|
||||
|
||||
impl<A, K: ?Sized> KeyId<A, K> {
|
||||
/// Creates a new `KeyId` from an algorithm and key name.
|
||||
pub fn from_parts(algorithm: A, key_name: &K) -> Self
|
||||
pub fn from_parts(algorithm: A, key_name: &K) -> Box<Self>
|
||||
where
|
||||
A: AsRef<str>,
|
||||
K: AsRef<str>,
|
||||
@ -32,11 +28,7 @@ impl<A, K: ?Sized> KeyId<A, K> {
|
||||
res.push(':');
|
||||
res.push_str(key_name);
|
||||
|
||||
let colon_idx =
|
||||
NonZeroU8::new(algorithm.len().try_into().expect("no algorithm name len > 255"))
|
||||
.expect("no empty algorithm name");
|
||||
|
||||
KeyId { full_id: res.into(), colon_idx, _phantom: PhantomData }
|
||||
Self::from_owned(res.into())
|
||||
}
|
||||
|
||||
/// Returns key algorithm of the key ID.
|
||||
@ -44,8 +36,7 @@ impl<A, K: ?Sized> KeyId<A, K> {
|
||||
where
|
||||
A: FromStr,
|
||||
{
|
||||
A::from_str(&self.full_id[..self.colon_idx.get() as usize])
|
||||
.unwrap_or_else(|_| unreachable!())
|
||||
A::from_str(&self.as_str()[..self.colon_idx()]).unwrap_or_else(|_| unreachable!())
|
||||
}
|
||||
|
||||
/// Returns the key name of the key ID.
|
||||
@ -53,33 +44,105 @@ impl<A, K: ?Sized> KeyId<A, K> {
|
||||
where
|
||||
&'a K: From<&'a str>,
|
||||
{
|
||||
self.full_id[self.colon_idx.get() as usize + 1..].into()
|
||||
}
|
||||
self.as_str()[self.colon_idx() + 1..].into()
|
||||
}
|
||||
|
||||
fn try_from<S, A, K: ?Sized>(key_identifier: S) -> Result<KeyId<A, K>, crate::Error>
|
||||
where
|
||||
S: AsRef<str> + Into<Box<str>>,
|
||||
{
|
||||
let colon_idx = ruma_identifiers_validation::key_id::validate(key_identifier.as_ref())?;
|
||||
Ok(KeyId { full_id: key_identifier.into(), colon_idx, _phantom: PhantomData })
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> KeyId<A, K> {
|
||||
/// Creates a string slice from this `KeyId<A, K>`
|
||||
/// Creates a string slice from this `KeyId`.
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.full_id
|
||||
&self.1
|
||||
}
|
||||
|
||||
/// Creates a byte slice from this `KeyId<A, K>`
|
||||
/// Creates a byte slice from this `KeyId`.
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.full_id.as_bytes()
|
||||
self.1.as_bytes()
|
||||
}
|
||||
|
||||
fn from_borrowed(s: &str) -> &Self {
|
||||
unsafe { std::mem::transmute(s) }
|
||||
}
|
||||
|
||||
fn from_owned(s: Box<str>) -> Box<Self> {
|
||||
unsafe { Box::from_raw(Box::into_raw(s) as _) }
|
||||
}
|
||||
|
||||
fn into_owned(self: Box<Self>) -> Box<str> {
|
||||
unsafe { Box::from_raw(Box::into_raw(self) as _) }
|
||||
}
|
||||
|
||||
fn colon_idx(&self) -> usize {
|
||||
self.as_str().find(':').unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> Clone for KeyId<A, K> {
|
||||
/// Algorithm + key name for signing keys.
|
||||
pub type SigningKeyId<K> = KeyId<SigningKeyAlgorithm, K>;
|
||||
|
||||
/// Algorithm + key name for homeserver signing keys.
|
||||
pub type ServerSigningKeyId = SigningKeyId<KeyName>;
|
||||
|
||||
/// Algorithm + key name for device keys.
|
||||
pub type DeviceSigningKeyId = SigningKeyId<DeviceId>;
|
||||
|
||||
impl<A, K: ?Sized> Clone for Box<KeyId<A, K>> {
|
||||
fn clone(&self) -> Self {
|
||||
Self { full_id: self.full_id.clone(), colon_idx: self.colon_idx, _phantom: PhantomData }
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> ToOwned for KeyId<A, K> {
|
||||
type Owned = Box<KeyId<A, K>>;
|
||||
fn to_owned(&self) -> Self::Owned {
|
||||
Self::from_owned(self.1.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> From<&KeyId<A, K>> for Box<KeyId<A, K>> {
|
||||
fn from(id: &KeyId<A, K>) -> Self {
|
||||
id.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> AsRef<str> for Box<KeyId<A, K>> {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> From<&KeyId<A, K>> for std::rc::Rc<KeyId<A, K>> {
|
||||
fn from(s: &KeyId<A, K>) -> std::rc::Rc<KeyId<A, K>> {
|
||||
let rc = std::rc::Rc::<str>::from(s.as_str());
|
||||
unsafe { std::rc::Rc::from_raw(std::rc::Rc::into_raw(rc) as *const KeyId<A, K>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> From<&KeyId<A, K>> for std::sync::Arc<KeyId<A, K>> {
|
||||
fn from(s: &KeyId<A, K>) -> std::sync::Arc<KeyId<A, K>> {
|
||||
let arc = std::sync::Arc::<str>::from(s.as_str());
|
||||
unsafe { std::sync::Arc::from_raw(std::sync::Arc::into_raw(arc) as *const KeyId<A, K>) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> PartialEq<KeyId<A, K>> for Box<KeyId<A, K>> {
|
||||
fn eq(&self, other: &KeyId<A, K>) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> PartialEq<&'_ KeyId<A, K>> for Box<KeyId<A, K>> {
|
||||
fn eq(&self, other: &&KeyId<A, K>) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> PartialEq<Box<KeyId<A, K>>> for KeyId<A, K> {
|
||||
fn eq(&self, other: &Box<KeyId<A, K>>) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> PartialEq<Box<KeyId<A, K>>> for &'_ KeyId<A, K> {
|
||||
fn eq(&self, other: &Box<KeyId<A, K>>) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,54 +152,15 @@ impl<A, K: ?Sized> AsRef<str> for KeyId<A, K> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> From<KeyId<A, K>> for String {
|
||||
fn from(id: KeyId<A, K>) -> Self {
|
||||
id.full_id.into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> FromStr for KeyId<A, K> {
|
||||
type Err = crate::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> TryFrom<&str> for KeyId<A, K> {
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> TryFrom<String> for KeyId<A, K>
|
||||
where
|
||||
A: FromStr,
|
||||
K: From<String>,
|
||||
{
|
||||
type Error = crate::Error;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
try_from(s)
|
||||
impl<A, K: ?Sized> fmt::Display for KeyId<A, K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> fmt::Debug for KeyId<A, K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Using struct debug format for consistency with other ID types.
|
||||
// FIXME: Change all ID types to have just a string debug format?
|
||||
f.debug_struct("KeyId")
|
||||
.field("full_id", &self.full_id)
|
||||
.field("colon_idxs", &self.colon_idx)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> fmt::Display for KeyId<A, K> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,13 +174,13 @@ 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> {
|
||||
self.as_str().partial_cmp(other.as_str())
|
||||
PartialOrd::partial_cmp(self.as_str(), other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> Ord for KeyId<A, K> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.as_str().cmp(other.as_str())
|
||||
Ord::cmp(self.as_str(), other.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +189,6 @@ impl<A, K: ?Sized> Hash for KeyId<A, K> {
|
||||
self.as_str().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<A, K: ?Sized> serde::Serialize for KeyId<A, K> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@ -176,24 +199,63 @@ impl<A, K: ?Sized> serde::Serialize for KeyId<A, K> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> From<Box<KeyId<A, K>>> for String {
|
||||
fn from(id: Box<KeyId<A, K>>) -> Self {
|
||||
id.into_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, A, K: ?Sized> serde::Deserialize<'de> for KeyId<A, K> {
|
||||
impl<'de, A, K: ?Sized> serde::Deserialize<'de> for Box<KeyId<A, K>> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
crate::deserialize_id(deserializer, "Key name with algorithm and key identifier")
|
||||
use serde::de::Error;
|
||||
let s = String::deserialize(deserializer)?;
|
||||
match try_from(s) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(e) => Err(D::Error::custom(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn try_from<S, A, K: ?Sized>(s: S) -> Result<Box<KeyId<A, K>>, crate::Error>
|
||||
where
|
||||
S: AsRef<str> + Into<Box<str>>,
|
||||
{
|
||||
ruma_identifiers_validation::key_id::validate(s.as_ref())?;
|
||||
Ok(KeyId::from_owned(s.into()))
|
||||
}
|
||||
|
||||
impl<'a, A, K: ?Sized> TryFrom<&'a str> for &'a KeyId<A, K> {
|
||||
type Error = crate::Error;
|
||||
fn try_from(s: &'a str) -> Result<Self, Self::Error> {
|
||||
(ruma_identifiers_validation::key_id::validate)(s)?;
|
||||
Ok(KeyId::from_borrowed(s))
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> FromStr for Box<KeyId<A, K>> {
|
||||
type Err = crate::Error;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> TryFrom<&str> for Box<KeyId<A, K>> {
|
||||
type Error = crate::Error;
|
||||
fn try_from(s: &str) -> Result<Self, Self::Error> {
|
||||
try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, K: ?Sized> TryFrom<String> for Box<KeyId<A, K>> {
|
||||
type Error = crate::Error;
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> {
|
||||
try_from(s)
|
||||
}
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
partial_eq_string!(KeyId<A, K> [A, K]);
|
||||
|
||||
/// Algorithm + key name for signing keys.
|
||||
pub type SigningKeyId<K> = KeyId<SigningKeyAlgorithm, K>;
|
||||
|
||||
/// Algorithm + key name for homeserver signing keys.
|
||||
pub type ServerSigningKeyId = SigningKeyId<KeyName>;
|
||||
|
||||
/// Algorithm + key name for device keys.
|
||||
pub type DeviceSigningKeyId = SigningKeyId<DeviceId>;
|
||||
|
@ -3,7 +3,7 @@ use std::{borrow::Borrow, collections::BTreeMap};
|
||||
use crate::{DeviceId, KeyName, ServerName, SigningKeyId, UserId};
|
||||
|
||||
/// Map of key identifier to signature values.
|
||||
pub type EntitySignatures<K> = BTreeMap<SigningKeyId<K>, String>;
|
||||
pub type EntitySignatures<K> = BTreeMap<Box<SigningKeyId<K>>, String>;
|
||||
|
||||
/// Map of all signatures, grouped by entity
|
||||
///
|
||||
@ -35,7 +35,7 @@ impl<E: Ord, K: ?Sized> Signatures<E, K> {
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
entity: E,
|
||||
key_identifier: SigningKeyId<K>,
|
||||
key_identifier: Box<SigningKeyId<K>>,
|
||||
value: String,
|
||||
) -> Option<String> {
|
||||
self.0.entry(entity).or_insert_with(Default::default).insert(key_identifier, value)
|
||||
|
@ -16,7 +16,7 @@ ruma_api! {
|
||||
request: {
|
||||
/// The ID of the key.
|
||||
#[ruma_api(path)]
|
||||
pub key_id: ServerSigningKeyId,
|
||||
pub key_id: &'a ServerSigningKeyId,
|
||||
}
|
||||
|
||||
response: {
|
||||
@ -25,9 +25,9 @@ ruma_api! {
|
||||
}
|
||||
}
|
||||
|
||||
impl Request {
|
||||
impl<'a> Request<'a> {
|
||||
/// Create a `Request` with the given key_id.
|
||||
pub fn new(key_id: ServerSigningKeyId) -> Self {
|
||||
pub fn new(key_id: &'a ServerSigningKeyId) -> Self {
|
||||
Self { key_id }
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +262,9 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
|
||||
} else if last_seg.ident == "ClientSecret"
|
||||
|| last_seg.ident == "DeviceId"
|
||||
|| last_seg.ident == "DeviceKeyId"
|
||||
|| last_seg.ident == "DeviceSigningKeyId"
|
||||
|| last_seg.ident == "EventId"
|
||||
|| last_seg.ident == "KeyId"
|
||||
|| last_seg.ident == "MxcUri"
|
||||
|| last_seg.ident == "ServerName"
|
||||
|| last_seg.ident == "SessionId"
|
||||
@ -271,6 +273,8 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
|
||||
|| last_seg.ident == "RoomId"
|
||||
|| last_seg.ident == "RoomIdOrAliasId"
|
||||
|| last_seg.ident == "RoomName"
|
||||
|| last_seg.ident == "ServerSigningKeyId"
|
||||
|| last_seg.ident == "SigningKeyId"
|
||||
|| last_seg.ident == "UserId"
|
||||
{
|
||||
// The identifiers that need to be boxed `Box<T>` since they are DST's.
|
||||
|
Loading…
x
Reference in New Issue
Block a user