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