2017-09-23 06:22:31 +08:00
|
|
|
use std::cmp;
|
2017-09-23 04:27:39 +08:00
|
|
|
use std::io::prelude::*;
|
2017-09-24 08:10:59 +08:00
|
|
|
use std::io::{SeekFrom, ErrorKind};
|
2017-09-23 04:27:39 +08:00
|
|
|
use std::io;
|
2017-09-23 05:20:06 +08:00
|
|
|
|
2017-10-04 19:56:44 +08:00
|
|
|
use fs::FatFileSystemRef;
|
2017-09-23 04:27:39 +08:00
|
|
|
|
2017-10-06 22:07:11 +08:00
|
|
|
#[derive(Clone)]
|
2017-09-27 20:05:58 +08:00
|
|
|
pub struct FatFile<'a, 'b: 'a> {
|
2017-10-07 08:37:29 +08:00
|
|
|
first_cluster: Option<u32>,
|
2017-09-24 03:53:32 +08:00
|
|
|
size: Option<u32>,
|
2017-09-23 04:27:39 +08:00
|
|
|
offset: u32,
|
2017-09-24 02:16:32 +08:00
|
|
|
current_cluster: Option<u32>,
|
2017-10-04 19:56:44 +08:00
|
|
|
fs: FatFileSystemRef<'a, 'b>,
|
2017-09-23 04:27:39 +08:00
|
|
|
}
|
|
|
|
|
2017-09-27 20:05:58 +08:00
|
|
|
impl <'a, 'b> FatFile<'a, 'b> {
|
2017-10-07 08:37:29 +08:00
|
|
|
pub(crate) fn new(first_cluster: Option<u32>, size: Option<u32>, fs: FatFileSystemRef<'a, 'b>) -> Self {
|
2017-09-23 04:27:39 +08:00
|
|
|
FatFile {
|
2017-10-04 19:56:44 +08:00
|
|
|
first_cluster, size, fs,
|
2017-10-07 08:37:29 +08:00
|
|
|
current_cluster: first_cluster,
|
2017-09-24 02:16:32 +08:00
|
|
|
offset: 0,
|
2017-09-23 04:27:39 +08:00
|
|
|
}
|
|
|
|
}
|
2017-09-24 01:42:09 +08:00
|
|
|
}
|
|
|
|
|
2017-09-27 20:05:58 +08:00
|
|
|
impl <'a, 'b> Read for FatFile<'a, 'b> {
|
2017-09-24 01:42:09 +08:00
|
|
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
2017-09-24 02:16:32 +08:00
|
|
|
let mut buf_offset: usize = 0;
|
2017-10-04 19:56:44 +08:00
|
|
|
let cluster_size = self.fs.get_cluster_size();
|
2017-09-24 02:16:32 +08:00
|
|
|
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);
|
2017-09-24 02:16:32 +08:00
|
|
|
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);
|
2017-10-07 08:37:29 +08:00
|
|
|
if read_size == 0 || self.current_cluster.is_none() {
|
2017-09-24 02:16:32 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
let current_cluster = self.current_cluster.unwrap();
|
2017-10-04 19:56:44 +08:00
|
|
|
let offset_in_fs = self.fs.offset_from_cluster(current_cluster) + (offset_in_cluster as u64);
|
|
|
|
let read_bytes = {
|
|
|
|
let mut rdr = self.fs.rdr.borrow_mut();
|
|
|
|
rdr.seek(SeekFrom::Start(offset_in_fs))?;
|
|
|
|
rdr.read(&mut buf[buf_offset..buf_offset+read_size])?
|
|
|
|
};
|
2017-09-24 02:16:32 +08:00
|
|
|
if read_bytes == 0 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
self.offset += read_bytes as u32;
|
|
|
|
buf_offset += read_bytes;
|
|
|
|
if self.offset % cluster_size == 0 {
|
2017-10-07 08:37:29 +08:00
|
|
|
let r = self.fs.cluster_iter(current_cluster).skip(1).next();
|
|
|
|
self.current_cluster = match r {
|
2017-10-07 08:19:19 +08:00
|
|
|
Some(Err(err)) => return Err(err),
|
2017-10-07 08:37:29 +08:00
|
|
|
Some(Ok(n)) => Some(n),
|
|
|
|
None => None,
|
|
|
|
};
|
2017-09-24 02:16:32 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(buf_offset)
|
2017-09-23 04:27:39 +08:00
|
|
|
}
|
|
|
|
}
|
2017-09-24 08:10:59 +08:00
|
|
|
|
2017-09-27 20:05:58 +08:00
|
|
|
impl <'a, 'b> Seek for FatFile<'a, 'b> {
|
2017-09-24 08:10:59 +08:00
|
|
|
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"));
|
|
|
|
}
|
2017-10-04 19:56:44 +08:00
|
|
|
let cluster_size = self.fs.get_cluster_size();
|
2017-09-24 08:10:59 +08:00
|
|
|
let cluster_count = (new_offset / cluster_size as i64) as usize;
|
2017-10-07 08:37:29 +08:00
|
|
|
let new_cluster = if cluster_count > 0 {
|
|
|
|
match self.fs.cluster_iter(self.first_cluster.unwrap()).skip(cluster_count).next() {
|
2017-10-07 08:19:19 +08:00
|
|
|
Some(Err(err)) => return Err(err),
|
2017-10-07 08:37:29 +08:00
|
|
|
Some(Ok(n)) => Some(n),
|
|
|
|
None => None,
|
2017-10-07 08:19:19 +08:00
|
|
|
}
|
2017-10-07 08:37:29 +08:00
|
|
|
} else {
|
|
|
|
self.first_cluster
|
|
|
|
};
|
2017-09-24 08:10:59 +08:00
|
|
|
self.offset = new_offset as u32;
|
|
|
|
self.current_cluster = new_cluster;
|
|
|
|
Ok(self.offset as u64)
|
|
|
|
}
|
|
|
|
}
|