forked from M-Labs/rust-fatfs
Take immutable self reference in Dir methods
Dir methods do not change Dir object itself. They usually clone inner stream so no change really happens self struct. Underlying partition is modified but it does not have to affect API. For example see std::fs::File::set_len. This change greatly simplifies rename API usage.
This commit is contained in:
parent
4f6ed94cb3
commit
2304b13ec4
@ -35,7 +35,7 @@ You can start using library now:
|
||||
let img_file = File::open("fat.img")?;
|
||||
let mut buf_stream = fatfs::BufStream::new(img_file);
|
||||
let fs = fatfs::FileSystem::new(&mut buf_stream, fatfs::FsOptions::new())?;
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut file = root_dir.create_file("hello.txt")?;
|
||||
file.write_all(b"Hello World!")?;
|
||||
|
||||
|
@ -10,7 +10,7 @@ fn main() -> io::Result<()> {
|
||||
let file = File::open("resources/fat32.img")?;
|
||||
let mut buf_rdr = BufStream::new(file);
|
||||
let fs = FileSystem::new(&mut buf_rdr, FsOptions::new())?;
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut file = root_dir.open_file(&env::args().nth(1).unwrap())?;
|
||||
let mut buf = vec![];
|
||||
file.read_to_end(&mut buf)?;
|
||||
|
@ -27,7 +27,7 @@ fn main() -> io::Result<()> {
|
||||
let file = File::open("resources/fat32.img")?;
|
||||
let mut buf_rdr = BufStream::new(file);
|
||||
let fs = FileSystem::new(&mut buf_rdr, FsOptions::new())?;
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let dir = match env::args().nth(1) {
|
||||
None => root_dir,
|
||||
Some(ref path) if path == "." => root_dir,
|
||||
|
26
src/dir.rs
26
src/dir.rs
@ -100,7 +100,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn find_entry(&mut self, name: &str, is_dir: Option<bool>, mut short_name_gen: Option<&mut ShortNameGenerator>) -> io::Result<DirEntry<'a, 'b>> {
|
||||
fn find_entry(&self, name: &str, is_dir: Option<bool>, mut short_name_gen: Option<&mut ShortNameGenerator>) -> io::Result<DirEntry<'a, 'b>> {
|
||||
for r in self.iter() {
|
||||
let e = r?;
|
||||
// compare name ignoring case
|
||||
@ -120,7 +120,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Opens existing directory
|
||||
pub fn open_dir(&mut self, path: &str) -> io::Result<Self> {
|
||||
pub fn open_dir(&self, path: &str) -> io::Result<Self> {
|
||||
let (name, rest_opt) = split_path(path);
|
||||
let e = self.find_entry(name, Some(true), None)?;
|
||||
match rest_opt {
|
||||
@ -130,7 +130,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Opens existing file.
|
||||
pub fn open_file(&mut self, path: &str) -> io::Result<File<'a, 'b>> {
|
||||
pub fn open_file(&self, path: &str) -> io::Result<File<'a, 'b>> {
|
||||
// traverse path
|
||||
let (name, rest_opt) = split_path(path);
|
||||
if let Some(rest) = rest_opt {
|
||||
@ -143,7 +143,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Creates new file or opens existing without truncating.
|
||||
pub fn create_file(&mut self, path: &str) -> io::Result<File<'a, 'b>> {
|
||||
pub fn create_file(&self, path: &str) -> io::Result<File<'a, 'b>> {
|
||||
// traverse path
|
||||
let (name, rest_opt) = split_path(path);
|
||||
if let Some(rest) = rest_opt {
|
||||
@ -167,7 +167,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
|
||||
/// Creates new directory or opens existing.
|
||||
pub fn create_dir(&mut self, path: &str) -> io::Result<Self> {
|
||||
pub fn create_dir(&self, path: &str) -> io::Result<Self> {
|
||||
// traverse path
|
||||
let (name, rest_opt) = split_path(path);
|
||||
if let Some(rest) = rest_opt {
|
||||
@ -202,7 +202,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_empty(&mut self) -> io::Result<bool> {
|
||||
fn is_empty(&self) -> io::Result<bool> {
|
||||
// check if directory contains no files
|
||||
for r in self.iter() {
|
||||
let e = r?;
|
||||
@ -219,7 +219,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
///
|
||||
/// Make sure there is no reference to this file (no File instance) or filesystem corruption
|
||||
/// can happen.
|
||||
pub fn remove(&mut self, path: &str) -> io::Result<()> {
|
||||
pub fn remove(&self, path: &str) -> io::Result<()> {
|
||||
// traverse path
|
||||
let (name, rest_opt) = split_path(path);
|
||||
if let Some(rest) = rest_opt {
|
||||
@ -255,7 +255,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
/// Destination directory can be cloned source directory in case of rename without moving operation.
|
||||
/// Make sure there is no reference to this file (no File instance) or filesystem corruption
|
||||
/// can happen.
|
||||
pub fn rename(&mut self, src_path: &str, dst_dir: &mut Dir, dst_path: &str) -> io::Result<()> {
|
||||
pub fn rename(&self, src_path: &str, dst_dir: &Dir, dst_path: &str) -> io::Result<()> {
|
||||
// traverse source path
|
||||
let (name, rest_opt) = split_path(src_path);
|
||||
if let Some(rest) = rest_opt {
|
||||
@ -272,7 +272,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
self.rename_internal(src_path, dst_dir, dst_path)
|
||||
}
|
||||
|
||||
fn rename_internal(&mut self, src_name: &str, dst_dir: &mut Dir, dst_name: &str) -> io::Result<()> {
|
||||
fn rename_internal(&self, src_name: &str, dst_dir: &Dir, dst_name: &str) -> io::Result<()> {
|
||||
trace!("moving {} to {}", src_name, dst_name);
|
||||
// find existing file
|
||||
let e = self.find_entry(src_name, None, None)?;
|
||||
@ -300,7 +300,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn find_free_entries(&mut self, num_entries: usize) -> io::Result<DirRawStream<'a, 'b>> {
|
||||
fn find_free_entries(&self, num_entries: usize) -> io::Result<DirRawStream<'a, 'b>> {
|
||||
let mut stream = self.stream.clone();
|
||||
let mut first_free = 0;
|
||||
let mut num_free = 0;
|
||||
@ -334,7 +334,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
fn create_lfn_entries(&mut self, name: &str, short_name: &[u8]) -> io::Result<(DirRawStream<'a, 'b>, u64)> {
|
||||
fn create_lfn_entries(&self, name: &str, short_name: &[u8]) -> io::Result<(DirRawStream<'a, 'b>, u64)> {
|
||||
// get short name checksum
|
||||
let lfn_chsum = lfn_checksum(&short_name);
|
||||
// convert long name to UTF-16
|
||||
@ -351,7 +351,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
Ok((stream, start_pos))
|
||||
}
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
fn create_lfn_entries(&mut self, _name: &str, _short_name: &[u8]) -> io::Result<(DirRawStream<'a, 'b>, u64)> {
|
||||
fn create_lfn_entries(&self, _name: &str, _short_name: &[u8]) -> io::Result<(DirRawStream<'a, 'b>, u64)> {
|
||||
let mut stream = self.find_free_entries(1)?;
|
||||
let start_pos = stream.seek(io::SeekFrom::Current(0))?;
|
||||
Ok((stream, start_pos))
|
||||
@ -366,7 +366,7 @@ impl <'a, 'b> Dir<'a, 'b> {
|
||||
raw_entry
|
||||
}
|
||||
|
||||
fn write_entry(&mut self, name: &str, raw_entry: DirFileEntryData) -> io::Result<DirEntry<'a, 'b>> {
|
||||
fn write_entry(&self, name: &str, raw_entry: DirFileEntryData) -> io::Result<DirEntry<'a, 'b>> {
|
||||
trace!("write_entry {}", name);
|
||||
// check if name doesn't contain unsupported characters
|
||||
validate_long_name(name)?;
|
||||
|
@ -350,10 +350,10 @@ pub(crate) enum DirEntryData {
|
||||
}
|
||||
|
||||
impl DirEntryData {
|
||||
pub(crate) fn serialize(&mut self, wrt: &mut Write) -> io::Result<()> {
|
||||
pub(crate) fn serialize(&self, wrt: &mut Write) -> io::Result<()> {
|
||||
match self {
|
||||
&mut DirEntryData::File(ref mut file) => file.serialize(wrt),
|
||||
&mut DirEntryData::Lfn(ref mut lfn) => lfn.serialize(wrt),
|
||||
&DirEntryData::File(ref file) => file.serialize(wrt),
|
||||
&DirEntryData::Lfn(ref lfn) => lfn.serialize(wrt),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ fn test_root_dir_fat32() {
|
||||
}
|
||||
|
||||
fn test_read_seek_short_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut short_file = root_dir.open_file("short.txt").unwrap();
|
||||
let mut buf = Vec::new();
|
||||
short_file.read_to_end(&mut buf).unwrap();
|
||||
@ -81,7 +81,7 @@ fn test_read_seek_short_file_fat32() {
|
||||
}
|
||||
|
||||
fn test_read_long_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut long_file = root_dir.open_file("long.txt").unwrap();
|
||||
let mut buf = Vec::new();
|
||||
long_file.read_to_end(&mut buf).unwrap();
|
||||
@ -110,7 +110,7 @@ fn test_read_long_file_fat32() {
|
||||
}
|
||||
|
||||
fn test_get_dir_by_path(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let dir = root_dir.open_dir("very/long/path/").unwrap();
|
||||
let names = dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||
assert_eq!(names, [".", "..", "test.txt"]);
|
||||
@ -143,7 +143,7 @@ fn test_get_dir_by_path_fat32() {
|
||||
}
|
||||
|
||||
fn test_get_file_by_path(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut file = root_dir.open_file("very/long/path/test.txt").unwrap();
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
|
@ -33,7 +33,7 @@ fn call_with_fs(f: &Fn(FileSystem) -> (), filename: &str, test_seq: u32) {
|
||||
}
|
||||
|
||||
fn test_write_short_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut file = root_dir.open_file("short.txt").expect("open file");
|
||||
file.truncate().unwrap();
|
||||
file.write_all(&TEST_STR.as_bytes()).unwrap();
|
||||
@ -59,7 +59,7 @@ fn test_write_file_fat32() {
|
||||
}
|
||||
|
||||
fn test_write_long_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let mut file = root_dir.open_file("long.txt").expect("open file");
|
||||
file.truncate().unwrap();
|
||||
let test_str = TEST_STR.repeat(100);
|
||||
@ -92,7 +92,7 @@ fn test_write_long_file_fat32() {
|
||||
}
|
||||
|
||||
fn test_remove(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
assert!(root_dir.remove("very/long/path").is_err());
|
||||
let dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let mut names = dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||
@ -125,8 +125,8 @@ fn test_remove_fat32() {
|
||||
}
|
||||
|
||||
fn test_create_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let mut dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let root_dir = fs.root_dir();
|
||||
let dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let mut names = dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||
assert_eq!(names, [".", "..", "test.txt"]);
|
||||
{
|
||||
@ -174,7 +174,7 @@ fn test_create_file_fat32() {
|
||||
}
|
||||
|
||||
fn test_create_dir(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let root_dir = fs.root_dir();
|
||||
let parent_dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let mut names = parent_dir.iter().map(|r| r.unwrap().file_name()).collect::<Vec<String>>();
|
||||
assert_eq!(names, [".", "..", "test.txt"]);
|
||||
@ -222,16 +222,15 @@ fn test_create_dir_fat32() {
|
||||
}
|
||||
|
||||
fn test_rename_file(fs: FileSystem) {
|
||||
let mut root_dir = fs.root_dir();
|
||||
let mut parent_dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let root_dir = fs.root_dir();
|
||||
let parent_dir = root_dir.open_dir("very/long/path").unwrap();
|
||||
let entries = parent_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
let names = entries.iter().map(|r| r.file_name()).collect::<Vec<_>>();
|
||||
assert_eq!(names, [".", "..", "test.txt"]);
|
||||
assert_eq!(entries[2].len(), 14);
|
||||
let stats = fs.stats().unwrap();
|
||||
|
||||
let mut parent_dir_cloned = parent_dir.clone();
|
||||
parent_dir.rename("test.txt", &mut parent_dir_cloned, "new-long-name.txt").unwrap();
|
||||
parent_dir.rename("test.txt", &parent_dir, "new-long-name.txt").unwrap();
|
||||
let entries = parent_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
let names = entries.iter().map(|r| r.file_name()).collect::<Vec<_>>();
|
||||
assert_eq!(names, [".", "..", "new-long-name.txt"]);
|
||||
@ -241,7 +240,7 @@ fn test_rename_file(fs: FileSystem) {
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
assert_eq!(str::from_utf8(&buf).unwrap(), TEST_STR2);
|
||||
|
||||
parent_dir.rename("new-long-name.txt", &mut root_dir, "moved-file.txt").unwrap();
|
||||
parent_dir.rename("new-long-name.txt", &root_dir, "moved-file.txt").unwrap();
|
||||
let entries = root_dir.iter().map(|r| r.unwrap()).collect::<Vec<_>>();
|
||||
let names = entries.iter().map(|r| r.file_name()).collect::<Vec<_>>();
|
||||
assert_eq!(names, ["long.txt", "short.txt", "very", "very-long-dir-name", "moved-file.txt"]);
|
||||
|
Loading…
Reference in New Issue
Block a user