use crate::UnicodeWidth;
use crate::WidthIterator;
use std::borrow::Cow;
#[derive(Debug)]
pub struct LineIterator<'a, 'b> {
uw: &'a UnicodeWidth,
input: &'b str,
max_width: usize,
}
impl<'a, 'b> LineIterator<'a, 'b> {
pub(crate) fn new(uw: &'a UnicodeWidth, input: &'b str, max_width: usize) -> Self {
Self {
uw,
input,
max_width,
}
}
}
impl<'a, 'b> Iterator for LineIterator<'a, 'b> {
type Item = Cow<'b, str>;
fn next(&mut self) -> Option<Self::Item> {
if self.input.is_empty() {
return None;
}
let mut iter = WidthIterator::new(self.uw, self.input);
iter.set_max_width(self.max_width);
iter.set_include_at_least_one(true);
iter.consume_all();
let end_index = iter.input_end_index.unwrap();
self.input = &self.input[end_index..];
Some(iter.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_tabs() {
let uw = UnicodeWidth::new();
let input = "hello world rust";
let mut iter = LineIterator::new(&uw, input, 5);
assert_eq!(iter.next(), Some(Cow::Borrowed("hello")));
assert_eq!(iter.next(), Some(Cow::Borrowed(" worl")));
assert_eq!(iter.next(), Some(Cow::Borrowed("d rus")));
assert_eq!(iter.next(), Some(Cow::Borrowed("t")));
assert_eq!(iter.next(), None);
}
#[test]
fn expand_tabs() {
let mut uw = UnicodeWidth::new();
uw.set_tab_size(4);
uw.set_expand_tab(true);
let input = "A\tB\tCD";
let mut iter = LineIterator::new(&uw, input, 5);
assert_eq!(iter.next(), Some(Cow::Owned("A B".to_string())));
assert_eq!(iter.next(), Some(Cow::Owned(" C".to_string())));
assert_eq!(iter.next(), Some(Cow::Borrowed("D")));
assert_eq!(iter.next(), None);
}
#[test]
fn cjk_boundary() {
let uw = UnicodeWidth::new();
let mut iter = LineIterator::new(&uw, "Aあ", 2);
assert_eq!(iter.next(), Some(Cow::Borrowed("A")));
assert_eq!(iter.next(), Some(Cow::Borrowed("あ")));
assert_eq!(iter.next(), None);
}
#[test]
fn at_least_one() {
let uw = UnicodeWidth::new();
let mut iter = LineIterator::new(&uw, "あA", 1);
assert_eq!(iter.next(), Some(Cow::Borrowed("あ")));
assert_eq!(iter.next(), Some(Cow::Borrowed("A")));
assert_eq!(iter.next(), None);
}
}