use {
alloc::string::String,
core::ops::{Deref, Range},
};
#[derive(Debug)]
pub struct SubStr<'a> {
target: &'a str,
start: usize,
end: usize,
inner: &'a str,
inner_start: usize,
inner_end: usize,
}
impl<'a> SubStr<'a> {
pub fn start(&self) -> usize {
self.start
}
pub fn end(&self) -> usize {
self.end
}
pub fn range(&self) -> Range<usize> {
self.start..self.end
}
pub fn inner(&self) -> &'a str {
self.inner
}
pub fn inner_start(&self) -> usize {
self.inner_start
}
pub fn inner_end(&self) -> usize {
self.inner_end
}
pub fn inner_range(&self) -> Range<usize> {
self.inner_start..self.inner_end
}
}
impl Deref for SubStr<'_> {
type Target = str;
fn deref(&self) -> &Self::Target {
self.target
}
}
impl PartialEq<str> for SubStr<'_> {
fn eq(&self, other: &str) -> bool {
self.target == other
}
}
impl PartialEq<SubStr<'_>> for &str {
fn eq(&self, other: &SubStr) -> bool {
self == &other.target
}
}
impl PartialEq<String> for SubStr<'_> {
fn eq(&self, other: &String) -> bool {
self.target == other
}
}
impl PartialEq<SubStr<'_>> for String {
fn eq(&self, other: &SubStr) -> bool {
self == other.target
}
}
#[derive(Debug)]
pub struct SubStrIter<'a, S, T> where S: AsRef<str>, T: AsRef<str> {
src: &'a str,
src_index: usize,
start: S,
end: T,
}
impl<'a, S, T> SubStrIter<'a, S, T> where S: AsRef<str>, T: AsRef<str> {
fn new(source: &'a str, start: S, end: T) -> Self {
Self {
src: source,
src_index: 0,
start,
end,
}
}
}
impl<'a, S, T> Iterator for SubStrIter<'a, S, T> where S: AsRef<str>, T: AsRef<str> {
type Item = SubStr<'a>;
fn next(&mut self) -> Option<Self::Item> {
let start = self.start.as_ref();
let start_len = start.len();
let src = &self.src[self.src_index..];
if let Some(mut start_idx) = src.find(start) {
let end = self.end.as_ref();
let delta = start_idx + start_len;
if let Some(end_idx) = src[delta..].find(end) {
if start_len > 0 && end_idx > 0 {
if let Some(next_char_bytes) = src[start_idx..].chars().next().map(|c| c.len_utf8()) {
if let Some(next_start_idx) = src[start_idx + next_char_bytes .. delta + end_idx].rfind(start) {
start_idx += next_char_bytes + next_start_idx;
}
}
}
let end_len = end.len();
let end_idx = delta + end_idx + end_len;
let sub_start = self.src_index + start_idx;
self.src_index += end_idx;
let target = &src[start_idx..end_idx];
let inner = &target[start_len .. target.len() - end_len];
return {
let start_idx = sub_start;
let end_idx = self.src_index;
let inner_start = start_idx + start.len();
let inner_end = end_idx - end.len();
Some(SubStr { target, start: start_idx, end: end_idx, inner, inner_start, inner_end })
};
}
}
None
}
}
pub fn sub_strs<'a, S, T>(source: &'a str, start: S, end: T) -> SubStrIter<'a, S, T> where S: AsRef<str>, T: AsRef<str> {
SubStrIter::new(source, start, end)
}