use std::ops::Range;
use std::fmt::Debug;
pub trait Slice<'source>: Sized + PartialEq + Eq + Debug {
fn as_bytes(&self) -> &'source [u8];
}
impl<'source> Slice<'source> for &'source str {
fn as_bytes(&self) -> &'source [u8] {
(*self).as_bytes()
}
}
impl<'source> Slice<'source> for &'source [u8] {
fn as_bytes(&self) -> &'source [u8] {
*self
}
}
pub trait Source<'source> {
type Slice: self::Slice<'source>;
fn len(&self) -> usize;
unsafe fn read(&self, offset: usize) -> u8;
fn slice(&self, range: Range<usize>) -> Option<Self::Slice>;
unsafe fn slice_unchecked(&self, range: Range<usize>) -> Self::Slice;
}
impl<'source> Source<'source> for &'source str {
type Slice = &'source str;
fn len(&self) -> usize {
(*self).len()
}
unsafe fn read(&self, offset: usize) -> u8 {
debug_assert!(offset <= self.len(), "Reading out founds!");
match self.as_bytes().get(offset) {
Some(byte) => *byte,
None => 0,
}
}
fn slice(&self, range: Range<usize>) -> Option<&'source str> {
self.get(range)
}
unsafe fn slice_unchecked(&self, range: Range<usize>) -> &'source str {
debug_assert!(
range.start <= self.len() && range.end <= self.len(),
"Reading out of bounds {:?} for {}!", range, self.len()
);
self.get_unchecked(range)
}
}
impl<'source> Source<'source> for &'source [u8] {
type Slice = &'source [u8];
fn len(&self) -> usize {
(*self).len()
}
unsafe fn read(&self, offset: usize) -> u8 {
debug_assert!(offset <= self.len(), "Reading out founds!");
match self.as_bytes().get(offset) {
Some(byte) => *byte,
None => 0,
}
}
fn slice(&self, range: Range<usize>) -> Option<&'source [u8]> {
self.get(range)
}
unsafe fn slice_unchecked(&self, range: Range<usize>) -> &'source [u8] {
debug_assert!(
range.start <= self.len() && range.end <= self.len(),
"Reading out of bounds {:?} for {}!", range, self.len()
);
self.get_unchecked(range)
}
}
#[cfg(feature = "nul_term_source")]
impl<'source> Source<'source> for toolshed::NulTermStr<'source> {
type Slice = &'source str;
fn len(&self) -> usize {
(**self).len()
}
unsafe fn read(&self, offset: usize) -> u8 {
debug_assert!(offset <= self.len(), "Reading out founds!");
self.byte_unchecked(offset)
}
fn slice(&self, range: Range<usize>) -> Option<&'source str> {
if range.start <= self.len() && range.end <= self.len() {
Some(unsafe { self.get_unchecked(range) })
} else {
None
}
}
unsafe fn slice_unchecked(&self, range: Range<usize>) -> &'source str {
debug_assert!(
range.start <= self.len() && range.end <= self.len(),
"Reading out of bounds {:?} for {}!", range, self.len()
);
self.get_unchecked(range)
}
}