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 `Parts` into a `Uri`.
205 ///
206 /// # Examples
207 ///
208 /// Relative URI
209 ///
210 /// ```
211 /// # use http::uri::*;
212 /// let mut parts = Parts::default();
213 /// parts.path_and_query = Some("/foo".parse().unwrap());
214 ///
215 /// let uri = Uri::from_parts(parts).unwrap();
216 ///
217 /// assert_eq!(uri.path(), "/foo");
218 ///
219 /// assert!(uri.scheme().is_none());
220 /// assert!(uri.authority().is_none());
221 /// ```
222 ///
223 /// Absolute URI
224 ///
225 /// ```
226 /// # use http::uri::*;
227 /// let mut parts = Parts::default();
228 /// parts.scheme = Some("http".parse().unwrap());
229 /// parts.authority = Some("foo.com".parse().unwrap());
230 /// parts.path_and_query = Some("/foo".parse().unwrap());
231 ///
232 /// let uri = Uri::from_parts(parts).unwrap();
233 ///
234 /// assert_eq!(uri.scheme().unwrap().as_str(), "http");
235 /// assert_eq!(uri.authority().unwrap(), "foo.com");
236 /// assert_eq!(uri.path(), "/foo");
237 /// ```
238 pub fn from_parts(src: Parts) -> Result<Uri, InvalidUriParts> {
239 if src.scheme.is_some() {
240 if src.authority.is_none() {
241 return Err(ErrorKind::AuthorityMissing.into());
242 }
243
244 if src.path_and_query.is_none() {
245 return Err(ErrorKind::PathAndQueryMissing.into());
246 }
247 } else {
248 if src.authority.is_some() && src.path_and_query.is_some() {
249 return Err(ErrorKind::SchemeMissing.into());
250 }
251 }
252
253 let scheme = match src.scheme {
254 Some(scheme) => scheme,
255 None => Scheme {
256 inner: Scheme2::None,
257 },
258 };
259
260 let authority = match src.authority {
261 Some(authority) => authority,
262 None => Authority::empty(),
263 };
264
265 let path_and_query = match src.path_and_query {
266 Some(path_and_query) => path_and_query,
267 None => PathAndQuery::empty(),
268 };
269
270 Ok(Uri {
271 scheme: scheme,
272 authority: authority,
273 path_and_query: path_and_query,
274 })
275 }
276
277 /// Attempt to convert a `Bytes` buffer to a `Uri`.
278 ///
279 /// This will try to prevent a copy if the type passed is the type used
280 /// internally, and will copy the data if it is not.
281 pub fn from_maybe_shared<T>(src: T) -> Result<Self, InvalidUri>
282 where
283 T: AsRef<[u8]> + 'static,
284 {
285 if_downcast_into!(T, Bytes, src, {
286 return Uri::from_shared(src);
287 });
288
289 Uri::try_from(src.as_ref())
290 }
291
292 // Not public while `bytes` is unstable.
293 fn from_shared(s: Bytes) -> Result<Uri, InvalidUri> {
294 use self::ErrorKind::*;
295
296 if s.len() > MAX_LEN {
297 return Err(TooLong.into());
298 }
299
300 match s.len() {
301 0 => {
302 return Err(Empty.into());
303 }
304 1 => match s[0] {
305 b'/' => {
306 return Ok(Uri {
307 scheme: Scheme::empty(),
308 authority: Authority::empty(),
309 path_and_query: PathAndQuery::slash(),
310 });
311 }
312 b'*' => {
313 return Ok(Uri {
314 scheme: Scheme::empty(),
315 authority: Authority::empty(),
316 path_and_query: PathAndQuery::star(),
317 });
318 }
319 _ => {
320 let authority = Authority::from_shared(s)?;
321
322 return Ok(Uri {
323 scheme: Scheme::empty(),
324 authority: authority,
325 path_and_query: PathAndQuery::empty(),
326 });
327 }
328 },
329 _ => {}
330 }
331
332 if s[0] == b'/' {
333 return Ok(Uri {
334 scheme: Scheme::empty(),
335 authority: Authority::empty(),
336 path_and_query: PathAndQuery::from_shared(s)?,
337 });
338 }
339
340 parse_full(s)
341 }
342
343 /// Convert a `Uri` from a static string.
344 ///
345 /// This function will not perform any copying, however the string is
346 /// checked to ensure that it is valid.
347 ///
348 /// # Panics
349 ///
350 /// This function panics if the argument is an invalid URI.
351 ///
352 /// # Examples
353 ///
354 /// ```
355 /// # use http::uri::Uri;
356 /// let uri = Uri::from_static("http://example.com/foo");
357 ///
358 /// assert_eq!(uri.host().unwrap(), "example.com");
359 /// assert_eq!(uri.path(), "/foo");
360 /// ```
361 pub fn from_static(src: &'static str) -> Self {
362 let s = Bytes::from_static(src.as_bytes());
363 match Uri::from_shared(s) {
364 Ok(uri) => uri,
365 Err(e) => panic!("static str is not valid URI: {}", e),
366 }
367 }
368
369 /// Convert a `Uri` into `Parts`.
370 ///
371 /// # Note
372 ///
373 /// This is just an inherent method providing the same functionality as
374 /// `let parts: Parts = uri.into()`
375 ///
376 /// # Examples
377 ///
378 /// ```
379 /// # use http::uri::*;
380 /// let uri: Uri = "/foo".parse().unwrap();
381 ///
382 /// let parts = uri.into_parts();
383 ///
384 /// assert_eq!(parts.path_and_query.unwrap(), "/foo");
385 ///
386 /// assert!(parts.scheme.is_none());
387 /// assert!(parts.authority.is_none());
388 /// ```
389 #[inline]
390 pub fn into_parts(self) -> Parts {
391 self.into()
392 }
393
394 /// Returns the path & query components of the Uri
395 #[inline]
396 pub fn path_and_query(&self) -> Option<&PathAndQuery> {
397 if !self.scheme.inner.is_none() || self.authority.data.is_empty() {
398 Some(&self.path_and_query)
399 } else {
400 None
401 }
402 }
403
404 /// Get the path of this `Uri`.
405 ///
406 /// Both relative and absolute URIs contain a path component, though it
407 /// might be the empty string. The path component is **case sensitive**.
408 ///
409 /// ```notrust
410 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
411 /// |--------|
412 /// |
413 /// path
414 /// ```
415 ///
416 /// If the URI is `*` then the path component is equal to `*`.
417 ///
418 /// # Examples
419 ///
420 /// A relative URI
421 ///
422 /// ```
423 /// # use http::Uri;
424 ///
425 /// let uri: Uri = "/hello/world".parse().unwrap();
426 ///
427 /// assert_eq!(uri.path(), "/hello/world");
428 /// ```
429 ///
430 /// An absolute URI
431 ///
432 /// ```
433 /// # use http::Uri;
434 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
435 ///
436 /// assert_eq!(uri.path(), "/hello/world");
437 /// ```
438 #[inline]
439 pub fn path(&self) -> &str {
440 if self.has_path() {
441 self.path_and_query.path()
442 } else {
443 ""
444 }
445 }
446
447 /// Get the scheme of this `Uri`.
448 ///
449 /// The URI scheme refers to a specification for assigning identifiers
450 /// within that scheme. Only absolute URIs contain a scheme component, but
451 /// not all absolute URIs will contain a scheme component. Although scheme
452 /// names are case-insensitive, the canonical form is lowercase.
453 ///
454 /// ```notrust
455 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
456 /// |-|
457 /// |
458 /// scheme
459 /// ```
460 ///
461 /// # Examples
462 ///
463 /// Absolute URI
464 ///
465 /// ```
466 /// use http::uri::{Scheme, Uri};
467 ///
468 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
469 ///
470 /// assert_eq!(uri.scheme(), Some(&Scheme::HTTP));
471 /// ```
472 ///
473 ///
474 /// Relative URI
475 ///
476 /// ```
477 /// # use http::Uri;
478 /// let uri: Uri = "/hello/world".parse().unwrap();
479 ///
480 /// assert!(uri.scheme().is_none());
481 /// ```
482 #[inline]
483 pub fn scheme(&self) -> Option<&Scheme> {
484 if self.scheme.inner.is_none() {
485 None
486 } else {
487 Some(&self.scheme)
488 }
489 }
490
491 /// Get the scheme of this `Uri` as a `&str`.
492 ///
493 /// # Example
494 ///
495 /// ```
496 /// # use http::Uri;
497 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
498 ///
499 /// assert_eq!(uri.scheme_str(), Some("http"));
500 /// ```
501 #[inline]
502 pub fn scheme_str(&self) -> Option<&str> {
503 if self.scheme.inner.is_none() {
504 None
505 } else {
506 Some(self.scheme.as_str())
507 }
508 }
509
510 /// Get the authority of this `Uri`.
511 ///
512 /// The authority is a hierarchical element for naming authority such that
513 /// the remainder of the URI is delegated to that authority. For HTTP, the
514 /// authority consists of the host and port. The host portion of the
515 /// authority is **case-insensitive**.
516 ///
517 /// The authority also includes a `username:password` component, however
518 /// the use of this is deprecated and should be avoided.
519 ///
520 /// ```notrust
521 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
522 /// |-------------------------------|
523 /// |
524 /// authority
525 /// ```
526 ///
527 /// # Examples
528 ///
529 /// Absolute URI
530 ///
531 /// ```
532 /// # use http::Uri;
533 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
534 ///
535 /// assert_eq!(uri.authority().map(|a| a.as_str()), Some("example.org:80"));
536 /// ```
537 ///
538 ///
539 /// Relative URI
540 ///
541 /// ```
542 /// # use http::Uri;
543 /// let uri: Uri = "/hello/world".parse().unwrap();
544 ///
545 /// assert!(uri.authority().is_none());
546 /// ```
547 #[inline]
548 pub fn authority(&self) -> Option<&Authority> {
549 if self.authority.data.is_empty() {
550 None
551 } else {
552 Some(&self.authority)
553 }
554 }
555
556 /// Get the host of this `Uri`.
557 ///
558 /// The host subcomponent of authority is identified by an IP literal
559 /// encapsulated within square brackets, an IPv4 address in dotted- decimal
560 /// form, or a registered name. The host subcomponent is **case-insensitive**.
561 ///
562 /// ```notrust
563 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
564 /// |---------|
565 /// |
566 /// host
567 /// ```
568 ///
569 /// # Examples
570 ///
571 /// Absolute URI
572 ///
573 /// ```
574 /// # use http::Uri;
575 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
576 ///
577 /// assert_eq!(uri.host(), Some("example.org"));
578 /// ```
579 ///
580 ///
581 /// Relative URI
582 ///
583 /// ```
584 /// # use http::Uri;
585 /// let uri: Uri = "/hello/world".parse().unwrap();
586 ///
587 /// assert!(uri.host().is_none());
588 /// ```
589 #[inline]
590 pub fn host(&self) -> Option<&str> {
591 self.authority().map(|a| a.host())
592 }
593
594 /// Get the port part of this `Uri`.
595 ///
596 /// The port subcomponent of authority is designated by an optional port
597 /// number following the host and delimited from it by a single colon (":")
598 /// character. It can be turned into a decimal port number with the `as_u16`
599 /// method or as a `str` with the `as_str` method.
600 ///
601 /// ```notrust
602 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
603 /// |-|
604 /// |
605 /// port
606 /// ```
607 ///
608 /// # Examples
609 ///
610 /// Absolute URI with port
611 ///
612 /// ```
613 /// # use http::Uri;
614 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
615 ///
616 /// let port = uri.port().unwrap();
617 /// assert_eq!(port.as_u16(), 80);
618 /// ```
619 ///
620 /// Absolute URI without port
621 ///
622 /// ```
623 /// # use http::Uri;
624 /// let uri: Uri = "http://example.org/hello/world".parse().unwrap();
625 ///
626 /// assert!(uri.port().is_none());
627 /// ```
628 ///
629 /// Relative URI
630 ///
631 /// ```
632 /// # use http::Uri;
633 /// let uri: Uri = "/hello/world".parse().unwrap();
634 ///
635 /// assert!(uri.port().is_none());
636 /// ```
637 pub fn port(&self) -> Option<Port<&str>> {
638 self.authority().and_then(|a| a.port())
639 }
640
641 /// Get the port of this `Uri` as a `u16`.
642 ///
643 ///
644 /// # Example
645 ///
646 /// ```
647 /// # use http::{Uri, uri::Port};
648 /// let uri: Uri = "http://example.org:80/hello/world".parse().unwrap();
649 ///
650 /// assert_eq!(uri.port_u16(), Some(80));
651 /// ```
652 pub fn port_u16(&self) -> Option<u16> {
653 self.port().and_then(|p| Some(p.as_u16()))
654 }
655
656 /// Get the query string of this `Uri`, starting after the `?`.
657 ///
658 /// The query component contains non-hierarchical data that, along with data
659 /// in the path component, serves to identify a resource within the scope of
660 /// the URI's scheme and naming authority (if any). The query component is
661 /// indicated by the first question mark ("?") character and terminated by a
662 /// number sign ("#") character or by the end of the URI.
663 ///
664 /// ```notrust
665 /// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
666 /// |-------------------|
667 /// |
668 /// query
669 /// ```
670 ///
671 /// # Examples
672 ///
673 /// Absolute URI
674 ///
675 /// ```
676 /// # use http::Uri;
677 /// let uri: Uri = "http://example.org/hello/world?key=value".parse().unwrap();
678 ///
679 /// assert_eq!(uri.query(), Some("key=value"));
680 /// ```
681 ///
682 /// Relative URI with a query string component
683 ///
684 /// ```
685 /// # use http::Uri;
686 /// let uri: Uri = "/hello/world?key=value&foo=bar".parse().unwrap();
687 ///
688 /// assert_eq!(uri.query(), Some("key=value&foo=bar"));
689 /// ```
690 ///
691 /// Relative URI without a query string component
692 ///
693 /// ```
694 /// # use http::Uri;
695 /// let uri: Uri = "/hello/world".parse().unwrap();
696 ///
697 /// assert!(uri.query().is_none());
698 /// ```
699 #[inline]
700 pub fn query(&self) -> Option<&str> {
701 self.path_and_query.query()
702 }
703
704 fn has_path(&self) -> bool {
705 !self.path_and_query.data.is_empty() || !self.scheme.inner.is_none()
706 }
707}
708
709impl<'a> TryFrom<&'a [u8]> for Uri {
710 type Error = InvalidUri;
711
712 #[inline]
713 fn try_from(t: &'a [u8]) -> Result<Self, Self::Error> {
714 Uri::from_shared(Bytes::copy_from_slice(data:t))
715 }
716}
717
718impl<'a> TryFrom<&'a str> for Uri {
719 type Error = InvalidUri;
720
721 #[inline]
722 fn try_from(t: &'a str) -> Result<Self, Self::Error> {
723 t.parse()
724 }
725}
726
727impl<'a> TryFrom<&'a String> for Uri {
728 type Error = InvalidUri;
729
730 #[inline]
731 fn try_from(t: &'a String) -> Result<Self, Self::Error> {
732 t.parse()
733 }
734}
735
736impl TryFrom<String> for Uri {
737 type Error = InvalidUri;
738
739 #[inline]
740 fn try_from(t: String) -> Result<Self, Self::Error> {
741 Uri::from_shared(Bytes::from(t))
742 }
743}
744
745impl<'a> TryFrom<Vec<u8>> for Uri {
746 type Error = InvalidUri;
747
748 #[inline]
749 fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
750 Uri::from_shared(Bytes::from(vec))
751 }
752}
753
754impl TryFrom<Parts> for Uri {
755 type Error = InvalidUriParts;
756
757 #[inline]
758 fn try_from(src: Parts) -> Result<Self, Self::Error> {
759 Uri::from_parts(src)
760 }
761}
762
763impl<'a> TryFrom<&'a Uri> for Uri {
764 type Error = crate::Error;
765
766 #[inline]
767 fn try_from(src: &'a Uri) -> Result<Self, Self::Error> {
768 Ok(src.clone())
769 }
770}
771
772/// Convert an `Authority` into a `Uri`.
773impl From<Authority> for Uri {
774 fn from(authority: Authority) -> Self {
775 Self {
776 scheme: Scheme::empty(),
777 authority,
778 path_and_query: PathAndQuery::empty(),
779 }
780 }
781}
782
783/// Convert a `PathAndQuery` into a `Uri`.
784impl From<PathAndQuery> for Uri {
785 fn from(path_and_query: PathAndQuery) -> Self {
786 Self {
787 scheme: Scheme::empty(),
788 authority: Authority::empty(),
789 path_and_query,
790 }
791 }
792}
793
794/// Convert a `Uri` into `Parts`
795impl From<Uri> for Parts {
796 fn from(src: Uri) -> Self {
797 let path_and_query = if src.has_path() {
798 Some(src.path_and_query)
799 } else {
800 None
801 };
802
803 let scheme = match src.scheme.inner {
804 Scheme2::None => None,
805 _ => Some(src.scheme),
806 };
807
808 let authority = if src.authority.data.is_empty() {
809 None
810 } else {
811 Some(src.authority)
812 };
813
814 Parts {
815 scheme: scheme,
816 authority: authority,
817 path_and_query: path_and_query,
818 _priv: (),
819 }
820 }
821}
822
823fn parse_full(mut s: Bytes) -> Result<Uri, InvalidUri> {
824 // Parse the scheme
825 let scheme = match Scheme2::parse(&s[..])? {
826 Scheme2::None => Scheme2::None,
827 Scheme2::Standard(p) => {
828 // TODO: use truncate
829 let _ = s.split_to(p.len() + 3);
830 Scheme2::Standard(p)
831 }
832 Scheme2::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 Scheme2::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: 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: 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.len() == 0 {
969 return query.len() == 0;
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: &Scheme) = self.scheme() {
1028 write!(f, "{}://", scheme)?;
1029 }
1030
1031 if let Some(authority: &Authority) = self.authority() {
1032 write!(f, "{}", authority)?;
1033 }
1034
1035 write!(f, "{}", self.path())?;
1036
1037 if let Some(query: &str) = 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 Error for InvalidUri {}
1088
1089impl fmt::Display for InvalidUriParts {
1090 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1091 self.0.fmt(f)
1092 }
1093}
1094
1095impl Error for InvalidUriParts {}
1096
1097impl Hash for Uri {
1098 fn hash<H>(&self, state: &mut H)
1099 where
1100 H: Hasher,
1101 {
1102 if !self.scheme.inner.is_none() {
1103 self.scheme.hash(state);
1104 state.write_u8(0xff);
1105 }
1106
1107 if let Some(auth: &Authority) = self.authority() {
1108 auth.hash(state);
1109 }
1110
1111 Hash::hash_slice(self.path().as_bytes(), state);
1112
1113 if let Some(query: &str) = self.query() {
1114 b'?'.hash(state);
1115 Hash::hash_slice(data:query.as_bytes(), state);
1116 }
1117 }
1118}
1119