1use alloc::vec::Vec;
2
3use crate::platform::{Pal, Sys, types::*};
4
5use crate::{
6 error::ResultExt,
7 header::unistd::{SEEK_SET, lseek},
8};
9#[derive(Clone)]
11pub struct RawLineBuffer {
12 pub fd: c_int,
13 buf: Vec<u8>,
14 newline: Option<usize>,
15 read: usize,
16}
17
18#[derive(PartialEq)]
19pub enum Line<'a> {
20 Error,
21 EOF,
22 Some(&'a [u8]),
23}
24
25impl RawLineBuffer {
26 pub const fn new(fd: c_int) -> Self {
27 Self {
28 fd,
29 buf: Vec::new(),
30 newline: None,
31 read: 0,
32 }
33 }
34
35 #[allow(clippy::should_implement_trait)]
38 pub fn next(&mut self) -> Line<'_> {
39 if let Some(newline) = self.newline {
41 self.buf.drain(..=newline);
42 }
43
44 loop {
45 self.newline = self.buf.iter().position(|b| *b == b'\n');
47
48 if self.newline.is_some() {
49 break;
50 }
51
52 let len = self.buf.len();
53
54 if len >= self.buf.capacity() {
55 self.buf.reserve(1024);
56 }
57
58 unsafe {
60 let capacity = self.buf.capacity();
61 self.buf.set_len(capacity);
62 }
63
64 let read = Sys::read(self.fd, &mut self.buf[len..])
65 .map(|u| u as isize)
66 .or_minus_one_errno();
67
68 let read_usize = read.max(0) as usize;
69
70 unsafe {
72 self.buf.set_len(len + read_usize);
73 }
74
75 self.read += read_usize;
76
77 if read == 0 {
78 return if self.buf.is_empty() {
79 Line::EOF
80 } else {
81 Line::Some(&self.buf)
82 };
83 }
84 if read < 0 {
85 return Line::Error;
86 }
87 }
88
89 let newline = self.newline.unwrap(); Line::Some(&self.buf[..newline])
91 }
92
93 pub fn line_pos(&self) -> usize {
95 self.read - self.buf.len()
96 }
97
98 pub fn seek(&mut self, pos: usize) -> off_t {
100 let ret = lseek(self.fd, pos as off_t, SEEK_SET);
101 if ret != !0 {
102 self.read = pos;
103 }
104 ret
105 }
106}