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