From 2d2deb4ca76f0bb8931599150a7937393f4f71cf Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 15 Aug 2024 23:38:44 +0000 Subject: [PATCH] structured Mxc type Signed-off-by: Jason Volk --- .../src/authenticated_media/get_content.rs | 4 +- .../get_content_as_filename.rs | 4 +- .../get_content_thumbnail.rs | 4 +- .../src/media/create_content_async.rs | 4 +- .../ruma-client-api/src/media/get_content.rs | 4 +- .../src/media/get_content_as_filename.rs | 4 +- .../src/media/get_content_thumbnail.rs | 4 +- crates/ruma-common/src/identifiers.rs | 2 +- crates/ruma-common/src/identifiers/mxc_uri.rs | 48 +++++++++++++++---- 9 files changed, 54 insertions(+), 24 deletions(-) diff --git a/crates/ruma-client-api/src/authenticated_media/get_content.rs b/crates/ruma-client-api/src/authenticated_media/get_content.rs index 6bb45b30..0c0f8050 100644 --- a/crates/ruma-client-api/src/authenticated_media/get_content.rs +++ b/crates/ruma-client-api/src/authenticated_media/get_content.rs @@ -13,7 +13,7 @@ pub mod v1 { use ruma_common::{ api::{request, response, Metadata}, http_headers::ContentDisposition, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -101,7 +101,7 @@ pub mod v1 { /// Creates a new `Request` with the given URI. pub fn from_uri(uri: &MxcUri) -> Result { - let (server_name, media_id) = uri.parts()?; + let Mxc { server_name, media_id } = uri.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned())) } diff --git a/crates/ruma-client-api/src/authenticated_media/get_content_as_filename.rs b/crates/ruma-client-api/src/authenticated_media/get_content_as_filename.rs index e307c46a..bba1450a 100644 --- a/crates/ruma-client-api/src/authenticated_media/get_content_as_filename.rs +++ b/crates/ruma-client-api/src/authenticated_media/get_content_as_filename.rs @@ -13,7 +13,7 @@ pub mod v1 { use ruma_common::{ api::{request, response, Metadata}, http_headers::ContentDisposition, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -106,7 +106,7 @@ pub mod v1 { /// Creates a new `Request` with the given URI and filename. pub fn from_uri(uri: &MxcUri, filename: String) -> Result { - let (server_name, media_id) = uri.parts()?; + let Mxc { server_name, media_id } = uri.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned(), filename)) } diff --git a/crates/ruma-client-api/src/authenticated_media/get_content_thumbnail.rs b/crates/ruma-client-api/src/authenticated_media/get_content_thumbnail.rs index 2fa38e5f..79f426ec 100644 --- a/crates/ruma-client-api/src/authenticated_media/get_content_thumbnail.rs +++ b/crates/ruma-client-api/src/authenticated_media/get_content_thumbnail.rs @@ -15,7 +15,7 @@ pub mod v1 { api::{request, response, Metadata}, http_headers::ContentDisposition, media::Method, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -140,7 +140,7 @@ pub mod v1 { /// Creates a new `Request` with the given URI, desired thumbnail width and /// desired thumbnail height. pub fn from_uri(uri: &MxcUri, width: UInt, height: UInt) -> Result { - let (server_name, media_id) = uri.parts()?; + let Mxc { server_name, media_id } = uri.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned(), width, height)) } diff --git a/crates/ruma-client-api/src/media/create_content_async.rs b/crates/ruma-client-api/src/media/create_content_async.rs index 284c5df3..b3195657 100644 --- a/crates/ruma-client-api/src/media/create_content_async.rs +++ b/crates/ruma-client-api/src/media/create_content_async.rs @@ -10,7 +10,7 @@ pub mod v3 { use http::header::CONTENT_TYPE; use ruma_common::{ api::{request, response, Metadata}, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; const METADATA: Metadata = metadata! { @@ -61,7 +61,7 @@ pub mod v3 { /// Creates a new `Request` with the given url and file contents. pub fn from_url(url: &MxcUri, file: Vec) -> Result { - let (server_name, media_id) = url.parts()?; + let Mxc { server_name, media_id } = url.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned(), file)) } } diff --git a/crates/ruma-client-api/src/media/get_content.rs b/crates/ruma-client-api/src/media/get_content.rs index 9a742597..6e0a1f12 100644 --- a/crates/ruma-client-api/src/media/get_content.rs +++ b/crates/ruma-client-api/src/media/get_content.rs @@ -13,7 +13,7 @@ pub mod v3 { use ruma_common::{ api::{request, response, Metadata}, http_headers::ContentDisposition, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -123,7 +123,7 @@ pub mod v3 { /// Creates a new `Request` with the given url. pub fn from_url(url: &MxcUri) -> Result { - let (server_name, media_id) = url.parts()?; + let Mxc { server_name, media_id } = url.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned())) } diff --git a/crates/ruma-client-api/src/media/get_content_as_filename.rs b/crates/ruma-client-api/src/media/get_content_as_filename.rs index 58d20b9e..4c5f6013 100644 --- a/crates/ruma-client-api/src/media/get_content_as_filename.rs +++ b/crates/ruma-client-api/src/media/get_content_as_filename.rs @@ -13,7 +13,7 @@ pub mod v3 { use ruma_common::{ api::{request, response, Metadata}, http_headers::ContentDisposition, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -128,7 +128,7 @@ pub mod v3 { /// Creates a new `Request` with the given url and filename. pub fn from_url(url: &MxcUri, filename: String) -> Result { - let (server_name, media_id) = url.parts()?; + let Mxc { server_name, media_id } = url.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned(), filename)) } diff --git a/crates/ruma-client-api/src/media/get_content_thumbnail.rs b/crates/ruma-client-api/src/media/get_content_thumbnail.rs index 6a29a1f3..4696f264 100644 --- a/crates/ruma-client-api/src/media/get_content_thumbnail.rs +++ b/crates/ruma-client-api/src/media/get_content_thumbnail.rs @@ -15,7 +15,7 @@ pub mod v3 { use ruma_common::{ api::{request, response, Metadata}, http_headers::ContentDisposition, - metadata, IdParseError, MxcUri, OwnedServerName, + metadata, IdParseError, Mxc, MxcUri, OwnedServerName, }; use crate::http_headers::CROSS_ORIGIN_RESOURCE_POLICY; @@ -166,7 +166,7 @@ pub mod v3 { /// Creates a new `Request` with the given url, desired thumbnail width and /// desired thumbnail height. pub fn from_url(url: &MxcUri, width: UInt, height: UInt) -> Result { - let (server_name, media_id) = url.parts()?; + let Mxc { server_name, media_id } = url.parts()?; Ok(Self::new(media_id.to_owned(), server_name.to_owned(), width, height)) } diff --git a/crates/ruma-common/src/identifiers.rs b/crates/ruma-common/src/identifiers.rs index 360cb425..d2fdbecf 100644 --- a/crates/ruma-common/src/identifiers.rs +++ b/crates/ruma-common/src/identifiers.rs @@ -26,7 +26,7 @@ pub use self::{ }, key_name::{KeyName, OwnedKeyName}, matrix_uri::{MatrixToUri, MatrixUri}, - mxc_uri::{MxcUri, OwnedMxcUri}, + mxc_uri::{Mxc, MxcUri, OwnedMxcUri}, room_alias_id::{OwnedRoomAliasId, RoomAliasId}, room_id::{OwnedRoomId, RoomId}, room_or_alias_id::{OwnedRoomOrAliasId, RoomOrAliasId}, diff --git a/crates/ruma-common/src/identifiers/mxc_uri.rs b/crates/ruma-common/src/identifiers/mxc_uri.rs index e2fcc001..33e99c6a 100644 --- a/crates/ruma-common/src/identifiers/mxc_uri.rs +++ b/crates/ruma-common/src/identifiers/mxc_uri.rs @@ -2,7 +2,7 @@ //! //! [MXC URI]: https://spec.matrix.org/latest/client-server-api/#matrix-content-mxc-uris -use std::num::NonZeroU8; +use std::{fmt, num::NonZeroU8}; use ruma_identifiers_validation::{error::MxcUriError, mxc_uri::validate}; use ruma_macros::IdZst; @@ -18,25 +18,33 @@ type Result = std::result::Result; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, IdZst)] pub struct MxcUri(str); +/// Structured MXC URI which may reference strings from separate sources without serialization +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Mxc<'a> { + /// ServerName part of the MXC URI + pub server_name: &'a ServerName, + + /// MediaId part of the MXC URI + pub media_id: &'a str, +} + impl MxcUri { /// If this is a valid MXC URI, returns the media ID. pub fn media_id(&self) -> Result<&str> { - self.parts().map(|(_, s)| s) + self.parts().map(|mxc| mxc.media_id) } /// If this is a valid MXC URI, returns the server name. pub fn server_name(&self) -> Result<&ServerName> { - self.parts().map(|(s, _)| s) + self.parts().map(|mxc| mxc.server_name) } /// If this is a valid MXC URI, returns a `(server_name, media_id)` tuple, else it returns the /// error. - pub fn parts(&self) -> Result<(&ServerName, &str)> { - self.extract_slash_idx().map(|idx| { - ( - ServerName::from_borrowed(&self.as_str()[6..idx.get() as usize]), - &self.as_str()[idx.get() as usize + 1..], - ) + pub fn parts(&self) -> Result> { + self.extract_slash_idx().map(|idx| Mxc::<'_> { + server_name: ServerName::from_borrowed(&self.as_str()[6..idx.get() as usize]), + media_id: &self.as_str()[idx.get() as usize + 1..], }) } @@ -58,6 +66,28 @@ impl MxcUri { } } +impl fmt::Display for Mxc<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "mxc://{}/{}", self.server_name, self.media_id) + } +} + +impl<'a> TryFrom<&'a MxcUri> for Mxc<'a> { + type Error = MxcUriError; + + fn try_from(s: &'a MxcUri) -> Result { + s.parts() + } +} + +impl<'a> TryFrom<&'a str> for Mxc<'a> { + type Error = MxcUriError; + + fn try_from(s: &'a str) -> Result { + s.try_into() + } +} + #[cfg(test)] mod tests { use ruma_identifiers_validation::error::MxcUriError;