Simplify BufStream implementation and use it in write test.
This commit is contained in:
parent
d8eba51b88
commit
13dd50bf61
154
src/utils.rs
154
src/utils.rs
@ -13,10 +13,9 @@ const BUF_SIZE: usize = 512;
|
||||
pub struct BufStream<T: Read+Write+Seek> {
|
||||
inner: T,
|
||||
buf: [u8; BUF_SIZE],
|
||||
buf_offset: usize,
|
||||
buf_len: usize,
|
||||
dirty: bool,
|
||||
inner_offset: usize,
|
||||
len: usize,
|
||||
pos: usize,
|
||||
write: bool,
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> BufStream<T> {
|
||||
@ -24,106 +23,103 @@ impl<T: Read+Write+Seek> BufStream<T> {
|
||||
BufStream::<T> {
|
||||
inner,
|
||||
buf: [0; BUF_SIZE],
|
||||
buf_offset: 0,
|
||||
buf_len: 0,
|
||||
dirty: false,
|
||||
inner_offset: 0,
|
||||
pos: 0,
|
||||
len: 0,
|
||||
write: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> Read for BufStream<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut num_done = 0;
|
||||
let mut num_todo = buf.len();
|
||||
let mut eof = false;
|
||||
loop {
|
||||
let num_ready = cmp::min(num_todo, self.buf_len - self.buf_offset);
|
||||
buf[num_done..num_done+num_ready].clone_from_slice(&self.buf[self.buf_offset..self.buf_offset+num_ready]);
|
||||
self.buf_offset += num_ready;
|
||||
num_done += num_ready;
|
||||
num_todo -= num_ready;
|
||||
if eof || num_todo == 0 {
|
||||
break;
|
||||
}
|
||||
if num_todo > BUF_SIZE {
|
||||
let num_read = self.inner.read(&mut buf[num_done..])?;
|
||||
num_done += num_read;
|
||||
num_todo -= num_read;
|
||||
let num_copy = cmp::min(BUF_SIZE, num_done);
|
||||
self.buf[..num_copy].clone_from_slice(&buf[num_done - num_copy..]);
|
||||
self.buf_len = num_copy;
|
||||
self.buf_offset = num_copy;
|
||||
self.inner_offset = num_copy;
|
||||
eof = true;
|
||||
} else {
|
||||
if self.inner_offset != self.buf_offset {
|
||||
self.inner.seek(io::SeekFrom::Current((self.buf_offset - self.inner_offset) as i64))?;
|
||||
}
|
||||
self.buf_len = self.inner.read(&mut self.buf)?;
|
||||
self.buf_offset = 0;
|
||||
self.inner_offset = self.buf_len;
|
||||
eof = true;
|
||||
}
|
||||
|
||||
fn flush_buf(&mut self) -> io::Result<()> {
|
||||
if self.write {
|
||||
self.inner.write_all(&self.buf[..self.pos])?;
|
||||
self.pos = 0;
|
||||
}
|
||||
Ok(num_done)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> BufStream<T> {
|
||||
fn write_buf(&mut self) -> io::Result<()> {
|
||||
if self.dirty {
|
||||
if self.inner_offset > 0 {
|
||||
self.inner.seek(io::SeekFrom::Current(-(self.inner_offset as i64)))?;
|
||||
}
|
||||
self.inner.write(&self.buf[..self.buf_len])?;
|
||||
self.inner_offset = self.buf_len;
|
||||
self.dirty = false;
|
||||
|
||||
fn make_reader(&mut self) -> io::Result<()> {
|
||||
if self.write {
|
||||
self.flush_buf()?;
|
||||
self.write = false;
|
||||
self.len = 0;
|
||||
self.pos = 0;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn make_writter(&mut self) -> io::Result<()> {
|
||||
if !self.write {
|
||||
self.inner.seek(io::SeekFrom::Current(-(self.len as i64 - self.pos as i64)))?;
|
||||
self.write = true;
|
||||
self.len = 0;
|
||||
self.pos = 0;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> BufRead for BufStream<T> {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
self.make_reader()?;
|
||||
if self.pos >= self.len {
|
||||
self.len = self.inner.read(&mut self.buf)?;
|
||||
self.pos = 0;
|
||||
}
|
||||
Ok(&self.buf[self.pos..self.len])
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.pos = cmp::min(self.pos + amt, self.len);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> Read for BufStream<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
// Make sure we are in read mode
|
||||
self.make_reader()?;
|
||||
// Check if this read is bigger than buffer size
|
||||
if self.pos == self.len && buf.len() >= BUF_SIZE {
|
||||
return self.inner.read(buf);
|
||||
}
|
||||
let nread = {
|
||||
let mut rem = self.fill_buf()?;
|
||||
rem.read(buf)?
|
||||
};
|
||||
self.consume(nread);
|
||||
Ok(nread)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> Write for BufStream<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
let mut num_done = 0;
|
||||
let mut num_todo = buf.len();
|
||||
|
||||
loop {
|
||||
let num_ready = cmp::min(num_todo, BUF_SIZE - self.buf_offset);
|
||||
self.buf[self.buf_offset..self.buf_offset+num_ready].clone_from_slice(&buf[num_done..num_done+num_ready]);
|
||||
self.buf_offset += num_ready;
|
||||
self.buf_len = cmp::max(self.buf_len, self.buf_offset);
|
||||
self.dirty = num_ready > 0;
|
||||
num_done += num_ready;
|
||||
num_todo -= num_ready;
|
||||
if num_todo == 0 {
|
||||
break;
|
||||
// Make sure we are in write mode
|
||||
self.make_writter()?;
|
||||
if self.pos + buf.len() > BUF_SIZE {
|
||||
self.flush_buf()?;
|
||||
if buf.len() >= BUF_SIZE {
|
||||
return self.inner.write(buf);
|
||||
}
|
||||
self.write_buf()?;
|
||||
self.buf_offset = 0;
|
||||
self.buf_len = 0;
|
||||
self.inner_offset = 0;
|
||||
}
|
||||
Ok(num_done)
|
||||
let written = (&mut self.buf[self.pos..]).write(buf)?;
|
||||
self.pos += written;
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.write_buf()?;
|
||||
self.flush_buf()?;
|
||||
self.inner.flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Read+Write+Seek> Seek for BufStream<T> {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
// FIXME: reuse buffer
|
||||
self.flush_buf()?;
|
||||
let new_pos = match pos {
|
||||
io::SeekFrom::Current(x) => io::SeekFrom::Current(x - self.inner_offset as i64 + self.buf_offset as i64),
|
||||
io::SeekFrom::Current(x) => io::SeekFrom::Current(x - (self.len as i64 - self.pos as i64)),
|
||||
_ => pos,
|
||||
};
|
||||
self.buf_offset = 0;
|
||||
self.buf_len = 0;
|
||||
self.inner_offset = 0;
|
||||
self.pos = 0;
|
||||
self.len = 0;
|
||||
self.inner.seek(new_pos)
|
||||
}
|
||||
}
|
||||
|
@ -16,8 +16,6 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str) {
|
||||
let file = fs::File::open(filename).unwrap();
|
||||
let mut buf_file = BufStream::new(file);
|
||||
let fs = FileSystem::new(&mut buf_file).unwrap();
|
||||
// let mut file = fs::File::open(filename).unwrap();
|
||||
// let fs = FileSystem::new(&mut file).unwrap();
|
||||
f(fs);
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@ use std::io;
|
||||
use std::str;
|
||||
|
||||
use fatfs::FileSystem;
|
||||
// use fatfs::BufStream;
|
||||
use fatfs::BufStream;
|
||||
|
||||
const FAT12_IMG: &str = "fat12.img";
|
||||
const FAT16_IMG: &str = "fat16.img";
|
||||
@ -21,12 +21,9 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str, test_seq: u32) {
|
||||
fs::create_dir(TMP_DIR).ok();
|
||||
fs::copy(&img_path, &tmp_path).unwrap();
|
||||
{
|
||||
// TODO: fix BufStream
|
||||
// let file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap();
|
||||
// let mut buf_file = BufStream::new(file);
|
||||
// let fs = FileSystem::new(&mut buf_file).unwrap();
|
||||
let mut file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap();
|
||||
let fs = FileSystem::new(&mut file).unwrap();
|
||||
let file = fs::OpenOptions::new().read(true).write(true).open(&tmp_path).unwrap();
|
||||
let mut buf_file = BufStream::new(file);
|
||||
let fs = FileSystem::new(&mut buf_file).unwrap();
|
||||
f(fs);
|
||||
}
|
||||
fs::remove_file(tmp_path).unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user