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}