76 lines
2 KiB
Rust
76 lines
2 KiB
Rust
// https://doc.rust-lang.org/src/std/io/buffered/bufreader.rs.html
|
|
|
|
use crate::unsafe_std::bufread::UnsafeBufRead;
|
|
use std::io::Read;
|
|
|
|
pub struct UnsafeBufReader<R> {
|
|
inner: R,
|
|
buf: Box<[u8]>,
|
|
pos: usize,
|
|
cap: usize,
|
|
}
|
|
|
|
impl<R: Read> UnsafeBufReader<R> {
|
|
pub fn new(inner: R) -> UnsafeBufReader<R> {
|
|
UnsafeBufReader::with_capacity(8192, inner)
|
|
}
|
|
|
|
pub fn with_capacity(capacity: usize, inner: R) -> UnsafeBufReader<R> {
|
|
unsafe {
|
|
let mut buf = Box::new_uninit_slice(capacity).assume_init();
|
|
inner.initializer().initialize(&mut buf);
|
|
UnsafeBufReader { inner, buf, pos: 0, cap: 0 }
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<R> UnsafeBufReader<R> {
|
|
#[inline]
|
|
fn discard_buffer(&mut self) {
|
|
self.pos = 0;
|
|
self.cap = 0;
|
|
}
|
|
}
|
|
|
|
impl<R: Read> Read for UnsafeBufReader<R> {
|
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
|
if self.pos == self.cap && buf.len() >= self.buf.len() {
|
|
self.discard_buffer();
|
|
return self.inner.read(buf)
|
|
}
|
|
let nread = {
|
|
let mut rem = self.fill_buf()?;
|
|
rem.read(buf)?
|
|
};
|
|
self.consume(nread);
|
|
Ok(nread)
|
|
}
|
|
}
|
|
|
|
impl<R: Read> UnsafeBufRead for UnsafeBufReader<R> {
|
|
fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
|
|
if self.pos >= self.cap {
|
|
debug_assert!(self.pos == self.cap);
|
|
self.cap = self.inner.read(&mut self.buf)?;
|
|
self.pos = 0;
|
|
}
|
|
Ok(&self.buf[self.pos..self.cap])
|
|
}
|
|
|
|
fn consume(&mut self, amt: usize) {
|
|
self.pos = std::cmp::min(self.pos + amt, self.cap);
|
|
}
|
|
}
|
|
|
|
impl<R> std::fmt::Debug for UnsafeBufReader<R>
|
|
where
|
|
R: std::fmt::Debug,
|
|
{
|
|
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
fmt.debug_struct("BufReader")
|
|
.field("reader", &self.inner)
|
|
.field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
|
|
.finish()
|
|
}
|
|
}
|