@@ -207,6 +207,63 @@ impl AsyncFileReader for PrefetchReader {
207207 }
208208}
209209
210+
211+ /// reader that holds a cache. Because of interior mutability, it will always
212+ /// lock the cache (twice) for each get_bytes. This also special-cases
213+ /// get_tile_bytes
214+ /// When doing metadata fetches, it will fetch twice the requested size for the cache
215+ ///
216+ #[ derive( Debug ) ]
217+ pub struct CacheReader {
218+ reader : Arc < dyn AsyncFileReader > ,
219+ cache : Arc < Mutex < ( Range < u64 > , Bytes ) > > , // not sure if this should be an async_mutex on wasm-like environments to prevent blocking the main thread
220+ }
221+
222+ impl CacheReader {
223+ /// creates a ew cachereader with empty cache
224+ pub fn new ( reader : Arc < dyn AsyncFileReader > ) -> Self {
225+ Self {
226+ reader,
227+ cache : Arc :: new ( Mutex :: new ( ( 0 ..0 , Bytes :: new ( ) ) ) ) ,
228+ }
229+ }
230+ }
231+
232+ impl AsyncFileReader for CacheReader {
233+ fn get_bytes ( & self , range : Range < u64 > ) -> BoxFuture < ' _ , AsyncTiffResult < Bytes > > {
234+ {
235+ let lock = self . cache . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
236+ // check for cache
237+ if range. start >= lock. 0 . start /*&& range.start < lock.0.end*/ && range. end <= lock. 0 . end
238+ {
239+ let usize_range =
240+ ( range. start - lock. 0 . start ) as usize ..( range. end - lock. 0 . start ) as usize ;
241+ let result = lock. 1 . slice ( usize_range) ;
242+ return async { Ok ( result) } . boxed ( ) ;
243+ } else {
244+ println ! ( "range {:?} doesn't contain {range:?}" , lock. 0 ) ;
245+ }
246+ }
247+ async move {
248+ let range_len = range. end - range. start ;
249+ // this is based on a geometric series, since each overview is 1/2
250+ // the size, the n of tiles (~area) of the next overview is 1/4
251+ // however, due to the edges, this underestimates, and we'd rather
252+ // over-estimate I think?
253+ // So we add the edge of the next overview as well, which would give
254+ // 1.5*isqrt, so we round up.
255+ let full_len = 2 * range_len + 2 * range_len. isqrt ( ) ;
256+ let new_range = range. start ..range. start + full_len;
257+ println ! ( "range {range:?} requested, fetching {new_range:?}" ) ;
258+ let res = self . reader . get_bytes ( new_range. clone ( ) ) . await ?;
259+ let mut lock = self . cache . lock ( ) . unwrap_or_else ( |e| e. into_inner ( ) ) ;
260+ * lock = ( new_range, res. clone ( ) ) ;
261+ Ok ( res. slice ( 0 ..( range. end - range. start ) as usize ) )
262+ }
263+ . boxed ( )
264+ }
265+ }
266+
210267#[ derive( Debug , Clone , Copy ) ]
211268pub ( crate ) enum Endianness {
212269 LittleEndian ,
0 commit comments