use core::ops::{
Range,
RangeInclusive,
RangeFrom,
RangeTo,
RangeToInclusive,
RangeFull
};
use crate::StringIterable;
pub trait StringIndex {
fn start(&self) -> usize;
fn len(&self) -> Option<usize>;
}
impl StringIndex for usize {
fn start(&self) -> usize {
*self
}
fn len(&self) -> Option<usize> {
Some(1)
}
}
impl StringIndex for Range<usize> {
fn start(&self) -> usize {
self.start
}
fn len(&self) -> Option<usize> {
Some(self.end - self.start)
}
}
impl StringIndex for RangeInclusive<usize> {
fn start(&self) -> usize {
*self.start()
}
fn len(&self) -> Option<usize> {
Some(self.end() - self.start() + 1)
}
}
impl StringIndex for RangeFrom<usize> {
fn start(&self) -> usize {
self.start
}
fn len(&self) -> Option<usize> {
None
}
}
impl StringIndex for RangeTo<usize> {
fn start(&self) -> usize {
0
}
fn len(&self) -> Option<usize> {
Some(self.end)
}
}
impl StringIndex for RangeToInclusive<usize> {
fn start(&self) -> usize {
0
}
fn len(&self) -> Option<usize> {
Some(self.end + 1)
}
}
impl StringIndex for RangeFull {
fn start(&self) -> usize {
0
}
fn len(&self) -> Option<usize> {
None
}
}
pub trait StringExt {
fn try_substr<'t>(&'t self, idx: impl StringIndex) -> Result<&'t str, &'t str>;
fn substr<'t>(&'t self, idx: impl StringIndex) -> &'t str{
match self.try_substr(idx) {
Ok(s) => s,
Err(s) => s,
}
}
fn try_substr_back<'t>(&'t self, idx: impl StringIndex) -> Result<&'t str, &'t str>;
fn substr_back<'t>(&'t self, idx: impl StringIndex) -> &'t str{
match self.try_substr_back(idx) {
Ok(s) => s,
Err(s) => s,
}
}
fn merge<'t>(&'t self, first: &str, second: &str) -> Option<&'t str>;
}
impl<T> StringExt for T where T: AsRef<str> {
fn try_substr<'t>(&'t self, idx: impl StringIndex) -> Result<&'t str, &'t str> {
let mut iter = self.str_iter();
iter.skip_front(idx.start());
match idx.len() {
Some(n) => iter.peekn(n),
None => Ok(iter.as_str()),
}
}
fn try_substr_back<'t>(&'t self, idx: impl StringIndex) -> Result<&'t str, &'t str> {
let mut iter = self.str_iter();
iter.skip_back(idx.start());
match idx.len() {
Some(n) => iter.peekn_back(n),
None => Ok(iter.as_str()),
}
}
fn merge<'t>(&'t self, first: &str, second: &str) -> Option<&'t str> {
crate::merge::merge(self.as_ref(), first, second)
}
}