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