rust-fatfs/src/file.rs

80 lines
3.0 KiB
Rust
Raw Normal View History

2017-09-23 06:22:31 +08:00
use std::cmp;
2017-09-23 04:27:39 +08:00
use std::io::prelude::*;
use std::io::{SeekFrom, ErrorKind};
2017-09-23 04:27:39 +08:00
use std::io;
2017-09-23 05:20:06 +08:00
use fs::FatSharedStateRef;
2017-09-23 04:27:39 +08:00
2017-09-24 09:08:00 +08:00
pub struct FatFile<'a, 'b: 'a> {
first_cluster: u32,
2017-09-24 03:53:32 +08:00
size: Option<u32>,
2017-09-23 04:27:39 +08:00
offset: u32,
current_cluster: Option<u32>,
state: FatSharedStateRef<'a, 'b>,
2017-09-23 04:27:39 +08:00
}
impl <'a, 'b> FatFile<'a, 'b> {
pub(crate) fn new(first_cluster: u32, size: Option<u32>, state: FatSharedStateRef<'a, 'b>) -> Self {
2017-09-23 04:27:39 +08:00
FatFile {
first_cluster, size, state,
current_cluster: Some(first_cluster),
offset: 0,
2017-09-23 04:27:39 +08:00
}
}
}
impl <'a, 'b> Read for FatFile<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let mut buf_offset: usize = 0;
let cluster_size = self.state.borrow().get_cluster_size();
let mut state = self.state.borrow_mut();
loop {
let offset_in_cluster = self.offset % cluster_size;
let bytes_left_in_cluster = (cluster_size - offset_in_cluster) as usize;
2017-09-24 03:53:32 +08:00
let bytes_left_in_file = self.size.map(|size| (size - self.offset) as usize).unwrap_or(bytes_left_in_cluster);
let bytes_left_in_buf = buf.len() - buf_offset;
2017-09-24 03:53:32 +08:00
let read_size = cmp::min(cmp::min(bytes_left_in_buf, bytes_left_in_cluster), bytes_left_in_file);
if read_size == 0 {
break;
}
let current_cluster = self.current_cluster.unwrap();
let offset_in_fs = state.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
state.rdr.seek(SeekFrom::Start(offset_in_fs))?;
let read_bytes = state.rdr.read(&mut buf[buf_offset..buf_offset+read_size])?;
if read_bytes == 0 {
break;
}
self.offset += read_bytes as u32;
buf_offset += read_bytes;
if self.offset % cluster_size == 0 {
self.current_cluster = state.table.get_next_cluster(current_cluster);
}
}
Ok(buf_offset)
2017-09-23 04:27:39 +08:00
}
}
impl <'a, 'b> Seek for FatFile<'a, 'b> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
let new_offset = match pos {
SeekFrom::Current(x) => self.offset as i64 + x,
SeekFrom::Start(x) => x as i64,
SeekFrom::End(x) => self.size.unwrap() as i64 + x,
};
if new_offset < 0 || (self.size.is_some() && new_offset as u64 > self.size.unwrap() as u64) {
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid seek"));
}
let cluster_size = self.state.borrow().get_cluster_size();
let cluster_count = (new_offset / cluster_size as i64) as usize;
let mut new_cluster = Some(self.first_cluster);
let state = self.state.borrow_mut();
for _ in 0..cluster_count {
new_cluster = state.table.get_next_cluster(new_cluster.unwrap());
}
self.offset = new_offset as u32;
self.current_cluster = new_cluster;
Ok(self.offset as u64)
}
}