use alloc::string::String;
use borrow_or_share::BorrowOrShare;
#[cfg(test)]
use borrow_or_share::Bos;
use super::parts::{Constraints, Meta, Parse, RiMaybeRef, RmrRef};
use crate::component::{IAuthority, Scheme};
use crate::error::IriParseError;
#[cfg(test)]
use crate::normalize::Normalizer;
use crate::pct_enc::EStr;
use crate::pct_enc::encoder::{IFragment, IPath, IQuery};
#[derive(Clone, Copy)]
pub struct Iri<T> {
pub(crate) val: T,
pub(crate) meta: Meta,
}
impl<T> RiMaybeRef for Iri<T> {
type Val = T;
type WithVal<U> = Iri<U>;
const CONSTRAINTS: Constraints = Constraints {
scheme_required: true,
};
fn new(val: T, meta: Meta) -> Self {
Self { val, meta }
}
fn make_ref<'i, 'o>(&'i self) -> RmrRef<'o, 'i>
where
T: BorrowOrShare<'i, 'o, str>,
{
RmrRef::new(self.as_str(), &self.meta)
}
}
impl<'a> Iri<&'a str> {
pub fn parse(input: &'a str) -> Result<Self, IriParseError> {
input.parse_iri()
}
}
impl Iri<String> {
pub fn parse_owned(input: String) -> Result<Self, (IriParseError, String)> {
input.parse_iri()
}
}
impl Iri<String> {
#[allow(clippy::should_implement_trait)]
#[inline]
#[must_use]
pub fn borrow(&self) -> Iri<&str> {
Iri {
val: &self.val,
meta: self.meta,
}
}
#[inline]
#[must_use]
pub fn into_string(self) -> String {
self.val
}
#[must_use]
pub fn known(value: &str) -> Self {
Iri::parse(value)
.unwrap_or_else(|e| panic!("Iri::known called with invalid IRI {value:?}: {e}"))
.to_owned()
}
}
impl Iri<&str> {
#[inline]
#[must_use]
pub fn to_owned(&self) -> Iri<String> {
Iri {
val: self.val.to_owned(),
meta: self.meta,
}
}
}
impl<'i, 'o, T: BorrowOrShare<'i, 'o, str>> Iri<T> {
#[must_use]
pub fn as_str(&'i self) -> &'o str {
self.val.borrow_or_share()
}
#[must_use]
pub(crate) fn scheme(&'i self) -> &'o Scheme {
self.make_ref().scheme()
}
#[must_use]
pub(crate) fn authority(&'i self) -> Option<IAuthority<'o>> {
self.make_ref().authority()
}
#[must_use]
pub(crate) fn path(&'i self) -> &'o EStr<IPath> {
self.make_ref().path()
}
#[must_use]
pub(crate) fn query(&'i self) -> Option<&'o EStr<IQuery>> {
self.make_ref().query()
}
#[must_use]
pub(crate) fn fragment(&'i self) -> Option<&'o EStr<IFragment>> {
self.make_ref().fragment()
}
}
#[cfg(test)]
impl<T: Bos<str>> Iri<T> {
#[must_use]
pub(crate) fn normalize(&self) -> Iri<String> {
Normalizer::new().normalize(self).unwrap()
}
#[must_use]
pub(crate) fn has_authority(&self) -> bool {
self.make_ref().has_authority()
}
#[must_use]
pub(crate) fn has_query(&self) -> bool {
self.make_ref().has_query()
}
#[must_use]
pub(crate) fn has_fragment(&self) -> bool {
self.make_ref().has_fragment()
}
#[must_use]
pub(crate) fn strip_fragment(&self) -> Iri<&str> {
RiMaybeRef::new(self.make_ref().strip_fragment(), self.meta)
}
}
#[cfg(test)]
impl Iri<String> {
pub(crate) fn set_fragment(&mut self, opt: Option<&EStr<IFragment>>) {
RmrRef::set_fragment(&mut self.val, &self.meta, opt.map(EStr::as_str));
}
}