identifiers: Provide Owned types

This commit is contained in:
Jonathan de Jong 2022-03-31 23:23:02 +02:00 committed by GitHub
parent a4aa7e0912
commit b77fee8948
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 250 additions and 36 deletions

View File

@ -25,6 +25,12 @@ jobs:
- name: Check Ruma
cmd: msrv-ruma
- name: Check Owned IDs with Box
cmd: msrv-owned-id-box
- name: Check Owned IDs with Arc
cmd: msrv-owned-id-arc
steps:
- name: Checkout repo
uses: actions/checkout@v2
@ -33,7 +39,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: '1.55'
toolchain: "1.55"
# Used to compile xtask
- name: Install rust stable toolchain

View File

@ -10,25 +10,25 @@ use serde::de::{self, Deserializer, Unexpected};
#[doc(inline)]
pub use self::{
client_secret::ClientSecret,
client_secret::{ClientSecret, OwnedClientSecret},
crypto_algorithms::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, SigningKeyAlgorithm},
device_id::DeviceId,
device_key_id::DeviceKeyId,
event_id::EventId,
device_id::{DeviceId, OwnedDeviceId},
device_key_id::{DeviceKeyId, OwnedDeviceKeyId},
event_id::{EventId, OwnedEventId},
key_id::{DeviceSigningKeyId, KeyId, ServerSigningKeyId, SigningKeyId},
key_name::KeyName,
key_name::{KeyName, OwnedKeyName},
matrix_uri::{MatrixToUri, MatrixUri},
mxc_uri::MxcUri,
room_alias_id::RoomAliasId,
room_id::RoomId,
room_name::RoomName,
room_or_room_alias_id::RoomOrAliasId,
mxc_uri::{MxcUri, OwnedMxcUri},
room_alias_id::{OwnedRoomAliasId, RoomAliasId},
room_id::{OwnedRoomId, RoomId},
room_name::{OwnedRoomName, RoomName},
room_or_room_alias_id::{OwnedRoomOrAliasId, RoomOrAliasId},
room_version_id::RoomVersionId,
server_name::ServerName,
session_id::SessionId,
server_name::{OwnedServerName, ServerName},
session_id::{OwnedSessionId, SessionId},
signatures::{DeviceSignatures, EntitySignatures, ServerSignatures, Signatures},
transaction_id::TransactionId,
user_id::UserId,
transaction_id::{OwnedTransactionId, TransactionId},
user_id::{OwnedUserId, UserId},
};
#[doc(inline)]
pub use ruma_identifiers_validation::error::Error as IdParseError;

View File

