1
1
use crate :: engine:: Engine ;
2
- use std:: {
3
- cmp, fmt, io,
4
- io:: { ErrorKind , Result } ,
5
- } ;
2
+ use std:: { cmp, fmt, io} ;
6
3
7
4
pub ( crate ) const BUF_SIZE : usize = 1024 ;
8
5
/// The most bytes whose encoding will fit in `BUF_SIZE`
@@ -74,21 +71,24 @@ pub struct EncoderWriter<'e, E: Engine, W: io::Write> {
74
71
/// Buffer to encode into. May hold leftover encoded bytes from a previous write call that the underlying writer
75
72
/// did not write last time.
76
73
output : [ u8 ; BUF_SIZE ] ,
77
- /// How much of ` output` is occupied with encoded data that couldn't be written last time
78
- output_occupied_len : usize ,
74
+ /// Occupied portion of output.
75
+ output_range : std :: ops :: Range < usize > ,
79
76
/// panic safety: don't write again in destructor if writer panicked while we were writing to it
80
77
panicked : bool ,
81
78
}
82
79
83
80
impl < ' e , E : Engine , W : io:: Write > fmt:: Debug for EncoderWriter < ' e , E , W > {
84
81
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
82
+ let range = self . output_range . clone ( ) ;
83
+ let truncated_len = range. len ( ) . min ( 5 ) ;
84
+ let truncated_range = range. start ..range. start + truncated_len;
85
85
write ! (
86
86
f,
87
- "extra_input: {:?} extra_input_occupied_len:{:?} output[..5 ]: {:?} output_occupied_len : {:?}" ,
88
- self . extra_input,
89
- self . extra_input_occupied_len ,
90
- & self . output[ 0 .. 5 ] ,
91
- self . output_occupied_len
87
+ "extra_input: {:?} occupied output[..{} ]: {:?} output_range : {:?}" ,
88
+ & self . extra_input[ .. self . extra_input_occupied_len ] ,
89
+ truncated_len ,
90
+ & self . output[ truncated_range ] ,
91
+ range ,
92
92
)
93
93
}
94
94
}
@@ -102,7 +102,7 @@ impl<'e, E: Engine, W: io::Write> EncoderWriter<'e, E, W> {
102
102
extra_input : [ 0u8 ; MIN_ENCODE_CHUNK_SIZE ] ,
103
103
extra_input_occupied_len : 0 ,
104
104
output : [ 0u8 ; BUF_SIZE ] ,
105
- output_occupied_len : 0 ,
105
+ output_range : 0 .. 0 ,
106
106
panicked : false ,
107
107
}
108
108
}
@@ -123,7 +123,7 @@ impl<'e, E: Engine, W: io::Write> EncoderWriter<'e, E, W> {
123
123
/// # Errors
124
124
///
125
125
/// The first error that is not of `ErrorKind::Interrupted` will be returned.
126
- pub fn finish ( & mut self ) -> Result < W > {
126
+ pub fn finish ( & mut self ) -> io :: Result < W > {
127
127
// If we could consume self in finish(), we wouldn't have to worry about this case, but
128
128
// finish() is retryable in the face of I/O errors, so we can't consume here.
129
129
if self . delegate . is_none ( ) {
@@ -138,91 +138,72 @@ impl<'e, E: Engine, W: io::Write> EncoderWriter<'e, E, W> {
138
138
}
139
139
140
140
/// Write any remaining buffered data to the delegate writer.
141
- fn write_final_leftovers ( & mut self ) -> Result < ( ) > {
141
+ fn write_final_leftovers ( & mut self ) -> io :: Result < ( ) > {
142
142
if self . delegate . is_none ( ) {
143
143
// finish() has already successfully called this, and we are now in drop() with a None
144
144
// writer, so just no-op
145
145
return Ok ( ( ) ) ;
146
146
}
147
147
148
- self . write_all_encoded_output ( ) ?;
149
-
150
148
if self . extra_input_occupied_len > 0 {
149
+ // Make sure output isn’t full so we can append to it.
150
+ if self . output_range . end == self . output . len ( ) {
151
+ self . flush_output ( ) ?;
152
+ }
153
+
151
154
let encoded_len = self
152
155
. engine
153
156
. encode_slice (
154
157
& self . extra_input [ ..self . extra_input_occupied_len ] ,
155
- & mut self . output [ ..] ,
158
+ & mut self . output [ self . output_range . end ..] ,
156
159
)
157
160
. expect ( "buffer is large enough" ) ;
158
161
159
- self . output_occupied_len = encoded_len;
160
-
161
- self . write_all_encoded_output ( ) ?;
162
-
163
- // write succeeded, do not write the encoding of extra again if finish() is retried
162
+ self . output_range . end += encoded_len;
164
163
self . extra_input_occupied_len = 0 ;
165
164
}
166
165
167
- Ok ( ( ) )
166
+ self . flush_output ( )
168
167
}
169
168
170
- /// Write as much of the encoded output to the delegate writer as it will accept, and store the
171
- /// leftovers to be attempted at the next write() call. Updates `self.output_occupied_len`.
169
+ /// Flushes output buffer to the delegate.
172
170
///
173
- /// # Errors
174
- ///
175
- /// Errors from the delegate writer are returned. In the case of an error,
176
- /// `self.output_occupied_len` will not be updated, as errors from `write` are specified to mean
177
- /// that no write took place.
178
- fn write_to_delegate ( & mut self , current_output_len : usize ) -> Result < ( ) > {
171
+ /// Loops writing data to the delegate until output buffer is empty or
172
+ /// delegate returns an error. A `Ok(0)` return from the delegate is
173
+ /// treated as an error. Updates `output_range` accordingly.
174
+ fn flush_output ( & mut self ) -> io:: Result < ( ) > {
175
+ if self . output_range . is_empty ( ) {
176
+ return Ok ( ( ) ) ;
177
+ }
178
+ loop {
179
+ match self . write_to_delegate ( self . output_range . clone ( ) ) {
180
+ Ok ( 0 ) => {
181
+ break Err ( io:: Error :: new (
182
+ io:: ErrorKind :: WriteZero ,
183
+ "failed to write whole buffer" ,
184
+ ) )
185
+ }
186
+ Ok ( n) if n == self . output_range . len ( ) => {
187
+ self . output_range = 0 ..0 ;
188
+ break Ok ( ( ) ) ;
189
+ }
190
+ Ok ( n) => self . output_range . start += n,
191
+ Err ( err) => break Err ( err) ,
192
+ }
193
+ }
194
+ }
195
+
196
+ /// Writes given range of output buffer to the delegate. Performs exactly
197
+ /// one write. Sets `panicked` to `true` if delegate panics.
198
+ fn write_to_delegate ( & mut self , range : std:: ops:: Range < usize > ) -> io:: Result < usize > {
179
199
self . panicked = true ;
180
200
let res = self
181
201
. delegate
182
202
. as_mut ( )
183
- . expect ( "Writer must be present " )
184
- . write ( & self . output [ ..current_output_len ] ) ;
203
+ . expect ( "Encoder has already had finish() called " )
204
+ . write ( & self . output [ range ] ) ;
185
205
self . panicked = false ;
186
-
187
- res. map ( |consumed| {
188
- debug_assert ! ( consumed <= current_output_len) ;
189
-
190
- if consumed < current_output_len {
191
- self . output_occupied_len = current_output_len. checked_sub ( consumed) . unwrap ( ) ;
192
- // If we're blocking on I/O, the minor inefficiency of copying bytes to the
193
- // start of the buffer is the least of our concerns...
194
- // TODO Rotate moves more than we need to; copy_within now stable.
195
- self . output . rotate_left ( consumed) ;
196
- } else {
197
- self . output_occupied_len = 0 ;
198
- }
199
- } )
200
- }
201
-
202
- /// Write all buffered encoded output. If this returns `Ok`, `self.output_occupied_len` is `0`.
203
- ///
204
- /// This is basically write_all for the remaining buffered data but without the undesirable
205
- /// abort-on-`Ok(0)` behavior.
206
- ///
207
- /// # Errors
208
- ///
209
- /// Any error emitted by the delegate writer abort the write loop and is returned, unless it's
210
- /// `Interrupted`, in which case the error is ignored and writes will continue.
211
- fn write_all_encoded_output ( & mut self ) -> Result < ( ) > {
212
- while self . output_occupied_len > 0 {
213
- let remaining_len = self . output_occupied_len ;
214
- match self . write_to_delegate ( remaining_len) {
215
- // try again on interrupts ala write_all
216
- Err ( ref e) if e. kind ( ) == ErrorKind :: Interrupted => { }
217
- // other errors return
218
- Err ( e) => return Err ( e) ,
219
- // success no-ops because remaining length is already updated
220
- Ok ( _) => { }
221
- } ;
222
- }
223
-
224
- debug_assert_eq ! ( 0 , self . output_occupied_len) ;
225
- Ok ( ( ) )
206
+ res
226
207
}
227
208
228
209
/// Unwraps this `EncoderWriter`, returning the base writer it writes base64 encoded output
@@ -262,38 +243,22 @@ impl<'e, E: Engine, W: io::Write> io::Write for EncoderWriter<'e, E, W> {
262
243
/// # Errors
263
244
///
264
245
/// Any errors emitted by the delegate writer are returned.
265
- fn write ( & mut self , input : & [ u8 ] ) -> Result < usize > {
246
+ fn write ( & mut self , input : & [ u8 ] ) -> io :: Result < usize > {
266
247
if self . delegate . is_none ( ) {
267
248
panic ! ( "Cannot write more after calling finish()" ) ;
268
249
}
269
250
251
+ self . flush_output ( ) ?;
252
+ debug_assert_eq ! ( 0 , self . output_range. len( ) ) ;
253
+
270
254
if input. is_empty ( ) {
271
255
return Ok ( 0 ) ;
272
256
}
273
257
274
- // The contract of `Write::write` places some constraints on this implementation:
275
- // - a call to `write()` represents at most one call to a wrapped `Write`, so we can't
276
- // iterate over the input and encode multiple chunks.
277
- // - Errors mean that "no bytes were written to this writer", so we need to reset the
278
- // internal state to what it was before the error occurred
279
-
280
- // before reading any input, write any leftover encoded output from last time
281
- if self . output_occupied_len > 0 {
282
- let current_len = self . output_occupied_len ;
283
- return self
284
- . write_to_delegate ( current_len)
285
- // did not read any input
286
- . map ( |_| 0 ) ;
287
- }
288
-
289
- debug_assert_eq ! ( 0 , self . output_occupied_len) ;
290
-
291
258
// how many bytes, if any, were read into `extra` to create a triple to encode
292
259
let mut extra_input_read_len = 0 ;
293
260
let mut input = input;
294
261
295
- let orig_extra_len = self . extra_input_occupied_len ;
296
-
297
262
let mut encoded_size = 0 ;
298
263
// always a multiple of MIN_ENCODE_CHUNK_SIZE
299
264
let mut max_input_len = MAX_INPUT_LEN ;
@@ -322,8 +287,10 @@ impl<'e, E: Engine, W: io::Write> io::Write for EncoderWriter<'e, E, W> {
322
287
323
288
input = & input[ extra_input_read_len..] ;
324
289
325
- // consider extra to be used up, since we encoded it
326
- self . extra_input_occupied_len = 0 ;
290
+ // Note: Not updating self.extra_input_occupied_len yet. It’s
291
+ // going to be zeroed at the end of the function if we
292
+ // successfully write some data to delegate.
293
+
327
294
// don't clobber where we just encoded to
328
295
encoded_size = 4 ;
329
296
// and don't read more than can be encoded
@@ -367,29 +334,28 @@ impl<'e, E: Engine, W: io::Write> io::Write for EncoderWriter<'e, E, W> {
367
334
& mut self . output [ encoded_size..] ,
368
335
) ;
369
336
370
- // not updating `self.output_occupied_len ` here because if the below write fails, it should
371
- // "never take place" -- the buffer contents we encoded are ignored and perhaps retried
372
- // later, if the consumer chooses.
337
+ // Not updating `self.output_range ` here because if the write fails, it
338
+ // should "never take place" -- the buffer contents we encoded are
339
+ // ignored and perhaps retried later, if the consumer chooses.
373
340
374
- self . write_to_delegate ( encoded_size)
375
- // no matter whether we wrote the full encoded buffer or not, we consumed the same
376
- // input
377
- . map ( |_| extra_input_read_len + input_chunks_to_encode_len)
378
- . map_err ( |e| {
379
- // in case we filled and encoded `extra`, reset extra_len
380
- self . extra_input_occupied_len = orig_extra_len;
381
-
382
- e
383
- } )
341
+ self . write_to_delegate ( 0 ..encoded_size) . map ( |written| {
342
+ if written < encoded_size {
343
+ self . output_range = written..encoded_size;
344
+ } else {
345
+ debug_assert_eq ! ( 0 , self . output_range. len( ) ) ;
346
+ }
347
+ self . extra_input_occupied_len = 0 ;
348
+ extra_input_read_len + input_chunks_to_encode_len
349
+ } )
384
350
}
385
351
386
352
/// Because this is usually treated as OK to call multiple times, it will *not* flush any
387
353
/// incomplete chunks of input or write padding.
388
354
/// # Errors
389
355
///
390
356
/// The first error that is not of [`ErrorKind::Interrupted`] will be returned.
391
- fn flush ( & mut self ) -> Result < ( ) > {
392
- self . write_all_encoded_output ( ) ?;
357
+ fn flush ( & mut self ) -> io :: Result < ( ) > {
358
+ self . flush_output ( ) ?;
393
359
self . delegate
394
360
. as_mut ( )
395
361
. expect ( "Writer must be present" )
0 commit comments