use std::borrow::Cow;
use std::iter::{Cloned, IntoIterator, ExactSizeIterator};
use std::slice;
use std::vec;
use hyphenator::*;
use extended::*;
#[derive(Clone, Debug)]
pub struct Hyphenating<'m, I> {
inner : I,
mark : &'m str
}
impl<'m, I, S> Hyphenating<'m, I>
where I : Iterator<Item = S>
, S : AsRef<str>
{
pub fn segments(self) -> I {
self.inner
}
pub fn mark_with(&mut self, mark : &'m str) {
self.mark = mark;
}
pub fn new(iter : I) -> Self { Hyphenating { inner : iter, mark : "-" } }
}
impl<'m, I, S> Iterator for Hyphenating<'m, I>
where I : Iterator<Item = S> + ExactSizeIterator
, S : AsRef<str>
{
type Item = String;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next().map(|segment|
if self.inner.len() > 0 {
[segment.as_ref(), self.mark].concat()
} else { segment.as_ref().to_owned() }
)
}
fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
}
impl<'m, I, S> ExactSizeIterator for Hyphenating<'m, I>
where I : Iterator<Item = S> + ExactSizeIterator
, S : AsRef<str> {}
pub trait Iter<'t> {
type Iter;
fn iter(&'t self) -> Hyphenating<'t, Self::Iter>;
}
impl<'t> Iter<'t> for Word<'t, usize> {
type Iter = Segments<'t, Cloned<slice::Iter<'t, usize>>>;
fn iter(&'t self) -> Hyphenating<'t, Self::Iter> {
Hyphenating::new(Segments::new(self.text, self.breaks.iter().cloned()))
}
}
impl<'t> IntoIterator for Word<'t, usize> {
type Item = String;
type IntoIter = Hyphenating<'t, Segments<'t, vec::IntoIter<usize>>>;
fn into_iter(self) -> Self::IntoIter {
Hyphenating::new(Segments::new(self.text, self.breaks.into_iter()))
}
}
impl<'t> IntoIterator for Word<'t, (usize, Option<&'t Subregion>)> {
type Item = String;
type IntoIter = Hyphenating<'t,
SegmentsExt<'t, vec::IntoIter<(usize, Option<&'t Subregion>)>>
>;
fn into_iter(self) -> Self::IntoIter {
Hyphenating::new(SegmentsExt::new(self.text, self.breaks.into_iter()))
}
}
#[derive(Clone, Debug)]
pub struct Segments<'t, I> {
text : &'t str,
breaks : I,
start : Option<usize>
}
impl<'t, I> Segments<'t, I> {
pub fn new(text : &'t str, breaks : I) -> Self {
Segments {
text,
breaks,
start : Some(0)
}
}
}
impl<'t, I> Iterator for Segments<'t, I> where I : Iterator<Item = usize> {
type Item = &'t str;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self.breaks.next() {
None => self.start.take().map(|i| &self.text[i ..]),
Some(index) => {
let (start, end) = (self.start.unwrap(), index);
let segment = &self.text[start .. end];
self.start = Some(end);
Some(segment)
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, upper) = self.breaks.size_hint();
let stagger = self.start.iter().len();
(lower + stagger, upper.map(|n| n + stagger))
}
}
impl<'t, I> ExactSizeIterator for Segments<'t, I>
where I : Iterator<Item = usize> + ExactSizeIterator {}
#[derive(Clone, Debug)]
pub struct SegmentsExt<'t, I> {
text : &'t str,
breaks : I,
start : Option<usize>,
queued : Option<(usize, &'t str)>
}
impl<'t, I> SegmentsExt<'t, I> {
pub fn new(text : &'t str, breaks : I) -> Self {
SegmentsExt {
text,
breaks,
start : Some(0),
queued : None
}
}
fn substitute(&mut self, text : &'t str) -> Cow<'t, str> {
match self.queued.take() {
None => Cow::Borrowed(text),
Some((skip, ref subst)) => Cow::Owned([subst, &text[skip ..]].concat())
}
}
}
impl<'t, I> Iterator for SegmentsExt<'t, I>
where I : Iterator<Item = (usize, Option<&'t Subregion>)> {
type Item = Cow<'t, str>;
fn next(&mut self) -> Option<Self::Item> {
match self.breaks.next() {
None => self.start.take().map(|start| self.substitute(&self.text[start ..])),
Some((index, None)) => {
let start = self.start.unwrap();
self.start = Some(index);
Some(self.substitute(&self.text[start .. index]))
},
Some((index, Some(ref subr))) => {
let (start, end) = (self.start.unwrap(), index);
self.start = Some(index);
let (segment_start, fore) = self.queued.take().unwrap_or((start, ""));
let (segment_end, aft) = {
let (subst, queued) = subr.substitution.split_at(subr.breakpoint);
if queued.len() > 0 {
self.queued = Some((subr.right, queued));
}
(end - subr.left, subst)
};
let segment = [fore, &self.text[segment_start .. segment_end], aft].concat();
Some(Cow::Owned(segment))
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, upper) = self.breaks.size_hint();
let stagger = self.start.iter().len();
(lower + stagger, upper.map(|n| n + stagger))
}
}
impl<'t, I> ExactSizeIterator for SegmentsExt<'t, I>
where I : Iterator<Item = (usize, Option<&'t Subregion>)>
+ ExactSizeIterator {}