identifiers: Make MxcUri a DST

This commit is contained in:
Jonas Platte 2021-09-18 00:39:36 +02:00
parent a38f78e2d3
commit ec605a0959
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
25 changed files with 70 additions and 127 deletions

View File

@ -54,7 +54,7 @@ pub struct PublicRoomsChunk {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The joining rule for the room. /// The joining rule for the room.
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]

View File

@ -39,7 +39,7 @@ ruma_api! {
response: { response: {
/// The MXC URI for the uploaded content. /// The MXC URI for the uploaded content.
pub content_uri: MxcUri, pub content_uri: Box<MxcUri>,
/// The [BlurHash](https://blurha.sh) for the uploaded content. /// The [BlurHash](https://blurha.sh) for the uploaded content.
/// ///
@ -68,7 +68,7 @@ impl<'a> Request<'a> {
impl Response { impl Response {
/// Creates a new `Response` with the given MXC URI. /// Creates a new `Response` with the given MXC URI.
pub fn new(content_uri: MxcUri) -> Self { pub fn new(content_uri: Box<MxcUri>) -> Self {
Self { Self {
content_uri, content_uri,
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]

View File

@ -62,7 +62,7 @@ pub struct RoomMember {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
} }
impl RoomMember { impl RoomMember {
@ -89,7 +89,7 @@ mod test {
display_name: Some(display_name), display_name: Some(display_name),
avatar_url: Some(avatar_url), avatar_url: Some(avatar_url),
} if display_name == "alice" } if display_name == "alice"
&& avatar_url.to_string() == "mxc://localhost/wefuiwegh8742w" && avatar_url == "mxc://localhost/wefuiwegh8742w"
); );
#[cfg(feature = "compat")] #[cfg(feature = "compat")]

View File

@ -30,7 +30,7 @@ ruma_api! {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The [BlurHash](https://blurha.sh) for the avatar pointed to by `avatar_url`. /// The [BlurHash](https://blurha.sh) for the avatar pointed to by `avatar_url`.
/// ///
@ -53,7 +53,7 @@ impl<'a> Request<'a> {
impl Response { impl Response {
/// Creates a new `Response` with the given avatar URL. /// Creates a new `Response` with the given avatar URL.
pub fn new(avatar_url: Option<MxcUri>) -> Self { pub fn new(avatar_url: Option<Box<MxcUri>>) -> Self {
Self { Self {
avatar_url, avatar_url,
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]

View File

@ -30,7 +30,7 @@ ruma_api! {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The user's display name, if set. /// The user's display name, if set.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -57,7 +57,7 @@ impl<'a> Request<'a> {
impl Response { impl Response {
/// Creates a new `Response` with the given avatar URL and display name. /// Creates a new `Response` with the given avatar URL and display name.
pub fn new(avatar_url: Option<MxcUri>, displayname: Option<String>) -> Self { pub fn new(avatar_url: Option<Box<MxcUri>>, displayname: Option<String>) -> Self {
Self { Self {
avatar_url, avatar_url,
displayname, displayname,

View File

@ -474,7 +474,7 @@ pub struct UserProfile {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The user's display name, if set. /// The user's display name, if set.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]

View File

@ -178,7 +178,7 @@ pub struct IdentityProvider {
name: String, name: String,
/// The icon for the provider. /// The icon for the provider.
icon: Option<MxcUri>, icon: Option<Box<MxcUri>>,
/// The brand identifier for the provider. /// The brand identifier for the provider.
brand: Option<IdentityProviderBrand>, brand: Option<IdentityProviderBrand>,
@ -337,7 +337,7 @@ mod tests {
brand: Some(IdentityProviderBrand::GitLab), brand: Some(IdentityProviderBrand::GitLab),
}) if id == "oidc-gitlab" }) if id == "oidc-gitlab"
&& name == "GitLab" && name == "GitLab"
&& icon.to_string() == "mxc://localhost/gitlab-icon" && icon == "mxc://localhost/gitlab-icon"
); );
} }

View File

@ -87,7 +87,7 @@ pub struct User {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
} }
impl User { impl User {

View File

@ -58,7 +58,7 @@ pub struct PublicRoomsChunk {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
} }
/// Initial set of mandatory fields of `PublicRoomsChunk`. /// Initial set of mandatory fields of `PublicRoomsChunk`.

View File

@ -57,7 +57,6 @@ event_enum! {
"m.sticker", "m.sticker",
} }
/// Any state event. /// Any state event.
enum State { enum State {
"m.policy.rule.room", "m.policy.rule.room",

View File

@ -37,7 +37,7 @@ pub struct PresenceEventContent {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// Whether or not the user is currently active. /// Whether or not the user is currently active.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -92,7 +92,7 @@ mod tests {
fn serialization() { fn serialization() {
let event = PresenceEvent { let event = PresenceEvent {
content: PresenceEventContent { content: PresenceEventContent {
avatar_url: Some(mxc_uri!("mxc://localhost/wefuiwegh8742w")), avatar_url: Some(mxc_uri!("mxc://localhost/wefuiwegh8742w").to_owned()),
currently_active: Some(false), currently_active: Some(false),
displayname: None, displayname: None,
last_active_ago: Some(uint!(2_478_593)), last_active_ago: Some(uint!(2_478_593)),
@ -143,7 +143,7 @@ mod tests {
status_msg: Some(status_msg), status_msg: Some(status_msg),
}, },
sender, sender,
} if avatar_url.to_string() == "mxc://localhost/wefuiwegh8742w" } if avatar_url == "mxc://localhost/wefuiwegh8742w"
&& status_msg == "Making cupcakes" && status_msg == "Making cupcakes"
&& sender == "@example:localhost" && sender == "@example:localhost"
&& last_active_ago == uint!(2_478_593) && last_active_ago == uint!(2_478_593)

View File

@ -56,7 +56,7 @@ pub struct ImageInfo {
/// ///
/// Only present if the thumbnail is unencrypted. /// Only present if the thumbnail is unencrypted.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail_url: Option<MxcUri>, pub thumbnail_url: Option<Box<MxcUri>>,
/// Information on the encrypted thumbnail image. /// Information on the encrypted thumbnail image.
/// ///
@ -116,7 +116,7 @@ impl ThumbnailInfo {
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)] #[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct EncryptedFile { pub struct EncryptedFile {
/// The URL to the file. /// The URL to the file.
pub url: MxcUri, pub url: Box<MxcUri>,
/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
pub key: JsonWebKey, pub key: JsonWebKey,
@ -143,7 +143,7 @@ pub struct EncryptedFile {
#[allow(clippy::exhaustive_structs)] #[allow(clippy::exhaustive_structs)]
pub struct EncryptedFileInit { pub struct EncryptedFileInit {
/// The URL to the file. /// The URL to the file.
pub url: MxcUri, pub url: Box<MxcUri>,
/// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object. /// A [JSON Web Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) object.
pub key: JsonWebKey, pub key: JsonWebKey,

View File

@ -25,13 +25,13 @@ pub struct RoomAvatarEventContent {
/// ///
/// With the `unstable-pre-spec` feature, this field is optional. /// With the `unstable-pre-spec` feature, this field is optional.
#[cfg(not(feature = "unstable-pre-spec"))] #[cfg(not(feature = "unstable-pre-spec"))]
pub url: MxcUri, pub url: Box<MxcUri>,
/// URL of the avatar image. /// URL of the avatar image.
/// ///
/// Without the `unstable-pre-spec` feature, this field is not optional. /// Without the `unstable-pre-spec` feature, this field is not optional.
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
pub url: Option<MxcUri>, pub url: Option<Box<MxcUri>>,
} }
impl RoomAvatarEventContent { impl RoomAvatarEventContent {
@ -39,7 +39,7 @@ impl RoomAvatarEventContent {
/// ///
/// With the `unstable-pre-spec` feature, this method takes no parameters. /// With the `unstable-pre-spec` feature, this method takes no parameters.
#[cfg(not(feature = "unstable-pre-spec"))] #[cfg(not(feature = "unstable-pre-spec"))]
pub fn new(url: MxcUri) -> Self { pub fn new(url: Box<MxcUri>) -> Self {
Self { info: None, url } Self { info: None, url }
} }
@ -78,7 +78,7 @@ pub struct ImageInfo {
/// The URL to the thumbnail of the image. /// The URL to the thumbnail of the image.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail_url: Option<MxcUri>, pub thumbnail_url: Option<Box<MxcUri>>,
/// The [BlurHash](https://blurha.sh) for this image. /// The [BlurHash](https://blurha.sh) for this image.
/// ///

View File

@ -49,7 +49,7 @@ pub struct RoomMemberEventContent {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The display name for this user, if any. /// The display name for this user, if any.
/// ///
@ -489,7 +489,7 @@ mod tests {
state_key, state_key,
unsigned, unsigned,
prev_content: None, prev_content: None,
} if avatar_url.to_string() == "mxc://example.org/SEsfnsuifSDFSSEF" } if avatar_url == "mxc://example.org/SEsfnsuifSDFSSEF"
&& displayname == "Alice Margatroid" && displayname == "Alice Margatroid"
&& third_party_displayname == "alice" && third_party_displayname == "alice"
&& mxid == "@alice:example.org" && mxid == "@alice:example.org"
@ -574,7 +574,7 @@ mod tests {
&& sender == "@alice:example.org" && sender == "@alice:example.org"
&& state_key == "@alice:example.org" && state_key == "@alice:example.org"
&& unsigned.is_empty() && unsigned.is_empty()
&& avatar_url.to_string() == "mxc://example.org/SEsfnsuifSDFSSEF" && avatar_url == "mxc://example.org/SEsfnsuifSDFSSEF"
&& displayname == "Alice Margatroid" && displayname == "Alice Margatroid"
&& third_party_displayname == "alice" && third_party_displayname == "alice"
&& mxid == "@alice:example.org" && mxid == "@alice:example.org"

View File

@ -403,7 +403,7 @@ pub struct AudioMessageEventContent {
/// ///
/// Required if the file is unencrypted. /// Required if the file is unencrypted.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<MxcUri>, pub url: Option<Box<MxcUri>>,
/// Information on the encrypted audio clip. /// Information on the encrypted audio clip.
/// ///
@ -419,7 +419,7 @@ pub struct AudioMessageEventContent {
impl AudioMessageEventContent { impl AudioMessageEventContent {
/// Creates a new non-encrypted `RoomAudioMessageEventContent` with the given body, url and /// Creates a new non-encrypted `RoomAudioMessageEventContent` with the given body, url and
/// optional extra info. /// optional extra info.
pub fn plain(body: String, url: MxcUri, info: Option<Box<AudioInfo>>) -> Self { pub fn plain(body: String, url: Box<MxcUri>, info: Option<Box<AudioInfo>>) -> Self {
Self { body, url: Some(url), info, file: None } Self { body, url: Some(url), info, file: None }
} }
@ -504,7 +504,7 @@ pub struct FileMessageEventContent {
/// The URL to the file. /// The URL to the file.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<MxcUri>, pub url: Option<Box<MxcUri>>,
/// Information on the encrypted file. /// Information on the encrypted file.
/// ///
@ -520,7 +520,7 @@ pub struct FileMessageEventContent {
impl FileMessageEventContent { impl FileMessageEventContent {
/// Creates a new non-encrypted `RoomFileMessageEventContent` with the given body, url and /// Creates a new non-encrypted `RoomFileMessageEventContent` with the given body, url and
/// optional extra info. /// optional extra info.
pub fn plain(body: String, url: MxcUri, info: Option<Box<FileInfo>>) -> Self { pub fn plain(body: String, url: Box<MxcUri>, info: Option<Box<FileInfo>>) -> Self {
Self { body, filename: None, url: Some(url), info, file: None } Self { body, filename: None, url: Some(url), info, file: None }
} }
@ -551,7 +551,7 @@ pub struct FileInfo {
/// ///
/// Only present if the thumbnail is unencrypted. /// Only present if the thumbnail is unencrypted.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail_url: Option<MxcUri>, pub thumbnail_url: Option<Box<MxcUri>>,
/// Information on the encrypted thumbnail file. /// Information on the encrypted thumbnail file.
/// ///
@ -580,7 +580,7 @@ pub struct ImageMessageEventContent {
/// The URL to the image. /// The URL to the image.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<MxcUri>, pub url: Option<Box<MxcUri>>,
/// Information on the encrypted image. /// Information on the encrypted image.
/// ///
@ -596,7 +596,7 @@ pub struct ImageMessageEventContent {
impl ImageMessageEventContent { impl ImageMessageEventContent {
/// Creates a new non-encrypted `RoomImageMessageEventContent` with the given body, url and /// Creates a new non-encrypted `RoomImageMessageEventContent` with the given body, url and
/// optional extra info. /// optional extra info.
pub fn plain(body: String, url: MxcUri, info: Option<Box<ImageInfo>>) -> Self { pub fn plain(body: String, url: Box<MxcUri>, info: Option<Box<ImageInfo>>) -> Self {
Self { body, url: Some(url), info, file: None } Self { body, url: Some(url), info, file: None }
} }
@ -639,7 +639,7 @@ pub struct LocationInfo {
/// ///
/// Only present if the thumbnail is unencrypted. /// Only present if the thumbnail is unencrypted.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail_url: Option<MxcUri>, pub thumbnail_url: Option<Box<MxcUri>>,
/// Information on an encrypted thumbnail of the location being represented. /// Information on an encrypted thumbnail of the location being represented.
/// ///
@ -871,7 +871,7 @@ pub struct VideoMessageEventContent {
/// The URL to the video clip. /// The URL to the video clip.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub url: Option<MxcUri>, pub url: Option<Box<MxcUri>>,
/// Information on the encrypted video clip. /// Information on the encrypted video clip.
/// ///
@ -887,7 +887,7 @@ pub struct VideoMessageEventContent {
impl VideoMessageEventContent { impl VideoMessageEventContent {
/// Creates a new non-encrypted `RoomVideoMessageEventContent` with the given body, url and /// Creates a new non-encrypted `RoomVideoMessageEventContent` with the given body, url and
/// optional extra info. /// optional extra info.
pub fn plain(body: String, url: MxcUri, info: Option<Box<VideoInfo>>) -> Self { pub fn plain(body: String, url: Box<MxcUri>, info: Option<Box<VideoInfo>>) -> Self {
Self { body, url: Some(url), info, file: None } Self { body, url: Some(url), info, file: None }
} }
@ -930,7 +930,7 @@ pub struct VideoInfo {
/// ///
/// Only present if the thumbnail is unencrypted. /// Only present if the thumbnail is unencrypted.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub thumbnail_url: Option<MxcUri>, pub thumbnail_url: Option<Box<MxcUri>>,
/// Information on the encrypted thumbnail file. /// Information on the encrypted thumbnail file.
/// ///

View File

@ -23,12 +23,12 @@ pub struct StickerEventContent {
pub info: ImageInfo, pub info: ImageInfo,
/// The URL to the sticker image. /// The URL to the sticker image.
pub url: MxcUri, pub url: Box<MxcUri>,
} }
impl StickerEventContent { impl StickerEventContent {
/// Creates a new `StickerEventContent` with the given body, image info and URL. /// Creates a new `StickerEventContent` with the given body, image info and URL.
pub fn new(body: String, info: ImageInfo, url: MxcUri) -> Self { pub fn new(body: String, info: ImageInfo, url: Box<MxcUri>) -> Self {
Self { body, info, url } Self { body, info, url }
} }
} }

View File

@ -82,9 +82,9 @@ fn serialize_message_event() {
mimetype: Some("image/png".into()), mimetype: Some("image/png".into()),
size: UInt::new(82595), size: UInt::new(82595),
}))), }))),
thumbnail_url: Some(mxc_uri!("mxc://matrix.org/mnrsnsRRS787TSts")), thumbnail_url: Some(mxc_uri!("mxc://matrix.org/mnrsnsRRS787TSts").to_owned()),
}), }),
mxc_uri!("mxc://matrix.org/arsrns98rsRSR"), mxc_uri!("mxc://matrix.org/arsrns98rsRSR").to_owned(),
), ),
event_id: event_id!("$h29iv0s8:example.com").to_owned(), event_id: event_id!("$h29iv0s8:example.com").to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),

View File

@ -28,9 +28,9 @@ fn message_serialize_sticker() {
mimetype: Some("image/png".into()), mimetype: Some("image/png".into()),
size: UInt::new(82595), size: UInt::new(82595),
}))), }))),
thumbnail_url: Some(mxc_uri!("mxc://matrix.org/irsns989Rrsn")), thumbnail_url: Some(mxc_uri!("mxc://matrix.org/irsns989Rrsn").to_owned()),
}), }),
mxc_uri!("mxc://matrix.org/rnsldl8srs98IRrs"), mxc_uri!("mxc://matrix.org/rnsldl8srs98IRrs").to_owned(),
), ),
event_id: event_id!("$h29iv0s8:example.com").to_owned(), event_id: event_id!("$h29iv0s8:example.com").to_owned(),
origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)), origin_server_ts: MilliSecondsSinceUnixEpoch(uint!(1)),
@ -203,7 +203,7 @@ fn deserialize_message_sticker() {
&& width == UInt::new(1011) && width == UInt::new(1011)
&& mimetype == "image/png" && mimetype == "image/png"
&& size == UInt::new(84242) && size == UInt::new(84242)
&& thumbnail_url.to_string() == "mxc://matrix.org/irnsNRS2879" && thumbnail_url == "mxc://matrix.org/irnsNRS2879"
&& matches!( && matches!(
thumbnail_info.as_ref(), thumbnail_info.as_ref(),
ThumbnailInfo { ThumbnailInfo {
@ -217,7 +217,7 @@ fn deserialize_message_sticker() {
&& *thumb_mimetype == Some("image/png".into()) && *thumb_mimetype == Some("image/png".into())
&& *thumb_size == UInt::new(82595) && *thumb_size == UInt::new(82595)
) )
&& url.to_string() == "mxc://matrix.org/jxPXTKpyydzdHJkdFNZjTZrD" && url == "mxc://matrix.org/jxPXTKpyydzdHJkdFNZjTZrD"
&& unsigned.is_empty() && unsigned.is_empty()
); );
} }

View File

@ -37,7 +37,7 @@ fn serialization() {
let ev = RoomMessageEvent { let ev = RoomMessageEvent {
content: RoomMessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain( content: RoomMessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain(
"test".into(), "test".into(),
mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd"), mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd").to_owned(),
None, None,
))), ))),
event_id: event_id!("$143273582443PhrSn:example.org").to_owned(), event_id: event_id!("$143273582443PhrSn:example.org").to_owned(),
@ -69,7 +69,7 @@ fn content_serialization() {
let message_event_content = let message_event_content =
RoomMessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain( RoomMessageEventContent::new(MessageType::Audio(AudioMessageEventContent::plain(
"test".into(), "test".into(),
mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd"), mxc_uri!("mxc://example.org/ffed755USFFxlgbQYZGtryd").to_owned(),
None, None,
))); )));
@ -380,7 +380,7 @@ fn content_deserialization() {
.. ..
}), }),
.. ..
} if body == "test" && url.to_string() == "mxc://example.org/ffed755USFFxlgbQYZGtryd" } if body == "test" && url == "mxc://example.org/ffed755USFFxlgbQYZGtryd"
); );
} }

View File

@ -150,6 +150,7 @@ fn deserialize_aliases_sync_with_room_id() {
} }
#[test] #[test]
#[allow(clippy::cmp_owned)] // seems buggy
fn deserialize_avatar_without_prev_content() { fn deserialize_avatar_without_prev_content() {
let json_data = json!({ let json_data = json!({
"content": { "content": {
@ -176,7 +177,7 @@ fn deserialize_avatar_without_prev_content() {
"type": "m.room.avatar" "type": "m.room.avatar"
}); });
let expected_url = "mxc://matrix.org/rnsldl8srs98IRrs".into(); let expected_url = mxc_uri!("mxc://matrix.org/rnsldl8srs98IRrs").to_owned();
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
let expected_url = Some(expected_url); let expected_url = Some(expected_url);
@ -227,7 +228,7 @@ fn deserialize_avatar_without_prev_content() {
&& *thumb_height == UInt::new(334) && *thumb_height == UInt::new(334)
&& *thumb_mimetype == Some("image/png".into()) && *thumb_mimetype == Some("image/png".into())
&& *thumb_size == UInt::new(82595) && *thumb_size == UInt::new(82595)
&& *thumbnail_url == mxc_uri!("mxc://matrix.org/98irRSS23srs") && thumbnail_url == mxc_uri!("mxc://matrix.org/98irRSS23srs")
) )
) )
&& url == expected_url && url == expected_url

View File

@ -120,7 +120,7 @@ fn deserialize_stripped_state_events() {
let expected_url = mxc_uri!("mxc://example.com/iMag3"); let expected_url = mxc_uri!("mxc://example.com/iMag3");
#[cfg(feature = "unstable-pre-spec")] #[cfg(feature = "unstable-pre-spec")]
let expected_url = Some(expected_url); let expected_url = Some(expected_url.to_owned());
assert_eq!(image_info.height.unwrap(), uint!(128)); assert_eq!(image_info.height.unwrap(), uint!(128));
assert_eq!(image_info.width.unwrap(), uint!(128)); assert_eq!(image_info.width.unwrap(), uint!(128));

View File

@ -40,7 +40,7 @@ ruma_api! {
feature = "compat", feature = "compat",
serde(default, deserialize_with = "ruma_serde::empty_string_as_none") serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
)] )]
pub avatar_url: Option<MxcUri>, pub avatar_url: Option<Box<MxcUri>>,
/// The [BlurHash](https://blurha.sh) for the avatar pointed to by `avatar_url`. /// The [BlurHash](https://blurha.sh) for the avatar pointed to by `avatar_url`.
/// ///

View File

@ -117,9 +117,7 @@ pub fn mxc_uri(input: TokenStream) -> TokenStream {
assert!(mxc_uri::validate(&id.value()).is_ok(), "Invalid mxc://"); assert!(mxc_uri::validate(&id.value()).is_ok(), "Invalid mxc://");
let output = quote! { let output = quote! {
<#dollar_crate::MxcUri as ::std::convert::TryFrom<&str>>::try_from( <&#dollar_crate::MxcUri as ::std::convert::From<&str>>::from(#id)
#id,
).unwrap()
}; };
output.into() output.into()

View File

@ -2,21 +2,22 @@
//! //!
//! [MXC URI]: https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri //! [MXC URI]: https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri
use std::{convert::TryInto, fmt, num::NonZeroU8}; use std::{convert::TryInto, num::NonZeroU8};
use ruma_identifiers_validation::{error::MxcUriError, mxc_uri::validate}; use ruma_identifiers_validation::{error::MxcUriError, mxc_uri::validate};
use crate::ServerName; use crate::ServerName;
type Result<T> = std::result::Result<T, MxcUriError>; type Result<T, E = MxcUriError> = std::result::Result<T, E>;
/// A URI that should be a Matrix-spec compliant [MXC URI]. /// A URI that should be a Matrix-spec compliant [MXC URI].
/// ///
/// [MXC URI]: https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri /// [MXC URI]: https://matrix.org/docs/spec/client_server/r0.6.1#mxc-uri
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct MxcUri { #[repr(transparent)]
full_uri: Box<str>, pub struct MxcUri(str);
}
opaque_identifier!(MxcUri);
impl MxcUri { impl MxcUri {
/// If this is a valid MXC URI, returns the media ID. /// If this is a valid MXC URI, returns the media ID.
@ -34,8 +35,8 @@ impl MxcUri {
pub fn parts(&self) -> Result<(&ServerName, &str)> { pub fn parts(&self) -> Result<(&ServerName, &str)> {
self.extract_slash_idx().map(|idx| { self.extract_slash_idx().map(|idx| {
( (
self.full_uri[6..idx.get() as usize].try_into().unwrap(), self.as_str()[6..idx.get() as usize].try_into().unwrap(),
&self.full_uri[idx.get() as usize + 1..], &self.as_str()[idx.get() as usize + 1..],
) )
}) })
} }
@ -51,12 +52,6 @@ impl MxcUri {
self.validate().is_ok() self.validate().is_ok()
} }
/// Create a string slice from this MXC URI.
#[inline(always)]
pub fn as_str(&self) -> &str {
&self.full_uri
}
// convenience method for calling validate(self) // convenience method for calling validate(self)
#[inline(always)] #[inline(always)]
fn extract_slash_idx(&self) -> Result<NonZeroU8> { fn extract_slash_idx(&self) -> Result<NonZeroU8> {
@ -64,57 +59,6 @@ impl MxcUri {
} }
} }
impl fmt::Debug for MxcUri {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.full_uri.fmt(f)
}
}
impl fmt::Display for MxcUri {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.full_uri.fmt(f)
}
}
fn from<S>(uri: S) -> MxcUri
where
S: AsRef<str> + Into<Box<str>>,
{
MxcUri { full_uri: uri.into() }
}
impl From<&str> for MxcUri {
fn from(s: &str) -> Self {
from(s)
}
}
impl From<String> for MxcUri {
fn from(s: String) -> Self {
from(s)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for MxcUri {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
String::deserialize(deserializer).map(Into::into)
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for MxcUri {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::convert::TryInto; use std::convert::TryInto;
@ -125,7 +69,7 @@ mod tests {
#[test] #[test]
fn parse_mxc_uri() { fn parse_mxc_uri() {
let mxc = MxcUri::from("mxc://127.0.0.1/asd32asdfasdsd"); let mxc = Box::<MxcUri>::from("mxc://127.0.0.1/asd32asdfasdsd");
assert!(mxc.is_valid()); assert!(mxc.is_valid());
assert_eq!( assert_eq!(
@ -136,7 +80,7 @@ mod tests {
#[test] #[test]
fn parse_mxc_uri_without_media_id() { fn parse_mxc_uri_without_media_id() {
let mxc = MxcUri::from("mxc://127.0.0.1"); let mxc = Box::<MxcUri>::from("mxc://127.0.0.1");
assert!(!mxc.is_valid()); assert!(!mxc.is_valid());
assert_eq!(mxc.parts(), Err(MxcUriError::MissingSlash)); assert_eq!(mxc.parts(), Err(MxcUriError::MissingSlash));
@ -144,14 +88,14 @@ mod tests {
#[test] #[test]
fn parse_mxc_uri_without_protocol() { fn parse_mxc_uri_without_protocol() {
assert!(!MxcUri::from("127.0.0.1/asd32asdfasdsd").is_valid()); assert!(!Box::<MxcUri>::from("127.0.0.1/asd32asdfasdsd").is_valid());
} }
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
#[test] #[test]
fn serialize_mxc_uri() { fn serialize_mxc_uri() {
assert_eq!( assert_eq!(
serde_json::to_string(&MxcUri::from("mxc://server/1234id")) serde_json::to_string(&Box::<MxcUri>::from("mxc://server/1234id"))
.expect("Failed to convert MxcUri to JSON."), .expect("Failed to convert MxcUri to JSON."),
r#""mxc://server/1234id""# r#""mxc://server/1234id""#
); );
@ -160,7 +104,7 @@ mod tests {
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
#[test] #[test]
fn deserialize_mxc_uri() { fn deserialize_mxc_uri() {
let mxc = serde_json::from_str::<MxcUri>(r#""mxc://server/1234id""#) let mxc = serde_json::from_str::<Box<MxcUri>>(r#""mxc://server/1234id""#)
.expect("Failed to convert JSON to MxcUri"); .expect("Failed to convert JSON to MxcUri");
assert_eq!(mxc.as_str(), "mxc://server/1234id"); assert_eq!(mxc.as_str(), "mxc://server/1234id");

View File

@ -263,6 +263,7 @@ fn strip_lifetimes(field_type: &mut Type) -> bool {
|| last_seg.ident == "DeviceId" || last_seg.ident == "DeviceId"
|| last_seg.ident == "DeviceKeyId" || last_seg.ident == "DeviceKeyId"
|| last_seg.ident == "EventId" || last_seg.ident == "EventId"
|| last_seg.ident == "MxcUri"
|| last_seg.ident == "ServerName" || last_seg.ident == "ServerName"
|| last_seg.ident == "SessionId" || last_seg.ident == "SessionId"
|| last_seg.ident == "RawJsonValue" || last_seg.ident == "RawJsonValue"