@@ -25,6 +25,17 @@ pub struct File<'a, IO: ReadWriteSeek, TP, OCC> {
2525 fs : & ' a FileSystem < IO , TP , OCC > ,
2626}
2727
28+ /// An extent containing a file's data on disk.
29+ ///
30+ /// This is created by the `extents` method on `File`, and represents
31+ /// a byte range on the disk that contains a file's data. All values
32+ /// are in bytes.
33+ #[ derive( Clone , Debug ) ]
34+ pub struct Extent {
35+ pub offset : u64 ,
36+ pub size : u32 ,
37+ }
38+
2839impl < ' a , IO : ReadWriteSeek , TP , OCC > File < ' a , IO , TP , OCC > {
2940 pub ( crate ) fn new (
3041 first_cluster : Option < u32 > ,
@@ -74,6 +85,39 @@ impl<'a, IO: ReadWriteSeek, TP, OCC> File<'a, IO, TP, OCC> {
7485 }
7586 }
7687
88+ /// Get the extents of a file on disk.
89+ ///
90+ /// This returns an iterator over the byte ranges on-disk occupied by
91+ /// this file.
92+ pub fn extents ( & mut self ) -> impl Iterator < Item =Result < Extent , Error < IO :: Error > > > + ' a {
93+
94+ let fs = self . fs ;
95+ let cluster_size = fs. cluster_size ( ) ;
96+ let mut bytes_left = match self . size ( ) {
97+ Some ( s) => s,
98+ None => return None . into_iter ( ) . flatten ( ) ,
99+ } ;
100+ let first = match self . first_cluster {
101+ Some ( f) => f,
102+ None => return None . into_iter ( ) . flatten ( ) ,
103+ } ;
104+
105+ Some ( core:: iter:: once ( Ok ( first) ) . chain ( fs. cluster_iter ( first) )
106+ . map ( move |cluster_err| {
107+ match cluster_err {
108+ Ok ( cluster) => {
109+ let size = cluster_size. min ( bytes_left) ;
110+ bytes_left -= size;
111+ Ok ( Extent {
112+ offset : fs. offset_from_cluster ( cluster) ,
113+ size : size,
114+ } )
115+ } ,
116+ Err ( e) => Err ( e) ,
117+ }
118+ } ) ) . into_iter ( ) . flatten ( )
119+ }
120+
77121 pub ( crate ) fn abs_pos ( & self ) -> Option < u64 > {
78122 // Returns current position relative to filesystem start
79123 // Note: when between clusters it returns position after previous cluster
0 commit comments