no_std_http/uri.rs
1//! URI component of request and response lines
2//!
3//! This module primarily contains the `Uri` type which is a component of all
4//! HTTP requests and also reexports this type at the root of the crate. A URI
5//! is not always a "full URL" in the sense of something you'd type into a web
6//! browser, but HTTP requests may only have paths on servers but may have full
7//! schemes and hostnames on clients.
8//!
9//! # Examples
10//!
11//! ```
12//! use http::Uri;
13//!
14//! let uri = "/foo/bar?baz".parse::<Uri>().unwrap();
15//! assert_eq!(uri.path(), "/foo/bar");
16//! assert_eq!(uri.query(), Some("baz"));
17//! assert_eq!(uri.host(), None);
18//!
19//! let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap();
20//! assert_eq!(uri.scheme_str(), Some("https"));
21//! assert_eq!(uri.host(), Some("www.rust-lang.org"));
22//! assert_eq!(uri.path(), "/install.html");
23//! ```
24extern crate alloc;
25
26use crate::byte_str::ByteStr;
27use crate::error::Error;
28use alloc::boxed::Box;
29use alloc::string::String;
30use alloc::vec::Vec;
31use bytes::Bytes;
32use core::convert::TryFrom;
33
34use core::hash::{Hash, Hasher};
35use core::str::{self, FromStr};
36use core::{fmt, u16, u8};
37
38use crate::if_downcast_into;
39
40use crate::uri::scheme::SchemeInner;
41
42pub use crate::uri::authority::Authority;
43pub use crate::uri::builder::Builder;
44pub use crate::uri::path::PathAndQuery;
45pub use crate::uri::port::Port;
46pub use crate::uri::scheme::Scheme;
47
48mod authority;
49mod builder;
50mod path;
51mod port;
52mod scheme;
53#[cfg(test)]
54mod tests;
55
56/// The URI component of a request.
57///
58/// For HTTP 1, this is included as part of the request line. From Section 5.3,
59/// Request Target:
60///
61/// > Once an inbound connection is obtained, the client sends an HTTP
62/// > request message (Section 3) with a request-target derived from the
63/// > target URI. There are four distinct formats for the request-target,
64/// > depending on both the method being requested and whether the request
65/// > is to a proxy.
66/// >
67/// > ```notrust
68/// > request-target = origin-form
69/// > / absolute-form
70/// > / authority-form
71/// > / asterisk-form
72/// > ```
73///
74/// The URI is structured as follows:
75///
76/// ```notrust
77/// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
78/// |-| |-------------------------------||--------| |-------------------| |-----|
79/// | | | | |
80/// scheme authority path query fragment
81/// ```
82///
83/// For HTTP 2.0, the URI is encoded using pseudoheaders.
84///
85/// # Examples
86///
87/// ```
88/// use http::Uri;
89///
90/// let uri = "/foo/bar?baz".parse::<Uri>().unwrap();
91/// assert_eq!(uri.path(), "/foo/bar");
92/// assert_eq!(uri.query(), Some("baz"));
93/// assert_eq!(uri.host(), None);
94///
95/// let uri = "https://www.rust-lang.org/install.html".parse::<Uri>().unwrap();
96/// assert_eq!(uri.scheme_str(), Some("https"));
97/// assert_eq!(uri.host(), Some("www.rust-lang.org"));
98/// assert_eq!(uri.path(), "/install.html");
99/// ```
100#[derive(Clone)]
101pub struct Uri {
102 scheme: Scheme,
103 authority: Authority,
104 path_and_query: PathAndQuery,
105}
106
107/// The various parts of a URI.
108///
109/// This struct is used to provide to and retrieve from a URI.
110#[derive(Debug, Default)]
111pub struct Parts {
112 /// The scheme component of a URI
113 pub scheme: Option<Scheme>,
114
115 /// The authority component of a URI
116 pub authority: Option<Authority>,
117
118 /// The origin-form component of a URI
119 pub path_and_query: Option<PathAndQuery>,
120}
121
122/// An error resulting from a failed attempt to construct a URI.
123#[derive(Debug)]
124pub struct InvalidUri(ErrorKind);
125
126/// An error resulting from a failed attempt to construct a URI.
127#[derive(Debug)]
128pub struct InvalidUriParts(InvalidUri);
129
130#[derive(Debug, Eq, PartialEq)]
131enum ErrorKind {
132 InvalidUriChar,
133 InvalidScheme,
134 InvalidAuthority,
135 InvalidPort,
136 InvalidFormat,
137 SchemeMissing,
138 AuthorityMissing,
139 PathAndQueryMissing,
140 TooLong,
141 Empty,
142 SchemeTooLong,
143}
144
145// u16::MAX is reserved for None
146const MAX_LEN: usize = (u16::MAX - 1) as usize;
147
148// URI_CHARS is a table of valid characters in a URI. An entry in the table is
149// 0 for invalid characters. For valid characters the entry is itself (i.e.
150// the entry for 33 is b'!' because b'!' == 33u8). An important characteristic
151// of this table is that all entries above 127 are invalid. This makes all of the
152// valid entries a valid single-byte UTF-8 code point. This means that a slice
153// of such valid entries is valid UTF-8.
154#[rustfmt::skip]
155const URI_CHARS: [u8; 256] = [
156 // 0 1 2 3 4 5 6 7 8 9
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // x
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1x
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2x
160 0, 0, 0, b'!', 0, b'#', b'$', 0, b'&', b'\'', // 3x
161 b'(', b')', b'*', b'+', b',', b'-', b'.', b'/', b'0', b'1', // 4x
162 b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', b';', // 5x
163 0, b'=', 0, b'?', b'@', b'A', b'B', b'C', b'D', b'E', // 6x
164 b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', // 7x
165 b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', // 8x
166 b'Z', b'[', 0, b']', 0, b'_', 0, b'a', b'b', b'c', // 9x
167 b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', // 10x
168 b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', // 11x
169 b'x', b'y', b'z', 0, 0, 0, b'~', 0, 0, 0, // 12x
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 13x
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 14x
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 15x
173 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16x
174 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 17x
175 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 18x
176 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 19x
177 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20x
178 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 21x
179 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 22x
180 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 23x
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 24x
182 0, 0, 0, 0, 0, 0 // 25x
183];
184
185impl Uri {
186 /// Creates a new builder-style object to manufacture a `Uri`.
187 ///
188 /// This method returns an instance of `Builder` which can be usd to
189 /// create a `Uri`.
190 ///
191 /// # Examples
192 ///
193 /// ```
194 /// use http::Uri;
195 ///
196 /// let uri = Uri::builder()
197 /// .scheme("https")
198 /// .authority("hyper.rs")
199 /// .path_and_query("/")
200 /// .build()
201 /// .unwrap();
202 /// ```
203 pub fn builder() -> Builder {
204 Builder::new()
205 }
206
207 /// Attempt to convert a `Parts` into a `Uri`.
208 ///
209 /// # Examples
210 ///
211 /// Relative URI
212 ///
213 /// ```
214 /// # use http::uri::*;
215 /// let mut parts = Parts::default();
216 /// parts.path_and_query = Some("/foo".parse().unwrap());
217 ///
218 /// let uri = Uri::from_parts(parts).unwrap();
219 ///
220 /// assert_eq!(uri.path(), "/foo");
221 ///
222 /// assert!(uri.scheme().is_none());
223 /// assert!(uri.authority().is_none());
224 /// ```
225 ///
226 /// Absolute URI
227 ///
228 /// ```
229 /// # use http::uri::*;
230 /// let mut parts = Parts::default();
231 /// parts.scheme = Some("http".parse().unwrap());
232 /// parts.authority = Some("foo.com".parse().unwrap());
233 /// parts.path_and_query = Some("/foo".parse().unwrap());
234 ///
235 /// let uri = Uri::from_parts(parts).unwrap();
236 ///
237 /// assert_eq!(uri.scheme().unwrap().as_str(), "http");
238 /// assert_eq!(uri.authority().unwrap(), "foo.com");
239 /// assert_eq!(uri.path(), "/foo");
240 /// ```
241 pub fn from_parts(src: Parts) -> Result<Uri, InvalidUriParts> {
242 if src.scheme.is_some() {
243 if src.authority.is_none() {
244 return Err(ErrorKind::AuthorityMissing.into());
245 }
246
247 if src.path_and_query.is_none() {
248 return Err(ErrorKind::PathAndQueryMissing.into());
249 }
250 } else if src.authority.is_some() && src.path_and_query.is_some() {
251 return Err(ErrorKind::SchemeMissing.into());
252 }
253
254 let scheme = match src.scheme {
255 Some(scheme) => scheme,
256 None => Scheme {
257 inner: SchemeInner::None,
258 },
259 };
260
261 let authority = match src.authority {
262 Some(authority) => authority,
263 None => Authority::empty(),
264 };
265
266 let path_and_query = match src.path_and_query {
267 Some(path_and_query) => path_and_query,
268 None => PathAndQuery::empty(),
269 };
270
271 Ok(Uri {
272 scheme,
273 authority,
274 path_and_query,
275 })
276 }
277
278 /// Attempt to convert a `Bytes` buffer to a `Uri`.
279 ///
280 /// This will try to prevent a copy if the type passed is the type used
281 /// internally, and will copy the data if it is not.
282 pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri>
283 where
284 T: AsRef<[u8]> + 'static,
285 {
286 if_downcast_into!(T, Bytes, src, {
287 return Uri::from_shared(src);
288 });
289
290 Uri::try_from(src.as_ref())
291 }
292
293 // Not public while `bytes` is unstable.
294 fn from_shared(s: Bytes) -> Result<Uri, InvalidUri> {
295 use self::ErrorKind::*;
296
297 if s.len() > MAX_LEN {
298 return Err(TooLong.into());
299 }
300
301 match s.len() {
302 0 => {
303 return Err(Empty.into());
304 }
305 1 => match s[0] {
306 b'/' => {
307 return Ok(Uri {
308 scheme: Scheme::empty(),
309 authority: Authority::empty(),
310 path_and_query: PathAndQuery::slash(),
311 });
312 }
313 b'*' => {
314 return Ok(Uri {
315 scheme: Scheme::empty(),
316 authority: Authority::empty(),
317 path_and_query: PathAndQuery::star(),
318 });
319 }
320 _ => {
321 let authority = Authority::from_shared(s)?;
322
323 return Ok(Uri {
324 scheme: Scheme::empty(),
325 authority,
326 path_and_query: PathAndQuery::empty(),
327 });
328 }
329 },
330 _ => {}
331 }
332
333 if s[0] == b'/' {
334 return Ok(Uri {
335 scheme: Scheme::empty(),
336 authority: Authority::empty(),
337 path_and_query: PathAndQuery::from_shared(s)?,
338 });
339 }
340
341 parse_full(s)
342 }
343
344 /// Convert a `Uri` from a static string.
345 ///
346 /// This function will not perform any copying, however the string is
347 /// checked to ensure that it is valid.
348 ///
349 /// # Panics
350 ///
351 /// This function panics if the argument is an invalid URI.
352 ///
353 /// # Examples
354 ///
355 /// ```
356 /// # use http::uri::Uri;
357 /// let uri = Uri::from_static("http://example.com/foo");
358 ///
359 /// assert_eq!(uri.host().unwrap(), "example.com");
360 /// assert_eq!(uri.path(), "/foo");
361 /// ```
362 pub fn from_static(src: &'static str) -> Self {
363 let s = Bytes::from_static(src.as_bytes());
364 match Uri::from_shared(s) {
365 Ok(uri) => uri,
366 Err(e) => panic!("static str is not valid URI: {}", e),
367 }
368 }
369
370 /// Convert a `Uri` into `Parts`.
371 ///
372 /// # Note
373 ///
374 /// This is just an inherent method providing the same functionality as
375 /// `let parts: Parts = uri.into()`
376 ///
377 /// # Examples
378 ///
379 /// ```
380 /// # use http::uri::*;
381 /// let uri: Uri = "/foo".parse().unwrap();
382 ///
383 /// let parts = uri.into_parts();
384 ///
385 /// assert_eq!(parts.path_and_query.unwrap(), "/foo");
386 ///
387 /// assert!(parts.scheme.is_none());
388 /// assert!(parts.authority.is_none());
389 /// ```
390 #[inline]
391 pub fn into_parts(self) -> Parts {
392 self.into()
393 }
394
395 /// Returns the path & query components of the Uri
396 #[inline]
397 pub fn path_and_query(&self) -> Option<&PathAndQuery> {
398 if !self.scheme.inner.is_none() || self.authority.data.is_empty() {
399 Some(&self.path_and_query)
400 } else {
401 None
402 }
403 }
404
405 /// Get the path of this `Uri`.
406 ///
407 /// Both relative and absolute URIs contain a path component, though it
408 /// might be the empty string. The path component is **case sensitive**.
409 ///
410 /// ```notrust
411 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
412 /// |--------|
413 /// |
414 /// path
415 /// ```
416 ///
417 /// If the URI is `*` then the path component is equal to `*`.
418 ///
419 /// # Examples
420 ///
421 /// A relative URI
422 ///
423 /// ```
424 /// # use http::Uri;
425 ///
426 /// let uri: Uri = "/hello/world".parse().unwrap();
427 ///
428 /// assert_eq!(uri.path(), "/hello/world");
429 /// ```
430 ///
431 /// An absolute URI
432 ///
433 /// ```
434 /// # use http::Uri;
435 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
436 ///
437 /// assert_eq!(uri.path(), "/hello/world");
438 /// ```
439 #[inline]
440 pub fn path(&self) -> &str {
441 if self.has_path() {
442 self.path_and_query.path()
443 } else {
444 ""
445 }
446 }
447
448 /// Get the scheme of this `Uri`.
449 ///
450 /// The URI scheme refers to a specification for assigning identifiers
451 /// within that scheme. Only absolute URIs contain a scheme component, but
452 /// not all absolute URIs will contain a scheme component. Although scheme
453 /// names are case-insensitive, the canonical form is lowercase.
454 ///
455 /// ```notrust
456 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
457 /// |-|
458 /// |
459 /// scheme
460 /// ```
461 ///
462 /// # Examples
463 ///
464 /// Absolute URI
465 ///
466 /// ```
467 /// use http::uri::{Scheme, Uri};
468 ///
469 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
470 ///
471 /// assert_eq!(uri.scheme(), Some(&Scheme::HTTP));
472 /// ```
473 ///
474 ///
475 /// Relative URI
476 ///
477 /// ```
478 /// # use http::Uri;
479 /// let uri: Uri = "/hello/world".parse().unwrap();
480 ///
481 /// assert!(uri.scheme().is_none());
482 /// ```
483 #[inline]
484 pub fn scheme(&self) -> Option<&Scheme> {
485 if self.scheme.inner.is_none() {
486 None
487 } else {
488 Some(&self.scheme)
489 }
490 }
491
492 /// Get the scheme of this `Uri` as a `&str`.
493 ///
494 /// # Example
495 ///
496 /// ```
497 /// # use http::Uri;
498 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
499 ///
500 /// assert_eq!(uri.scheme_str(), Some("http"));
501 /// ```
502 #[inline]
503 pub fn scheme_str(&self) -> Option<&str> {
504 if self.scheme.inner.is_none() {
505 None
506 } else {
507 Some(self.scheme.as_str())
508 }
509 }
510
511 /// Get the authority of this `Uri`.
512 ///
513 /// The authority is a hierarchical element for naming authority such that
514 /// the remainder of the URI is delegated to that authority. For HTTP, the
515 /// authority consists of the host and port. The host portion of the
516 /// authority is **case-insensitive**.
517 ///
518 /// The authority also includes a `username:password` component, however
519 /// the use of this is deprecated and should be avoided.
520 ///
521 /// ```notrust
522 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
523 /// |-------------------------------|
524 /// |
525 /// authority
526 /// ```
527 ///
528 /// # Examples
529 ///
530 /// Absolute URI
531 ///
532 /// ```
533 /// # use http::Uri;
534 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
535 ///
536 /// assert_eq!(uri.authority().map(|a| a.as_str()), Some("example.org:80"));
537 /// ```
538 ///
539 ///
540 /// Relative URI
541 ///
542 /// ```
543 /// # use http::Uri;
544 /// let uri: Uri = "/hello/world".parse().unwrap();
545 ///
546 /// assert!(uri.authority().is_none());
547 /// ```
548 #[inline]
549 pub fn authority(&self) -> Option<&Authority> {
550 if self.authority.data.is_empty() {
551 None
552 } else {
553 Some(&self.authority)
554 }
555 }
556
557 /// Get the host of this `Uri`.
558 ///
559 /// The host subcomponent of authority is identified by an IP literal
560 /// encapsulated within square brackets, an IPv4 address in dotted- decimal
561 /// form, or a registered name. The host subcomponent is **case-insensitive**.
562 ///
563 /// ```notrust
564 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
565 /// |---------|
566 /// |
567 /// host
568 /// ```
569 ///
570 /// # Examples
571 ///
572 /// Absolute URI
573 ///
574 /// ```
575 /// # use http::Uri;
576 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
577 ///
578 /// assert_eq!(uri.host(), Some("example.org"));
579 /// ```
580 ///
581 ///
582 /// Relative URI
583 ///
584 /// ```
585 /// # use http::Uri;
586 /// let uri: Uri = "/hello/world".parse().unwrap();
587 ///
588 /// assert!(uri.host().is_none());
589 /// ```
590 #[inline]
591 pub fn host(&self) -> Option<&str> {
592 self.authority().map(|a| a.host())
593 }
594
595 /// Get the port part of this `Uri`.
596 ///
597 /// The port subcomponent of authority is designated by an optional port
598 /// number following the host and delimited from it by a single colon (":")
599 /// character. It can be turned into a decimal port number with the `as_u16`
600 /// method or as a `str` with the `as_str` method.
601 ///
602 /// ```notrust
603 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
604 /// |-|
605 /// |
606 /// port
607 /// ```
608 ///
609 /// # Examples
610 ///
611 /// Absolute URI with port
612 ///
613 /// ```
614 /// # use http::Uri;
615 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
616 ///
617 /// let port = uri.port().unwrap();
618 /// assert_eq!(port.as_u16(), 80);
619 /// ```
620 ///
621 /// Absolute URI without port
622 ///
623 /// ```
624 /// # use http::Uri;
625 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
626 ///
627 /// assert!(uri.port().is_none());
628 /// ```
629 ///
630 /// Relative URI
631 ///
632 /// ```
633 /// # use http::Uri;
634 /// let uri: Uri = "/hello/world".parse().unwrap();
635 ///
636 /// assert!(uri.port().is_none());
637 /// ```
638 pub fn port(&self) -> Option<Port<&str>> {
639 self.authority().and_then(|a| a.port())
640 }
641
642 /// Get the port of this `Uri` as a `u16`.
643 ///
644 ///
645 /// # Example
646 ///
647 /// ```
648 /// # use http::{Uri, uri::Port};
649 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
650 ///
651 /// assert_eq!(uri.port_u16(), Some(80));
652 /// ```
653 pub fn port_u16(&self) -> Option<u16> {
654 self.port().map(|p| p.as_u16())
655 }
656
657 /// Get the query string of this `Uri`, starting after the `?`.
658 ///
659 /// The query component contains non-hierarchical data that, along with data
660 /// in the path component, serves to identify a resource within the scope of
661 /// the URI's scheme and naming authority (if any). The query component is
662 /// indicated by the first question mark ("?") character and terminated by a
663 /// number sign ("#") character or by the end of the URI.
664 ///
665 /// ```notrust
666 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
667 /// |-------------------|
668 /// |
669 /// query
670 /// ```
671 ///
672 /// # Examples
673 ///
674 /// Absolute URI
675 ///
676 /// ```
677 /// # use http::Uri;
678 /// let uri: Uri = "http://example.org/hello/world?key=value".parse().unwrap();
679 ///
680 /// assert_eq!(uri.query(), Some("key=value"));
681 /// ```
682 ///
683 /// Relative URI with a query string component
684 ///
685 /// ```
686 /// # use http::Uri;
687 /// let uri: Uri = "/hello/world?key=value&foo=bar".parse().unwrap();
688 ///
689 /// assert_eq!(uri.query(), Some("key=value&foo=bar"));
690 /// ```
691 ///
692 /// Relative URI without a query string component
693 ///
694 /// ```
695 /// # use http::Uri;
696 /// let uri: Uri = "/hello/world".parse().unwrap();
697 ///
698 /// assert!(uri.query().is_none());
699 /// ```
700 #[inline]
701 pub fn query(&self) -> Option<&str> {
702 self.path_and_query.query()
703 }
704
705 fn has_path(&self) -> bool {
706 !self.path_and_query.data.is_empty() || !self.scheme.inner.is_none()
707 }
708}
709
710impl<'a> TryFrom<&'a [u8]> for Uri {
711 type Error = InvalidUri;
712
713 #[inline]
714 fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
715 Uri::from_shared(Bytes::copy_from_slice(t))
716 }
717}
718
719impl<'a> TryFrom<&'a str> for Uri {
720 type Error = InvalidUri;
721
722 #[inline]
723 fn try_from(t: &'a str) -> Result<Self, Self::Error> {
724 t.parse()
725 }
726}
727
728impl<'a> TryFrom<&'a String> for Uri {
729 type Error = InvalidUri;
730
731 #[inline]
732 fn try_from(t: &'a String) -> Result<Self, Self::Error> {
733 t.parse()
734 }
735}
736
737impl TryFrom<String> for Uri {
738 type Error = InvalidUri;
739
740 #[inline]
741 fn try_from(t: String) -> Result<Self, Self::Error> {
742 Uri::from_shared(Bytes::from(t))
743 }
744}
745
746impl TryFrom<Vec<u8>> for Uri {
747 type Error = InvalidUri;
748
749 #[inline]
750 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
751 Uri::from_shared(Bytes::from(vec))
752 }
753}
754
755impl TryFrom<Parts> for Uri {
756 type Error = InvalidUriParts;
757
758 #[inline]
759 fn try_from(src: Parts) -> Result<Self, Self::Error> {
760 Uri::from_parts(src)
761 }
762}
763
764impl<'a> TryFrom<&'a Uri> for Uri {
765 type Error = Error;
766
767 #[inline]
768 fn try_from(src: &'a Uri) -> Result<Self, Self::Error> {
769 Ok(src.clone())
770 }
771}
772
773/// Convert an `Authority` into a `Uri`.
774impl From<Authority> for Uri {
775 fn from(authority: Authority) -> Self {
776 Self {
777 scheme: Scheme::empty(),
778 authority,
779 path_and_query: PathAndQuery::empty(),
780 }
781 }
782}
783
784/// Convert a `PathAndQuery` into a `Uri`.
785impl From<PathAndQuery> for Uri {
786 fn from(path_and_query: PathAndQuery) -> Self {
787 Self {
788 scheme: Scheme::empty(),
789 authority: Authority::empty(),
790 path_and_query,
791 }
792 }
793}
794
795/// Convert a `Uri` into `Parts`
796impl From<Uri> for Parts {
797 fn from(src: Uri) -> Self {
798 let path_and_query = if src.has_path() {
799 Some(src.path_and_query)
800 } else {
801 None
802 };
803
804 let scheme = match src.scheme.inner {
805 SchemeInner::None => None,
806 _ => Some(src.scheme),
807 };
808
809 let authority = if src.authority.data.is_empty() {
810 None
811 } else {
812 Some(src.authority)
813 };
814
815 Parts {
816 scheme,
817 authority,
818 path_and_query,
819 }
820 }
821}
822
823fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
824 // Parse the scheme
825 let scheme = match SchemeInner::parse(&s[..])? {
826 SchemeInner::None => SchemeInner::None,
827 SchemeInner::Standard(p) => {
828 // TODO: use truncate
829 let _ = s.split_to(p.len() + 3);
830 SchemeInner::Standard(p)
831 }
832 SchemeInner::Other(n) => {
833 // Grab the protocol
834 let mut scheme = s.split_to(n + 3);
835
836 // Strip ://, TODO: truncate
837 let _ = scheme.split_off(n);
838
839 // Allocate the ByteStr
840 let val = unsafe { ByteStr::from_utf8_unchecked(scheme) };
841
842 SchemeInner::Other(Box::new(val))
843 }
844 };
845
846 // Find the end of the authority. The scheme will already have been
847 // extracted.
848 let authority_end = Authority::parse(&s[..])?;
849
850 if scheme.is_none() {
851 if authority_end != s.len() {
852 return Err(ErrorKind::InvalidFormat.into());
853 }
854
855 let authority = Authority {
856 data: unsafe { ByteStr::from_utf8_unchecked(s) },
857 };
858
859 return Ok(Uri {
860 scheme: scheme.into(),
861 authority,
862 path_and_query: PathAndQuery::empty(),
863 });
864 }
865
866 // Authority is required when absolute
867 if authority_end == 0 {
868 return Err(ErrorKind::InvalidFormat.into());
869 }
870
871 let authority = s.split_to(authority_end);
872 let authority = Authority {
873 data: unsafe { ByteStr::from_utf8_unchecked(authority) },
874 };
875
876 Ok(Uri {
877 scheme: scheme.into(),
878 authority,
879 path_and_query: PathAndQuery::from_shared(s)?,
880 })
881}
882
883impl FromStr for Uri {
884 type Err = InvalidUri;
885
886 #[inline]
887 fn from_str(s: &str) -> Result<Uri, InvalidUri> {
888 Uri::try_from(s.as_bytes())
889 }
890}
891
892impl PartialEq for Uri {
893 fn eq(&self, other: &Uri) -> bool {
894 if self.scheme() != other.scheme() {
895 return false;
896 }
897
898 if self.authority() != other.authority() {
899 return false;
900 }
901
902 if self.path() != other.path() {
903 return false;
904 }
905
906 if self.query() != other.query() {
907 return false;
908 }
909
910 true
911 }
912}
913
914impl PartialEq<str> for Uri {
915 fn eq(&self, other: &str) -> bool {
916 let mut other = other.as_bytes();
917 let mut absolute = false;
918
919 if let Some(scheme) = self.scheme() {
920 let scheme = scheme.as_str().as_bytes();
921 absolute = true;
922
923 if other.len() < scheme.len() + 3 {
924 return false;
925 }
926
927 if !scheme.eq_ignore_ascii_case(&other[..scheme.len()]) {
928 return false;
929 }
930
931 other = &other[scheme.len()..];
932
933 if &other[..3] != b"://" {
934 return false;
935 }
936
937 other = &other[3..];
938 }
939
940 if let Some(auth) = self.authority() {
941 let len = auth.data.len();
942 absolute = true;
943
944 if other.len() < len {
945 return false;
946 }
947
948 if !auth.data.as_bytes().eq_ignore_ascii_case(&other[..len]) {
949 return false;
950 }
951
952 other = &other[len..];
953 }
954
955 let path = self.path();
956
957 if other.len() < path.len() || path.as_bytes() != &other[..path.len()] {
958 if absolute && path == "/" {
959 // PathAndQuery can be omitted, fall through
960 } else {
961 return false;
962 }
963 } else {
964 other = &other[path.len()..];
965 }
966
967 if let Some(query) = self.query() {
968 if other.is_empty() {
969 return query.is_empty();
970 }
971
972 if other[0] != b'?' {
973 return false;
974 }
975
976 other = &other[1..];
977
978 if other.len() < query.len() {
979 return false;
980 }
981
982 if query.as_bytes() != &other[..query.len()] {
983 return false;
984 }
985
986 other = &other[query.len()..];
987 }
988
989 other.is_empty() || other[0] == b'#'
990 }
991}
992
993impl PartialEq<Uri> for str {
994 fn eq(&self, uri: &Uri) -> bool {
995 uri == self
996 }
997}
998
999impl<'a> PartialEq<&'a str> for Uri {
1000 fn eq(&self, other: &&'a str) -> bool {
1001 self == *other
1002 }
1003}
1004
1005impl<'a> PartialEq<Uri> for &'a str {
1006 fn eq(&self, uri: &Uri) -> bool {
1007 uri == *self
1008 }
1009}
1010
1011impl Eq for Uri {}
1012
1013/// Returns a `Uri` representing `/`
1014impl Default for Uri {
1015 #[inline]
1016 fn default() -> Uri {
1017 Uri {
1018 scheme: Scheme::empty(),
1019 authority: Authority::empty(),
1020 path_and_query: PathAndQuery::slash(),
1021 }
1022 }
1023}
1024
1025impl fmt::Display for Uri {
1026 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1027 if let Some(scheme) = self.scheme() {
1028 write!(f, "{}://", scheme)?;
1029 }
1030
1031 if let Some(authority) = self.authority() {
1032 write!(f, "{}", authority)?;
1033 }
1034
1035 write!(f, "{}", self.path())?;
1036
1037 if let Some(query) = self.query() {
1038 write!(f, "?{}", query)?;
1039 }
1040
1041 Ok(())
1042 }
1043}
1044
1045impl fmt::Debug for Uri {
1046 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1047 fmt::Display::fmt(self, f)
1048 }
1049}
1050
1051impl From<ErrorKind> for InvalidUri {
1052 fn from(src: ErrorKind) -> InvalidUri {
1053 InvalidUri(src)
1054 }
1055}
1056
1057impl From<ErrorKind> for InvalidUriParts {
1058 fn from(src: ErrorKind) -> InvalidUriParts {
1059 InvalidUriParts(src.into())
1060 }
1061}
1062
1063impl InvalidUri {
1064 fn s(&self) -> &str {
1065 match self.0 {
1066 ErrorKind::InvalidUriChar => "invalid uri character",
1067 ErrorKind::InvalidScheme => "invalid scheme",
1068 ErrorKind::InvalidAuthority => "invalid authority",
1069 ErrorKind::InvalidPort => "invalid port",
1070 ErrorKind::InvalidFormat => "invalid format",
1071 ErrorKind::SchemeMissing => "scheme missing",
1072 ErrorKind::AuthorityMissing => "authority missing",
1073 ErrorKind::PathAndQueryMissing => "path missing",
1074 ErrorKind::TooLong => "uri too long",
1075 ErrorKind::Empty => "empty string",
1076 ErrorKind::SchemeTooLong => "scheme too long",
1077 }
1078 }
1079}
1080
1081impl fmt::Display for InvalidUri {
1082 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1083 self.s().fmt(f)
1084 }
1085}
1086
1087impl fmt::Display for InvalidUriParts {
1088 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1089 self.0.fmt(f)
1090 }
1091}
1092
1093impl Hash for Uri {
1094 fn hash<H>(&self, state: &mut H)
1095 where
1096 H: Hasher,
1097 {
1098 if !self.scheme.inner.is_none() {
1099 self.scheme.hash(state);
1100 state.write_u8(0xff);
1101 }
1102
1103 if let Some(auth) = self.authority() {
1104 auth.hash(state);
1105 }
1106
1107 Hash::hash_slice(self.path().as_bytes(), state);
1108
1109 if let Some(query) = self.query() {
1110 b'?'.hash(state);
1111 Hash::hash_slice(query.as_bytes(), state);
1112 }
1113 }
1114}