use core::hash::Hash;
use crate::std::borrow::Cow;
use super::encode::{
encoded_fragment, encoded_fragment_cmp, encoded_fragment_eq, hash_encoded_fragment,
write_encoded_fragment,
};
use rama_core::bytes::BytesMut;
use percent_encoding::percent_decode;
#[derive(Debug, Clone, Default)]
pub struct Fragment {
pub(crate) bytes: BytesMut,
}
impl Fragment {
#[must_use]
pub fn as_encoded_str(&self) -> Cow<'_, str> {
encoded_fragment(&self.bytes)
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
#[must_use]
pub fn as_decoded_str(&self) -> Cow<'_, str> {
percent_decode(&self.bytes).decode_utf8_lossy()
}
#[must_use]
#[inline]
pub fn view(&self) -> FragmentRef<'_> {
FragmentRef { bytes: &self.bytes }
}
}
impl PartialEq for Fragment {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
self.view() == other.view()
}
}
impl Eq for Fragment {}
impl PartialOrd for Fragment {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Fragment {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.view().cmp(&other.view())
}
}
impl Hash for Fragment {
#[inline(always)]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.view().hash(state);
}
}
#[derive(Debug, Clone, Copy)]
pub struct FragmentRef<'a> {
pub(crate) bytes: &'a [u8],
}
impl<'a> FragmentRef<'a> {
#[must_use]
#[inline]
pub(crate) const fn new(bytes: &'a [u8]) -> Self {
Self { bytes }
}
#[must_use]
#[inline]
pub fn from_raw_str(fragment: &'a str) -> Self {
Self::new(fragment.as_bytes())
}
#[must_use]
pub fn as_encoded_str(self) -> Cow<'a, str> {
encoded_fragment(self.bytes)
}
#[must_use]
#[inline]
pub fn is_empty(self) -> bool {
self.bytes.is_empty()
}
#[must_use]
pub fn as_decoded_str(&self) -> Cow<'a, str> {
percent_decode(self.bytes).decode_utf8_lossy()
}
#[must_use]
pub fn into_owned(self) -> Fragment {
Fragment {
bytes: BytesMut::from(self.bytes),
}
}
}
impl PartialEq for FragmentRef<'_> {
#[inline(always)]
fn eq(&self, other: &Self) -> bool {
encoded_fragment_eq(self.bytes, other.bytes)
}
}
impl Eq for FragmentRef<'_> {}
impl PartialEq<str> for FragmentRef<'_> {
#[inline(always)]
fn eq(&self, other: &str) -> bool {
self.eq(&FragmentRef::from_raw_str(other))
}
}
impl PartialEq<&str> for FragmentRef<'_> {
#[inline(always)]
fn eq(&self, other: &&str) -> bool {
self.eq(&FragmentRef::from_raw_str(other))
}
}
impl<'a> PartialEq<FragmentRef<'a>> for str {
#[inline(always)]
fn eq(&self, other: &FragmentRef<'a>) -> bool {
FragmentRef::from_raw_str(self).eq(other)
}
}
impl<'a> PartialEq<FragmentRef<'a>> for &str {
#[inline(always)]
fn eq(&self, other: &FragmentRef<'a>) -> bool {
FragmentRef::from_raw_str(self).eq(other)
}
}
impl PartialOrd for FragmentRef<'_> {
#[inline(always)]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for FragmentRef<'_> {
#[inline(always)]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
encoded_fragment_cmp(self.bytes, other.bytes)
}
}
impl Hash for FragmentRef<'_> {
#[inline(always)]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
hash_encoded_fragment(state, self.bytes);
}
}
impl core::fmt::Display for Fragment {
#[inline(always)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Display::fmt(&self.view(), f)
}
}
impl core::fmt::Display for FragmentRef<'_> {
#[inline(always)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write_encoded_fragment(f, self.bytes)
}
}
impl core::str::FromStr for Fragment {
type Err = core::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
bytes: super::encode::encode_fragment(s),
})
}
}