12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- use alloc::vec::Vec;
- use platform::{Pal, Sys};
- use platform::types::*;
- use header::unistd::{lseek, SEEK_SET};
- /// Implements an `Iterator` which returns on either newline or EOF.
- #[derive(Clone)]
- pub struct RawLineBuffer {
- pub fd: c_int,
- buf: Vec<u8>,
- newline: Option<usize>,
- read: usize
- }
- #[derive(PartialEq)]
- pub enum Line<'a> {
- Error,
- EOF,
- Some(&'a [u8])
- }
- impl RawLineBuffer {
- pub const fn new(fd: c_int) -> Self {
- Self {
- fd: fd,
- buf: Vec::new(),
- newline: None,
- read: 0
- }
- }
- // Can't use iterators because we want to return a reference.
- // See https://stackoverflow.com/a/30422716/5069285
- pub fn next(&mut self) -> Line {
- // Remove last line
- if let Some(newline) = self.newline {
- self.buf.drain(..newline + 1);
- }
- loop {
- // Exit if newline was read already
- self.newline = self.buf.iter().position(|b| *b == b'\n');
- if self.newline.is_some() {
- break;
- }
- let len = self.buf.len();
- if len >= self.buf.capacity() {
- self.buf.reserve(1024);
- }
- // Create buffer of what's left in the vector, uninitialized memory
- unsafe {
- let capacity = self.buf.capacity();
- self.buf.set_len(capacity);
- }
- let read = Sys::read(self.fd, &mut self.buf[len..]);
- let read_usize = read.max(0) as usize;
- // Remove all uninitialized memory that wasn't read
- unsafe {
- self.buf.set_len(len + read_usize);
- }
- self.read += read_usize;
- if read == 0 {
- return Line::EOF;
- }
- if read < 0 {
- return Line::Error;
- }
- }
- let newline = self.newline.unwrap(); // safe because it doesn't break the loop otherwise
- Line::Some(&self.buf[..newline])
- }
- /// Return the byte position of the start of the line
- pub fn line_pos(&self) -> usize {
- self.read - self.buf.len()
- }
- /// Seek to a byte position in the file
- pub fn seek(&mut self, pos: usize) -> off_t {
- let ret = lseek(self.fd, pos as i64, SEEK_SET);
- if ret != !0 {
- self.read = pos;
- }
- ret
- }
- }
|