pub struct IriRef<T> { /* private fields */ }
Expand description
An IRI reference, i.e., either a IRI or a relative reference.
See the crate-level documentation for an explanation of the above term(s).
§Variants
Two variants of IriRef
are available:
IriRef<&str>
(borrowed) and IriRef<String>
(owned).
IriRef<&'a str>
outputs references with lifetime 'a
where possible
(thanks to borrow-or-share
):
use fluent_uri::IriRef;
// Keep a reference to the path after dropping the `IriRef`.
let path = IriRef::parse("foo:bar")?.path();
assert_eq!(path, "bar");
§Comparison
IriRef
s
are compared lexicographically
by their byte values. Normalization is not performed prior to comparison.
§Examples
Parse and extract components from an IRI reference:
use fluent_uri::{
component::{Host, Scheme},
encoding::EStr,
IriRef,
};
const SCHEME_FOO: &Scheme = Scheme::new_or_panic("foo");
let s = "foo://user@example.com:8042/over/there?name=ferret#nose";
let iri_ref = IriRef::parse(s)?;
assert_eq!(iri_ref.scheme().unwrap(), SCHEME_FOO);
let auth = iri_ref.authority().unwrap();
assert_eq!(auth.as_str(), "user@example.com:8042");
assert_eq!(auth.userinfo().unwrap(), "user");
assert_eq!(auth.host(), "example.com");
assert!(matches!(auth.host_parsed(), Host::RegName(name) if name == "example.com"));
assert_eq!(auth.port().unwrap(), "8042");
assert_eq!(auth.port_to_u16(), Ok(Some(8042)));
assert_eq!(iri_ref.path(), "/over/there");
assert_eq!(iri_ref.query().unwrap(), "name=ferret");
assert_eq!(iri_ref.fragment().unwrap(), "nose");
Parse into and convert between
IriRef<&str>
and IriRef<String>
:
use fluent_uri::IriRef;
let s = "http://example.com/";
// Parse into a `IriRef<&str>` from a string slice.
let iri_ref: IriRef<&str> = IriRef::parse(s)?;
// Parse into a `IriRef<String>` from an owned string.
let iri_ref_owned: IriRef<String> = IriRef::parse(s.to_owned()).map_err(|e| e.strip_input())?;
// Convert a `IriRef<&str>` to `IriRef<String>`.
let iri_ref_owned: IriRef<String> = iri_ref.to_owned();
// Borrow a `IriRef<String>` as `IriRef<&str>`.
let iri_ref: IriRef<&str> = iri_ref_owned.borrow();
Implementations§
Source§impl<T> IriRef<T>
impl<T> IriRef<T>
Sourcepub fn parse<I>(input: I) -> Result<IriRef<T>, <I as Parse>::Err>where
I: Parse<Val = T>,
pub fn parse<I>(input: I) -> Result<IriRef<T>, <I as Parse>::Err>where
I: Parse<Val = T>,
Parses an IRI reference from a string into an IriRef
.
The return type is
Result<IriRef<&str>, ParseError>
forI = &str
;Result<IriRef<String>, ParseError<String>>
forI = String
.
§Errors
Returns Err
if the string does not match the
IRI-reference
ABNF rule from RFC 3987.
From a ParseError<String>
, you may recover or strip the input
by calling into_input
or strip_input
on it.
Source§impl<'i, 'o, T> IriRef<T>where
T: BorrowOrShare<'i, 'o, str>,
impl<'i, 'o, T> IriRef<T>where
T: BorrowOrShare<'i, 'o, str>,
Sourcepub fn scheme(&'i self) -> Option<&'o Scheme>
pub fn scheme(&'i self) -> Option<&'o Scheme>
Returns the optional scheme component.
Note that the scheme component is case-insensitive.
See the documentation of Scheme
for more details on comparison.
§Examples
use fluent_uri::{component::Scheme, IriRef};
const SCHEME_HTTP: &Scheme = Scheme::new_or_panic("http");
let iri_ref = IriRef::parse("http://example.com/")?;
assert_eq!(iri_ref.scheme(), Some(SCHEME_HTTP));
let iri_ref = IriRef::parse("/path/to/file")?;
assert_eq!(iri_ref.scheme(), None);
Sourcepub fn path(&'i self) -> &'o EStr<IPath>
pub fn path(&'i self) -> &'o EStr<IPath>
Returns the path component.
The path component is always present, although it may be empty.
The returned EStr
slice has extension methods for the path component.
§Examples
use fluent_uri::IriRef;
let iri_ref = IriRef::parse("http://example.com/")?;
assert_eq!(iri_ref.path(), "/");
let iri_ref = IriRef::parse("mailto:user@example.com")?;
assert_eq!(iri_ref.path(), "user@example.com");
let iri_ref = IriRef::parse("http://example.com")?;
assert_eq!(iri_ref.path(), "");
Sourcepub fn query(&'i self) -> Option<&'o EStr<IQuery>>
pub fn query(&'i self) -> Option<&'o EStr<IQuery>>
Returns the optional query component.
§Examples
use fluent_uri::{encoding::EStr, IriRef};
let iri_ref = IriRef::parse("http://example.com/?lang=en")?;
assert_eq!(iri_ref.query(), Some(EStr::new_or_panic("lang=en")));
let iri_ref = IriRef::parse("ftp://192.0.2.1/")?;
assert_eq!(iri_ref.query(), None);
Sourcepub fn fragment(&'i self) -> Option<&'o EStr<IFragment>>
pub fn fragment(&'i self) -> Option<&'o EStr<IFragment>>
Returns the optional fragment component.
§Examples
use fluent_uri::{encoding::EStr, IriRef};
let iri_ref = IriRef::parse("http://example.com/#usage")?;
assert_eq!(iri_ref.fragment(), Some(EStr::new_or_panic("usage")));
let iri_ref = IriRef::parse("ftp://192.0.2.1/")?;
assert_eq!(iri_ref.fragment(), None);
Source§impl<'i, 'o, T> IriRef<T>
impl<'i, 'o, T> IriRef<T>
Sourcepub fn resolve_against<U>(
&self,
base: &Iri<U>,
) -> Result<Iri<String>, ResolveError>
pub fn resolve_against<U>( &self, base: &Iri<U>, ) -> Result<Iri<String>, ResolveError>
Resolves the IRI reference against the given base IRI and returns the target IRI.
The base IRI
must contain no fragment, i.e., match the
absolute-IRI
ABNF rule from RFC 3987.
To prepare a base IRI,
you can use with_fragment
or set_fragment
to remove the fragment
from any IRI.
Note that a base without fragment does not guarantee a successful resolution
(see the must below).
This method applies the reference resolution algorithm defined in Section 5 of RFC 3986, except for the following deviations:
- If
base
contains no authority and its path is rootless, thenself
must either contain a scheme, be empty, or start with'#'
. - When the target contains no authority and its path would start
with
"//"
, the string"/."
is prepended to the path. This closes a loophole in the original algorithm that resolving".//@@"
against"foo:/"
yields"foo://@@"
which is not a valid URI/IRI. - Percent-encoded dot segments (e.g.
"%2E"
and".%2e"
) are also removed. This closes a loophole in the original algorithm that resolving".."
against"foo:/bar/.%2E/"
yields"foo:/bar/"
, while first normalizing the base and then resolving".."
against it yields"foo:/"
. - A slash (
'/'
) is appended to the base when it ends with a double-dot segment. This closes a loophole in the original algorithm that resolving"."
against"foo:/bar/.."
yields"foo:/bar/"
, while first normalizing the base and then resolving"."
against it yields"foo:/"
.
No normalization except the removal of dot segments will be performed.
Use normalize
if necessary.
This method has the property that
self.resolve_against(base).map(|r| r.normalize()).ok()
equals
self.normalize().resolve_against(&base.normalize()).ok()
.
§Errors
Returns Err
if any of the above two musts is violated.
§Examples
use fluent_uri::{Iri, IriRef};
let base = Iri::parse("http://example.com/foo/bar")?;
let iri_ref = IriRef::parse("baz")?;
assert_eq!(iri_ref.resolve_against(&base).unwrap(), "http://example.com/foo/baz");
let iri_ref = IriRef::parse("../baz")?;
assert_eq!(iri_ref.resolve_against(&base).unwrap(), "http://example.com/baz");
let iri_ref = IriRef::parse("?baz")?;
assert_eq!(iri_ref.resolve_against(&base).unwrap(), "http://example.com/foo/bar?baz");
Sourcepub fn normalize(&self) -> IriRef<String>
pub fn normalize(&self) -> IriRef<String>
Normalizes the IRI reference.
This method applies the syntax-based normalization described in Section 6.2.2 of RFC 3986 and Section 5.3.2 of RFC 3987, which is effectively equivalent to taking the following steps in order:
- Decode any percent-encoded octets that correspond to an allowed character which is not reserved.
- Uppercase the hexadecimal digits within all percent-encoded octets.
- Lowercase all ASCII characters within the scheme and the host except the percent-encoded octets.
- Turn any IPv6 literal address into its canonical form as per RFC 5952.
- If the port is empty, remove its
':'
delimiter. - If
self
contains a scheme and an absolute path, apply theremove_dot_segments
algorithm to the path, taking account of percent-encoded dot segments as described atUriRef::resolve_against
. - If
self
contains no authority and its path would start with"//"
, prepend"/."
to the path.
This method is idempotent: self.normalize()
equals self.normalize().normalize()
.
§Examples
use fluent_uri::IriRef;
let iri_ref = IriRef::parse("eXAMPLE://a/./b/../b/%63/%7bfoo%7d")?;
assert_eq!(iri_ref.normalize(), "example://a/b/c/%7Bfoo%7D");
Sourcepub fn has_scheme(&self) -> bool
pub fn has_scheme(&self) -> bool
Checks whether a scheme component is present.
§Examples
use fluent_uri::IriRef;
assert!(IriRef::parse("http://example.com/")?.has_scheme());
assert!(!IriRef::parse("/path/to/file")?.has_scheme());
Checks whether an authority component is present.
§Examples
use fluent_uri::IriRef;
assert!(IriRef::parse("http://example.com/")?.has_authority());
assert!(!IriRef::parse("mailto:user@example.com")?.has_authority());
Sourcepub fn has_query(&self) -> bool
pub fn has_query(&self) -> bool
Checks whether a query component is present.
§Examples
use fluent_uri::IriRef;
assert!(IriRef::parse("http://example.com/?lang=en")?.has_query());
assert!(!IriRef::parse("ftp://192.0.2.1/")?.has_query());
Sourcepub fn has_fragment(&self) -> bool
pub fn has_fragment(&self) -> bool
Checks whether a fragment component is present.
§Examples
use fluent_uri::IriRef;
assert!(IriRef::parse("http://example.com/#usage")?.has_fragment());
assert!(!IriRef::parse("ftp://192.0.2.1/")?.has_fragment());
Sourcepub fn with_fragment(&self, opt: Option<&EStr<IFragment>>) -> IriRef<String>
pub fn with_fragment(&self, opt: Option<&EStr<IFragment>>) -> IriRef<String>
Creates a new IRI reference
by replacing the fragment component of self
with the given one.
The fragment component is removed when opt.is_none()
.
§Examples
use fluent_uri::{encoding::EStr, IriRef};
let iri_ref = IriRef::parse("http://example.com/")?;
assert_eq!(
iri_ref.with_fragment(Some(EStr::new_or_panic("fragment"))),
"http://example.com/#fragment"
);
let iri_ref = IriRef::parse("http://example.com/#fragment")?;
assert_eq!(
iri_ref.with_fragment(None),
"http://example.com/"
);
Source§impl IriRef<String>
impl IriRef<String>
Sourcepub fn set_fragment(&mut self, opt: Option<&EStr<IFragment>>)
pub fn set_fragment(&mut self, opt: Option<&EStr<IFragment>>)
Replaces the fragment component of self
with the given one.
The fragment component is removed when opt.is_none()
.
§Examples
use fluent_uri::{encoding::EStr, IriRef};
let mut iri_ref = IriRef::parse("http://example.com/")?.to_owned();
iri_ref.set_fragment(Some(EStr::new_or_panic("fragment")));
assert_eq!(iri_ref, "http://example.com/#fragment");
iri_ref.set_fragment(None);
assert_eq!(iri_ref, "http://example.com/");
Source§impl<T> IriRef<T>
impl<T> IriRef<T>
Sourcepub fn to_uri_ref(&self) -> UriRef<String>
pub fn to_uri_ref(&self) -> UriRef<String>
Converts the IRI reference to a URI reference by percent-encoding non-ASCII characters.
Punycode encoding is not performed during conversion.
§Examples
use fluent_uri::IriRef;
let iri_ref = IriRef::parse("résumé.html").unwrap();
assert_eq!(iri_ref.to_uri_ref(), "r%C3%A9sum%C3%A9.html");
let iri_ref = IriRef::parse("//résumé.example.org").unwrap();
assert_eq!(iri_ref.to_uri_ref(), "//r%C3%A9sum%C3%A9.example.org");
Trait Implementations§
Source§impl<'de> Deserialize<'de> for IriRef<&'de str>
impl<'de> Deserialize<'de> for IriRef<&'de str>
Source§fn deserialize<D>(
deserializer: D,
) -> Result<IriRef<&'de str>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<IriRef<&'de str>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl<'de> Deserialize<'de> for IriRef<String>
impl<'de> Deserialize<'de> for IriRef<String>
Source§fn deserialize<D>(
deserializer: D,
) -> Result<IriRef<String>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<IriRef<String>, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl<T> Ord for IriRef<T>
impl<T> Ord for IriRef<T>
Source§impl<T> PartialOrd for IriRef<T>
impl<T> PartialOrd for IriRef<T>
Source§impl<T> Serialize for IriRef<T>
impl<T> Serialize for IriRef<T>
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
impl<T> Copy for IriRef<T>where
T: Copy,
impl<T> Eq for IriRef<T>
Auto Trait Implementations§
impl<T> Freeze for IriRef<T>where
T: Freeze,
impl<T> RefUnwindSafe for IriRef<T>where
T: RefUnwindSafe,
impl<T> Send for IriRef<T>where
T: Send,
impl<T> Sync for IriRef<T>where
T: Sync,
impl<T> Unpin for IriRef<T>where
T: Unpin,
impl<T> UnwindSafe for IriRef<T>where
T: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)