@@ -207,6 +207,63 @@ impl AsyncFileReader for PrefetchReader {
207
207
}
208
208
}
209
209
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
+
210
267
#[ derive( Debug , Clone , Copy ) ]
211
268
pub ( crate ) enum Endianness {
212
269
LittleEndian ,
0 commit comments