Make DeviceId a newtype rather than an alias
This commit is contained in:
parent
8d8e18afbc
commit
b24df92692
@ -288,7 +288,7 @@ mod tests {
|
||||
key_agreement_protocols,
|
||||
message_authentication_codes,
|
||||
short_authentication_string,
|
||||
}) if from_device.as_ref() == "123"
|
||||
}) if from_device.as_str() == "123"
|
||||
&& transaction_id == "456"
|
||||
&& hashes == vec![HashAlgorithm::Sha256]
|
||||
&& key_agreement_protocols == vec![KeyAgreementProtocol::Curve25519]
|
||||
@ -323,7 +323,7 @@ mod tests {
|
||||
message_authentication_codes,
|
||||
short_authentication_string,
|
||||
})
|
||||
} if from_device.as_ref() == "123"
|
||||
} if from_device.as_str() == "123"
|
||||
&& transaction_id == "456"
|
||||
&& hashes == vec![HashAlgorithm::Sha256]
|
||||
&& key_agreement_protocols == vec![KeyAgreementProtocol::Curve25519]
|
||||
|
@ -161,7 +161,7 @@ mod tests {
|
||||
session_id,
|
||||
}) if ciphertext == "ciphertext"
|
||||
&& sender_key == "sender_key"
|
||||
&& device_id.as_ref() == "device_id"
|
||||
&& device_id.as_str() == "device_id"
|
||||
&& session_id == "session_id"
|
||||
);
|
||||
}
|
||||
|
@ -32,9 +32,9 @@ Breaking changes:
|
||||
```rust
|
||||
fn server_name() -> &ServerName
|
||||
```
|
||||
* Change `DeviceId` from being an alias for `String` to being an alias for `str`
|
||||
* This means any string slice or string literal is a valid `&DeviceId` now
|
||||
* But to store one, you need to box it: `Box<DeviceId>`
|
||||
* Change `DeviceId` from being an alias for `String` to being a newtype around `str`
|
||||
|
||||
This means owned device IDs are now `Box<DeviceId>`.
|
||||
* Change `RoomVersionId` from being an opaque struct to a non-exhaustive enum
|
||||
* The constructor functions and `is_` predicates are now deprecated
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
//! Matrix device identifiers.
|
||||
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
mem,
|
||||
};
|
||||
|
||||
#[cfg(feature = "rand")]
|
||||
use crate::generate_localpart;
|
||||
|
||||
@ -7,21 +12,142 @@ use crate::generate_localpart;
|
||||
///
|
||||
/// Device identifiers in Matrix are completely opaque character sequences. This type alias is
|
||||
/// provided simply for its semantic value.
|
||||
pub type DeviceId = str;
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize), serde(transparent))]
|
||||
pub struct DeviceId(str);
|
||||
|
||||
impl DeviceId {
|
||||
#[allow(clippy::transmute_ptr_to_ptr)]
|
||||
fn from_borrowed(s: &str) -> &Self {
|
||||
unsafe { mem::transmute(s) }
|
||||
}
|
||||
|
||||
fn from_owned(s: Box<str>) -> Box<Self> {
|
||||
unsafe { mem::transmute(s) }
|
||||
}
|
||||
|
||||
fn into_owned(self: Box<Self>) -> Box<str> {
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Generates a random `DeviceId`, suitable for assignment to a new device.
|
||||
#[cfg(feature = "rand")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||
pub fn new() -> Box<Self> {
|
||||
Self::from_owned(generate_localpart(8))
|
||||
}
|
||||
|
||||
/// Creates a string slice from this `DeviceId`.
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Box<DeviceId> {
|
||||
fn clone(&self) -> Self {
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOwned for DeviceId {
|
||||
type Owned = Box<DeviceId>;
|
||||
|
||||
fn to_owned(&self) -> Self::Owned {
|
||||
Self::from_owned(self.0.to_owned().into_boxed_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for DeviceId {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Box<DeviceId> {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for &'a DeviceId {
|
||||
fn from(s: &'a str) -> Self {
|
||||
DeviceId::from_borrowed(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for Box<DeviceId> {
|
||||
fn from(s: &str) -> Self {
|
||||
DeviceId::from_owned(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Box<DeviceId> {
|
||||
fn from(s: String) -> Self {
|
||||
DeviceId::from_owned(s.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Box<DeviceId>> for String {
|
||||
fn from(id: Box<DeviceId>) -> Self {
|
||||
id.into_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DeviceId {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> serde::Deserialize<'de> for Box<DeviceId> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
crate::deserialize_id(deserializer, "An IP address or hostname")
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for DeviceId {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.as_str() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<DeviceId> for str {
|
||||
fn eq(&self, other: &DeviceId) -> bool {
|
||||
self == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for DeviceId {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<DeviceId> for String {
|
||||
fn eq(&self, other: &DeviceId) -> bool {
|
||||
self.as_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a random `DeviceId`, suitable for assignment to a new device.
|
||||
#[cfg(feature = "rand")]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "rand")))]
|
||||
#[deprecated = "use DeviceId::new instead"]
|
||||
pub fn generate() -> Box<DeviceId> {
|
||||
generate_localpart(8)
|
||||
DeviceId::new()
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "rand"))]
|
||||
mod tests {
|
||||
use super::generate;
|
||||
use super::DeviceId;
|
||||
|
||||
#[test]
|
||||
fn generate_device_id() {
|
||||
assert_eq!(generate().len(), 8);
|
||||
assert_eq!(DeviceId::new().as_str().len(), 8);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ impl DeviceKeyId {
|
||||
|
||||
/// Returns device ID of the device key ID.
|
||||
pub fn device_id(&self) -> &DeviceId {
|
||||
&self.full_id[self.colon_idx.get() as usize + 1..]
|
||||
(&self.full_id[self.colon_idx.get() as usize + 1..]).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user