gif/reader/
decoder.rs

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