extern crate alloc;
use alloc::string::String;
use core::ops::{RangeBounds, Bound};
use crate::parse::Parse;
pub trait Slice {
type Output: Slice;
fn slice<R: RangeBounds<usize>>(&self, bounds: R) -> Option<Self::Output>;
fn len(&self) -> usize;
fn split_at(&self, index: usize) -> Option<(Self::Output, Self::Output)> {
Some((self.slice(..index)?, self.slice(index..)?))
}
fn parse_with<P>(self, parser: P) -> Result<(Self, P::Output), P::Err>
where P: Parse<Self>, Self: Sized {
parser.parse(self)
}
}
fn into_indices<R: RangeBounds<usize>>(bounds: R, len: usize) -> (usize, usize) {
let start = match bounds.start_bound().cloned() {
Bound::Included(idx) => idx,
Bound::Excluded(idx) => idx + 1,
Bound::Unbounded => 0,
};
let end = match bounds.end_bound().cloned() {
Bound::Included(idx) => idx + 1,
Bound::Excluded(idx) => idx,
Bound::Unbounded => len,
};
(start, end)
}
impl Slice for &str {
type Output = Self;
fn slice<R: RangeBounds<usize>>(&self, bounds: R) -> Option<Self::Output> {
let (start, end) = into_indices(bounds, self.len());
self.get(start..end)
}
fn len(&self) -> usize { str::len(self) }
}
impl<'a> Slice for &'a String {
type Output = &'a str;
fn slice<R: RangeBounds<usize>>(&self, bounds: R) -> Option<Self::Output> {
let (start, end) = into_indices(bounds, self.len());
self.get(start..end)
}
fn len(&self) -> usize { str::len(self) }
}
impl<T> Slice for &[T] {
type Output = Self;
fn slice<R: RangeBounds<usize>>(&self, bounds: R) -> Option<Self::Output> {
self.get((bounds.start_bound().cloned(), bounds.end_bound().cloned()))
}
fn len(&self) -> usize { <[T]>::len(self) }
}
impl<'a, T, const N: usize> Slice for &'a [T; N] {
type Output = &'a [T];
fn slice<R: RangeBounds<usize>>(&self, bounds: R) -> Option<Self::Output> {
self.get((bounds.start_bound().cloned(), bounds.end_bound().cloned()))
}
fn len(&self) -> usize { N }
}