use std::fmt::{self, Display};
use std::convert::From;
use std::borrow::Cow;
use std::str::Utf8Error;
use std::convert::TryFrom;
use ext::IntoOwned;
use parse::Indexed;
use uri::{Origin, Authority, Absolute, Error};
use uri::encoding::{percent_encode, DEFAULT_ENCODE_SET};
#[derive(Debug, PartialEq, Clone)]
pub enum Uri<'a> {
Origin(Origin<'a>),
Authority(Authority<'a>),
Absolute(Absolute<'a>),
Asterisk,
}
impl<'a> Uri<'a> {
#[inline]
pub(crate) unsafe fn raw_absolute(
source: Cow<'a, [u8]>,
scheme: Indexed<'a, [u8]>,
path: Indexed<'a, [u8]>,
query: Option<Indexed<'a, [u8]>>,
) -> Uri<'a> {
let origin = Origin::raw(source.clone(), path, query);
Uri::Absolute(Absolute::raw(source.clone(), scheme, None, Some(origin)))
}
pub fn parse(string: &'a str) -> Result<Uri<'a>, Error> {
::parse::uri::from_str(string)
}
pub fn origin(&self) -> Option<&Origin<'a>> {
match self {
Uri::Origin(ref inner) => Some(inner),
_ => None
}
}
pub fn authority(&self) -> Option<&Authority<'a>> {
match self {
Uri::Authority(ref inner) => Some(inner),
_ => None
}
}
pub fn absolute(&self) -> Option<&Absolute<'a>> {
match self {
Uri::Absolute(ref inner) => Some(inner),
_ => None
}
}
pub fn percent_encode(string: &str) -> Cow<str> {
percent_encode::<DEFAULT_ENCODE_SET>(string)
}
pub fn percent_decode(string: &[u8]) -> Result<Cow<str>, Utf8Error> {
let decoder = ::percent_encoding::percent_decode(string);
decoder.decode_utf8()
}
pub fn percent_decode_lossy(string: &[u8]) -> Cow<str> {
let decoder = ::percent_encoding::percent_decode(string);
decoder.decode_utf8_lossy()
}
}
pub(crate) unsafe fn as_utf8_unchecked(input: Cow<[u8]>) -> Cow<str> {
match input {
Cow::Borrowed(bytes) => Cow::Borrowed(::std::str::from_utf8_unchecked(bytes)),
Cow::Owned(bytes) => Cow::Owned(String::from_utf8_unchecked(bytes))
}
}
impl<'a> TryFrom<&'a str> for Uri<'a> {
type Error = Error<'a>;
#[inline]
fn try_from(string: &'a str) -> Result<Uri<'a>, Self::Error> {
Uri::parse(string)
}
}
impl TryFrom<String> for Uri<'static> {
type Error = Error<'static>;
#[inline]
fn try_from(string: String) -> Result<Uri<'static>, Self::Error> {
Uri::parse(&string)
.map(|u| u.into_owned())
.map_err(|e| e.into_owned())
}
}
impl<'a> IntoOwned for Uri<'a> {
type Owned = Uri<'static>;
fn into_owned(self) -> Uri<'static> {
match self {
Uri::Origin(origin) => Uri::Origin(origin.into_owned()),
Uri::Authority(authority) => Uri::Authority(authority.into_owned()),
Uri::Absolute(absolute) => Uri::Absolute(absolute.into_owned()),
Uri::Asterisk => Uri::Asterisk
}
}
}
impl<'a> Display for Uri<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Uri::Origin(ref origin) => write!(f, "{}", origin),
Uri::Authority(ref authority) => write!(f, "{}", authority),
Uri::Absolute(ref absolute) => write!(f, "{}", absolute),
Uri::Asterisk => write!(f, "*")
}
}
}
macro_rules! impl_uri_from {
($type:ident) => (
impl<'a> From<$type<'a>> for Uri<'a> {
fn from(other: $type<'a>) -> Uri<'a> {
Uri::$type(other)
}
}
)
}
impl_uri_from!(Origin);
impl_uri_from!(Authority);
impl_uri_from!(Absolute);