Add FatDir::iter() method returning dir entries iterator.
FatDir is no longer iterator. Change allows to iterate over directory and still be able to use it.
This commit is contained in:
parent
bfa4984ae3
commit
a7ca474a2f
@ -32,7 +32,7 @@ fn main() {
|
|||||||
Some(ref path) if path == "." => root_dir,
|
Some(ref path) if path == "." => root_dir,
|
||||||
Some(ref path) => root_dir.open_dir(&path).unwrap(),
|
Some(ref path) => root_dir.open_dir(&path).unwrap(),
|
||||||
};
|
};
|
||||||
for r in dir {
|
for r in dir.iter() {
|
||||||
let e = r.unwrap();
|
let e = r.unwrap();
|
||||||
let modified = e.modified().format("%Y-%m-%d %H:%M:%S").to_string();
|
let modified = e.modified().format("%Y-%m-%d %H:%M:%S").to_string();
|
||||||
println!("{:4} {} {}", format_file_size(e.len()), modified, e.file_name());
|
println!("{:4} {} {}", format_file_size(e.len()), modified, e.file_name());
|
||||||
|
90
src/dir.rs
90
src/dir.rs
@ -9,6 +9,7 @@ use chrono::{DateTime, Date, TimeZone, Local};
|
|||||||
use fs::{FatFileSystemRef, FatSlice};
|
use fs::{FatFileSystemRef, FatSlice};
|
||||||
use file::FatFile;
|
use file::FatFile;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub(crate) enum FatDirReader<'a, 'b: 'a> {
|
pub(crate) enum FatDirReader<'a, 'b: 'a> {
|
||||||
File(FatFile<'a, 'b>),
|
File(FatFile<'a, 'b>),
|
||||||
Root(FatSlice<'a, 'b>),
|
Root(FatSlice<'a, 'b>),
|
||||||
@ -174,6 +175,7 @@ impl <'a, 'b> fmt::Debug for FatDirEntry<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct FatDir<'a, 'b: 'a> {
|
pub struct FatDir<'a, 'b: 'a> {
|
||||||
rdr: FatDirReader<'a, 'b>,
|
rdr: FatDirReader<'a, 'b>,
|
||||||
fs: FatFileSystemRef<'a, 'b>,
|
fs: FatFileSystemRef<'a, 'b>,
|
||||||
@ -185,10 +187,56 @@ impl <'a, 'b> FatDir<'a, 'b> {
|
|||||||
FatDir { rdr, fs }
|
FatDir { rdr, fs }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rewind(&mut self) {
|
pub fn iter(&self) -> FatDirIter<'a, 'b> {
|
||||||
self.rdr.seek(SeekFrom::Start(0)).unwrap();
|
FatDirIter {
|
||||||
|
rdr: self.rdr.clone(),
|
||||||
|
fs: self.fs.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_path<'c>(path: &'c str) -> (&'c str, Option<&'c str>) {
|
||||||
|
let mut path_split = path.trim_matches('/').splitn(2, "/");
|
||||||
|
let comp = path_split.next().unwrap();
|
||||||
|
let rest_opt = path_split.next();
|
||||||
|
(comp, rest_opt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_entry(&mut self, name: &str) -> io::Result<FatDirEntry<'a, 'b>> {
|
||||||
|
for r in self.iter() {
|
||||||
|
let e = r?;
|
||||||
|
if e.file_name().eq_ignore_ascii_case(name) {
|
||||||
|
return Ok(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(io::Error::new(ErrorKind::NotFound, "file not found"))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_dir(&mut self, path: &str) -> io::Result<FatDir<'a, 'b>> {
|
||||||
|
let (name, rest_opt) = Self::split_path(path);
|
||||||
|
let e = self.find_entry(name)?;
|
||||||
|
match rest_opt {
|
||||||
|
Some(rest) => e.to_dir().open_dir(rest),
|
||||||
|
None => Ok(e.to_dir())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_file(&mut self, path: &str) -> io::Result<FatFile<'a, 'b>> {
|
||||||
|
let (name, rest_opt) = Self::split_path(path);
|
||||||
|
let e = self.find_entry(name)?;
|
||||||
|
match rest_opt {
|
||||||
|
Some(rest) => e.to_dir().open_file(rest),
|
||||||
|
None => Ok(e.to_file())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct FatDirIter<'a, 'b: 'a> {
|
||||||
|
rdr: FatDirReader<'a, 'b>,
|
||||||
|
fs: FatFileSystemRef<'a, 'b>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <'a, 'b> FatDirIter<'a, 'b> {
|
||||||
fn read_dir_entry_data(&mut self) -> io::Result<FatDirEntryData> {
|
fn read_dir_entry_data(&mut self) -> io::Result<FatDirEntryData> {
|
||||||
let mut name = [0; 11];
|
let mut name = [0; 11];
|
||||||
self.rdr.read(&mut name)?;
|
self.rdr.read(&mut name)?;
|
||||||
@ -224,45 +272,9 @@ impl <'a, 'b> FatDir<'a, 'b> {
|
|||||||
Ok(FatDirEntryData::File(data))
|
Ok(FatDirEntryData::File(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_path<'c>(path: &'c str) -> (&'c str, Option<&'c str>) {
|
|
||||||
let mut path_split = path.trim_matches('/').splitn(2, "/");
|
|
||||||
let comp = path_split.next().unwrap();
|
|
||||||
let rest_opt = path_split.next();
|
|
||||||
(comp, rest_opt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_entry(&mut self, name: &str) -> io::Result<FatDirEntry<'a, 'b>> {
|
impl <'a, 'b> Iterator for FatDirIter<'a, 'b> {
|
||||||
self.rewind();
|
|
||||||
for r in self {
|
|
||||||
let e = r?;
|
|
||||||
if e.file_name().eq_ignore_ascii_case(name) {
|
|
||||||
return Ok(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(io::Error::new(ErrorKind::NotFound, "file not found"))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open_dir(&mut self, path: &str) -> io::Result<FatDir<'a, 'b>> {
|
|
||||||
let (name, rest_opt) = Self::split_path(path);
|
|
||||||
let e = self.find_entry(name)?;
|
|
||||||
match rest_opt {
|
|
||||||
Some(rest) => e.to_dir().open_dir(rest),
|
|
||||||
None => Ok(e.to_dir())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn open_file(&mut self, path: &str) -> io::Result<FatFile<'a, 'b>> {
|
|
||||||
let (name, rest_opt) = Self::split_path(path);
|
|
||||||
let e = self.find_entry(name)?;
|
|
||||||
match rest_opt {
|
|
||||||
Some(rest) => e.to_dir().open_file(rest),
|
|
||||||
None => Ok(e.to_file())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl <'a, 'b> Iterator for FatDir<'a, 'b> {
|
|
||||||
type Item = io::Result<FatDirEntry<'a, 'b>>;
|
type Item = io::Result<FatDirEntry<'a, 'b>>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
@ -5,7 +5,7 @@ use std::io;
|
|||||||
|
|
||||||
use fs::FatFileSystemRef;
|
use fs::FatFileSystemRef;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct FatFile<'a, 'b: 'a> {
|
pub struct FatFile<'a, 'b: 'a> {
|
||||||
first_cluster: u32,
|
first_cluster: u32,
|
||||||
size: Option<u32>,
|
size: Option<u32>,
|
||||||
|
@ -226,6 +226,7 @@ impl <'a> FatFileSystem<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub(crate) struct FatSlice<'a, 'b: 'a> {
|
pub(crate) struct FatSlice<'a, 'b: 'a> {
|
||||||
begin: u64,
|
begin: u64,
|
||||||
size: u64,
|
size: u64,
|
||||||
|
@ -21,14 +21,14 @@ fn call_with_fs(f: &Fn(FatFileSystem) -> (), filename: &str) {
|
|||||||
|
|
||||||
fn test_root_dir(fs: FatFileSystem) {
|
fn test_root_dir(fs: FatFileSystem) {
|
||||||
let root_dir = fs.root_dir();
|
let root_dir = fs.root_dir();
|
||||||
let entries = root_dir.map(|r| r.unwrap()).collect::<Vec<FatDirEntry>>();
|
let entries = root_dir.iter().map(|r| r.unwrap()).collect::<Vec<FatDirEntry>>();
|
||||||
let short_names = entries.iter().map(|e| e.short_file_name()).collect::<Vec<String>>();
|
let short_names = entries.iter().map(|e| e.short_file_name()).collect::<Vec<String>>();
|
||||||
assert_eq!(short_names, ["LONG.TXT", "SHORT.TXT", "VERY", "VERY-L~1"]);
|
assert_eq!(short_names, ["LONG.TXT", "SHORT.TXT", "VERY", "VERY-L~1"]);
|
||||||
let names = entries.iter().map(|e| e.file_name()).collect::<Vec<String>>();
|
let names = entries.iter().map(|e| e.file_name()).collect::<Vec<String>>();
|
||||||
assert_eq!(names, ["long.txt", "short.txt", "very", "very-long-dir-name"]);
|
assert_eq!(names, ["long.txt", "short.txt", "very", "very-long-dir-name"]);
|
||||||
// Try read again
|
// Try read again
|
||||||
//let names2 = root_dir.map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
let names2 = root_dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||||
//assert_eq!(names2, names);
|
assert_eq!(names2, names);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -106,7 +106,7 @@ fn test_read_long_file_fat32() {
|
|||||||
fn test_get_dir_by_path(fs: FatFileSystem) {
|
fn test_get_dir_by_path(fs: FatFileSystem) {
|
||||||
let mut root_dir = fs.root_dir();
|
let mut root_dir = fs.root_dir();
|
||||||
let dir = root_dir.open_dir("very/long/path/").unwrap();
|
let dir = root_dir.open_dir("very/long/path/").unwrap();
|
||||||
let names = dir.map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
let names = dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||||
assert_eq!(names, [".", "..", "test.txt"]);
|
assert_eq!(names, [".", "..", "test.txt"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user