Skip to content

Commit 1e89779

Browse files
committed
split FatVolume.iterate_dir into 2 subfunctions
1 parent 710bd34 commit 1e89779

File tree

1 file changed

+108
-83
lines changed

1 file changed

+108
-83
lines changed

src/fat/volume.rs

Lines changed: 108 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -435,105 +435,130 @@ impl FatVolume {
435435
&self,
436436
block_device: &D,
437437
dir: &DirectoryInfo,
438-
mut func: F,
438+
func: F,
439439
) -> Result<(), Error<D::Error>>
440440
where
441441
F: FnMut(&DirEntry),
442442
D: BlockDevice,
443443
{
444444
match &self.fat_specific_info {
445445
FatSpecificInfo::Fat16(fat16_info) => {
446-
// Root directories on FAT16 have a fixed size, because they use
447-
// a specially reserved space on disk (see
448-
// `first_root_dir_block`). Other directories can have any size
449-
// as they are made of regular clusters.
450-
let mut current_cluster = Some(dir.cluster);
451-
let mut first_dir_block_num = match dir.cluster {
452-
ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
453-
_ => self.cluster_to_block(dir.cluster),
454-
};
455-
let dir_size = match dir.cluster {
456-
ClusterId::ROOT_DIR => {
457-
let len_bytes =
458-
u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
459-
BlockCount::from_bytes(len_bytes)
460-
}
461-
_ => BlockCount(u32::from(self.blocks_per_cluster)),
462-
};
446+
self.iterate_fat16(dir, fat16_info, block_device, func)
447+
}
448+
FatSpecificInfo::Fat32(fat32_info) => {
449+
self.iterate_fat32(dir, fat32_info, block_device, func)
450+
}
451+
}
452+
}
463453

