15
15
// specific language governing permissions and limitations
16
16
// under the License.
17
17
18
- use std:: ops:: Range ;
18
+ use std:: ops:: { Bound , Range , RangeBounds } ;
19
19
use std:: sync:: Arc ;
20
20
21
21
use crate :: raw:: * ;
@@ -68,6 +68,38 @@ impl ReadContext {
68
68
pub fn options ( & self ) -> & OpReader {
69
69
& self . options
70
70
}
71
+
72
+ /// Parse the range bounds into a range.
73
+ pub ( crate ) async fn parse_into_range (
74
+ & self ,
75
+ range : impl RangeBounds < u64 > ,
76
+ ) -> Result < Range < u64 > > {
77
+ let start = match range. start_bound ( ) {
78
+ Bound :: Included ( v) => * v,
79
+ Bound :: Excluded ( v) => v + 1 ,
80
+ Bound :: Unbounded => 0 ,
81
+ } ;
82
+
83
+ let end = match range. end_bound ( ) {
84
+ Bound :: Included ( v) => v + 1 ,
85
+ Bound :: Excluded ( v) => * v,
86
+ Bound :: Unbounded => {
87
+ let mut op_stat = OpStat :: new ( ) ;
88
+
89
+ if let Some ( v) = self . args ( ) . version ( ) {
90
+ op_stat = op_stat. with_version ( v) ;
91
+ }
92
+
93
+ self . accessor ( )
94
+ . stat ( self . path ( ) , op_stat)
95
+ . await ?
96
+ . into_metadata ( )
97
+ . content_length ( )
98
+ }
99
+ } ;
100
+
101
+ Ok ( start..end)
102
+ }
71
103
}
72
104
73
105
/// ReadGenerator is used to generate new readers.
@@ -83,62 +115,65 @@ pub struct ReadGenerator {
83
115
ctx : Arc < ReadContext > ,
84
116
85
117
offset : u64 ,
86
- end : u64 ,
118
+ size : Option < u64 > ,
87
119
}
88
120
89
121
impl ReadGenerator {
90
122
/// Create a new ReadGenerator.
91
123
#[ inline]
92
- pub fn new ( ctx : Arc < ReadContext > , range : Range < u64 > ) -> Self {
93
- Self {
94
- ctx,
95
- offset : range. start ,
96
- end : range. end ,
124
+ pub fn new ( ctx : Arc < ReadContext > , offset : u64 , size : Option < u64 > ) -> Self {
125
+ Self { ctx, offset, size }
126
+ }
127
+
128
+ /// Generate next range to read.
129
+ fn next_range ( & mut self ) -> Option < BytesRange > {
130
+ if self . size == Some ( 0 ) {
131
+ return None ;
97
132
}
133
+
134
+ let next_offset = self . offset ;
135
+ let next_size = match self . size {
136
+ // Given size is None, read all data.
137
+ None => {
138
+ // Update size to Some(0) to indicate that there is no more data to read.
139
+ self . size = Some ( 0 ) ;
140
+ None
141
+ }
142
+ Some ( remaining) => {
143
+ // If chunk is set, read data in chunks.
144
+ let read_size = self
145
+ . ctx
146
+ . options
147
+ . chunk ( )
148
+ . map_or ( remaining, |chunk| remaining. min ( chunk as u64 ) ) ;
149
+ // Update (offset, size) before building future.
150
+ self . offset += read_size;
151
+ self . size = Some ( remaining - read_size) ;
152
+ Some ( read_size)
153
+ }
154
+ } ;
155
+
156
+ Some ( BytesRange :: new ( next_offset, next_size) )
98
157
}
99
158
100
159
/// Generate next reader.
101
160
pub async fn next_reader ( & mut self ) -> Result < Option < oio:: Reader > > {
102
- if self . offset > = self . end {
161
+ let Some ( range ) = self . next_range ( ) else {
103
162
return Ok ( None ) ;
104
- }
163
+ } ;
105
164
106
- let offset = self . offset ;
107
- let mut size = ( self . end - self . offset ) as usize ;
108
- if let Some ( chunk) = self . ctx . options . chunk ( ) {
109
- size = size. min ( chunk)
110
- }
111
-
112
- // Update self.offset before building future.
113
- self . offset += size as u64 ;
114
- let args = self
115
- . ctx
116
- . args
117
- . clone ( )
118
- . with_range ( BytesRange :: new ( offset, Some ( size as u64 ) ) ) ;
165
+ let args = self . ctx . args . clone ( ) . with_range ( range) ;
119
166
let ( _, r) = self . ctx . acc . read ( & self . ctx . path , args) . await ?;
120
167
Ok ( Some ( r) )
121
168
}
122
169
123
170
/// Generate next blocking reader.
124
171
pub fn next_blocking_reader ( & mut self ) -> Result < Option < oio:: BlockingReader > > {
125
- if self . offset > = self . end {
172
+ let Some ( range ) = self . next_range ( ) else {
126
173
return Ok ( None ) ;
127
- }
174
+ } ;
128
175
129
- let offset = self . offset ;
130
- let mut size = ( self . end - self . offset ) as usize ;
131
- if let Some ( chunk) = self . ctx . options . chunk ( ) {
132
- size = size. min ( chunk)
133
- }
134
-
135
- // Update self.offset before building future.
136
- self . offset += size as u64 ;
137
- let args = self
138
- . ctx
139
- . args
140
- . clone ( )
141
- . with_range ( BytesRange :: new ( offset, Some ( size as u64 ) ) ) ;
176
+ let args = self . ctx . args . clone ( ) . with_range ( range) ;
142
177
let ( _, r) = self . ctx . acc . blocking_read ( & self . ctx . path , args) ?;
143
178
Ok ( Some ( r) )
144
179
}
@@ -167,7 +202,7 @@ mod tests {
167
202
OpRead :: new ( ) ,
168
203
OpReader :: new ( ) . with_chunk ( 3 ) ,
169
204
) ) ;
170
- let mut generator = ReadGenerator :: new ( ctx, 0 .. 10 ) ;
205
+ let mut generator = ReadGenerator :: new ( ctx, 0 , Some ( 10 ) ) ;
171
206
let mut readers = vec ! [ ] ;
172
207
while let Some ( r) = generator. next_reader ( ) . await ? {
173
208
readers. push ( r) ;
@@ -177,6 +212,32 @@ mod tests {
177
212
Ok ( ( ) )
178
213
}
179
214
215
+ #[ tokio:: test]
216
+ async fn test_next_reader_without_size ( ) -> Result < ( ) > {
217
+ let op = Operator :: via_iter ( Scheme :: Memory , [ ] ) ?;
218
+ op. write (
219
+ "test" ,
220
+ Buffer :: from ( vec ! [ Bytes :: from( "Hello" ) , Bytes :: from( "World" ) ] ) ,
221
+ )
222
+ . await ?;
223
+
224
+ let acc = op. into_inner ( ) ;
225
+ let ctx = Arc :: new ( ReadContext :: new (
226
+ acc,
227
+ "test" . to_string ( ) ,
228
+ OpRead :: new ( ) ,
229
+ OpReader :: new ( ) . with_chunk ( 3 ) ,
230
+ ) ) ;
231
+ let mut generator = ReadGenerator :: new ( ctx, 0 , None ) ;
232
+ let mut readers = vec ! [ ] ;
233
+ while let Some ( r) = generator. next_reader ( ) . await ? {
234
+ readers. push ( r) ;
235
+ }
236
+
237
+ pretty_assertions:: assert_eq!( readers. len( ) , 1 ) ;
238
+ Ok ( ( ) )
239
+ }
240
+
180
241
#[ test]
181
242
fn test_next_blocking_reader ( ) -> Result < ( ) > {
182
243
let op = Operator :: via_iter ( Scheme :: Memory , [ ] ) ?;
@@ -192,7 +253,7 @@ mod tests {
192
253
OpRead :: new ( ) ,
193
254
OpReader :: new ( ) . with_chunk ( 3 ) ,
194
255
) ) ;
195
- let mut generator = ReadGenerator :: new ( ctx, 0 .. 10 ) ;
256
+ let mut generator = ReadGenerator :: new ( ctx, 0 , Some ( 10 ) ) ;
196
257
let mut readers = vec ! [ ] ;
197
258
while let Some ( r) = generator. next_blocking_reader ( ) ? {
198
259
readers. push ( r) ;
0 commit comments