Documentation
use std::str::from_utf8_unchecked;

pub struct Line<'a> {
  pub bin: &'a [u8],
  pub pre: usize,
  pub cur: usize,
}

impl<'a> Line<'a> {
  pub fn new(str: &'a str) -> Self {
    Self {
      bin: str.as_bytes(),
      pre: 0,
      cur: 0,
    }
  }
}

impl<'a> Iterator for Line<'a> {
  type Item = &'a str;

  fn next(&mut self) -> Option<Self::Item> {
    let bin = self.bin;
    let len = bin.len();
    let mut cur = self.cur;
    while cur < len {
      self.cur += 1;
      let i = bin[cur];
      if b"\r\n".contains(&i) {
        let pre = self.pre;
        self.pre = self.cur;
        if cur != pre {
          let r = &bin[pre..cur];
          return Some(unsafe { from_utf8_unchecked(r) });
        }
      } else if b" \t".contains(&i) && self.pre + 1 == self.cur {
        self.pre += 1;
      }
      cur = self.cur;
    }
    if self.cur != self.pre {
      let r = Some(unsafe { from_utf8_unchecked(&bin[self.pre..]) });
      self.pre = self.cur;
      return r;
    }
    None
  }
}