use super::sequence::{Sequence, TakePrefx};
use std::hash::{Hash, Hasher};
use std::iter::Chain;
use std::{fmt, slice};
pub struct SplitSlice<'a, T> {
pub front: &'a [T],
pub back: &'a [T],
}
impl<'a, T: fmt::Debug> fmt::Debug for SplitSlice<'a, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.front, f)?;
write!(f, " + ")?;
fmt::Debug::fmt(&self.back, f)
}
}
impl<'a, T> Clone for SplitSlice<'a, T> {
#[inline]
fn clone(&self) -> Self {
Self {
front: self.front,
back: self.back,
}
}
}
impl<'a, T> Copy for SplitSlice<'a, T> {}
impl<'a, T> From<&'a [T]> for SplitSlice<'a, T> {
#[inline]
fn from(slice: &'a [T]) -> Self {
Self {
front: slice,
back: &[],
}
}
}
impl<'a, T> From<(&'a [T], &'a [T])> for SplitSlice<'a, T> {
#[inline]
fn from((front, back): (&'a [T], &'a [T])) -> Self {
Self { front, back }
}
}
impl<'a, T, U> PartialEq<[U]> for SplitSlice<'a, T>
where
T: PartialEq<U>,
{
#[inline]
fn eq(&self, rhs: &[U]) -> bool {
self.front.eq(&rhs[..self.front.len()]) && self.back.eq(&rhs[self.front.len()..])
}
}
impl<'a, T, U> PartialEq<&'a [U]> for SplitSlice<'a, T>
where
T: PartialEq<U>,
{
#[inline]
fn eq(&self, rhs: &&'a [U]) -> bool {
self.eq(*rhs)
}
}
impl<'a, 'b, T, U> PartialEq<SplitSlice<'b, U>> for SplitSlice<'a, T>
where
T: PartialEq<U>,
{
#[inline]
fn eq(&self, rhs: &SplitSlice<'b, U>) -> bool {
let self_split = self.front.len();
let rhs_split = rhs.front.len();
if self_split <= rhs_split {
let (rhs_front, rhs_mid) = rhs.front.split_at(self_split);
let (self_mid, self_back) = self.back.split_at(rhs_split - self_split);
self.front == rhs_front && self_mid == rhs_mid && self_back == rhs.back
} else {
let (self_front, self_mid) = self.front.split_at(rhs_split);
let (rhs_mid, rhs_back) = rhs.back.split_at(self_split - rhs_split);
self_front == rhs.front && self_mid == rhs_mid && self.back == rhs_back
}
}
}
impl<'a, T: Eq> Eq for SplitSlice<'a, T> {}
impl<'a, T> SplitSlice<'a, T> {
#[inline]
pub fn iter(self) -> SplitSliceIter<'a, T> {
self.into_iter()
}
#[inline]
#[must_use]
pub fn split_at(self, mid: usize) -> (Self, Self) {
if let Some(back_split_at) = mid.checked_sub(self.front.len()) {
let (first_back, second_back) = self.back.split_at(back_split_at);
(
Self {
front: self.front,
back: first_back,
},
second_back.into(),
)
} else {
let (first_front, second_front) = self.front.split_at(mid);
(
first_front.into(),
Self {
front: second_front,
back: self.back,
},
)
}
}
}
pub type SplitSliceIter<'a, T> = Chain<slice::Iter<'a, T>, slice::Iter<'a, T>>;
impl<'a, T> IntoIterator for SplitSlice<'a, T> {
type Item = &'a T;
type IntoIter = SplitSliceIter<'a, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.front.iter().chain(self.back)
}
}
impl<'a, T> Sequence for SplitSlice<'a, T> {
type Item = &'a T;
#[inline]
fn len(&self) -> usize {
self.front.len() + self.back.len()
}
#[inline]
fn is_empty(&self) -> bool {
self.front.is_empty() && self.back.is_empty()
}
#[inline]
fn get(&self, idx: usize) -> Option<Self::Item> {
self.front
.get(idx)
.or_else(|| self.back.get(idx - self.front.len()))
}
}
impl<'a, T> TakePrefx for SplitSlice<'a, T> {
#[inline]
fn take_prefix(&mut self, len: usize) -> Self {
let (prefix, rest) = self.split_at(len);
*self = rest;
prefix
}
}
impl<'a, T: Hash> Hash for SplitSlice<'a, T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state);
Hash::hash_slice(self.front, state);
Hash::hash_slice(self.back, state);
}
}