ruma_identifiers/
mxc_uri.rs1use std::num::NonZeroU8;
6
7use ruma_identifiers_validation::{error::MxcUriError, mxc_uri::validate};
8
9use crate::ServerName;
10
11type Result<T, E = MxcUriError> = std::result::Result<T, E>;
12
13#[repr(transparent)]
18#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct MxcUri(str);
20
21opaque_identifier!(MxcUri);
22
23impl MxcUri {
24 pub fn media_id(&self) -> Result<&str> {
26 self.parts().map(|(_, s)| s)
27 }
28
29 pub fn server_name(&self) -> Result<&ServerName> {
31 self.parts().map(|(s, _)| s)
32 }
33
34 pub fn parts(&self) -> Result<(&ServerName, &str)> {
37 self.extract_slash_idx().map(|idx| {
38 (
39 ServerName::from_borrowed(&self.as_str()[6..idx.get() as usize]),
40 &self.as_str()[idx.get() as usize + 1..],
41 )
42 })
43 }
44
45 pub fn validate(&self) -> Result<()> {
47 self.extract_slash_idx().map(|_| ())
48 }
49
50 #[inline(always)]
52 pub fn is_valid(&self) -> bool {
53 self.validate().is_ok()
54 }
55
56 #[inline(always)]
58 fn extract_slash_idx(&self) -> Result<NonZeroU8> {
59 validate(self.as_str())
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use std::convert::TryInto;
66
67 use ruma_identifiers_validation::error::MxcUriError;
68
69 use super::MxcUri;
70
71 #[test]
72 fn parse_mxc_uri() {
73 let mxc = Box::<MxcUri>::from("mxc://127.0.0.1/asd32asdfasdsd");
74
75 assert!(mxc.is_valid());
76 assert_eq!(
77 mxc.parts(),
78 Ok(("127.0.0.1".try_into().expect("Failed to create ServerName"), "asd32asdfasdsd"))
79 );
80 }
81
82 #[test]
83 fn parse_mxc_uri_without_media_id() {
84 let mxc = Box::<MxcUri>::from("mxc://127.0.0.1");
85
86 assert!(!mxc.is_valid());
87 assert_eq!(mxc.parts(), Err(MxcUriError::MissingSlash));
88 }
89
90 #[test]
91 fn parse_mxc_uri_without_protocol() {
92 assert!(!Box::<MxcUri>::from("127.0.0.1/asd32asdfasdsd").is_valid());
93 }
94
95 #[cfg(feature = "serde")]
96 #[test]
97 fn serialize_mxc_uri() {
98 assert_eq!(
99 serde_json::to_string(&Box::<MxcUri>::from("mxc://server/1234id"))
100 .expect("Failed to convert MxcUri to JSON."),
101 r#""mxc://server/1234id""#
102 );
103 }
104
105 #[cfg(feature = "serde")]
106 #[test]
107 fn deserialize_mxc_uri() {
108 let mxc = serde_json::from_str::<Box<MxcUri>>(r#""mxc://server/1234id""#)
109 .expect("Failed to convert JSON to MxcUri");
110
111 assert_eq!(mxc.as_str(), "mxc://server/1234id");
112 assert!(mxc.is_valid());
113 assert_eq!(
114 mxc.parts(),
115 Ok(("server".try_into().expect("Failed to create ServerName"), "1234id"))
116 );
117 }
118}