464-
let mut block_cache = BlockCache::empty();
465-
while let Some(cluster) = current_cluster {
466-
for block_idx in first_dir_block_num.range(dir_size) {
467-
let block = block_cache.read(block_device, block_idx, "read_dir")?;
468-
for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
469-
let start = entry * OnDiskDirEntry::LEN;
470-
let end = (entry + 1) * OnDiskDirEntry::LEN;
471-
let dir_entry = OnDiskDirEntry::new(&block[start..end]);
472-
if dir_entry.is_end() {
473-
// Can quit early
474-
return Ok(());
475-
} else if dir_entry.is_valid() && !dir_entry.is_lfn() {
476-
// Safe, since Block::LEN always fits on a u32
477-
let start = u32::try_from(start).unwrap();
478-
let entry = dir_entry.get_entry(FatType::Fat16, block_idx, start);
479-
func(&entry);
480-
}
481-
}
482-
}
483-
if cluster != ClusterId::ROOT_DIR {
484-
current_cluster =
485-
match self.next_cluster(block_device, cluster, &mut block_cache) {
486-
Ok(n) => {
487-
first_dir_block_num = self.cluster_to_block(n);
488-
Some(n)
489-
}
490-
_ => None,
491-
};
492-
} else {
493-
current_cluster = None;
454+
fn iterate_fat16<D, F>(
455+
&self,
456+
dir: &DirectoryInfo,
457+
fat16_info: &Fat16Info,
458+
block_device: &D,
459+
mut func: F,
460+
) -> Result<(), Error<D::Error>>
461+
where
462+
F: FnMut(&DirEntry),
463+
D: BlockDevice,
464+
{
465+
// Root directories on FAT16 have a fixed size, because they use
466+
// a specially reserved space on disk (see
467+
// `first_root_dir_block`). Other directories can have any size
468+
// as they are made of regular clusters.
469+
let mut current_cluster = Some(dir.cluster);
470+
let mut first_dir_block_num = match dir.cluster {
471+
ClusterId::ROOT_DIR => self.lba_start + fat16_info.first_root_dir_block,
472+
_ => self.cluster_to_block(dir.cluster),
473+
};
474+
let dir_size = match dir.cluster {
475+
ClusterId::ROOT_DIR => {
476+
let len_bytes = u32::from(fat16_info.root_entries_count) * OnDiskDirEntry::LEN_U32;
477+
BlockCount::from_bytes(len_bytes)
478+
}
479+
_ => BlockCount(u32::from(self.blocks_per_cluster)),
480+
};
481+
482+
let mut block_cache = BlockCache::empty();
483+
while let Some(cluster) = current_cluster {
484+
for block_idx in first_dir_block_num.range(dir_size) {
485+
let block = block_cache.read(block_device, block_idx, "read_dir")?;
486+
for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
487+
let start = entry * OnDiskDirEntry::LEN;
488+
let end = (entry + 1) * OnDiskDirEntry::LEN;
489+
let dir_entry = OnDiskDirEntry::new(&block[start..end]);
490+
if dir_entry.is_end() {
491+
// Can quit early
492+
return Ok(());
493+
} else if dir_entry.is_valid() && !dir_entry.is_lfn() {
494+
// Safe, since Block::LEN always fits on a u32
495+
let start = u32::try_from(start).unwrap();
496+
let entry = dir_entry.get_entry(FatType::Fat16, block_idx, start);
497+
func(&entry);
494498
}
495499
}
496-
Ok(())
497500
}
498-
FatSpecificInfo::Fat32(fat32_info) => {
499-
// All directories on FAT32 have a cluster chain but the root
500-
// dir starts in a specified cluster.
501-
let mut current_cluster = match dir.cluster {
502-
ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
503-
_ => Some(dir.cluster),
501+
if cluster != ClusterId::ROOT_DIR {
502+
current_cluster = match self.next_cluster(block_device, cluster, &mut block_cache) {
503+
Ok(n) => {
504+
first_dir_block_num = self.cluster_to_block(n);
505+
Some(n)
506+
}
507+
_ => None,
504508
};
505-
let mut blocks = [Block::new()];
506-
let mut block_cache = BlockCache::empty();
507-
while let Some(cluster) = current_cluster {
508-
let block_idx = self.cluster_to_block(cluster);
509-
for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) {
510-
block_device
511-
.read(&mut blocks, block, "read_dir")
512-
.map_err(Error::DeviceError)?;
513-
for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
514-
let start = entry * OnDiskDirEntry::LEN;
515-
let end = (entry + 1) * OnDiskDirEntry::LEN;
516-
let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
517-
if dir_entry.is_end() {
518-
// Can quit early
519-
return Ok(());
520-
} else if dir_entry.is_valid() && !dir_entry.is_lfn() {
521-
// Safe, since Block::LEN always fits on a u32
522-
let start = u32::try_from(start).unwrap();
523-
let entry = dir_entry.get_entry(FatType::Fat32, block, start);
524-
func(&entry);
525-
}
526-
}
509+
} else {
510+
current_cluster = None;
511+
}
512+
}
513+
Ok(())
514+
}
515+
516+
fn iterate_fat32<D, F>(
517+
&self,
518+
dir: &DirectoryInfo,
519+
fat32_info: &Fat32Info,
520+
block_device: &D,
521+
mut func: F,
522+
) -> Result<(), Error<D::Error>>
523+
where
524+
F: FnMut(&DirEntry),
525+
D: BlockDevice,
526+
{
527+
// All directories on FAT32 have a cluster chain but the root
528+
// dir starts in a specified cluster.
529+
let mut current_cluster = match dir.cluster {
530+
ClusterId::ROOT_DIR => Some(fat32_info.first_root_dir_cluster),
531+
_ => Some(dir.cluster),
532+
};
533+
let mut blocks = [Block::new()];
534+
let mut block_cache = BlockCache::empty();
535+
while let Some(cluster) = current_cluster {
536+
let block_idx = self.cluster_to_block(cluster);
537+
for block in block_idx.range(BlockCount(u32::from(self.blocks_per_cluster))) {
538+
block_device
539+
.read(&mut blocks, block, "read_dir")
540+
.map_err(Error::DeviceError)?;
541+
for entry in 0..Block::LEN / OnDiskDirEntry::LEN {
542+
let start = entry * OnDiskDirEntry::LEN;
543+
let end = (entry + 1) * OnDiskDirEntry::LEN;
544+
let dir_entry = OnDiskDirEntry::new(&blocks[0][start..end]);
545+
if dir_entry.is_end() {
546+
// Can quit early
547+
return Ok(());
548+
} else if dir_entry.is_valid() && !dir_entry.is_lfn() {
549+
// Safe, since Block::LEN always fits on a u32
550+
let start = u32::try_from(start).unwrap();
551+
let entry = dir_entry.get_entry(FatType::Fat32, block, start);
552+
func(&entry);
527553
}
528-
current_cluster =
529-
match self.next_cluster(block_device, cluster, &mut block_cache) {
530-
Ok(n) => Some(n),
531-
_ => None,
532-
};
533554
}
534-
Ok(())
535555
}
556+
current_cluster = match self.next_cluster(block_device, cluster, &mut block_cache) {
557+
Ok(n) => Some(n),
558+
_ => None,
559+
};
536560
}
561+
Ok(())
537562
}
538563

539564
/// Get an entry from the given directory

0 commit comments

Comments
 (0)