use core::iter::Peekable;
pub(crate) fn merge<'t>(parent: &'t str, first: &str, second: &str) -> Option<&'t str> {
let st = first.as_ptr() as usize;
if st as usize + first.len() == second.as_ptr() as usize {
let start = st.checked_sub(parent.as_ptr() as usize)?;
let end = start + first.len() + second.len();
if end > parent.len() {
return None;
}
Some(unsafe {
&parent.get_unchecked(start..end)
})
} else {
None
}
}
pub trait Merge<'t>: Iterator<Item = &'t str> + Sized {
fn merge_all(mut self, parent: &'t str) -> Option<&'t str>{
let first = self.next();
self.fold(first, |x, y| merge(parent, x?, y))
}
fn merge_by<F: FnMut(&str, &str) -> bool>(self, parent: &'t str, f: F) -> MergeIter<'t, Self, F>{
MergeIter { parent, iter: self.peekable(), predicate: f }
}
}
impl<'t, T> Merge<'t> for T where T: Iterator<Item = &'t str> {}
pub struct MergeIter<'t, T: Iterator<Item = &'t str>, F: FnMut(&str, &str) -> bool>{
parent: &'t str,
iter: Peekable<T>,
predicate: F,
}
impl<'t, T, F> Iterator for MergeIter<'t, T, F>
where T: Iterator<Item = &'t str>, F: FnMut(&str, &str) -> bool{
type Item = &'t str;
fn next(&mut self) -> Option<Self::Item> {
let mut curr = self.iter.next()?;
let mut last = curr;
while let Some(next) = self.iter.peek() {
if let Some(merged) = merge(self.parent, curr, next) {
if (self.predicate)(last, next) {
curr = merged;
last = next;
self.iter.next();
}
} else {
break;
}
}
Some(curr)
}
}