Files
RedBear-OS/src/platform/rlb.rs
T
Red Bear OS 1b3e94a20d Red Bear OS relibc baseline
From release 0.1.0 pre-patched archive.
This includes all Red Bear modifications previously maintained
as patches in local/patches/relibc/.
2026-06-27 09:19:26 +03:00

107 lines
2.6 KiB
Rust

use alloc::vec::Vec;
use crate::platform::{Pal, Sys, types::*};
use crate::{
error::ResultExt,
header::unistd::{SEEK_SET, lseek},
};
/// 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,
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
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Line<'_> {
// Remove last line
if let Some(newline) = self.newline {
self.buf.drain(..=newline);
}
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..])
.map(|u| u as isize)
.or_minus_one_errno();
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 if self.buf.is_empty() {
Line::EOF
} else {
Line::Some(&self.buf)
};
}
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 off_t, SEEK_SET);
if ret != !0 {
self.read = pos;
}
ret
}
}