use std::convert::TryFrom;
#[cfg(feature = "serde")]
use serde::Serialize;
use validated_slice::{OwnedSliceSpec, SliceSpec};
use crate::{
types::{
iri::set_fragment, IriCreationError, IriFragmentStr, IriReferenceStr, IriReferenceString,
},
validate::iri::{relative_ref, Error},
};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
#[allow(clippy::derive_hash_xor_eq)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct RelativeIriStr(str);
impl RelativeIriStr {
pub fn new(s: &str) -> Result<&Self, Error> {
TryFrom::try_from(s)
}
pub(crate) unsafe fn new_unchecked(s: &str) -> &Self {
debug_assert_eq!(StrSpec::validate(s), Ok(()));
StrSpec::from_inner_unchecked(s)
}
pub fn as_str(&self) -> &str {
self.as_ref()
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct RelativeIriString(String);
impl RelativeIriString {
pub(crate) unsafe fn new_unchecked(s: String) -> Self {
debug_assert_eq!(StrSpec::validate(&s), Ok(()));
StringSpec::from_inner_unchecked(s)
}
pub fn set_fragment(&mut self, fragment: Option<&IriFragmentStr>) {
set_fragment(&mut self.0, fragment.map(AsRef::as_ref));
debug_assert!(relative_ref(&self.0).is_ok());
}
pub fn shrink_to_fit(&mut self) {
self.0.shrink_to_fit()
}
}
impl_basics! {
Slice {
spec: StrSpec,
custom: RelativeIriStr,
validator: relative_ref,
error: Error,
},
Owned {
spec: StringSpec,
custom: RelativeIriString,
error: IriCreationError<String>,
},
}
impl std::ops::Deref for RelativeIriStr {
type Target = IriReferenceStr;
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl_conv_and_cmp! {
source: {
owned: RelativeIriString,
slice: RelativeIriStr,
creation_error: IriCreationError,
validation_error: Error,
},
target: [
{
owned: IriReferenceString,
slice: IriReferenceStr,
},
],
}
impl_serde! {
expecting: "a relative IRI",
slice: RelativeIriStr,
owned: RelativeIriString,
}