gif/reader/
decoder.rs

1use std::borrow::Cow;
2use std::cmp;
3use std::default::Default;
4use std::error;
5use std::fmt;
6use std::io;
7use std::mem;
8use std::num::NonZeroUsize;
9
10use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame};
11use crate::reader::DecodeOptions;
12use crate::MemoryLimit;
13use crate::Repeat;
14
15use weezl::{decode::Decoder as LzwDecoder, BitOrder, LzwError, LzwStatus};
16
17/// GIF palettes are RGB
18pub const PLTE_CHANNELS: usize = 3;
19
20/// An error returned in the case of the image not being formatted properly.
21#[derive(Debug)]
22pub struct DecodingFormatError {
23    underlying: Box<dyn error::Error + Send + Sync + 'static>,
24}
25
26impl fmt::Display for DecodingFormatError {
27    #[cold]
28    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
29        fmt::Display::fmt(&*self.underlying, fmt)
30    }
31}
32
33impl error::Error for DecodingFormatError {
34    #[cold]
35    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
36        Some(&*self.underlying as _)
37    }
38}
39
40#[derive(Debug)]
41/// Decoding error.
42pub enum DecodingError {
43    /// Returned if the image is found to be malformed.
44    Format(DecodingFormatError),
45    /// Wraps `std::io::Error`.
46    Io(io::Error),
47}
48
49impl DecodingError {
50    #[cold]
51    pub(crate) fn format(err: &'static str) -> Self {
52        Self::Format(DecodingFormatError {
53            underlying: err.into(),
54        })
55    }
56}
57
58impl fmt::Display for DecodingError {
59    #[cold]
60    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
61        match *self {
62            Self::Format(ref d) => d.fmt(fmt),
63            Self::Io(ref err) => err.fmt(fmt),
64        }
65    }
66}
67
68impl error::Error for DecodingError {
69    #[cold]
70    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
71        match *self {
72            Self::Format(ref err) => Some(err),
73            Self::Io(ref err) => Some(err),
74        }
75    }
76}
77
78impl From<io::Error> for DecodingError {
79    #[inline]
80    fn from(err: io::Error) -> Self {
81        Self::Io(err)
82    }
83}
84
85impl From<io::ErrorKind> for DecodingError {
86    #[cold]
87    fn from(err: io::ErrorKind) -> Self {
88        Self::Io(io::Error::from(err))
89    }
90}
91
92impl From<DecodingFormatError> for DecodingError {
93    #[inline]
94    fn from(err: DecodingFormatError) -> Self {
95        Self::Format(err)
96    }
97}
98
99/// Varies depending on `skip_frame_decoding`
100#[derive(Debug, Copy, Clone)]
101pub enum FrameDataType {
102    /// `Frame.buffer` will be regular pixel data
103    Pixels,
104    /// Raw LZW data
105    Lzw {
106        /// Needed for decoding
107        min_code_size: u8,
108    },
109}
110
111/// Indicates whether a certain object has been decoded
112#[derive(Debug)]
113#[non_exhaustive]
114pub enum Decoded {
115    /// Decoded nothing.
116    Nothing,
117    /// Global palette.
118    GlobalPalette(Box<[u8]>),
119    /// Index of the background color in the global palette.
120    BackgroundColor(u8),
121    /// Loop count is known
122    Repetitions(Repeat),
123    /// Palette and optional `Application` extension have been parsed,
124    /// reached frame data.
125    HeaderEnd,
126    /// The start of a block.
127    /// `BlockStart(Block::Trailer)` is the very last decode event
128    BlockStart(Block),
129    /// Decoded a sub-block. More sub-block are available.
130    ///
131    /// Indicates the label of the extension which might be unknown. A label of `0` is used when
132    /// the sub block does not belong to an extension.
133    ///
134    /// Call `last_ext()` to get the data
135    SubBlockFinished(AnyExtension),
136    /// Decoded the last (or only) sub-block of a block.
137    ///
138    /// Indicates the label of the extension which might be unknown. A label of `0` is used when
139    /// the sub block does not belong to an extension.
140    ///
141    /// Call `last_ext()` to get the data
142    BlockFinished(AnyExtension),
143    /// Decoded all information of the next frame, except the image data.
144    ///
145    /// The returned frame does **not** contain any owned image data.
146    ///
147    /// Call `current_frame_mut()` to access the frame info.
148    FrameMetadata(FrameDataType),
149    /// Decoded some data of the current frame. Size is in bytes, always > 0
150    BytesDecoded(NonZeroUsize),
151    /// Copied (or consumed and discarded) compressed data of the current frame. In bytes.
152    LzwDataCopied(usize),
153    /// No more data available the current frame.
154    DataEnd,
155}
156
157/// Internal state of the GIF decoder
158#[derive(Debug, Copy, Clone)]
159enum State {
160    Magic,
161    ScreenDescriptor,
162    ImageBlockStart,
163    GlobalPalette(usize),
164    BlockStart(u8),
165    BlockEnd,
166    ExtensionBlockStart,
167    /// Collects data in ext.data
168    ExtensionDataBlock(usize),
169    ApplicationExtension,
170    LocalPalette(usize),
171    LzwInit(u8),
172    /// Decompresses LZW
173    DecodeSubBlock(usize),
174    /// Keeps LZW compressed
175    CopySubBlock(usize),
176    FrameDecoded,
177    Trailer,
178}
179use self::State::*;
180
181use super::converter::PixelConverter;
182
183/// Decoder for `Frame::make_lzw_pre_encoded`
184pub struct FrameDecoder {
185    lzw_reader: LzwReader,
186    pixel_converter: PixelConverter,
187}
188
189impl FrameDecoder {
190    /// See also `set_global_palette`
191    #[inline]
192    #[must_use]
193    pub fn new(options: DecodeOptions) -> Self {
194        Self {
195            lzw_reader: LzwReader::new(options.check_for_end_code),
196            pixel_converter: PixelConverter::new(options.color_output, options.memory_limit),
197        }
198    }
199
200    /// Palette used for RGBA conversion
201    #[inline]
202    pub fn set_global_palette(&mut self, palette: Vec<u8>) {
203        self.pixel_converter.set_global_palette(palette);
204    }
205
206    /// Converts the frame in-place, replacing its LZW buffer with pixels.
207    ///
208    /// If you get an error about invalid min code size, the buffer was probably pixels, not compressed data.
209    #[inline]
210    pub fn decode_lzw_encoded_frame(&mut self, frame: &mut Frame<'_>) -> Result<(), DecodingError> {
211        let pixel_bytes = self.pixel_converter.check_buffer_size(frame)?;
212        let mut vec = vec![0; pixel_bytes];
213        self.decode_lzw_encoded_frame_into_buffer(frame, &mut vec)?;
214        frame.buffer = Cow::Owned(vec);
215        frame.interlaced = false;
216        Ok(())
217    }
218
219    /// Converts into the given buffer. It must be [`buffer_size()`] bytes large.
220    ///
221    /// Pixels are always deinterlaced, so update `frame.interlaced` afterwards if you're putting the buffer back into the frame.
222    pub fn decode_lzw_encoded_frame_into_buffer(
223        &mut self,
224        frame: &Frame<'_>,
225        buf: &mut [u8],
226    ) -> Result<(), DecodingError> {
227        let (&min_code_size, mut data) = frame.buffer.split_first().unwrap_or((&2, &[]));
228        self.lzw_reader.reset(min_code_size)?;
229        let lzw_reader = &mut self.lzw_reader;
230        self.pixel_converter
231            .read_into_buffer(frame, buf, &mut move |out| loop {
232                let (bytes_read, bytes_written, status) = lzw_reader.decode_bytes(data, out)?;
233                data = data.get(bytes_read..).unwrap_or_default();
234                if bytes_written > 0 || matches!(status, LzwStatus::NoProgress) {
235                    return Ok(bytes_written);
236                }
237            })?;
238        Ok(())
239    }
240
241    /// Number of bytes required for `decode_lzw_encoded_frame_into_buffer`
242    #[inline]
243    #[must_use]
244    pub fn buffer_size(&self, frame: &Frame<'_>) -> usize {
245        self.pixel_converter.buffer_size(frame).unwrap()
246    }
247}
248
249struct LzwReader {
250    decoder: Option<LzwDecoder>,
251    min_code_size: u8,
252    check_for_end_code: bool,
253}
254
255impl LzwReader {
256    pub fn new(check_for_end_code: bool) -> Self {
257        Self {
258            decoder: None,
259            min_code_size: 0,
260            check_for_end_code,
261        }
262    }
263
264    pub fn check_code_size(min_code_size: u8) -> Result<(), DecodingError> {
265        // LZW spec: max 12 bits per code. This check helps catch confusion
266        // between LZW-compressed buffers and raw pixel data
267        if min_code_size > 11 || min_code_size < 1 {
268            return Err(DecodingError::format("invalid minimal code size"));
269        }
270        Ok(())
271    }
272
273    pub fn reset(&mut self, min_code_size: u8) -> Result<(), DecodingError> {
274        Self::check_code_size(min_code_size)?;
275
276        // The decoder can be reused if the code size stayed the same
277        if self.min_code_size != min_code_size || self.decoder.is_none() {
278            self.min_code_size = min_code_size;
279            self.decoder = Some(LzwDecoder::new(BitOrder::Lsb, min_code_size));
280        } else {
281            self.decoder.as_mut().ok_or_else(|| DecodingError::format("bad state"))?.reset();
282        }
283
284        Ok(())
285    }
286
287    pub fn has_ended(&self) -> bool {
288        self.decoder.as_ref().map_or(true, |e| e.has_ended())
289    }
290
291    pub fn decode_bytes(
292        &mut self,
293        lzw_data: &[u8],
294        decode_buffer: &mut OutputBuffer<'_>,
295    ) -> io::Result<(usize, usize, LzwStatus)> {
296        let decoder = self.decoder.as_mut().ok_or(io::ErrorKind::Unsupported)?;
297
298        let decode_buffer = match decode_buffer {
299            OutputBuffer::Slice(buf) => &mut **buf,
300            OutputBuffer::None => &mut [],
301            OutputBuffer::Vec(_) => return Err(io::Error::from(io::ErrorKind::Unsupported)),
302        };
303
304        let decoded = decoder.decode_bytes(lzw_data, decode_buffer);
305
306        let status = match decoded.status {
307            Ok(ok @ LzwStatus::Done | ok @ LzwStatus::Ok) => ok,
308            Ok(ok @ LzwStatus::NoProgress) => {
309                if self.check_for_end_code {
310                    return Err(io::Error::new(
311                        io::ErrorKind::InvalidData,
312                        "no end code in lzw stream",
313                    ));
314                }
315
316                ok
317            }
318            Err(err @ LzwError::InvalidCode) => {
319                return Err(io::Error::new(io::ErrorKind::InvalidData, err));
320            }
321        };
322
323        Ok((decoded.consumed_in, decoded.consumed_out, status))
324    }
325}
326
327/// GIF decoder which emits [low-level events](Decoded) for items in the GIF file
328///
329/// To just get GIF frames, use [`crate::Decoder`] instead.
330pub struct StreamingDecoder {
331    state: State,
332    /// Input bytes are collected here if `update` got `buf` smaller than the minimum required
333    internal_buffer: [u8; 9],
334    unused_internal_buffer_len: u8,
335    lzw_reader: LzwReader,
336    skip_frame_decoding: bool,
337    check_frame_consistency: bool,
338    allow_unknown_blocks: bool,
339    memory_limit: MemoryLimit,
340    version: Version,
341    width: u16,
342    height: u16,
343    global_color_table: Vec<u8>,
344    /// ext buffer
345    ext: ExtensionData,
346    /// Frame data
347    current: Option<Frame<'static>>,
348    /// Needs to emit `HeaderEnd` once
349    header_end_reached: bool,
350}
351
352/// One version number of the GIF standard.
353#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
354pub enum Version {
355    /// Version 87a, from May 1987.
356    V87a,
357    /// Version 89a, from July 1989.
358    V89a,
359}
360
361struct ExtensionData {
362    id: AnyExtension,
363    data: Vec<u8>,
364    is_block_end: bool,
365}
366
367/// Destination to write to for `StreamingDecoder::update`
368pub enum OutputBuffer<'a> {
369    /// Overwrite bytes
370    Slice(&'a mut [u8]),
371    /// Append LZW bytes
372    Vec(&'a mut Vec<u8>),
373    /// Discard bytes
374    None,
375}
376
377impl OutputBuffer<'_> {
378    fn append(&mut self, buf: &[u8], memory_limit: &MemoryLimit) -> Result<(usize, usize), DecodingError> {
379        let (consumed, copied) = match self {
380            OutputBuffer::Slice(slice) => {
381                let len = cmp::min(buf.len(), slice.len());
382                slice[..len].copy_from_slice(&buf[..len]);
383                (len, len)
384            },
385            OutputBuffer::Vec(vec) => {
386                let vec: &mut Vec<u8> = vec;
387                let len = buf.len();
388                memory_limit.check_size(vec.len() + len)?;
389                vec.try_reserve(len).map_err(|_| io::ErrorKind::OutOfMemory)?;
390                if vec.capacity() - vec.len() >= len {
391                    vec.extend_from_slice(buf);
392                }
393                (len, len)
394            },
395            // It's valid that bytes are discarded. For example,
396            // when using next_frame_info() with skip_frame_decoding to only get metadata.
397            OutputBuffer::None => (buf.len(), 0),
398        };
399        Ok((consumed, copied))
400    }
401}
402
403impl StreamingDecoder {
404    /// Creates a new streaming decoder
405    #[must_use]
406    pub fn new() -> Self {
407        let options = DecodeOptions::new();
408        Self::with_options(&options)
409    }
410
411    pub(crate) fn with_options(options: &DecodeOptions) -> Self {
412        Self {
413            internal_buffer: [0; 9],
414            unused_internal_buffer_len: 0,
415            state: Magic,
416            lzw_reader: LzwReader::new(options.check_for_end_code),
417            skip_frame_decoding: options.skip_frame_decoding,
418            check_frame_consistency: options.check_frame_consistency,
419            allow_unknown_blocks: options.allow_unknown_blocks,
420            memory_limit: options.memory_limit.clone(),
421            version: Version::V87a,
422            width: 0,
423            height: 0,
424            global_color_table: Vec::new(),
425            ext: ExtensionData {
426                id: AnyExtension(0),
427                data: Vec::with_capacity(256), // 0xFF + 1 byte length
428                is_block_end: true,
429            },
430            current: None,
431            header_end_reached: false,
432        }
433    }
434
435    /// Updates the internal state of the decoder.
436    ///
437    /// Returns the number of bytes consumed from the input buffer
438    /// and the last decoding result.
439    pub fn update(
440        &mut self,
441        mut buf: &[u8],
442        write_into: &mut OutputBuffer<'_>,
443    ) -> Result<(usize, Decoded), DecodingError> {
444        let len = buf.len();
445        while !buf.is_empty() {
446            let (bytes, decoded) = self.next_state(buf, write_into)?;
447            buf = buf.get(bytes..).unwrap_or_default();
448            match decoded {
449                Decoded::Nothing => {},
450                result => {
451                    return Ok((len-buf.len(), result));
452                },
453            };
454        }
455        Ok((len - buf.len(), Decoded::Nothing))
456    }
457
458    /// Returns the data of the last extension that has been decoded.
459    #[must_use]
460    pub fn last_ext(&self) -> (AnyExtension, &[u8], bool) {
461        (self.ext.id, &self.ext.data, self.ext.is_block_end)
462    }
463
464    /// Current frame info as a mutable ref.
465    #[must_use]
466    #[track_caller]
467    pub fn current_frame_mut(&mut self) -> &mut Frame<'static> {
468        self.current.as_mut().unwrap()
469    }
470
471    /// Current frame info as a ref.
472    #[track_caller]
473    #[must_use]
474    pub fn current_frame(&self) -> &Frame<'static> {
475        self.current.as_ref().unwrap()
476    }
477
478    /// Current frame info as a mutable ref.
479    #[inline(always)]
480    fn try_current_frame(&mut self) -> Result<&mut Frame<'static>, DecodingError> {
481        self.current.as_mut().ok_or_else(|| DecodingError::format("bad state"))
482    }
483
484    /// Width of the image
485    #[must_use]
486    pub fn width(&self) -> u16 {
487        self.width
488    }
489
490    /// Height of the image
491    #[must_use]
492    pub fn height(&self) -> u16 {
493        self.height
494    }
495
496    /// The version number of the GIF standard used in this image.
497    ///
498    /// We suppose a minimum of `V87a` compatibility. This value will be reported until we have
499    /// read the version information in the magic header bytes.
500    #[must_use]
501    pub fn version(&self) -> Version {
502        self.version
503    }
504
505    #[inline]
506    fn next_state(&mut self, buf: &[u8], write_into: &mut OutputBuffer<'_>) -> Result<(usize, Decoded), DecodingError> {
507        macro_rules! goto (
508            ($n:expr, $state:expr) => ({
509                self.state = $state;
510                Ok(($n, Decoded::Nothing))
511            });
512            ($state:expr) => ({
513                self.state = $state;
514                Ok((1, Decoded::Nothing))
515            });
516            ($n:expr, $state:expr, emit $res:expr) => ({
517                self.state = $state;
518                Ok(($n, $res))
519            });
520            ($state:expr, emit $res:expr) => ({
521                self.state = $state;
522                Ok((1, $res))
523            })
524        );
525
526        macro_rules! ensure_min_length_buffer (
527            ($required:expr) => ({
528                let required: usize = $required;
529                if buf.len() >= required && self.unused_internal_buffer_len == 0 {
530                    (required, &buf[..required])
531                } else {
532                    let has = usize::from(self.unused_internal_buffer_len);
533                    let mut consumed = 0;
534                    if has < required {
535                        let to_copy = buf.len().min(required - has);
536                        let new_len = has + to_copy;
537                        self.internal_buffer[has .. new_len].copy_from_slice(&buf[..to_copy]);
538                        consumed += to_copy;
539                        if new_len < required {
540                            self.unused_internal_buffer_len = new_len as u8;
541                            return Ok((consumed, Decoded::Nothing));
542                        } else {
543                            self.unused_internal_buffer_len = 0;
544                        }
545                    }
546                    (consumed, &self.internal_buffer[..required])
547                }
548            })
549        );
550
551        let b = *buf.first().ok_or(io::ErrorKind::UnexpectedEof)?;
552
553        match self.state {
554            Magic => {
555                let (consumed, version) = ensure_min_length_buffer!(6);
556
557                self.version = match version {
558                    b"GIF87a" => Version::V87a,
559                    b"GIF89a" => Version::V89a,
560                    _ => return Err(DecodingError::format("malformed GIF header")),
561                };
562
563                goto!(consumed, ScreenDescriptor)
564            },
565            ScreenDescriptor => {
566                let (consumed, desc) = ensure_min_length_buffer!(7);
567
568                self.width = u16::from_le_bytes(desc[..2].try_into().unwrap());
569                self.height = u16::from_le_bytes(desc[2..4].try_into().unwrap());
570                let global_flags = desc[4];
571                let background_color = desc[5];
572
573                let global_table = global_flags & 0x80 != 0;
574                let table_size = if global_table {
575                    let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize);
576                    self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::ErrorKind::OutOfMemory)?;
577                    table_size
578                } else {
579                    0usize
580                };
581
582                goto!(
583                    consumed,
584                    GlobalPalette(table_size),
585                    emit Decoded::BackgroundColor(background_color)
586                )
587            },
588            ImageBlockStart => {
589                let (consumed, header) = ensure_min_length_buffer!(9);
590
591                let frame = self.current.as_mut().ok_or_else(|| DecodingError::format("bad state"))?;
592                frame.left = u16::from_le_bytes(header[..2].try_into().unwrap());
593                frame.top = u16::from_le_bytes(header[2..4].try_into().unwrap());
594                frame.width = u16::from_le_bytes(header[4..6].try_into().unwrap());
595                frame.height = u16::from_le_bytes(header[6..8].try_into().unwrap());
596
597                let flags = header[8];
598                frame.interlaced = (flags & 0b0100_0000) != 0;
599
600                if self.check_frame_consistency {
601                    // Consistency checks.
602                    if self.width.checked_sub(frame.width) < Some(frame.left)
603                        || self.height.checked_sub(frame.height) < Some(frame.top)
604                    {
605                        return Err(DecodingError::format("frame descriptor is out-of-bounds"));
606                    }
607                }
608
609                let local_table = (flags & 0b1000_0000) != 0;
610                if local_table {
611                    let table_size = flags & 0b0000_0111;
612                    let pal_len = PLTE_CHANNELS * (1 << (table_size + 1));
613                    frame.palette.get_or_insert_with(Vec::new)
614                        .try_reserve_exact(pal_len).map_err(|_| io::ErrorKind::OutOfMemory)?;
615                    goto!(consumed, LocalPalette(pal_len))
616                } else {
617                    goto!(consumed, LocalPalette(0))
618                }
619            },
620            GlobalPalette(left) => {
621                // the global_color_table is guaranteed to have the exact capacity required
622                if left > 0 {
623                    let n = cmp::min(left, buf.len());
624                    if n <= self.global_color_table.capacity() - self.global_color_table.len() {
625                        self.global_color_table.extend_from_slice(&buf[..n]);
626                    }
627                    goto!(n, GlobalPalette(left - n))
628                } else {
629                    goto!(BlockStart(b), emit Decoded::GlobalPalette(
630                        mem::take(&mut self.global_color_table).into_boxed_slice()
631                    ))
632                }
633            }
634            BlockStart(type_) => {
635                if !self.header_end_reached && type_ != Block::Extension as u8 {
636                    self.header_end_reached = true;
637                    return goto!(0, BlockStart(type_), emit Decoded::HeaderEnd);
638                }
639
640                match Block::from_u8(type_) {
641                    Some(Block::Image) => {
642                        self.add_frame();
643                        goto!(0, ImageBlockStart, emit Decoded::BlockStart(Block::Image))
644                    }
645                    Some(Block::Extension) => {
646                        self.ext.data.clear();
647                        self.ext.id = AnyExtension(b);
648                        if self.ext.id.into_known().is_none() {
649                            if !self.allow_unknown_blocks {
650                                return Err(DecodingError::format(
651                                    "unknown extension block encountered",
652                                ));
653                            }
654                        }
655                        goto!(ExtensionBlockStart, emit Decoded::BlockStart(Block::Extension))
656                    }
657                    Some(Block::Trailer) => {
658                        // The `Trailer` is the final state, and isn't reachable without extraneous data after the end of file
659                        goto!(Trailer, emit Decoded::BlockStart(Block::Trailer))
660                    }
661                    None => {
662                        if self.allow_unknown_blocks {
663                            goto!(ExtensionDataBlock(b as usize))
664                        } else {
665                            Err(DecodingError::format("unknown block type encountered"))
666                        }
667                    }
668                }
669            },
670            BlockEnd => {
671                if b == Block::Trailer as u8 {
672                    // can't consume yet, because the trailer is not a real block,
673                    // and won't have futher data for BlockStart
674                    goto!(0, BlockStart(b))
675                } else {
676                    goto!(BlockStart(b))
677                }
678            }
679            ExtensionBlockStart => {
680                self.ext.data.push(b);
681                goto!(ExtensionDataBlock(b as usize))
682            }
683            ExtensionDataBlock(left) => {
684                if left > 0 {
685                    let n = cmp::min(left, buf.len());
686                    self.memory_limit.check_size(self.ext.data.len() + n)?;
687                    self.ext.data.try_reserve(n).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
688                    self.ext.data.extend_from_slice(&buf[..n]);
689                    goto!(n, ExtensionDataBlock(left - n))
690                } else if b == 0 {
691                    self.ext.is_block_end = true;
692                    match self.ext.id.into_known() {
693                        Some(Extension::Application) => {
694                            goto!(0, ApplicationExtension, emit Decoded::BlockFinished(self.ext.id))
695                        }
696                        Some(Extension::Control) => {
697                            self.read_control_extension()?;
698                            goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id))
699                        },
700                        _ => {
701                            goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id))
702                        }
703                    }
704                } else {
705                    self.ext.is_block_end = false;
706                    goto!(ExtensionDataBlock(b as usize), emit Decoded::SubBlockFinished(self.ext.id))
707                }
708            }
709            ApplicationExtension => {
710                debug_assert_eq!(0, b);
711                // the parser removes sub-block lenghts, so app name and data are concatenated
712                if self.ext.data.len() >= 15 && &self.ext.data[1..13] == b"NETSCAPE2.0\x01" {
713                    let repeat = &self.ext.data[13..15];
714                    let repeat = u16::from(repeat[0]) | u16::from(repeat[1]) << 8;
715                    goto!(BlockEnd, emit Decoded::Repetitions(if repeat == 0 { Repeat::Infinite } else { Repeat::Finite(repeat) }))
716                } else {
717                    goto!(BlockEnd)
718                }
719            }
720            LocalPalette(left) => {
721                if left > 0 {
722                    let n = cmp::min(left, buf.len());
723                    let src = &buf[..n];
724                    if let Some(pal) = self.try_current_frame()?.palette.as_mut() {
725                        // capacity has already been reserved in ImageBlockStart
726                        if pal.capacity() - pal.len() >= src.len() {
727                            pal.extend_from_slice(src);
728                        }
729                    }
730                    goto!(n, LocalPalette(left - n))
731                } else {
732                    goto!(LzwInit(b))
733                }
734            }
735            LzwInit(min_code_size) => {
736                if !self.skip_frame_decoding {
737                    // Reset validates the min code size
738                    self.lzw_reader.reset(min_code_size)?;
739                    goto!(DecodeSubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Pixels))
740                } else {
741                    LzwReader::check_code_size(min_code_size)?;
742                    goto!(CopySubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Lzw { min_code_size }))
743                }
744            }
745            CopySubBlock(left) => {
746                debug_assert!(self.skip_frame_decoding);
747                if left > 0 {
748                    let n = cmp::min(left, buf.len());
749                    let (consumed, copied) = write_into.append(&buf[..n], &self.memory_limit)?;
750                    goto!(consumed, CopySubBlock(left - consumed), emit Decoded::LzwDataCopied(copied))
751                } else if b != 0 {
752                    goto!(CopySubBlock(b as usize))
753                } else {
754                    goto!(0, FrameDecoded)
755                }
756            }
757            DecodeSubBlock(left) => {
758                debug_assert!(!self.skip_frame_decoding);
759                if left > 0 {
760                    let n = cmp::min(left, buf.len());
761                    if self.lzw_reader.has_ended() || matches!(write_into, OutputBuffer::None) {
762                        return goto!(n, DecodeSubBlock(left - n), emit Decoded::Nothing);
763                    }
764
765                    let (mut consumed, bytes_len, status) =
766                        self.lzw_reader.decode_bytes(&buf[..n], write_into)?;
767
768                    // skip if can't make progress (decode would fail if check_for_end_code was set)
769                    if matches!(status, LzwStatus::NoProgress) {
770                        consumed = n;
771                    }
772
773                    let decoded = if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
774                        Decoded::BytesDecoded(bytes_len)
775                    } else {
776                        Decoded::Nothing
777                    };
778                    goto!(consumed, DecodeSubBlock(left - consumed), emit decoded)
779                } else if b != 0 {
780                    // decode next sub-block
781                    goto!(DecodeSubBlock(b as usize))
782                } else {
783                    let (_, bytes_len, status) = self.lzw_reader.decode_bytes(&[], write_into)?;
784
785                    if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
786                        goto!(0, DecodeSubBlock(0), emit Decoded::BytesDecoded(bytes_len))
787                    } else if matches!(status, LzwStatus::Ok) {
788                        goto!(0, DecodeSubBlock(0), emit Decoded::Nothing)
789                    } else if matches!(status, LzwStatus::Done) {
790                        goto!(0, FrameDecoded)
791                    } else {
792                        goto!(0, FrameDecoded)
793                    }
794                }
795            }
796            FrameDecoded => {
797                // end of image data reached
798                self.current = None;
799                debug_assert_eq!(0, b);
800                goto!(BlockEnd, emit Decoded::DataEnd)
801            }
802            Trailer => goto!(0, Trailer, emit Decoded::Nothing),
803        }
804    }
805
806    fn read_control_extension(&mut self) -> Result<(), DecodingError> {
807        if self.ext.data.len() != 5 {
808            return Err(DecodingError::format("control extension has wrong length"));
809        }
810        let control = &self.ext.data[1..];
811
812        let frame = self.current.get_or_insert_with(Frame::default);
813        let control_flags = control[0];
814        frame.needs_user_input = control_flags & 0b10 != 0;
815        frame.dispose = match DisposalMethod::from_u8((control_flags & 0b11100) >> 2) {
816            Some(method) => method,
817            None => DisposalMethod::Any,
818        };
819        frame.delay = u16::from_le_bytes(control[1..3].try_into().unwrap());
820        frame.transparent = (control_flags & 1 != 0).then_some(control[3]);
821        Ok(())
822    }
823
824    fn add_frame(&mut self) {
825        if self.current.is_none() {
826            self.current = Some(Frame::default());
827        }
828    }
829}
830
831#[test]
832fn error_cast() {
833    let _ : Box<dyn error::Error> = DecodingError::format("testing").into();
834}