@@ -145,8 +145,8 @@ pub enum Decoded<'a> {
145
145
FrameMetadata ( & ' a Frame < ' static > , FrameDataType ) ,
146
146
/// Decoded some data of the current frame.
147
147
BytesDecoded ( usize ) ,
148
- /// Copied compressed data of the current frame.
149
- LzwData ( & ' a [ u8 ] ) ,
148
+ /// Copied (or consumed and discarded) compressed data of the current frame. In bytes .
149
+ LzwDataCopied ( usize ) ,
150
150
/// No more data available the current frame.
151
151
DataEnd ,
152
152
}
@@ -244,8 +244,15 @@ impl LzwReader {
244
244
self . decoder . as_ref ( ) . map_or ( true , |e| e. has_ended ( ) )
245
245
}
246
246
247
- pub fn decode_bytes ( & mut self , lzw_data : & [ u8 ] , decode_buffer : & mut [ u8 ] ) -> io:: Result < ( usize , usize ) > {
247
+ pub fn decode_bytes ( & mut self , lzw_data : & [ u8 ] , decode_buffer : & mut OutputBuffer < ' _ > ) -> io:: Result < ( usize , usize ) > {
248
248
let decoder = self . decoder . as_mut ( ) . ok_or_else ( || io:: ErrorKind :: Unsupported ) ?;
249
+
250
+ let decode_buffer = match decode_buffer {
251
+ OutputBuffer :: Slice ( buf) => & mut * * buf,
252
+ OutputBuffer :: None => & mut [ ] ,
253
+ OutputBuffer :: Vec ( _) => return Err ( io:: Error :: from ( io:: ErrorKind :: Unsupported ) ) ,
254
+ } ;
255
+
249
256
let decoded = decoder. decode_bytes ( lzw_data, decode_buffer) ;
250
257
251
258
match decoded. status {
@@ -298,6 +305,15 @@ struct ExtensionData {
298
305
is_block_end : bool ,
299
306
}
300
307
308
+ pub enum OutputBuffer < ' a > {
309
+ /// Overwrite bytes
310
+ Slice ( & ' a mut [ u8 ] ) ,
311
+ /// Append LZW bytes
312
+ Vec ( & ' a mut Vec < u8 > ) ,
313
+ /// Discard bytes
314
+ None ,
315
+ }
316
+
301
317
impl StreamingDecoder {
302
318
/// Creates a new streaming decoder
303
319
pub fn new ( ) -> StreamingDecoder {
@@ -331,16 +347,24 @@ impl StreamingDecoder {
331
347
///
332
348
/// Returns the number of bytes consumed from the input buffer
333
349
/// and the last decoding result.
334
- pub fn update < ' a > ( & ' a mut self , mut buf : & [ u8 ] , mut decode_bytes_into : Option < & mut [ u8 ] > )
350
+ pub fn update < ' a > ( & ' a mut self , mut buf : & [ u8 ] , write_into : & mut OutputBuffer < ' _ > )
335
351
-> Result < ( usize , Decoded < ' a > ) , DecodingError > {
336
352
// NOTE: Do not change the function signature without double-checking the
337
353
// unsafe block!
338
354
let len = buf. len ( ) ;
339
355
while buf. len ( ) > 0 {
356
+ // This dead code is a compile-check for lifetimes that otherwise aren't checked
357
+ // due to the `mem::transmute` used later.
358
+ // Keep it in sync with the other call to `next_state`.
359
+ #[ cfg( test) ]
360
+ if false {
361
+ return self . next_state ( buf, write_into) ;
362
+ }
363
+
340
364
// It's not necessary to check here whether state is `Some`,
341
365
// because `next_state` checks it anyway, and will return `DecodeError`
342
366
// if the state has already been set to `None`.
343
- match self . next_state ( buf, decode_bytes_into . as_deref_mut ( ) ) {
367
+ match self . next_state ( buf, write_into ) {
344
368
Ok ( ( bytes, Decoded :: Nothing ) ) => {
345
369
buf = & buf[ bytes..]
346
370
}
@@ -370,7 +394,6 @@ impl StreamingDecoder {
370
394
}
371
395
}
372
396
Ok ( ( len-buf. len ( ) , Decoded :: Nothing ) )
373
-
374
397
}
375
398
376
399
/// Returns the data of the last extension that has been decoded.
@@ -417,7 +440,7 @@ impl StreamingDecoder {
417
440
}
418
441
}
419
442
420
- fn next_state < ' a > ( & ' a mut self , buf : & ' a [ u8 ] , decode_bytes_into : Option < & mut [ u8 ] > ) -> Result < ( usize , Decoded < ' a > ) , DecodingError > {
443
+ fn next_state ( & mut self , buf : & [ u8 ] , write_into : & mut OutputBuffer < ' _ > ) -> Result < ( usize , Decoded < ' _ > ) , DecodingError > {
421
444
macro_rules! goto (
422
445
( $n: expr, $state: expr) => ( {
423
446
self . state = Some ( $state) ;
@@ -685,9 +708,24 @@ impl StreamingDecoder {
685
708
}
686
709
CopySubBlock ( left) => {
687
710
debug_assert ! ( self . skip_frame_decoding) ;
688
- let n = cmp:: min ( left, buf. len ( ) ) ;
689
711
if left > 0 {
690
- goto ! ( n, CopySubBlock ( left - n) , emit Decoded :: LzwData ( & buf[ ..n] ) )
712
+ let n = cmp:: min ( left, buf. len ( ) ) ;
713
+ let ( consumed, copied) = match write_into {
714
+ OutputBuffer :: Slice ( slice) => {
715
+ let len = cmp:: min ( n, slice. len ( ) ) ;
716
+ slice[ ..len] . copy_from_slice ( & buf[ ..len] ) ;
717
+ ( len, len)
718
+ } ,
719
+ OutputBuffer :: Vec ( vec) => {
720
+ vec. try_reserve ( n) . map_err ( |_| io:: Error :: from ( io:: ErrorKind :: OutOfMemory ) ) ?;
721
+ vec. extend_from_slice ( & buf[ ..n] ) ;
722
+ ( n, n)
723
+ } ,
724
+ // It's valid that bytes are discarded. For example,
725
+ // when using next_frame_info() with skip_frame_decoding to only get metadata.
726
+ OutputBuffer :: None => ( n, 0 ) ,
727
+ } ;
728
+ goto ! ( consumed, CopySubBlock ( left - consumed) , emit Decoded :: LzwDataCopied ( copied) )
691
729
} else if b != 0 {
692
730
goto ! ( CopySubBlock ( b as usize ) )
693
731
} else {
@@ -700,11 +738,11 @@ impl StreamingDecoder {
700
738
debug_assert ! ( !self . skip_frame_decoding) ;
701
739
if left > 0 {
702
740
let n = cmp:: min ( left, buf. len ( ) ) ;
703
- if self . lzw_reader . has_ended ( ) || decode_bytes_into . is_none ( ) {
741
+ if self . lzw_reader . has_ended ( ) || matches ! ( write_into , OutputBuffer :: None ) {
704
742
return goto ! ( n, DecodeSubBlock ( 0 ) , emit Decoded :: BytesDecoded ( 0 ) ) ;
705
743
}
706
744
707
- let ( mut consumed, bytes_len) = self . lzw_reader . decode_bytes ( & buf[ ..n] , decode_bytes_into . unwrap ( ) ) ?;
745
+ let ( mut consumed, bytes_len) = self . lzw_reader . decode_bytes ( & buf[ ..n] , write_into ) ?;
708
746
709
747
// skip if can't make progress (decode would fail if check_for_end_code was set)
710
748
if consumed == 0 && bytes_len == 0 {
@@ -715,7 +753,7 @@ impl StreamingDecoder {
715
753
} else if b != 0 { // decode next sub-block
716
754
goto ! ( DecodeSubBlock ( b as usize ) )
717
755
} else {
718
- let ( _, bytes_len) = self . lzw_reader . decode_bytes ( & [ ] , decode_bytes_into . unwrap_or ( & mut [ ] ) ) ?;
756
+ let ( _, bytes_len) = self . lzw_reader . decode_bytes ( & [ ] , write_into ) ?;
719
757
720
758
if bytes_len > 0 {
721
759
goto ! ( 0 , DecodeSubBlock ( 0 ) , emit Decoded :: BytesDecoded ( bytes_len) )
0 commit comments