@@ -9,8 +9,11 @@ use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
9
9
use bytes:: buf:: Reader ;
10
10
use bytes:: { Buf , Bytes } ;
11
11
use futures:: future:: { BoxFuture , FutureExt , TryFutureExt } ;
12
+ #[ cfg( feature = "object_store" ) ]
12
13
use object_store:: ObjectStore ;
13
14
15
+ use crate :: coalesce_ranges;
16
+
14
17
use crate :: error:: { AsyncTiffError , AsyncTiffResult } ;
15
18
16
19
/// The asynchronous interface used to read COG files
@@ -33,17 +36,19 @@ pub trait AsyncFileReader: Debug + Send + Sync {
33
36
/// Retrieve the bytes in `range`
34
37
fn get_bytes ( & self , range : Range < u64 > ) -> BoxFuture < ' _ , AsyncTiffResult < Bytes > > ;
35
38
36
- /// Retrieve multiple byte ranges. The default implementation will call `get_bytes`
37
- /// sequentially
39
+ /// Retrieve multiple byte ranges. The default implementation will
40
+ /// coalesce ranges with:
41
+ /// - less than 1024*1024=1MB space in between
42
+ /// - 10 parallel requests
38
43
fn get_byte_ranges (
39
44
& self ,
40
45
ranges : Vec < Range < u64 > > ,
41
46
) -> BoxFuture < ' _ , AsyncTiffResult < Vec < Bytes > > > {
42
47
async move {
43
48
let mut result = Vec :: with_capacity ( ranges. len ( ) ) ;
44
49
45
- for range in ranges. into_iter ( ) {
46
- let data = self . get_bytes ( range ) . await ? ;
50
+ for data in coalesce_ranges ( & ranges, |range| self . get_bytes ( range ) , 1024 * 1024 ) . await ?
51
+ {
47
52
result. push ( data) ;
48
53
}
49
54
@@ -91,12 +96,13 @@ impl AsyncFileReader for Box<dyn AsyncFileReader + '_> {
91
96
// }
92
97
93
98
/// An AsyncFileReader that reads from an [`ObjectStore`] instance.
99
+ #[ cfg( feature = "object_store" ) ]
94
100
#[ derive( Clone , Debug ) ]
95
101
pub struct ObjectReader {
96
102
store : Arc < dyn ObjectStore > ,
97
103
path : object_store:: path:: Path ,
98
104
}
99
-
105
+ # [ cfg ( feature = "object_store" ) ]
100
106
impl ObjectReader {
101
107
/// Creates a new [`ObjectReader`] for the provided [`ObjectStore`] and path
102
108
///
@@ -105,7 +111,7 @@ impl ObjectReader {
105
111
Self { store, path }
106
112
}
107
113
}
108
-
114
+ # [ cfg ( feature = "object_store" ) ]
109
115
impl AsyncFileReader for ObjectReader {
110
116
fn get_bytes ( & self , range : Range < u64 > ) -> BoxFuture < ' _ , AsyncTiffResult < Bytes > > {
111
117
let range = range. start as _ ..range. end as _ ;
@@ -134,19 +140,20 @@ impl AsyncFileReader for ObjectReader {
134
140
}
135
141
136
142
/// An AsyncFileReader that reads from a URL using reqwest.
143
+ #[ cfg( feature = "reqwest" ) ]
137
144
#[ derive( Debug , Clone ) ]
138
145
pub struct ReqwestReader {
139
146
client : reqwest:: Client ,
140
147
url : reqwest:: Url ,
141
148
}
142
-
149
+ # [ cfg ( feature = "reqwest" ) ]
143
150
impl ReqwestReader {
144
151
/// Construct a new ReqwestReader from a reqwest client and URL.
145
152
pub fn new ( client : reqwest:: Client , url : reqwest:: Url ) -> Self {
146
153
Self { client, url }
147
154
}
148
155
}
149
-
156
+ # [ cfg ( feature = "reqwest" ) ]
150
157
impl AsyncFileReader for ReqwestReader {
151
158
fn get_bytes ( & self , range : Range < u64 > ) -> BoxFuture < ' _ , AsyncTiffResult < Bytes > > {
152
159
let url = self . url . clone ( ) ;
0 commit comments