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:
Rafał Harabień 2018-06-12 00:07:30 +02:00
parent 4f6ed94cb3
commit 2304b13ec4
7 changed files with 33 additions and 34 deletions

View File

@ -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!")?;

View File

@ -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)?;

View File

@ -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,

View File

@ -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)?;

View File

@ -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),
}
}

View File

@ -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();

View File

@ -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"]);