use core::cmp::min;
use core::ffi::c_int;
extern crate alloc;
use alloc::string::String;
use core::cmp;
use crate::{ErrorKind, OrtResult, Read, net::AsFd, ort_error};
const BUF_SIZE: usize = 8 * 1024;
pub struct OrtBufReader<R: Read> {
inner: R,
buf: [u8; BUF_SIZE],
pos: usize, cap: usize, }
impl<T: Read + AsFd> AsFd for OrtBufReader<T> {
fn as_fd(&self) -> i32 {
self.inner.as_fd()
}
}
impl<R: Read> Read for OrtBufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> OrtResult<usize> {
self.inner.read(buf)
}
}
impl<R: Read> OrtBufReader<R> {
#[inline]
pub fn new(inner: R) -> Self {
Self {
inner,
buf: [0; BUF_SIZE],
pos: 0,
cap: 0,
}
}
#[inline(always)]
fn buffer_consumed(&self) -> bool {
self.pos >= self.cap
}
#[inline]
fn fill_buf(&mut self) -> OrtResult<()> {
let n = self.inner.read(&mut self.buf)?;
self.pos = 0;
self.cap = n;
Ok(())
}
pub fn read_line(&mut self, buf: &mut String) -> OrtResult<usize> {
let mut total = 0;
loop {
if self.buffer_consumed() {
self.fill_buf()?;
if self.cap == 0 {
return Ok(total);
}
}
let available = &self.buf[self.pos..self.cap];
let mut newline_rel = None;
for (i, &b) in available.iter().enumerate() {
if b == b'\n' {
newline_rel = Some(i);
break;
}
}
let end = match newline_rel {
Some(i) => self.pos + i + 1, None => self.cap,
};
let chunk = &self.buf[self.pos..end];
let s = core::str::from_utf8(chunk)
.map_err(|_| ort_error(ErrorKind::FormatError, "utf8 decode"))?;
buf.push_str(s);
total += chunk.len();
self.pos = end;
if newline_rel.is_some() {
return Ok(total);
}
}
}
pub fn read_exact(&mut self, buf: &mut [u8]) -> OrtResult<()> {
let mut offset = 0;
let len = buf.len();
while offset < len {
if !self.buffer_consumed() {
let n = cmp::min(len - offset, self.cap - self.pos);
buf[offset..offset + n].copy_from_slice(&self.buf[self.pos..self.pos + n]);
self.pos += n;
offset += n;
continue;
}
if len - offset >= BUF_SIZE {
let n = self.inner.read(&mut buf[offset..])?;
if n == 0 {
return Err(ort_error(
ErrorKind::UnexpectedEof,
"unexpected EOF in read_exact",
));
}
offset += n;
} else {
self.fill_buf()?;
if self.cap == 0 {
return Err(ort_error(
ErrorKind::UnexpectedEof,
"unexpected EOF in read_exact",
));
}
}
}
Ok(())
}
}
pub fn fd_read_to_string(fd: c_int, buffer: &mut String) {
const READ_CHUNK: usize = 64 * 1024;
let v = unsafe { buffer.as_mut_vec() };
loop {
let len = v.len();
if v.capacity() == len {
v.reserve(READ_CHUNK);
}
let avail = v.capacity() - len;
let to_read = min(avail, READ_CHUNK);
let n = unsafe {
crate::syscall::read(
fd,
v.as_mut_ptr().add(len) as *mut _,
to_read as crate::syscall::size_t,
)
};
if n == 0 {
break; }
if n < 0 {
break;
}
unsafe {
v.set_len(len + n as usize);
}
}
if core::str::from_utf8(v.as_slice()).is_err() {
v.clear();
}
}