1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
use std::borrow::Cow;
use std::fmt::{self, Display};
use ext::IntoOwned;
use parse::{Indexed, IndexedStr};
use uri::{Authority, Origin, Error, as_utf8_unchecked};
/// A URI with a scheme, authority, path, and query:
/// `http://user:pass@domain.com:4444/path?query`.
///
/// # Structure
///
/// The following diagram illustrates the syntactic structure of an absolute
/// URI with all optional parts:
///
/// ```text
/// http://user:pass@domain.com:4444/path?query
/// |--| |-----------------------||---------|
/// scheme authority origin
/// ```
///
/// The scheme part of the absolute URI and at least one of authority or origin
/// are required.
#[derive(Debug, Clone)]
pub struct Absolute<'a> {
source: Option<Cow<'a, str>>,
scheme: IndexedStr<'a>,
authority: Option<Authority<'a>>,
origin: Option<Origin<'a>>,
}
impl<'a> IntoOwned for Absolute<'a> {
type Owned = Absolute<'static>;
fn into_owned(self) -> Self::Owned {
Absolute {
source: self.source.into_owned(),
scheme: self.scheme.into_owned(),
authority: self.authority.into_owned(),
origin: self.origin.into_owned(),
}
}
}
impl<'a> Absolute<'a> {
#[inline]
crate unsafe fn raw(
source: Cow<'a, [u8]>,
scheme: Indexed<'a, [u8]>,
authority: Option<Authority<'a>>,
origin: Option<Origin<'a>>,
) -> Absolute<'a> {
Absolute {
source: Some(as_utf8_unchecked(source)),
scheme: scheme.coerce(),
authority: authority,
origin: origin,
}
}
#[cfg(test)]
crate fn new(
scheme: &'a str,
authority: Option<Authority<'a>>,
origin: Option<Origin<'a>>
) -> Absolute<'a> {
Absolute {
source: None, scheme: scheme.into(), authority, origin
}
}
/// Parses the string `string` into an `Absolute`. Parsing will never
/// allocate. Returns an `Error` if `string` is not a valid absolute URI.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::uri::Absolute;
///
/// // Parse a valid authority URI.
/// let uri = Absolute::parse("http://google.com").expect("valid URI");
/// assert_eq!(uri.scheme(), "http");
/// assert_eq!(uri.authority().unwrap().host(), "google.com");
/// assert_eq!(uri.origin(), None);
/// ```
pub fn parse(string: &'a str) -> Result<Absolute<'a>, Error<'a>> {
::parse::uri::absolute_from_str(string)
}
/// Returns the scheme part of the absolute URI.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::uri::Absolute;
///
/// let uri = Absolute::parse("ftp://127.0.0.1").expect("valid URI");
/// assert_eq!(uri.scheme(), "ftp");
/// ```
#[inline(always)]
pub fn scheme(&self) -> &str {
self.scheme.from_cow_source(&self.source)
}
/// Returns the authority part of the absolute URI, if there is one.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::uri::Absolute;
///
/// let uri = Absolute::parse("https://rocket.rs:80").expect("valid URI");
/// assert_eq!(uri.scheme(), "https");
/// let authority = uri.authority().unwrap();
/// assert_eq!(authority.host(), "rocket.rs");
/// assert_eq!(authority.port(), Some(80));
///
/// let uri = Absolute::parse("file:/web/home").expect("valid URI");
/// assert_eq!(uri.authority(), None);
/// ```
#[inline(always)]
pub fn authority(&self) -> Option<&Authority<'a>> {
self.authority.as_ref()
}
/// Returns the origin part of the absolute URI, if there is one.
///
/// # Example
///
/// ```rust
/// # extern crate rocket;
/// use rocket::http::uri::Absolute;
///
/// let uri = Absolute::parse("file:/web/home.html?new").expect("valid URI");
/// assert_eq!(uri.scheme(), "file");
/// let origin = uri.origin().unwrap();
/// assert_eq!(origin.path(), "/web/home.html");
/// assert_eq!(origin.query(), Some("new"));
///
/// let uri = Absolute::parse("https://rocket.rs").expect("valid URI");
/// assert_eq!(uri.origin(), None);
/// ```
#[inline(always)]
pub fn origin(&self) -> Option<&Origin<'a>> {
self.origin.as_ref()
}
}
impl<'a, 'b> PartialEq<Absolute<'b>> for Absolute<'a> {
fn eq(&self, other: &Absolute<'b>) -> bool {
self.scheme() == other.scheme()
&& self.authority() == other.authority()
&& self.origin() == other.origin()
}
}
impl<'a> Display for Absolute<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.scheme())?;
match self.authority {
Some(ref authority) => write!(f, "://{}", authority)?,
None => write!(f, ":")?
}
if let Some(ref origin) = self.origin {
write!(f, "{}", origin)?;
}
Ok(())
}
}