ruma_identifiers/
room_id.rs1use crate::{matrix_uri::UriAction, EventId, MatrixToUri, MatrixUri, ServerName};
4
5#[repr(transparent)]
18#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
19pub struct RoomId(str);
20
21opaque_identifier_validated!(RoomId, ruma_identifiers_validation::room_id::validate);
22
23impl RoomId {
24 #[cfg(feature = "rand")]
29 pub fn new(server_name: &ServerName) -> Box<Self> {
30 Self::from_owned(format!("!{}:{}", crate::generate_localpart(18), server_name).into())
31 }
32
33 pub fn localpart(&self) -> &str {
35 &self.as_str()[1..self.colon_idx()]
36 }
37
38 pub fn server_name(&self) -> &ServerName {
40 ServerName::from_borrowed(&self.as_str()[self.colon_idx() + 1..])
41 }
42
43 pub fn matrix_to_uri<'a>(&self, via: impl IntoIterator<Item = &'a ServerName>) -> MatrixToUri {
58 MatrixToUri::new(self.into(), via.into_iter().collect())
59 }
60
61 pub fn matrix_to_event_uri(&self, ev_id: &EventId) -> MatrixToUri {
63 MatrixToUri::new((self, ev_id).into(), Vec::new())
64 }
65
66 pub fn matrix_uri<'a>(
83 &self,
84 via: impl IntoIterator<Item = &'a ServerName>,
85 join: bool,
86 ) -> MatrixUri {
87 MatrixUri::new(
88 self.into(),
89 via.into_iter().collect(),
90 Some(UriAction::Join).filter(|_| join),
91 )
92 }
93
94 pub fn matrix_event_uri<'a>(
96 &self,
97 ev_id: &EventId,
98 via: impl IntoIterator<Item = &'a ServerName>,
99 ) -> MatrixUri {
100 MatrixUri::new((self, ev_id).into(), via.into_iter().collect(), None)
101 }
102
103 fn colon_idx(&self) -> usize {
104 self.as_str().find(':').unwrap()
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use std::convert::TryFrom;
111
112 use super::RoomId;
113 use crate::Error;
114
115 #[test]
116 fn valid_room_id() {
117 assert_eq!(
118 <&RoomId>::try_from("!29fhd83h92h0:example.com")
119 .expect("Failed to create RoomId.")
120 .as_ref(),
121 "!29fhd83h92h0:example.com"
122 );
123 }
124
125 #[test]
126 fn empty_localpart() {
127 assert_eq!(
128 <&RoomId>::try_from("!:example.com").expect("Failed to create RoomId.").as_ref(),
129 "!:example.com"
130 );
131 }
132
133 #[cfg(feature = "rand")]
134 #[test]
135 fn generate_random_valid_room_id() {
136 use crate::server_name;
137
138 let room_id = RoomId::new(server_name!("example.com"));
139 let id_str = room_id.as_str();
140
141 assert!(id_str.starts_with('!'));
142 assert_eq!(id_str.len(), 31);
143 }
144
145 #[cfg(feature = "serde")]
146 #[test]
147 fn serialize_valid_room_id() {
148 assert_eq!(
149 serde_json::to_string(
150 <&RoomId>::try_from("!29fhd83h92h0:example.com").expect("Failed to create RoomId.")
151 )
152 .expect("Failed to convert RoomId to JSON."),
153 r#""!29fhd83h92h0:example.com""#
154 );
155 }
156
157 #[cfg(feature = "serde")]
158 #[test]
159 fn deserialize_valid_room_id() {
160 assert_eq!(
161 serde_json::from_str::<Box<RoomId>>(r#""!29fhd83h92h0:example.com""#)
162 .expect("Failed to convert JSON to RoomId"),
163 <&RoomId>::try_from("!29fhd83h92h0:example.com").expect("Failed to create RoomId.")
164 );
165 }
166
167 #[test]
168 fn valid_room_id_with_explicit_standard_port() {
169 assert_eq!(
170 <&RoomId>::try_from("!29fhd83h92h0:example.com:443")
171 .expect("Failed to create RoomId.")
172 .as_ref(),
173 "!29fhd83h92h0:example.com:443"
174 );
175 }
176
177 #[test]
178 fn valid_room_id_with_non_standard_port() {
179 assert_eq!(
180 <&RoomId>::try_from("!29fhd83h92h0:example.com:5000")
181 .expect("Failed to create RoomId.")
182 .as_ref(),
183 "!29fhd83h92h0:example.com:5000"
184 );
185 }
186
187 #[test]
188 fn missing_room_id_sigil() {
189 assert_eq!(
190 <&RoomId>::try_from("carl:example.com").unwrap_err(),
191 Error::MissingLeadingSigil
192 );
193 }
194
195 #[test]
196 fn missing_room_id_delimiter() {
197 assert_eq!(<&RoomId>::try_from("!29fhd83h92h0").unwrap_err(), Error::MissingDelimiter);
198 }
199
200 #[test]
201 fn invalid_room_id_host() {
202 assert_eq!(<&RoomId>::try_from("!29fhd83h92h0:/").unwrap_err(), Error::InvalidServerName);
203 }
204
205 #[test]
206 fn invalid_room_id_port() {
207 assert_eq!(
208 <&RoomId>::try_from("!29fhd83h92h0:example.com:notaport").unwrap_err(),
209 Error::InvalidServerName
210 );
211 }
212}