use std::fmt;
use std::ops::{Range, RangeFrom, RangeTo};
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct IndexStr<'a> {
idx: usize,
string: &'a [u8],
}
#[allow(dead_code)]
impl<'a> IndexStr<'a> {
#[inline]
pub fn new(string: &'a [u8]) -> IndexStr<'a> {
IndexStr {
idx: 0,
string: string,
}
}
#[inline]
pub fn len(&self) -> usize {
self.string.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.string.is_empty()
}
#[inline]
pub fn index(&self) -> usize {
self.idx
}
#[inline]
pub fn peek(&self) -> Option<u8> {
self.as_ref().get(0).cloned()
}
#[inline]
pub fn split_at(&self, idx: usize) -> (IndexStr<'a>, IndexStr<'a>) {
(self.range_to(..idx), self.range_from(idx..))
}
#[inline]
pub fn try_split_at(&self, idx: usize) -> Option<(IndexStr<'a>, IndexStr<'a>)> {
if idx > self.len() {
None
} else {
Some(self.split_at(idx))
}
}
}
#[allow(dead_code)]
impl<'a> IndexStr<'a> {
#[inline]
pub fn range(&self, idx: Range<usize>) -> IndexStr<'a> {
IndexStr {
idx: self.idx + idx.start,
string: &self.string[idx],
}
}
#[inline]
pub fn range_from(&self, idx: RangeFrom<usize>) -> IndexStr<'a> {
IndexStr {
idx: self.idx + idx.start,
string: &self.string[idx],
}
}
#[inline]
pub fn range_to(&self, idx: RangeTo<usize>) -> IndexStr<'a> {
IndexStr {
idx: self.idx,
string: &self.string[idx],
}
}
}
impl<'a> AsRef<[u8]> for IndexStr<'a> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.string
}
}
impl<'a> From<&'a [u8]> for IndexStr<'a> {
fn from(s: &[u8]) -> IndexStr {
IndexStr::new(s)
}
}
impl<'a> Into<&'a [u8]> for IndexStr<'a> {
fn into(self) -> &'a [u8] {
self.string
}
}
impl<'a, 'b> PartialEq<&'a [u8]> for IndexStr<'b> {
fn eq(&self, rhs: &&[u8]) -> bool {
self.string == *rhs
}
}
impl<'a> fmt::Debug for IndexStr<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"IndexStr {{ idx: {}, string: \"{}\" }}",
self.idx,
String::from_utf8_lossy(self.as_ref()))
}
}