@ -24,7 +24,13 @@ impl ClientSecret {
}
}
opaque_identifier_validated!(ClientSecret, ruma_identifiers_validation::client_secret::validate);
owned_identifier!(OwnedClientSecret, ClientSecret);
opaque_identifier_validated!(
ClientSecret,
OwnedClientSecret,
ruma_identifiers_validation::client_secret::validate
);
#[cfg(test)]
mod tests {

View File

@ -29,7 +29,9 @@ use super::generate_localpart;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId(str);
opaque_identifier!(DeviceId);
owned_identifier!(OwnedDeviceId, DeviceId);
opaque_identifier!(DeviceId, OwnedDeviceId);
impl DeviceId {
/// Generates a random `DeviceId`, suitable for assignment to a new device.

View File

@ -7,7 +7,13 @@ use super::{crypto_algorithms::DeviceKeyAlgorithm, DeviceId};
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceKeyId(str);
opaque_identifier_validated!(DeviceKeyId, ruma_identifiers_validation::device_key_id::validate);
owned_identifier!(OwnedDeviceKeyId, DeviceKeyId);
opaque_identifier_validated!(
DeviceKeyId,
OwnedDeviceKeyId,
ruma_identifiers_validation::device_key_id::validate
);
impl DeviceKeyId {
/// Create a `DeviceKeyId` from a `DeviceKeyAlgorithm` and a `DeviceId`.

View File

@ -38,7 +38,13 @@ use super::ServerName;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EventId(str);
opaque_identifier_validated!(EventId, ruma_identifiers_validation::event_id::validate);
owned_identifier!(OwnedEventId, EventId);
opaque_identifier_validated!(
EventId,
OwnedEventId,
ruma_identifiers_validation::event_id::validate
);
impl EventId {
/// Attempts to generate an `EventId` for the given origin server with a localpart consisting

View File

@ -6,4 +6,6 @@
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct KeyName(str);
opaque_identifier!(KeyName);
owned_identifier!(OwnedKeyName, KeyName);
opaque_identifier!(KeyName, OwnedKeyName);

View File

@ -24,8 +24,100 @@ macro_rules! partial_eq_string {
}
}
macro_rules! owned_identifier {
($owned:ident, $id:ident) => {
#[doc = concat!("Owned variant of ", stringify!($id))]
///
/// The wrapper type for this type is variable, by default it'll use [`Box`],
/// but you can change that by setting "`--cfg=ruma_identifiers_storage=...`" using
/// `RUSTFLAGS` or `.cargo/config.toml` (under `[build]` -> `rustflags = ["..."]`)
/// to the following;
/// - `ruma_identifiers_storage="Arc"` to use [`Arc`](std::sync::Arc) as a wrapper type.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct $owned {
#[cfg(not(any(ruma_identifiers_storage = "Arc")))]
inner: Box<$id>,
#[cfg(ruma_identifiers_storage = "Arc")]
inner: std::sync::Arc<$id>,
}
impl AsRef<$id> for $owned {
fn as_ref(&self) -> &$id {
&*self.inner
}
}
impl AsRef<str> for $owned {
fn as_ref(&self) -> &str {
(*self.inner).as_ref()
}
}
impl std::ops::Deref for $owned {
type Target = $id;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl std::borrow::Borrow<$id> for $owned {
fn borrow(&self) -> &$id {
self.as_ref()
}
}
impl From<&'_ $id> for $owned {
fn from(id: &$id) -> $owned {
$owned { inner: id.into() }
}
}
impl From<Box<$id>> for $owned {
fn from(b: Box<$id>) -> $owned {
Self { inner: b.into() }
}
}
impl From<std::sync::Arc<$id>> for $owned {
fn from(a: std::sync::Arc<$id>) -> $owned {
Self {
#[cfg(not(any(ruma_identifiers_storage = "Arc")))]
inner: a.as_ref().into(),
#[cfg(ruma_identifiers_storage = "Arc")]
inner: a,
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for $owned {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(self.as_ref().as_str())
}
}
partial_eq_string!($owned);
impl PartialEq<Box<$id>> for $owned {
fn eq(&self, other: &Box<$id>) -> bool {
AsRef::<$id>::as_ref(self) == AsRef::<$id>::as_ref(other)
}
}
impl PartialEq<$owned> for Box<$id> {
fn eq(&self, other: &$owned) -> bool {
AsRef::<$id>::as_ref(self) == AsRef::<$id>::as_ref(other)
}
}
};
}
macro_rules! opaque_identifier_common_impls {
($id:ty) => {
($id:ident, $owned:ident) => {
impl $id {
pub(super) fn from_borrowed(s: &str) -> &Self {
unsafe { std::mem::transmute(s) }
@ -64,10 +156,20 @@ macro_rules! opaque_identifier_common_impls {
impl Clone for Box<$id> {
fn clone(&self) -> Self {
(**self).to_owned()
(**self).into()
}
}
// impl ToOwned for $id {
// type Owned = $owned;
// fn to_owned(&self) -> Self::Owned {
// Self::from_owned(self.0.into()).into()
// }
// }
// TODO swap below with above after codebase has been converted
// to not use `to_owned` as equivalent to "into Box"
impl ToOwned for $id {
type Owned = Box<$id>;
@ -90,7 +192,7 @@ macro_rules! opaque_identifier_common_impls {
impl From<&$id> for Box<$id> {
fn from(id: &$id) -> Self {
id.to_owned()
$id::from_owned(id.0.into())
}
}
@ -154,13 +256,13 @@ macro_rules! opaque_identifier_common_impls {
}
partial_eq_string!($id);
partial_eq_string!(Box<$id>);
partial_eq_string!(Box<$id>); // todo: Remove when all instances of Box have been converted to Owned
};
}
macro_rules! opaque_identifier {
($id:ident) => {
opaque_identifier_common_impls!($id);
($id:ident, $owned:ident) => {
opaque_identifier_common_impls!($id, $owned);
impl<'a> From<&'a str> for &'a $id {
fn from(s: &'a str) -> Self {
@ -206,11 +308,21 @@ macro_rules! opaque_identifier {
Box::<str>::deserialize(deserializer).map($id::from_owned)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for $owned {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Box::<str>::deserialize(deserializer).map($id::from_owned).map(Into::into)
}
}
};
}
macro_rules! opaque_identifier_validated {
($id:ident, $validate_id:expr) => {
($id:ident, $owned:ident, $validate_id:expr) => {
impl $id {
#[rustfmt::skip]
doc_concat! {
@ -249,7 +361,7 @@ macro_rules! opaque_identifier_validated {
}
}
opaque_identifier_common_impls!($id);
opaque_identifier_common_impls!($id, $owned);
impl From<Box<$id>> for String {
fn from(id: Box<$id>) -> Self {
@ -273,6 +385,23 @@ macro_rules! opaque_identifier_validated {
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for $owned {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
let s = String::deserialize(deserializer)?;
match $id::parse(s) {
Ok(o) => Ok(o.into()),
Err(e) => Err(D::Error::custom(e)),
}
}
}
impl<'a> std::convert::TryFrom<&'a str> for &'a $id {
type Error = crate::IdParseError;

View File

@ -18,7 +18,9 @@ type Result<T, E = MxcUriError> = std::result::Result<T, E>;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MxcUri(str);
opaque_identifier!(MxcUri);
owned_identifier!(OwnedMxcUri, MxcUri);
opaque_identifier!(MxcUri, OwnedMxcUri);
impl MxcUri {
/// If this is a valid MXC URI, returns the media ID.

View File

@ -18,7 +18,13 @@ use super::{matrix_uri::UriAction, server_name::ServerName, EventId, MatrixToUri
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RoomAliasId(str);
opaque_identifier_validated!(RoomAliasId, ruma_identifiers_validation::room_alias_id::validate);
owned_identifier!(OwnedRoomAliasId, RoomAliasId);
opaque_identifier_validated!(
RoomAliasId,
OwnedRoomAliasId,
ruma_identifiers_validation::room_alias_id::validate
);
impl RoomAliasId {
/// Returns the room's alias.

View File

@ -18,7 +18,9 @@ use super::{matrix_uri::UriAction, EventId, MatrixToUri, MatrixUri, ServerName};
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RoomId(str);
opaque_identifier_validated!(RoomId, ruma_identifiers_validation::room_id::validate);
owned_identifier!(OwnedRoomId, RoomId);
opaque_identifier_validated!(RoomId, OwnedRoomId, ruma_identifiers_validation::room_id::validate);
impl RoomId {
/// Attempts to generate a `RoomId` for the given origin server with a localpart consisting of

View File

@ -7,4 +7,10 @@
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RoomName(str);
opaque_identifier_validated!(RoomName, ruma_identifiers_validation::room_name::validate);
owned_identifier!(OwnedRoomName, RoomName);
opaque_identifier_validated!(
RoomName,
OwnedRoomName,
ruma_identifiers_validation::room_name::validate
);

View File

@ -27,8 +27,11 @@ use super::{server_name::ServerName, RoomAliasId, RoomId};
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RoomOrAliasId(str);
owned_identifier!(OwnedRoomOrAliasId, RoomOrAliasId);
opaque_identifier_validated!(
RoomOrAliasId,
OwnedRoomOrAliasId,
ruma_identifiers_validation::room_id_or_alias_id::validate
);

View File

@ -11,7 +11,13 @@ use std::net::Ipv4Addr;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ServerName(str);
opaque_identifier_validated!(ServerName, ruma_identifiers_validation::server_name::validate);
owned_identifier!(OwnedServerName, ServerName);
opaque_identifier_validated!(
ServerName,
OwnedServerName,
ruma_identifiers_validation::server_name::validate
);
impl ServerName {
/// Returns the host of the server name.

View File

@ -8,4 +8,10 @@
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SessionId(str);
opaque_identifier_validated!(SessionId, ruma_identifiers_validation::session_id::validate);
owned_identifier!(OwnedSessionId, SessionId);
opaque_identifier_validated!(
SessionId,
OwnedSessionId,
ruma_identifiers_validation::session_id::validate
);

View File

@ -22,4 +22,6 @@ impl TransactionId {
}
}
opaque_identifier!(TransactionId);
owned_identifier!(OwnedTransactionId, TransactionId);
opaque_identifier!(TransactionId, OwnedTransactionId);

View File

@ -20,7 +20,9 @@ use super::{matrix_uri::UriAction, IdParseError, MatrixToUri, MatrixUri, ServerN
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UserId(str);
opaque_identifier_validated!(UserId, ruma_identifiers_validation::user_id::validate);
owned_identifier!(OwnedUserId, UserId);
opaque_identifier_validated!(UserId, OwnedUserId, ruma_identifiers_validation::user_id::validate);
impl UserId {
/// Attempts to generate a `UserId` for the given origin server with a localpart consisting of

View File

@ -28,6 +28,10 @@ pub enum CiCmd {
MsrvClient,
/// Check ruma crate with default features (msrv)
MsrvRuma,
/// Check ruma-identifiers with `ruma_identifiers_storage="Box"`
MsrvOwnedIdBox,
/// Check ruma-identifiers with `ruma_identifiers_storage="Arc"`
MsrvOwnedIdArc,
/// Run all the tasks that use the stable version
Stable,
/// Check all crates with all features (stable)
@ -85,6 +89,8 @@ impl CiTask {
Some(CiCmd::MsrvAll) => self.msrv_all()?,
Some(CiCmd::MsrvClient) => self.msrv_client()?,
Some(CiCmd::MsrvRuma) => self.msrv_ruma()?,
Some(CiCmd::MsrvOwnedIdBox) => self.msrv_owned_id_box()?,
Some(CiCmd::MsrvOwnedIdArc) => self.msrv_owned_id_arc()?,
Some(CiCmd::Stable) => self.stable()?,
Some(CiCmd::StableAll) => self.stable_all()?,
Some(CiCmd::StableClient) => self.stable_client()?,
@ -210,6 +216,22 @@ impl CiTask {
cmd!("rustup run {NIGHTLY} cargo check -p ruma --features full").run().map_err(Into::into)
}
/// Check ruma-common with `ruma_identifiers_storage="Box"`
fn msrv_owned_id_box(&self) -> Result<()> {
cmd!("rustup run {MSRV} cargo check -p ruma-common")
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Box\"")
.run()
.map_err(Into::into)
}
/// Check ruma-common with `ruma_identifiers_storage="Arc"`
fn msrv_owned_id_arc(&self) -> Result<()> {
cmd!("rustup run {MSRV} cargo check -p ruma-common")
.env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Arc\"")
.run()
.map_err(Into::into)
}
/// Lint default features with clippy with the nightly version.
fn clippy_default(&self) -> Result<()> {
cmd!(