use std::ops::{Deref, Range};
use std::fmt::Debug;
use std::mem;
pub unsafe trait Hay {
type Index: Copy + Debug + Eq;
fn empty<'a>() -> &'a Self;
fn start_index(&self) -> Self::Index;
fn end_index(&self) -> Self::Index;
unsafe fn next_index(&self, index: Self::Index) -> Self::Index;
unsafe fn prev_index(&self, index: Self::Index) -> Self::Index;
unsafe fn slice_unchecked(&self, range: Range<Self::Index>) -> &Self;
}
pub unsafe trait Haystack: Deref + Sized where Self::Target: Hay {
fn empty() -> Self;
unsafe fn split_around(self, range: Range<<Self::Target as Hay>::Index>) -> [Self; 3];
unsafe fn slice_unchecked(self, range: Range<<Self::Target as Hay>::Index>) -> Self {
let [_, middle, _] = self.split_around(range);
middle
}
fn restore_range(
&self,
original: Range<<Self::Target as Hay>::Index>,
parent: Range<<Self::Target as Hay>::Index>,
) -> Range<<Self::Target as Hay>::Index>;
}
pub trait SharedHaystack: Haystack + Clone
where Self::Target: Hay {}
trait SpanBehavior: Haystack
where Self::Target: Hay {
fn take(&mut self) -> Self;
fn from_span(span: Span<Self>) -> Self;
unsafe fn split_around_for_span(self, subrange: Range<<Self::Target as Hay>::Index>) -> [Self; 3];
unsafe fn slice_unchecked_for_span(self, subrange: Range<<Self::Target as Hay>::Index>) -> Self;
fn borrow_range(
&self,
range: Range<<Self::Target as Hay>::Index>,
) -> Range<<Self::Target as Hay>::Index>;
fn do_restore_range(
&self,
range: Range<<Self::Target as Hay>::Index>,
subrange: Range<<Self::Target as Hay>::Index>,
) -> Range<<Self::Target as Hay>::Index>;
}
impl<H: Haystack> SpanBehavior for H
where H::Target: Hay {
#[inline]
default fn take(&mut self) -> Self {
mem::replace(self, Self::empty())
}
#[inline]
default fn from_span(span: Span<Self>) -> Self {
span.haystack
}
#[inline]
default fn borrow_range(&self, _: Range<<Self::Target as Hay>::Index>) -> Range<<Self::Target as Hay>::Index> {
self.start_index()..self.end_index()
}
#[inline]
default fn do_restore_range(
&self,
range: Range<<Self::Target as Hay>::Index>,
subrange: Range<<Self::Target as Hay>::Index>,
) -> Range<<Self::Target as Hay>::Index> {
self.restore_range(range, subrange)
}
#[inline]
default unsafe fn split_around_for_span(self, subrange: Range<<Self::Target as Hay>::Index>) -> [Self; 3] {
self.split_around(subrange)
}
#[inline]
default unsafe fn slice_unchecked_for_span(self, subrange: Range<<Self::Target as Hay>::Index>) -> Self {
self.slice_unchecked(subrange)
}
}
impl<H: SharedHaystack> SpanBehavior for H
where H::Target: Hay {
#[inline]
fn take(&mut self) -> Self {
self.clone()
}
#[inline]
fn from_span(span: Span<Self>) -> Self {
unsafe {
span.haystack.slice_unchecked(span.range)
}
}
#[inline]
fn borrow_range(&self, range: Range<<Self::Target as Hay>::Index>) -> Range<<Self::Target as Hay>::Index> {
range
}
#[inline]
fn do_restore_range(
&self,
_: Range<<Self::Target as Hay>::Index>,
subrange: Range<<Self::Target as Hay>::Index>,
) -> Range<<Self::Target as Hay>::Index> {
subrange
}
#[inline]
unsafe fn split_around_for_span(self, _: Range<<Self::Target as Hay>::Index>) -> [Self; 3] {
[self.clone(), self.clone(), self]
}
#[inline]
unsafe fn slice_unchecked_for_span(self, _: Range<<Self::Target as Hay>::Index>) -> Self {
self
}
}
#[derive(Debug, Clone)]
pub struct Span<H: Haystack>
where H::Target: Hay {
haystack: H,
range: Range<<<H as Deref>::Target as Hay>::Index>,
}
impl<H: Haystack> From<H> for Span<H>
where H::Target: Hay {
#[inline]
fn from(haystack: H) -> Self {
let range = haystack.start_index()..haystack.end_index();
Self { haystack, range }
}
}
impl<H: SharedHaystack> Span<H>
where H::Target: Hay {
#[inline]
pub fn into_parts(self) -> (H, Range<<H::Target as Hay>::Index>) {
(self.haystack, self.range)
}
#[inline]
pub unsafe fn from_parts(haystack: H, range: Range<<H::Target as Hay>::Index>) -> Self {
Self { haystack, range }
}
}
impl<'h> Span<&'h str> {
#[inline]
pub fn as_bytes(self) -> Span<&'h [u8]> {
Span {
haystack: self.haystack.as_bytes(),
range: self.range,
}
}
}
impl<H: Haystack> Span<H>
where H::Target: Hay {
#[inline]
pub fn original_range(&self) -> Range<<H::Target as Hay>::Index> {
self.range.clone()
}
#[inline]
pub fn borrow(&self) -> Span<&H::Target> {
Span {
haystack: &*self.haystack,
range: self.haystack.borrow_range(self.range.clone()),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.range.start == self.range.end
}
#[inline]
pub fn take(&mut self) -> Self {
let haystack = self.haystack.take();
let range = self.range.clone();
self.range.end = self.range.start;
Span { haystack, range }
}
#[inline]
pub fn into(self) -> H {
H::from_span(self)
}
#[inline]
pub unsafe fn split_around(self, subrange: Range<<H::Target as Hay>::Index>) -> [Self; 3] {
let self_range = self.haystack.borrow_range(self.range.clone());
let [left, middle, right] = self.haystack.split_around_for_span(subrange.clone());
let left_range = left.do_restore_range(self.range.clone(), self_range.start..subrange.start);
let right_range = right.do_restore_range(self.range.clone(), subrange.end..self_range.end);
let middle_range = middle.do_restore_range(self.range, subrange);
[
Self { haystack: left, range: left_range },
Self { haystack: middle, range: middle_range },
Self { haystack: right, range: right_range },
]
}
#[inline]
pub unsafe fn slice_unchecked(self, subrange: Range<<H::Target as Hay>::Index>) -> Self {
let haystack = self.haystack.slice_unchecked_for_span(subrange.clone());
let range = haystack.do_restore_range(self.range, subrange);
Self { haystack, range }
}
}
unsafe impl<'a, A: Hay + ?Sized + 'a> Haystack for &'a A {
#[inline]
fn empty() -> Self {
A::empty()
}
#[inline]
unsafe fn split_around(self, range: Range<A::Index>) -> [Self; 3] {
[
self.slice_unchecked(self.start_index()..range.start),
self.slice_unchecked(range.clone()),
self.slice_unchecked(range.end..self.end_index()),
]
}
#[inline]
unsafe fn slice_unchecked(self, range: Range<A::Index>) -> Self {
A::slice_unchecked(self, range)
}
#[inline]
fn restore_range(&self, _: Range<A::Index>, _: Range<A::Index>) -> Range<A::Index> {
unreachable!()
}
}
impl<'a, A: Hay + ?Sized + 'a> SharedHaystack for &'a A {}