diff --git a/Cargo.toml b/Cargo.toml index d1d7562..46ba8da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,4 @@ core_io = { version = "0.1", optional = true } [dev-dependencies] env_logger = "0.5" +fscommon = "0.1" diff --git a/examples/cat.rs b/examples/cat.rs index e9ea2bf..dba0411 100644 --- a/examples/cat.rs +++ b/examples/cat.rs @@ -1,10 +1,12 @@ extern crate fatfs; +extern crate fscommon; use std::env; use std::fs::File; use std::io::{self, prelude::*}; -use fatfs::{FileSystem, FsOptions, BufStream}; +use fatfs::{FileSystem, FsOptions}; +use fscommon::BufStream; fn main() -> io::Result<()> { let file = File::open("resources/fat32.img")?; diff --git a/examples/ls.rs b/examples/ls.rs index 2fdaf00..151cd4a 100644 --- a/examples/ls.rs +++ b/examples/ls.rs @@ -1,4 +1,5 @@ extern crate fatfs; +extern crate fscommon; extern crate chrono; use std::env; @@ -6,7 +7,8 @@ use std::fs::File; use std::io; use chrono::{DateTime, Local}; -use fatfs::{FileSystem, FsOptions, BufStream}; +use fatfs::{FileSystem, FsOptions}; +use fscommon::BufStream; fn format_file_size(size: u64) -> String { const KB: u64 = 1024; diff --git a/examples/partition.rs b/examples/partition.rs index b8e2ff0..19cd9be 100644 --- a/examples/partition.rs +++ b/examples/partition.rs @@ -1,69 +1,9 @@ extern crate fatfs; +extern crate fscommon; -use std::{cmp, fs, io}; -use std::io::{prelude::*, SeekFrom, ErrorKind}; -use fatfs::{FileSystem, FsOptions, BufStream}; - -trait ReadWriteSeek: Read + Write + Seek {} -impl ReadWriteSeek for T where T: Read + Write + Seek {} - -// File wrapper for accessing part of file -#[derive(Clone)] -pub(crate) struct Partition { - inner: T, - start_offset: u64, - current_offset: u64, - size: u64, -} - -impl Partition { - pub(crate) fn new(mut inner: T, start_offset: u64, size: u64) -> io::Result { - inner.seek(SeekFrom::Start(start_offset))?; - Ok(Self { - start_offset, size, inner, - current_offset: 0, - }) - } -} - -impl Read for Partition { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - let max_read_size = cmp::min((self.size - self.current_offset) as usize, buf.len()); - let bytes_read = self.inner.read(&mut buf[..max_read_size])?; - self.current_offset += bytes_read as u64; - Ok(bytes_read) - } -} - -impl Write for Partition { - fn write(&mut self, buf: &[u8]) -> io::Result { - let max_write_size = cmp::min((self.size - self.current_offset) as usize, buf.len()); - let bytes_written = self.inner.write(&buf[..max_write_size])?; - self.current_offset += bytes_written as u64; - Ok(bytes_written) - } - - fn flush(&mut self) -> io::Result<()> { - self.inner.flush() - } -} - -impl Seek for Partition { - fn seek(&mut self, pos: SeekFrom) -> io::Result { - let new_offset = match pos { - SeekFrom::Current(x) => self.current_offset as i64 + x, - SeekFrom::Start(x) => x as i64, - SeekFrom::End(x) => self.size as i64 + x, - }; - if new_offset < 0 || new_offset as u64 > self.size { - Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek")) - } else { - self.inner.seek(SeekFrom::Start(self.start_offset + new_offset as u64))?; - self.current_offset = new_offset as u64; - Ok(self.current_offset) - } - } -} +use std::{fs, io}; +use fatfs::{FileSystem, FsOptions}; +use fscommon::{BufStream, StreamSlice}; fn main() -> io::Result<()> { // Open disk image @@ -72,7 +12,7 @@ fn main() -> io::Result<()> { let first_lba = 0; let last_lba = 10000; // Create partition using provided start address and size in bytes - let partition = Partition::::new(file, first_lba, last_lba - first_lba + 1)?; + let partition = StreamSlice::new(file, first_lba, last_lba + 1)?; // Create buffered stream to optimize file access let buf_rdr = BufStream::new(partition); // Finally initialize filesystem struct using provided partition diff --git a/examples/write.rs b/examples/write.rs index ee23cff..a9c9920 100644 --- a/examples/write.rs +++ b/examples/write.rs @@ -1,9 +1,11 @@ extern crate fatfs; +extern crate fscommon; use std::fs::OpenOptions; use std::io::{self, prelude::*}; -use fatfs::{FileSystem, FsOptions, BufStream}; +use fatfs::{FileSystem, FsOptions}; +use fscommon::BufStream; fn main() -> io::Result<()> { let img_file = match OpenOptions::new().read(true).write(true).open("fat.img") { diff --git a/src/lib.rs b/src/lib.rs index 0cb032f..c0c6137 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,9 +30,6 @@ mod dir_entry; mod file; mod table; -#[cfg(all(feature = "alloc"))] -mod utils; - #[cfg(not(feature = "std"))] mod byteorder_core_io; @@ -52,6 +49,3 @@ pub use fs::*; pub use dir::*; pub use dir_entry::*; pub use file::*; - -#[cfg(all(feature = "alloc"))] -pub use utils::*; diff --git a/src/utils.rs b/src/utils.rs deleted file mode 100644 index 0df2ca1..0000000 --- a/src/utils.rs +++ /dev/null @@ -1,131 +0,0 @@ -use io::prelude::*; -use io; -use core::cmp; - -const BUF_SIZE: usize = 512; - -pub struct BufStream { - inner: T, - buf: [u8; BUF_SIZE], - len: usize, - pos: usize, - write: bool, -} - -/// The BufStream struct adds buffering to underlying file or device. -/// -/// It's basically composition of BufReader and BufWritter. -impl BufStream { - /// Creates new BufStream object for given stream. - pub fn new(inner: T) -> Self { - BufStream:: { - inner, - buf: [0; BUF_SIZE], - pos: 0, - len: 0, - write: false, - } - } - - fn flush_buf(&mut self) -> io::Result<()> { - if self.write { - self.inner.write_all(&self.buf[..self.pos])?; - self.pos = 0; - } - Ok(()) - } - - 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 BufRead for BufStream { - 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 Read for BufStream { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - // 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 Write for BufStream { - fn write(&mut self, buf: &[u8]) -> io::Result { - // 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); - } - } - let written = (&mut self.buf[self.pos..]).write(buf)?; - self.pos += written; - Ok(written) - } - - fn flush(&mut self) -> io::Result<()> { - self.flush_buf()?; - self.inner.flush() - } -} - -impl Seek for BufStream { - fn seek(&mut self, pos: io::SeekFrom) -> io::Result { - self.flush_buf()?; - let new_pos = match pos { - io::SeekFrom::Current(x) => io::SeekFrom::Current(x - (self.len as i64 - self.pos as i64)), - _ => pos, - }; - self.pos = 0; - self.len = 0; - self.inner.seek(new_pos) - } -} - -impl Drop for BufStream { - fn drop(&mut self) { - if let Err(err) = self.flush() { - error!("flush failed {}", err); - } - } -} diff --git a/tests/read.rs b/tests/read.rs index 2c37257..d29b7c8 100644 --- a/tests/read.rs +++ b/tests/read.rs @@ -1,4 +1,5 @@ extern crate fatfs; +extern crate fscommon; extern crate env_logger; use std::fs; @@ -6,7 +7,8 @@ use std::io::SeekFrom; use std::io::prelude::*; use std::str; -use fatfs::{FsOptions, FatType, BufStream}; +use fatfs::{FsOptions, FatType}; +use fscommon::BufStream; const TEST_TEXT: &str = "Rust is cool!\n"; const FAT12_IMG: &str = "resources/fat12.img"; diff --git a/tests/write.rs b/tests/write.rs index 0ec0651..f9a6ad4 100644 --- a/tests/write.rs +++ b/tests/write.rs @@ -1,4 +1,5 @@ extern crate fatfs; +extern crate fscommon; extern crate env_logger; use std::fs; @@ -6,7 +7,8 @@ use std::io::prelude::*; use std::io; use std::str; -use fatfs::{FsOptions, BufStream}; +use fatfs::FsOptions; +use fscommon::BufStream; const FAT12_IMG: &str = "fat12.img"; const FAT16_IMG: &str = "fat16.img";