Fixed unsafe bufread (still cringe)

This commit is contained in:
famfo 2022-01-29 17:10:39 +01:00
parent 7dd830c7c8
commit 68d63901d6
3 changed files with 28 additions and 33 deletions

View file

@ -233,8 +233,6 @@ fn decoder(inputfile: &str) -> Result<(u32, u32, ColorType, ArrayVec<String, 124
let infile = File::open(inputfile)?;
let mut lines = UnsafeBufReader::new(infile).lines();
println!("{:?}", lines);
// "CIF: <flags>"
if !lines.next().transpose()?.ok_or(InvalidHeaderError)?.starts_with("CIF:") {
return Err(InvalidHeaderError)

View file

@ -17,21 +17,6 @@ impl Drop for Guard<'_> {
}
}
pub(crate) unsafe fn append_to_string_unchecked<F>(buf: &mut ArrayString<8192>, f: F) -> usize
where
F: FnOnce(&mut ArrayVec<u8, 8192>) -> usize,
{
let mut buf_vec = ArrayVec::<u8, 8192>::new();
for u in buf.as_bytes() {
buf_vec.push(*u);
}
let mut g = Guard { len: buf.len(), buf: &mut buf_vec };
let ret = f(g.buf);
//std::str::from_utf8_unchecked(&g.buf[g.len..]); // Do we need it? (https://doc.rust-lang.org/src/std/io/mod.rs.html#342-349)
g.len = g.buf.len();
ret
}
pub trait UnsafeBufRead: Read {
fn consume(&mut self, amt: usize);
fn fill_buf(&mut self) -> Result<&[u8], Error>;
@ -39,8 +24,14 @@ pub trait UnsafeBufRead: Read {
read_until(self, byte, buf)
}
fn read_line(&mut self, buf: &mut ArrayString<8192>) -> Result<usize, Error> {
unsafe { Ok(append_to_string_unchecked(buf, |b| read_until(self, b'\n', b).unwrap())) }
fn read_line(&mut self, buf: &mut ArrayString<8192>) -> usize {
let mut buf_vec = ArrayVec::<u8, 8192>::new();
for u in buf.as_bytes() {
buf_vec.push(*u);
}
let return_val = read_until(self, b'\n', &mut buf_vec).unwrap();
unsafe { buf.push_str(std::str::from_utf8_unchecked(buf_vec.as_slice())) };
return_val
}
fn lines(self) -> UnsafeLines<Self>
@ -62,17 +53,13 @@ impl<B: UnsafeBufRead> Iterator for UnsafeLines<B> {
fn next(&mut self) -> Option<Result<ArrayString<8192>, CifError>> {
let mut buf = ArrayString::<8192>::new();
match self.buf.read_line(&mut buf) {
Ok(0) => None,
Ok(_n) => {
0 => None,
_n => {
if buf.ends_with('\n') {
buf.pop();
if buf.ends_with('\r') {
buf.pop();
}
}
Some(Ok(buf))
}
Err(e) => Some(Err(CifError::IoError(e))),
}
}
}

View file

@ -1,11 +1,8 @@
// https://doc.rust-lang.org/src/std/io/buffered/bufreader.rs.html
use crate::unsafe_std::bufread::UnsafeBufRead;
use crate::CifError;
use arrayvec::{ArrayString, ArrayVec};
use std::io::{Error, Read};
use std::io::Read;
#[derive(Debug)]
pub struct UnsafeBufReader<R> {
inner: R,
buf: Box<[u8]>,
@ -15,8 +12,12 @@ pub struct UnsafeBufReader<R> {
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 = std::boxed::Box::new_uninit_slice(8192).assume_init();
let mut buf = Box::new_uninit_slice(capacity).assume_init();
inner.initializer().initialize(&mut buf);
UnsafeBufReader { inner, buf, pos: 0, cap: 0 }
}
@ -33,9 +34,6 @@ impl<R> UnsafeBufReader<R> {
impl<R: Read> Read for UnsafeBufReader<R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
// If we don't have any buffered data and we're doing a massive read
// (larger than our internal buffer), bypass our internal buffer
// entirely.
if self.pos == self.cap && buf.len() >= self.buf.len() {
self.discard_buffer();
return self.inner.read(buf)
@ -63,3 +61,15 @@ impl<R: Read> UnsafeBufRead for UnsafeBufReader<R> {
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()
}
}