use super::*;
use core::ops::Deref;
use alloc::string::{String, ToString};
#[derive(Clone, Eq, Hash)]
pub struct RelRefBuf(pub(super) UriRefBuf);
impl_uri_buf_traits!(RelRefBuf, RelRef);
impl Default for RelRefBuf {
fn default() -> Self {
Self::new()
}
}
impl core::fmt::Display for RelRefBuf {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::result::Result<(), core::fmt::Error> {
self.write_to(f)
}
}
impl Deref for RelRefBuf {
type Target = RelRef;
fn deref(&self) -> &Self::Target {
self.as_rel_ref()
}
}
impl AsRef<RelRef> for RelRefBuf {
fn as_ref(&self) -> &RelRef {
self.as_rel_ref()
}
}
impl From<&RelRef> for RelRefBuf {
fn from(x: &RelRef) -> Self {
x.to_rel_ref_buf()
}
}
impl RelRefBuf {
pub fn new() -> RelRefBuf {
RelRefBuf(UriRefBuf::new())
}
pub fn with_capacity(capacity: usize) -> RelRefBuf {
RelRefBuf(UriRefBuf::with_capacity(capacity))
}
pub fn from_str<S: AsRef<str>>(s: S) -> Result<RelRefBuf, ParseError> {
RelRef::from_str(s.as_ref()).map(Self::from_rel_ref)
}
pub fn from_string(s: String) -> Result<RelRefBuf, ParseError> {
if let Some(first_error) = s.as_str().unescape_uri().first_error() {
return Err(ParseError::from(first_error));
} else {
let mut ret = unsafe { Self::from_string_unchecked(s) };
ret.disambiguate();
Ok(ret)
}
}
pub fn from_uri_ref<S: AsRef<UriRef>>(s: S) -> Option<RelRefBuf> {
s.as_ref()
.as_rel_ref()
.map(ToString::to_string)
.map(|s| unsafe { Self::from_string_unchecked(s) })
}
pub fn from_rel_ref<S: AsRef<RelRef>>(s: S) -> RelRefBuf {
unsafe { Self::from_string_unchecked(s.as_ref().to_string()) }
}
}
impl RelRefBuf {
#[inline(always)]
pub fn as_rel_ref(&self) -> &RelRef {
unsafe { RelRef::from_str_unchecked(self.as_str()) }
}
#[inline(always)]
pub fn as_mut_rel_ref(&mut self) -> &mut RelRef {
unsafe { RelRef::from_str_unchecked_mut(self.as_mut_str()) }
}
}
impl RelRefBuf {
pub fn disambiguate(&mut self) -> bool {
if let Some(i) = self.colon_in_first_path_segment() {
(self.0).0.replace_range(i..i + 1, "%3A");
true
} else if self.starts_with("//") {
(self.0).0.insert_str(0, "/.");
true
} else {
false
}
}
#[must_use]
pub fn into_unescape_buf(self) -> UriUnescapeBuf {
UriUnescapeBuf::new(self)
}
pub fn resolve<T: AsRef<RelRef>>(&mut self, dest: T) {
if !dest.as_ref().is_empty() {
*self = self.resolved_rel_ref(dest);
}
}
#[inline(always)]
pub fn clear(&mut self) {
self.0.clear()
}
}
inherits_uri_ref_buf!(RelRefBuf);
impl RelRefBuf {
#[inline(always)]
pub unsafe fn from_string_unchecked(s: String) -> RelRefBuf {
RelRefBuf(UriRefBuf::from_string_unchecked(s))
}
}