use core::ops::RangeBounds;
#[cfg(feature = "bytes")]
mod bytes;
#[cfg(feature = "bstr")]
mod bstr;
#[cfg(feature = "hipstr")]
mod hipstr;
pub trait Slice<'source>: PartialEq + Eq + core::fmt::Debug {
type Char: Copy + core::fmt::Debug + PartialEq + Eq + core::hash::Hash;
type Iter<'a>: Iterator<Item = Self::Char>
where
Self: 'a;
type PositionedIter<'a>: Iterator<Item = (usize, Self::Char)>
where
Self: 'a;
fn iter<'a>(&'a self) -> Self::Iter<'a>
where
Self: 'a;
fn positioned_iter<'a>(&'a self) -> Self::PositionedIter<'a>
where
Self: 'a;
fn len(&self) -> usize;
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<'source> Slice<'source> for &'source [u8] {
type Char = u8;
type Iter<'a>
= core::iter::Copied<core::slice::Iter<'a, u8>>
where
Self: 'a;
type PositionedIter<'a>
= core::iter::Enumerate<core::iter::Copied<core::slice::Iter<'a, u8>>>
where
Self: 'a;
#[cfg_attr(not(tarpaulin), inline(always))]
fn iter<'a>(&'a self) -> Self::Iter<'a>
where
Self: 'a,
{
<[u8]>::iter(self).copied()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn positioned_iter<'a>(&'a self) -> Self::PositionedIter<'a>
where
Self: 'a,
{
<[u8]>::iter(self).copied().enumerate()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn len(&self) -> usize {
<[u8]>::len(self)
}
}
impl<'source> Slice<'source> for &'source str {
type Char = char;
type Iter<'a>
= core::str::Chars<'a>
where
Self: 'a;
type PositionedIter<'a>
= core::str::CharIndices<'a>
where
Self: 'a;
#[cfg_attr(not(tarpaulin), inline(always))]
fn iter<'a>(&'a self) -> Self::Iter<'a>
where
Self: 'a,
{
self.chars()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn positioned_iter<'a>(&'a self) -> Self::PositionedIter<'a>
where
Self: 'a,
{
self.char_indices()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn len(&self) -> usize {
<str>::len(self)
}
}
pub trait Source<Cursor> {
type Slice<'source>: Slice<'source>
where
Self: 'source;
fn is_empty(&self) -> bool;
fn len(&self) -> Cursor;
fn slice<'a, R>(&self, range: R) -> Option<Self::Slice<'_>>
where
R: RangeBounds<&'a Cursor>,
Cursor: 'a;
#[inline]
fn find_boundary(&self, index: Cursor) -> Cursor {
index
}
fn is_boundary(&self, index: Cursor) -> bool;
}
impl Source<usize> for [u8] {
type Slice<'source>
= &'source [u8]
where
Self: 'source;
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_empty(&self) -> bool {
<[u8]>::is_empty(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn len(&self) -> usize {
self.len()
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn slice<'a, R>(&self, range: R) -> Option<Self::Slice<'_>>
where
R: RangeBounds<&'a usize>,
usize: 'a,
{
self.get((
range.start_bound().map(|s| **s),
range.end_bound().map(|s| **s),
))
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_boundary(&self, index: usize) -> bool {
index <= self.len()
}
}
impl Source<usize> for str {
type Slice<'source>
= &'source str
where
Self: 'source;
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_empty(&self) -> bool {
<str>::is_empty(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn len(&self) -> usize {
<str>::len(self)
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn slice<'a, R>(&self, range: R) -> Option<Self::Slice<'_>>
where
R: RangeBounds<&'a usize>,
{
self.get((
range.start_bound().map(|s| **s),
range.end_bound().map(|s| **s),
))
}
#[cfg_attr(not(tarpaulin), inline(always))]
fn is_boundary(&self, index: usize) -> bool {
self.is_char_boundary(index)
}
}