@@ -302,16 +302,37 @@ fn decode_without_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes
302
302
/// `decode_without_base64()` composed with
303
303
/// <https://infra.spec.whatwg.org/#isomorphic-decode> composed with
304
304
/// <https://infra.spec.whatwg.org/#forgiving-base64-decode>.
305
- fn decode_with_base64 < F , E > ( encoded_body_plus_fragment : & str , mut write_bytes : F )
305
+ fn decode_with_base64 < F , E > ( encoded_body_plus_fragment : & str , write_bytes : F )
306
306
-> Result < Option < FragmentIdentifier > , DecodeError < E > >
307
307
where F : FnMut ( & [ u8 ] ) -> Result < ( ) , E >
308
308
{
309
- let mut bit_buffer: u32 = 0 ;
310
- let mut buffer_bit_length: u8 = 0 ;
311
- let mut padding_symbols: u8 = 0 ;
309
+ let mut decoder = ForgivingBase64Decoder :: new ( write_bytes) ;
310
+ let fragment = decode_without_base64 ( encoded_body_plus_fragment, |bytes| decoder. feed ( bytes) ) ?;
311
+ decoder. finish ( ) ?;
312
+ Ok ( fragment)
313
+ }
314
+
315
+ /// <https://infra.spec.whatwg.org/#forgiving-base64-decode>
316
+ pub struct ForgivingBase64Decoder < F , E > where F : FnMut ( & [ u8 ] ) -> Result < ( ) , E > {
317
+ write_bytes : F ,
318
+ bit_buffer : u32 ,
319
+ buffer_bit_length : u8 ,
320
+ padding_symbols : u8 ,
321
+ }
322
+
323
+ impl < F , E > ForgivingBase64Decoder < F , E > where F : FnMut ( & [ u8 ] ) -> Result < ( ) , E > {
324
+ pub fn new ( write_bytes : F ) -> Self {
325
+ Self {
326
+ write_bytes,
327
+ bit_buffer : 0 ,
328
+ buffer_bit_length : 0 ,
329
+ padding_symbols : 0 ,
330
+ }
331
+ }
312
332
313
- let fragment = decode_without_base64 :: < _ , DecodeError < E > > ( encoded_body_plus_fragment, |bytes| {
314
- for & byte in bytes. iter ( ) {
333
+ /// Feed to the decoder partial input in an ASCII-compatible encoding
334
+ pub fn feed ( & mut self , input : & [ u8 ] ) -> Result < ( ) , DecodeError < E > > {
335
+ for & byte in input. iter ( ) {
315
336
let value = BASE64_DECODE_TABLE [ byte as usize ] ;
316
337
if value < 0 {
317
338
// A character that’s not part of the alphabet
@@ -323,64 +344,69 @@ fn decode_with_base64<F, E>(encoded_body_plus_fragment: &str, mut write_bytes: F
323
344
}
324
345
325
346
if byte == b'=' {
326
- padding_symbols = padding_symbols. saturating_add ( 8 ) ;
347
+ self . padding_symbols = self . padding_symbols . saturating_add ( 8 ) ;
327
348
continue
328
349
}
329
350
330
351
Err ( InvalidBase64 ( ( ) ) ) ?
331
352
}
332
- if padding_symbols > 0 {
353
+ if self . padding_symbols > 0 {
333
354
// Alphabet symbols after padding
334
355
Err ( InvalidBase64 ( ( ) ) ) ?
335
356
}
336
- bit_buffer <<= 6 ;
337
- bit_buffer |= value as u32 ;
338
- if buffer_bit_length < 24 {
339
- buffer_bit_length += 6 ;
357
+ self . bit_buffer <<= 6 ;
358
+ self . bit_buffer |= value as u32 ;
359
+ if self . buffer_bit_length < 24 {
360
+ self . buffer_bit_length += 6 ;
340
361
} else {
341
362
// We’ve accumulated four times 6 bits, which equals three times 8 bits.
342
363
let byte_buffer = [
343
- ( bit_buffer >> 16 ) as u8 ,
344
- ( bit_buffer >> 8 ) as u8 ,
345
- bit_buffer as u8 ,
364
+ ( self . bit_buffer >> 16 ) as u8 ,
365
+ ( self . bit_buffer >> 8 ) as u8 ,
366
+ self . bit_buffer as u8 ,
346
367
] ;
347
- write_bytes ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
348
- buffer_bit_length = 0 ;
368
+ ( self . write_bytes ) ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
369
+ self . buffer_bit_length = 0 ;
349
370
// No need to reset bit_buffer,
350
371
// since next time we’re only gonna read relevant bits.
351
372
}
352
373
}
353
374
Ok ( ( ) )
354
- } ) ?;
355
- match ( buffer_bit_length, padding_symbols) {
356
- ( 0 , 0 ) => {
357
- // A multiple of four of alphabet symbols, and nothing else.
358
- }
359
- ( 12 , 2 ) | ( 12 , 0 ) => {
360
- // A multiple of four of alphabet symbols, followed by two more symbols,
361
- // optionally followed by two padding characters (which make a total multiple of four).
362
- let byte_buffer = [
363
- ( bit_buffer >> 4 ) as u8 ,
364
- ] ;
365
- write_bytes ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
366
- }
367
- ( 18 , 1 ) | ( 18 , 0 ) => {
368
- // A multiple of four of alphabet symbols, followed by three more symbols,
369
- // optionally followed by one padding character (which make a total multiple of four).
370
- let byte_buffer = [
371
- ( bit_buffer >> 10 ) as u8 ,
372
- ( bit_buffer >> 2 ) as u8 ,
373
- ] ;
374
- write_bytes ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
375
- }
376
- _ => {
377
- // No other combination is acceptable
378
- Err ( InvalidBase64 ( ( ) ) ) ?
375
+ }
376
+
377
+ /// Call this to signal the end of the input
378
+ pub fn finish ( mut self ) -> Result < ( ) , DecodeError < E > > {
379
+ match ( self . buffer_bit_length , self . padding_symbols ) {
380
+ ( 0 , 0 ) => {
381
+ // A multiple of four of alphabet symbols, and nothing else.
382
+ }
383
+ ( 12 , 2 ) | ( 12 , 0 ) => {
384
+ // A multiple of four of alphabet symbols, followed by two more symbols,
385
+ // optionally followed by two padding characters (which make a total multiple of four).
386
+ let byte_buffer = [
387
+ ( self . bit_buffer >> 4 ) as u8 ,
388
+ ] ;
389
+ ( self . write_bytes ) ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
390
+ }
391
+ ( 18 , 1 ) | ( 18 , 0 ) => {
392
+ // A multiple of four of alphabet symbols, followed by three more symbols,
393
+ // optionally followed by one padding character (which make a total multiple of four).
394
+ let byte_buffer = [
395
+ ( self . bit_buffer >> 10 ) as u8 ,
396
+ ( self . bit_buffer >> 2 ) as u8 ,
397
+ ] ;
398
+ ( self . write_bytes ) ( & byte_buffer) . map_err ( DecodeError :: WriteError ) ?;
399
+ }
400
+ _ => {
401
+ // No other combination is acceptable
402
+ Err ( InvalidBase64 ( ( ) ) ) ?
403
+ }
379
404
}
405
+ Ok ( ( ) )
380
406
}
381
- Ok ( fragment)
382
407
}
383
408
409
+
384
410
/// Generated by `make_base64_decode_table.py` based on "Table 1: The Base 64 Alphabet"
385
411
/// at <https://tools.ietf.org/html/rfc4648#section-4>
386
412
///
0 commit comments