diff --git a/ruma-identifiers/src/device_key_id.rs b/ruma-identifiers/src/device_key_id.rs index ce6ee730..f824c286 100644 --- a/ruma-identifiers/src/device_key_id.rs +++ b/ruma-identifiers/src/device_key_id.rs @@ -10,21 +10,23 @@ pub struct DeviceKeyId { colon_idx: NonZeroU8, } -impl DeviceKeyId { +impl DeviceKeyId +where + T: AsRef, +{ + /// Creates a reference to this `DeviceKeyId`. + pub fn as_ref(&self) -> DeviceKeyId<&str> { + DeviceKeyId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } + /// Returns key algorithm of the device key ID. - pub fn algorithm(&self) -> DeviceKeyAlgorithm - where - T: AsRef, - { + pub fn algorithm(&self) -> DeviceKeyAlgorithm { DeviceKeyAlgorithm::from_str(&self.full_id.as_ref()[..self.colon_idx.get() as usize]) .unwrap() } /// Returns device ID of the device key ID. - pub fn device_id(&self) -> DeviceIdRef<'_> - where - T: AsRef, - { + pub fn device_id(&self) -> DeviceIdRef<'_> { &self.full_id.as_ref()[self.colon_idx.get() as usize + 1..] } } diff --git a/ruma-identifiers/src/event_id.rs b/ruma-identifiers/src/event_id.rs index 998659d6..feffc248 100644 --- a/ruma-identifiers/src/event_id.rs +++ b/ruma-identifiers/src/event_id.rs @@ -46,7 +46,10 @@ pub struct EventId { colon_idx: Option, } -impl EventId { +impl EventId +where + String: Into, +{ /// Attempts to generate an `EventId` for the given origin server with a localpart consisting /// of 18 random ASCII characters. This should only be used for events in the original format /// as used by Matrix room versions 1 and 2. @@ -55,24 +58,28 @@ impl EventId { /// parsed as a valid host. #[cfg(feature = "rand")] #[cfg_attr(docsrs, doc(cfg(feature = "rand")))] - pub fn new(server_name: ServerNameRef<'_>) -> Self - where - String: Into, - { + pub fn new(server_name: ServerNameRef<'_>) -> Self { use crate::generate_localpart; let full_id = format!("${}:{}", generate_localpart(18), server_name).into(); Self { full_id, colon_idx: NonZeroU8::new(19) } } +} + +impl EventId +where + T: AsRef, +{ + /// Creates a reference to this `EventId`. + pub fn as_ref(&self) -> EventId<&str> { + EventId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } /// Returns the event's unique ID. For the original event format as used by Matrix room /// versions 1 and 2, this is the "localpart" that precedes the homeserver. For later formats, /// this is the entire ID without the leading $ sigil. - pub fn localpart(&self) -> &str - where - T: AsRef, - { + pub fn localpart(&self) -> &str { let idx = match self.colon_idx { Some(idx) => idx.get() as usize, None => self.full_id.as_ref().len(), @@ -84,10 +91,7 @@ impl EventId { /// Returns the server name of the event ID. /// /// Only applicable to events in the original format as used by Matrix room versions 1 and 2. - pub fn server_name(&self) -> Option> - where - T: AsRef, - { + pub fn server_name(&self) -> Option> { self.colon_idx.map(|idx| { ServerNameRef::try_from(&self.full_id.as_ref()[idx.get() as usize + 1..]).unwrap() }) @@ -162,7 +166,7 @@ mod tests { let server_name = ServerNameRef::try_from("example.com").expect("Failed to parse ServerName"); let event_id = EventId::new(server_name); - let id_str: &str = event_id.as_ref(); + let id_str = event_id.as_str(); assert!(id_str.starts_with('$')); assert_eq!(id_str.len(), 31); diff --git a/ruma-identifiers/src/key_algorithms.rs b/ruma-identifiers/src/key_algorithms.rs index a4879b6e..3b489f2a 100644 --- a/ruma-identifiers/src/key_algorithms.rs +++ b/ruma-identifiers/src/key_algorithms.rs @@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize}; use strum::{AsRefStr, Display, EnumString}; -/// The basic key algorithms in the specification +/// The basic key algorithms in the specification. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsRefStr, Display, EnumString)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[non_exhaustive] @@ -23,6 +23,7 @@ pub enum DeviceKeyAlgorithm { SignedCurve25519, } +/// The server key algorithms defined in the Matrix spec. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, AsRefStr, Display, EnumString)] #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] #[non_exhaustive] diff --git a/ruma-identifiers/src/lib.rs b/ruma-identifiers/src/lib.rs index 168f0fa8..df4d10ce 100644 --- a/ruma-identifiers/src/lib.rs +++ b/ruma-identifiers/src/lib.rs @@ -2,11 +2,7 @@ //! for events, rooms, room aliases, room versions, and users. #![warn(rust_2018_idioms)] -#![deny( - missing_copy_implementations, - missing_debug_implementations, - //missing_docs -)] +#![deny(missing_copy_implementations, missing_debug_implementations, missing_docs)] // Since we support Rust 1.36.0, we can't apply this suggestion yet #![allow(clippy::use_self)] #![cfg_attr(docsrs, feature(doc_cfg))] diff --git a/ruma-identifiers/src/macros.rs b/ruma-identifiers/src/macros.rs index a072a6aa..24b8a54d 100644 --- a/ruma-identifiers/src/macros.rs +++ b/ruma-identifiers/src/macros.rs @@ -1,5 +1,27 @@ +/// Declares an item with a doc attribute computed by some macro expression. +/// This allows documentation to be dynamically generated based on input. +/// Necessary to work around https://github.com/rust-lang/rust/issues/52607. +macro_rules! doc_concat { + ( $( #[doc = $doc:expr] $thing:item )* ) => ( $( #[doc = $doc] $thing )* ); +} + macro_rules! common_impls { ($id:ident, $try_from:ident, $desc:literal) => { + impl> $id { + doc_concat! { + #[doc = concat!("Creates a string slice from this `", stringify!($id), "`")] + pub fn as_str(&self) -> &str { + self.full_id.as_ref() + } + } + } + + impl<'a> ::std::convert::From<&'a $id>> for $id<&'a str> { + fn from(id: &'a $id>) -> Self { + id.as_ref() + } + } + impl ::std::convert::From<$id>> for ::std::string::String { fn from(id: $id>) -> Self { id.full_id.into() diff --git a/ruma-identifiers/src/room_alias_id.rs b/ruma-identifiers/src/room_alias_id.rs index fc0cccf1..01000551 100644 --- a/ruma-identifiers/src/room_alias_id.rs +++ b/ruma-identifiers/src/room_alias_id.rs @@ -26,7 +26,15 @@ pub struct RoomAliasId { pub(crate) colon_idx: NonZeroU8, } -impl> RoomAliasId { +impl RoomAliasId +where + T: AsRef, +{ + /// Creates a reference to this `RoomAliasId`. + pub fn as_ref(&self) -> RoomAliasId<&str> { + RoomAliasId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } + /// Returns the room's alias. pub fn alias(&self) -> &str { &self.full_id.as_ref()[1..self.colon_idx.get() as usize] diff --git a/ruma-identifiers/src/room_id.rs b/ruma-identifiers/src/room_id.rs index cee4a567..672020a8 100644 --- a/ruma-identifiers/src/room_id.rs +++ b/ruma-identifiers/src/room_id.rs @@ -26,37 +26,41 @@ pub struct RoomId { pub(crate) colon_idx: NonZeroU8, } -impl RoomId { +impl RoomId +where + String: Into, +{ /// Attempts to generate a `RoomId` for the given origin server with a localpart consisting of /// 18 random ASCII characters. /// /// Fails if the given homeserver cannot be parsed as a valid host. #[cfg(feature = "rand")] #[cfg_attr(docsrs, doc(cfg(feature = "rand")))] - pub fn new(server_name: ServerNameRef<'_>) -> Self - where - String: Into, - { + pub fn new(server_name: ServerNameRef<'_>) -> Self { use crate::generate_localpart; let full_id = format!("!{}:{}", generate_localpart(18), server_name).into(); Self { full_id, colon_idx: NonZeroU8::new(19).unwrap() } } +} + +impl RoomId +where + T: AsRef, +{ + /// Creates a reference to this `RoomId`. + pub fn as_ref(&self) -> RoomId<&str> { + RoomId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } /// Returns the rooms's unique ID. - pub fn localpart(&self) -> &str - where - T: AsRef, - { + pub fn localpart(&self) -> &str { &self.full_id.as_ref()[1..self.colon_idx.get() as usize] } /// Returns the server name of the room ID. - pub fn server_name(&self) -> ServerNameRef<'_> - where - T: AsRef, - { + pub fn server_name(&self) -> ServerNameRef<'_> { ServerNameRef::try_from(&self.full_id.as_ref()[self.colon_idx.get() as usize + 1..]) .unwrap() } @@ -103,7 +107,7 @@ mod tests { let server_name = ServerNameRef::try_from("example.com").expect("Failed to parse ServerName"); let room_id = RoomId::new(server_name); - let id_str: &str = room_id.as_ref(); + let id_str = room_id.as_str(); assert!(id_str.starts_with('!')); assert_eq!(id_str.len(), 31); diff --git a/ruma-identifiers/src/room_id_or_room_alias_id.rs b/ruma-identifiers/src/room_id_or_room_alias_id.rs index 3af9f604..b9f59012 100644 --- a/ruma-identifiers/src/room_id_or_room_alias_id.rs +++ b/ruma-identifiers/src/room_id_or_room_alias_id.rs @@ -34,7 +34,15 @@ pub struct RoomIdOrAliasId { colon_idx: NonZeroU8, } -impl> RoomIdOrAliasId { +impl RoomIdOrAliasId +where + T: AsRef, +{ + /// Creates a reference to this `RoomIdOrAliasId`. + pub fn as_ref(&self) -> RoomIdOrAliasId<&str> { + RoomIdOrAliasId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } + /// Returns the local part (everything after the `!` or `#` and before the first colon). pub fn localpart(&self) -> &str { &self.full_id.as_ref()[1..self.colon_idx.get() as usize] diff --git a/ruma-identifiers/src/server_key_id.rs b/ruma-identifiers/src/server_key_id.rs index f19d514b..57318557 100644 --- a/ruma-identifiers/src/server_key_id.rs +++ b/ruma-identifiers/src/server_key_id.rs @@ -11,21 +11,23 @@ pub struct ServerKeyId { colon_idx: NonZeroU8, } -impl ServerKeyId { +impl ServerKeyId +where + T: AsRef, +{ + /// Creates a reference to this `ServerKeyId`. + pub fn as_ref(&self) -> ServerKeyId<&str> { + ServerKeyId { full_id: self.full_id.as_ref(), colon_idx: self.colon_idx } + } + /// Returns key algorithm of the server key ID. - pub fn algorithm(&self) -> ServerKeyAlgorithm - where - T: AsRef, - { + pub fn algorithm(&self) -> ServerKeyAlgorithm { ServerKeyAlgorithm::from_str(&self.full_id.as_ref()[..self.colon_idx.get() as usize]) .unwrap() } /// Returns the version of the server key ID. - pub fn version(&self) -> &str - where - T: AsRef, - { + pub fn version(&self) -> &str { &self.full_id.as_ref()[self.colon_idx.get() as usize + 1..] } } diff --git a/ruma-identifiers/src/server_name.rs b/ruma-identifiers/src/server_name.rs index 88f263bc..80027317 100644 --- a/ruma-identifiers/src/server_name.rs +++ b/ruma-identifiers/src/server_name.rs @@ -11,6 +11,16 @@ pub struct ServerName { full_id: T, } +impl ServerName +where + T: AsRef, +{ + /// Creates a reference to this `ServerName`. + pub fn as_ref(&self) -> ServerName<&str> { + ServerName { full_id: self.full_id.as_ref() } + } +} + fn try_from(server_name: S) -> Result, Error> where S: AsRef + Into, diff --git a/ruma-identifiers/src/user_id.rs b/ruma-identifiers/src/user_id.rs index 753cda4f..63f3c5cc 100644 --- a/ruma-identifiers/src/user_id.rs +++ b/ruma-identifiers/src/user_id.rs @@ -32,15 +32,15 @@ pub struct UserId { is_historical: bool, } -impl UserId { +impl UserId +where + String: Into, +{ /// Attempts to generate a `UserId` for the given origin server with a localpart consisting of /// 12 random ASCII characters. #[cfg(feature = "rand")] #[cfg_attr(docsrs, doc(cfg(feature = "rand")))] - pub fn new(server_name: ServerNameRef<'_>) -> Self - where - String: Into, - { + pub fn new(server_name: ServerNameRef<'_>) -> Self { use crate::generate_localpart; let full_id = format!("@{}:{}", generate_localpart(12).to_lowercase(), server_name).into(); @@ -58,10 +58,7 @@ impl UserId { pub fn parse_with_server_name( id: impl AsRef + Into, server_name: ServerNameRef<'_>, - ) -> Result - where - String: Into, - { + ) -> Result { let id_str = id.as_ref(); if id_str.starts_with('@') { @@ -76,24 +73,34 @@ impl UserId { }) } } +} + +impl UserId +where + T: AsRef, +{ + /// Creates a reference to this `UserId`. + pub fn as_ref(&self) -> UserId<&str> { + UserId { + full_id: self.full_id.as_ref(), + colon_idx: self.colon_idx, + is_historical: self.is_historical, + } + } /// Returns the user's localpart. - pub fn localpart(&self) -> &str - where - T: AsRef, - { + pub fn localpart(&self) -> &str { &self.full_id.as_ref()[1..self.colon_idx.get() as usize] } /// Returns the server name of the user ID. - pub fn server_name(&self) -> ServerNameRef<'_> - where - T: AsRef, - { + pub fn server_name(&self) -> ServerNameRef<'_> { ServerNameRef::try_from(&self.full_id.as_ref()[self.colon_idx.get() as usize + 1..]) .unwrap() } +} +impl UserId { /// Whether this user ID is a historical one, i.e. one that doesn't conform to the latest /// specification of the user ID grammar but is still accepted because it was previously /// allowed. @@ -232,7 +239,7 @@ mod tests { assert_eq!(user_id.localpart().len(), 12); assert_eq!(user_id.server_name(), "example.com"); - let id_str: &str = user_id.as_ref(); + let id_str = user_id.as_str(); assert!(id_str.starts_with('@')); assert_eq!(id_str.len(), 25);