diff options
| author | Max Verevkin <maxxverrr@gmail.com> | 2022-04-01 21:50:19 +0300 |
|---|---|---|
| committer | Max Verevkin <maxxverrr@gmail.com> | 2022-04-01 21:50:19 +0300 |
| commit | 7bcaa341b8685ba411d206c1a89dc3ca77aa71bb (patch) | |
| tree | 917dec11c47ce71fe9486e56f94015bd12c496b7 /src/lines_buffer.rs | |
| download | i3bar-mango-7bcaa341b8685ba411d206c1a89dc3ca77aa71bb.tar.gz | |
initial commit
Diffstat (limited to 'src/lines_buffer.rs')
| -rw-r--r-- | src/lines_buffer.rs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/lines_buffer.rs b/src/lines_buffer.rs new file mode 100644 index 0000000..7813ea2 --- /dev/null +++ b/src/lines_buffer.rs @@ -0,0 +1,54 @@ +use std::borrow::Cow; +use std::io::{BufRead, BufReader, Read, Result}; + +pub struct LinesBuffer<R> { + reader: BufReader<R>, + next_line: Vec<u8>, +} + +impl<R: Read> LinesBuffer<R> { + pub fn new(inner: R) -> Self { + Self { + reader: BufReader::new(inner), + next_line: Vec::new(), + } + } + + pub fn fill_buf(&mut self) -> Result<()> { + self.reader.fill_buf()?; + Ok(()) + } + + pub fn inner(&self) -> &R { + self.reader.get_ref() + } +} + +impl<R: Read> Iterator for &mut LinesBuffer<R> { + type Item = String; + + fn next(&mut self) -> Option<Self::Item> { + let pending = self.reader.buffer(); + let (result, used) = match memchr::memchr(b'\n', pending) { + None => { + self.next_line.extend_from_slice(pending); + (None, pending.len()) + } + Some(i) => { + self.next_line.extend_from_slice(&pending[..i]); + let line = from_utf8(&self.next_line); + self.next_line.clear(); + (Some(line), i + 1) + } + }; + self.reader.consume(used); + result + } +} + +fn from_utf8(bytes: &[u8]) -> String { + match String::from_utf8_lossy(bytes) { + Cow::Borrowed(s) => s.to_owned(), + Cow::Owned(s) => s, + } +} |
