forked from M-Labs/rust-fatfs
Move BufStream to fscommon crate (BREAKING CHANGE)
BufStream is universal and can be used with any filesystem so its place is in different crate. Also moved Partition struct from examples to fscommon::StreamSlice struct (please note constructor arguments has changed).
This commit is contained in:
parent
5f7fb04084
commit
892c3974d3
@ -34,3 +34,4 @@ core_io = { version = "0.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.5"
|
||||
fscommon = "0.1"
|
||||
|
@ -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")?;
|
||||
|
@ -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;
|
||||
|
@ -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<T> ReadWriteSeek for T where T: Read + Write + Seek {}
|
||||
|
||||
// File wrapper for accessing part of file
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct Partition<T: ReadWriteSeek> {
|
||||
inner: T,
|
||||
start_offset: u64,
|
||||
current_offset: u64,
|
||||
size: u64,
|
||||
}
|
||||
|
||||
impl <T: ReadWriteSeek> Partition<T> {
|
||||
pub(crate) fn new(mut inner: T, start_offset: u64, size: u64) -> io::Result<Self> {
|
||||
inner.seek(SeekFrom::Start(start_offset))?;
|
||||
Ok(Self {
|
||||
start_offset, size, inner,
|
||||
current_offset: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl <T: ReadWriteSeek> Read for Partition<T> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
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 <T: ReadWriteSeek> Write for Partition<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
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 <T: ReadWriteSeek> Seek for Partition<T> {
|
||||
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
|
||||
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::<fs::File>::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
|
||||
|
@ -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") {
|
||||
|
@ -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::*;
|
||||
|
131
src/utils.rs
131
src/utils.rs
@ -1,131 +0,0 @@
|
||||
use io::prelude::*;
|
||||
use io;
|
||||
use core::cmp;
|
||||
|
||||
const BUF_SIZE: usize = 512;
|
||||
|
||||
pub struct BufStream<T: Read+Write+Seek> {
|
||||
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<T: Read+Write+Seek> BufStream<T> {
|
||||
/// Creates new BufStream object for given stream.
|
||||
pub fn new(inner: T) -> Self {
|
||||
BufStream::<T> {
|
||||
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<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> {
|
||||
// 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<T: Read+Write+Seek> Seek for BufStream<T> {
|
||||
fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
|
||||
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<T: Read+Write+Seek> Drop for BufStream<T> {
|
||||
fn drop(&mut self) {
|
||||
if let Err(err) = self.flush() {
|
||||
error!("flush failed {}", err);
|
||||
}
|
||||
}
|
||||
}
|
@ -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";
|
||||
|
@ -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";
|
||||
|
Loading…
Reference in New Issue
Block a user