@@ -16,6 +16,23 @@ use heapless::Vec;
1616
1717static ID_GENERATOR : IdGenerator = IdGenerator :: new ( ) ;
1818
19+ #[ derive( PartialEq , Eq ) ]
20+ struct UniqueCluster {
21+ volume_idx : VolumeIdx ,
22+ cluster : Cluster ,
23+ search_id : SearchId ,
24+ }
25+
26+ impl UniqueCluster {
27+ fn compare_volume_and_cluster ( & self , volume_idx : VolumeIdx , cluster : Cluster ) -> bool {
28+ self . volume_idx == volume_idx && self . cluster == cluster
29+ }
30+
31+ fn compare_id ( & self , search_id : SearchId ) -> bool {
32+ self . search_id == search_id
33+ }
34+ }
35+
1936/// A `VolumeManager` wraps a block device and gives access to the volumes within it.
2037pub struct VolumeManager < D , T , const MAX_DIRS : usize = 4 , const MAX_FILES : usize = 4 >
2138where
2542{
2643 pub ( crate ) block_device : D ,
2744 pub ( crate ) timesource : T ,
28- open_dirs : Vec < ( VolumeIdx , Cluster , SearchId ) , MAX_DIRS > ,
29- open_files : Vec < ( VolumeIdx , Cluster , SearchId ) , MAX_FILES > ,
45+ open_dirs : Vec < UniqueCluster , MAX_DIRS > ,
46+ open_files : Vec < UniqueCluster , MAX_FILES > ,
3047}
3148
3249impl < D , T > VolumeManager < D , T , 4 , 4 >
@@ -161,15 +178,19 @@ where
161178 // Find a free directory entry, and check the root dir isn't open. As
162179 // we already know the root dir's magic cluster number, we can do both
163180 // checks in one loop.
164- for ( v , c , _ ) in self . open_dirs . iter ( ) {
165- if * v == volume. idx && * c == Cluster :: ROOT_DIR {
181+ for u in self . open_dirs . iter ( ) {
182+ if u . compare_volume_and_cluster ( volume. idx , Cluster :: ROOT_DIR ) {
166183 return Err ( Error :: DirAlreadyOpen ) ;
167184 }
168185 }
169186 let search_id = ID_GENERATOR . next ( ) ;
170187 // Remember this open directory
171188 self . open_dirs
172- . push ( ( volume. idx , Cluster :: ROOT_DIR , search_id) )
189+ . push ( UniqueCluster {
190+ volume_idx : volume. idx ,
191+ cluster : Cluster :: ROOT_DIR ,
192+ search_id,
193+ } )
173194 . map_err ( |_| Error :: TooManyOpenDirs ) ?;
174195
175196 Ok ( Directory {
@@ -205,15 +226,19 @@ where
205226 }
206227
207228 // Check it's not already open
208- for dir_table_row in self . open_dirs . iter ( ) {
209- if dir_table_row . 0 == volume. idx && dir_table_row . 1 == dir_entry. cluster {
229+ for d in self . open_dirs . iter ( ) {
230+ if d . compare_volume_and_cluster ( volume. idx , dir_entry. cluster ) {
210231 return Err ( Error :: DirAlreadyOpen ) ;
211232 }
212233 }
213234 // Remember this open directory.
214235 let search_id = ID_GENERATOR . next ( ) ;
215236 self . open_dirs
216- . push ( ( volume. idx , dir_entry. cluster , search_id) )
237+ . push ( UniqueCluster {
238+ volume_idx : volume. idx ,
239+ cluster : dir_entry. cluster ,
240+ search_id,
241+ } )
217242 . map_err ( |_| Error :: TooManyOpenDirs ) ?;
218243
219244 Ok ( Directory {
@@ -226,7 +251,7 @@ where
226251 /// and so must close it if you want to do something with it.
227252 pub fn close_dir ( & mut self , volume : & Volume , dir : Directory ) {
228253 for ( i, d) in self . open_dirs . iter ( ) . enumerate ( ) {
229- if d. 2 == dir. search_id {
254+ if d. compare_id ( dir. search_id ) {
230255 self . open_dirs . swap_remove ( i) ;
231256 break ;
232257 }
@@ -271,8 +296,8 @@ where
271296 return Err ( Error :: TooManyOpenFiles ) ;
272297 }
273298 // Check it's not already open
274- for dir_table_row in self . open_files . iter ( ) {
275- if dir_table_row . 0 == volume. idx && dir_table_row . 1 == dir_entry. cluster {
299+ for d in self . open_files . iter ( ) {
300+ if d . compare_volume_and_cluster ( volume. idx , dir_entry. cluster ) {
276301 return Err ( Error :: DirAlreadyOpen ) ;
277302 }
278303 }
@@ -340,7 +365,11 @@ where
340365 } ;
341366 // Remember this open file
342367 self . open_files
343- . push ( ( volume. idx , file. starting_cluster , search_id) )
368+ . push ( UniqueCluster {
369+ volume_idx : volume. idx ,
370+ cluster : file. starting_cluster ,
371+ search_id,
372+ } )
344373 . map_err ( |_| Error :: TooManyOpenDirs ) ?;
345374
346375 Ok ( file)
@@ -404,7 +433,11 @@ where
404433
405434 // Remember this open file
406435 self . open_files
407- . push ( ( volume. idx , file. starting_cluster , search_id) )
436+ . push ( UniqueCluster {
437+ volume_idx : volume. idx ,
438+ cluster : file. starting_cluster ,
439+ search_id,
440+ } )
408441 . map_err ( |_| Error :: TooManyOpenFiles ) ?;
409442
410443 Ok ( file)
@@ -419,18 +452,6 @@ where
419452 }
420453 }
421454
422- /// Get the next entry in open_files list
423- fn get_open_files_row ( & self ) -> Result < usize , Error < D :: Error > > {
424- // Find a free directory entry
425- let mut open_files_row = None ;
426- for ( i, d) in self . open_files . iter ( ) . enumerate ( ) {
427- if d. 1 == Cluster :: INVALID {
428- open_files_row = Some ( i) ;
429- }
430- }
431- open_files_row. ok_or ( Error :: TooManyOpenFiles )
432- }
433-
434455 /// Delete a closed file with the given full path, if exists.
435456 pub fn delete_file_in_dir (
436457 & mut self ,
@@ -451,7 +472,7 @@ where
451472 }
452473
453474 for d in self . open_files . iter_mut ( ) {
454- if d. 0 == volume. idx && d . 1 == dir_entry. cluster {
475+ if d. compare_volume_and_cluster ( volume. idx , dir_entry. cluster ) {
455476 return Err ( Error :: FileIsOpen ) ;
456477 }
457478 }
@@ -610,7 +631,7 @@ where
610631 /// Close a file with the given full path.
611632 pub fn close_file ( & mut self , volume : & Volume , file : File ) -> Result < ( ) , Error < D :: Error > > {
612633 for ( i, f) in self . open_files . iter ( ) . enumerate ( ) {
613- if f. 2 == file. search_id {
634+ if f. compare_id ( file. search_id ) {
614635 self . open_files . swap_remove ( i) ;
615636 break ;
616637 }
@@ -620,11 +641,7 @@ where
620641
621642 /// Check if any files or folders are open.
622643 pub fn has_open_handles ( & self ) -> bool {
623- !self
624- . open_dirs
625- . iter ( )
626- . chain ( self . open_files . iter ( ) )
627- . all ( |( _, c, _) | c == & Cluster :: INVALID )
644+ !( self . open_dirs . is_empty ( ) || self . open_files . is_empty ( ) )
628645 }
629646
630647 /// Consume self and return BlockDevice and TimeSource
0 commit comments