async_coap_uri/
uri_buf.rs1use super::*;
17use std::fmt::Write;
18use std::ops::Deref;
19
20#[derive(Clone, Eq, Hash)]
30pub struct UriBuf(pub(super) UriRefBuf);
31
32impl_uri_buf_traits!(UriBuf, Uri);
33
34impl Deref for UriBuf {
35 type Target = Uri;
36
37 fn deref(&self) -> &Self::Target {
38 self.as_uri()
39 }
40}
41
42impl AsRef<Uri> for UriBuf {
43 fn as_ref(&self) -> &Uri {
44 self.as_uri()
45 }
46}
47
48impl From<&Uri> for UriBuf {
49 fn from(x: &Uri) -> Self {
50 x.to_uri_buf()
51 }
52}
53
54impl std::fmt::Display for UriBuf {
55 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
56 self.write_to(f)
57 }
58}
59
60impl UriBuf {
65 #[inline(always)]
72 pub unsafe fn from_string_unchecked(s: String) -> UriBuf {
73 UriBuf(UriRefBuf::from_string_unchecked(s))
74 }
75}
76
77impl UriBuf {
78 pub fn new<Sch, Hos, Pat, Que, Frg>(
80 scheme: Sch,
81 host: Hos,
82 port: Option<u16>,
83 path: Pat,
84 query: Option<Que>,
85 fragment: Option<Frg>,
86 ) -> UriBuf
87 where
88 Sch: Into<String>,
89 Hos: AsRef<str>,
90 Pat: AsRef<str>,
91 Que: AsRef<str>,
92 Frg: AsRef<str>,
93 {
94 let mut ret: String = Self::from_scheme_host_port(scheme, host, port).into();
95
96 let mut path = path.as_ref();
97
98 if path.starts_with('/') {
99 path = &path[1..];
100 }
101
102 let path_segment_iter =
103 path.split('/')
104 .filter_map(|seg| if seg == "." { None } else { Some(seg) });
105
106 for seg in path_segment_iter {
107 ret.push('/');
108 ret.extend(seg.escape_uri());
109 }
110
111 if let Some(query) = query {
112 let mut first = true;
113 ret.push('?');
114 for seg in query.as_ref().split(|c| c == '&' || c == ';') {
115 if first {
116 first = false;
117 } else {
118 ret.push('&');
119 }
120 ret.extend(seg.escape_uri().for_query());
121 }
122 }
123
124 if let Some(fragment) = fragment {
125 ret.push('#');
126 ret.extend(fragment.as_ref().escape_uri().for_fragment());
127 }
128
129 unsafe { Self::from_string_unchecked(ret) }
130 }
131
132 pub fn from_scheme_authority<Sch, Aut>(scheme: Sch, authority: Aut) -> UriBuf
149 where
150 Sch: Into<String>,
151 Aut: AsRef<str>,
152 {
153 let mut ret = scheme.into();
154
155 assert_eq!(
158 ret.find(|c: char| !(c.is_ascii_alphanumeric() || c == '+' || c == '-' || c == '.')),
159 None,
160 "Scheme contains invalid characters: {:?}",
161 ret
162 );
163
164 ret.push_str("://");
165
166 ret.extend(authority.as_ref().escape_uri().for_authority());
167
168 unsafe { Self::from_string_unchecked(ret) }
169 }
170
171 pub fn from_host_rel_ref<Hos, RR>(host: Hos, rel_ref: RR) -> UriBuf
186 where
187 Hos: AsRef<str>,
188 RR: AsRef<RelRef>,
189 {
190 let host = host.as_ref();
191 let rel_ref = rel_ref
192 .as_ref()
193 .trim_leading_dot_slashes()
194 .trim_leading_slashes();
195
196 uri_format!("//{}/{}", host.escape_uri().full(), rel_ref).unwrap()
200 }
201
202 pub fn from_scheme_host_port<Sch, Hos>(scheme: Sch, host: Hos, port: Option<u16>) -> UriBuf
207 where
208 Sch: Into<String>,
209 Hos: AsRef<str>,
210 {
211 let mut ret = scheme.into();
212
213 assert_eq!(
216 ret.find(|c: char| !(c.is_ascii_alphanumeric() || c == '+' || c == '-' || c == '.')),
217 None,
218 "Scheme contains invalid characters: {:?}",
219 ret
220 );
221
222 ret.push_str("://");
223
224 let mut host = host.as_ref();
225
226 if host.starts_with('[') && host.ends_with(']') {
228 host = &host[1..host.len()];
229 }
230
231 if host.find(':').is_some() {
232 ret.push('[');
233 ret.extend(host.escape_uri());
234 ret.push(']');
235 }
236
237 if let Some(port) = port {
238 write!(ret, ":{}", port).unwrap();
239 }
240
241 unsafe { Self::from_string_unchecked(ret) }
242 }
243
244 pub fn from_str<S: AsRef<str>>(s: S) -> Result<UriBuf, ParseError> {
246 let s = s.as_ref();
247 let components = UriRawComponents::from_str(s)?;
248
249 if components.uri_type().can_borrow_as_uri() {
250 Ok(unsafe { Self::from_string_unchecked(s.to_string()) })
251 } else {
252 Err(ParseError::new("Missing scheme or authority", None))
253 }
254 }
255
256 pub fn from_string(s: String) -> Result<UriBuf, ParseError> {
258 let components = UriRawComponents::from_str(s.as_str())?;
259
260 if components.uri_type().can_borrow_as_uri() {
261 Ok(unsafe { Self::from_string_unchecked(s) })
262 } else {
263 Err(ParseError::new("Missing scheme or authority", None))
264 }
265 }
266
267 pub fn from_uri<S: AsRef<UriRef>>(s: S) -> Option<UriBuf> {
269 if s.as_ref().uri_type().can_borrow_as_uri() {
270 Some(UriBuf(s.as_ref().to_uri_ref_buf()))
271 } else {
272 None
273 }
274 }
275}
276
277impl UriBuf {
278 #[inline(always)]
280 pub fn as_uri(&self) -> &Uri {
281 unsafe { Uri::from_str_unchecked(self.as_str()) }
282 }
283}
284
285impl UriBuf {
287 pub fn resolve<T: AnyUriRef + ?Sized>(&mut self, dest: &T) -> Result<(), ResolveError> {
290 self.0.resolve(dest)
291 }
292
293 pub fn replace_path(&mut self, rel: &RelRef) {
295 self.0.replace_path(rel)
296 }
297}
298
299inherits_uri_ref_buf!(UriBuf);