[go: up one dir, main page]

gif/reader/
decoder.rs

1use std::borrow::Cow;
2use std::cmp;
3use std::error;
4use std::fmt;
5use std::io;
6use std::mem;
7use std::default::Default;
8use std::num::NonZeroUsize;
9
10use crate::Repeat;
11use crate::MemoryLimit;
12use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame};
13use crate::reader::DecodeOptions;
14
15use weezl::{BitOrder, decode::Decoder as LzwDecoder, 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(&mut self, frame: &Frame<'_>, buf: &mut [u8]) -> Result<(), DecodingError> {
223        let (&min_code_size, mut data) = frame.buffer.split_first().unwrap_or((&2, &[]));
224        self.lzw_reader.reset(min_code_size)?;
225        let lzw_reader = &mut self.lzw_reader;
226        self.pixel_converter.read_into_buffer(frame, buf, &mut move |out| {
227            loop {
228                let (bytes_read, bytes_written) = lzw_reader.decode_bytes(data, out)?;
229                data = data.get(bytes_read..).unwrap_or_default();
230                if bytes_written > 0 || bytes_read == 0 || data.is_empty() {
231                    return Ok(bytes_written);
232                }
233            }
234        })?;
235        Ok(())
236    }
237
238    /// Number of bytes required for `decode_lzw_encoded_frame_into_buffer`
239    #[inline]
240    #[must_use]
241    pub fn buffer_size(&self, frame: &Frame<'_>) -> usize {
242        self.pixel_converter.buffer_size(frame).unwrap()
243    }
244}
245
246struct LzwReader {
247    decoder: Option<LzwDecoder>,
248    min_code_size: u8,
249    check_for_end_code: bool,
250}
251
252impl LzwReader {
253    pub fn new(check_for_end_code: bool) -> Self {
254        Self {
255            decoder: None,
256            min_code_size: 0,
257            check_for_end_code,
258        }
259    }
260
261    pub fn check_code_size(min_code_size: u8) -> Result<(), DecodingError> {
262        // LZW spec: max 12 bits per code. This check helps catch confusion
263        // between LZW-compressed buffers and raw pixel data
264        if min_code_size > 11 || min_code_size < 1 {
265            return Err(DecodingError::format("invalid minimal code size"));
266        }
267        Ok(())
268    }
269
270    pub fn reset(&mut self, min_code_size: u8) -> Result<(), DecodingError> {
271        Self::check_code_size(min_code_size)?;
272
273        // The decoder can be reused if the code size stayed the same
274        if self.min_code_size != min_code_size || self.decoder.is_none() {
275            self.min_code_size = min_code_size;
276            self.decoder = Some(LzwDecoder::new(BitOrder::Lsb, min_code_size));
277        } else {
278            self.decoder.as_mut().ok_or_else(|| DecodingError::format("bad state"))?.reset();
279        }
280
281        Ok(())
282    }
283
284    pub fn has_ended(&self) -> bool {
285        self.decoder.as_ref().map_or(true, |e| e.has_ended())
286    }
287
288    pub fn decode_bytes(&mut self, lzw_data: &[u8], decode_buffer: &mut OutputBuffer<'_>) -> io::Result<(usize, usize)> {
289        let decoder = self.decoder.as_mut().ok_or(io::ErrorKind::Unsupported)?;
290
291        let decode_buffer = match decode_buffer {
292            OutputBuffer::Slice(buf) => &mut **buf,
293            OutputBuffer::None => &mut [],
294            OutputBuffer::Vec(_) => return Err(io::Error::from(io::ErrorKind::Unsupported)),
295        };
296
297        let decoded = decoder.decode_bytes(lzw_data, decode_buffer);
298
299        match decoded.status {
300            Ok(LzwStatus::Done | LzwStatus::Ok) => {},
301            Ok(LzwStatus::NoProgress) => {
302                if self.check_for_end_code {
303                    return Err(io::Error::new(io::ErrorKind::InvalidData, "no end code in lzw stream"));
304                }
305            },
306            Err(err @ LzwError::InvalidCode) => {
307                return Err(io::Error::new(io::ErrorKind::InvalidData, err));
308            }
309        }
310        Ok((decoded.consumed_in, decoded.consumed_out))
311    }
312}
313
314/// GIF decoder which emits [low-level events](Decoded) for items in the GIF file
315///
316/// To just get GIF frames, use [`crate::Decoder`] instead.
317pub struct StreamingDecoder {
318    state: State,
319    /// Input bytes are collected here if `update` got `buf` smaller than the minimum required
320    internal_buffer: [u8; 9],
321    unused_internal_buffer_len: u8,
322    lzw_reader: LzwReader,
323    skip_frame_decoding: bool,
324    check_frame_consistency: bool,
325    allow_unknown_blocks: bool,
326    memory_limit: MemoryLimit,
327    version: Version,
328    width: u16,
329    height: u16,
330    global_color_table: Vec<u8>,
331    /// ext buffer
332    ext: ExtensionData,
333    /// Frame data
334    current: Option<Frame<'static>>,
335    /// Needs to emit `HeaderEnd` once
336    header_end_reached: bool,
337}
338
339/// One version number of the GIF standard.
340#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
341pub enum Version {
342    /// Version 87a, from May 1987.
343    V87a,
344    /// Version 89a, from July 1989.
345    V89a,
346}
347
348struct ExtensionData {
349    id: AnyExtension,
350    data: Vec<u8>,
351    is_block_end: bool,
352}
353
354/// Destination to write to for `StreamingDecoder::update`
355pub enum OutputBuffer<'a> {
356    /// Overwrite bytes
357    Slice(&'a mut [u8]),
358    /// Append LZW bytes
359    Vec(&'a mut Vec<u8>),
360    /// Discard bytes
361    None,
362}
363
364impl OutputBuffer<'_> {
365    fn append(&mut self, buf: &[u8], memory_limit: &MemoryLimit) -> Result<(usize, usize), DecodingError> {
366        let (consumed, copied) = match self {
367            OutputBuffer::Slice(slice) => {
368                let len = cmp::min(buf.len(), slice.len());
369                slice[..len].copy_from_slice(&buf[..len]);
370                (len, len)
371            },
372            OutputBuffer::Vec(vec) => {
373                let vec: &mut Vec<u8> = vec;
374                let len = buf.len();
375                memory_limit.check_size(vec.len() + len)?;
376                vec.try_reserve(len).map_err(|_| io::ErrorKind::OutOfMemory)?;
377                if vec.capacity() - vec.len() >= len {
378                    vec.extend_from_slice(buf);
379                }
380                (len, len)
381            },
382            // It's valid that bytes are discarded. For example,
383            // when using next_frame_info() with skip_frame_decoding to only get metadata.
384            OutputBuffer::None => (buf.len(), 0),
385        };
386        Ok((consumed, copied))
387    }
388}
389
390impl StreamingDecoder {
391    /// Creates a new streaming decoder
392    #[must_use]
393    pub fn new() -> Self {
394        let options = DecodeOptions::new();
395        Self::with_options(&options)
396    }
397
398    pub(crate) fn with_options(options: &DecodeOptions) -> Self {
399        Self {
400            internal_buffer: [0; 9],
401            unused_internal_buffer_len: 0,
402            state: Magic,
403            lzw_reader: LzwReader::new(options.check_for_end_code),
404            skip_frame_decoding: options.skip_frame_decoding,
405            check_frame_consistency: options.check_frame_consistency,
406            allow_unknown_blocks: options.allow_unknown_blocks,
407            memory_limit: options.memory_limit.clone(),
408            version: Version::V87a,
409            width: 0,
410            height: 0,
411            global_color_table: Vec::new(),
412            ext: ExtensionData {
413                id: AnyExtension(0),
414                data: Vec::with_capacity(256), // 0xFF + 1 byte length
415                is_block_end: true,
416            },
417            current: None,
418            header_end_reached: false,
419        }
420    }
421
422    /// Updates the internal state of the decoder.
423    ///
424    /// Returns the number of bytes consumed from the input buffer
425    /// and the last decoding result.
426    pub fn update(
427        &mut self,
428        mut buf: &[u8],
429        write_into: &mut OutputBuffer<'_>,
430    ) -> Result<(usize, Decoded), DecodingError> {
431        let len = buf.len();
432        while !buf.is_empty() {
433            let (bytes, decoded) = self.next_state(buf, write_into)?;
434            buf = buf.get(bytes..).unwrap_or_default();
435            match decoded {
436                Decoded::Nothing => {},
437                result => {
438                    return Ok((len-buf.len(), result));
439                },
440            };
441        }
442        Ok((len - buf.len(), Decoded::Nothing))
443    }
444
445    /// Returns the data of the last extension that has been decoded.
446    #[must_use]
447    pub fn last_ext(&self) -> (AnyExtension, &[u8], bool) {
448        (self.ext.id, &self.ext.data, self.ext.is_block_end)
449    }
450
451    /// Current frame info as a mutable ref.
452    #[must_use]
453    #[track_caller]
454    pub fn current_frame_mut(&mut self) -> &mut Frame<'static> {
455        self.current.as_mut().unwrap()
456    }
457
458    /// Current frame info as a ref.
459    #[track_caller]
460    #[must_use]
461    pub fn current_frame(&self) -> &Frame<'static> {
462        self.current.as_ref().unwrap()
463    }
464
465    /// Current frame info as a mutable ref.
466    #[inline(always)]
467    fn try_current_frame(&mut self) -> Result<&mut Frame<'static>, DecodingError> {
468        self.current.as_mut().ok_or_else(|| DecodingError::format("bad state"))
469    }
470
471    /// Width of the image
472    #[must_use]
473    pub fn width(&self) -> u16 {
474        self.width
475    }
476
477    /// Height of the image
478    #[must_use]
479    pub fn height(&self) -> u16 {
480        self.height
481    }
482
483    /// The version number of the GIF standard used in this image.
484    ///
485    /// We suppose a minimum of `V87a` compatibility. This value will be reported until we have
486    /// read the version information in the magic header bytes.
487    #[must_use]
488    pub fn version(&self) -> Version {
489        self.version
490    }
491
492    #[inline]
493    fn next_state(&mut self, buf: &[u8], write_into: &mut OutputBuffer<'_>) -> Result<(usize, Decoded), DecodingError> {
494        macro_rules! goto (
495            ($n:expr, $state:expr) => ({
496                self.state = $state;
497                Ok(($n, Decoded::Nothing))
498            });
499            ($state:expr) => ({
500                self.state = $state;
501                Ok((1, Decoded::Nothing))
502            });
503            ($n:expr, $state:expr, emit $res:expr) => ({
504                self.state = $state;
505                Ok(($n, $res))
506            });
507            ($state:expr, emit $res:expr) => ({
508                self.state = $state;
509                Ok((1, $res))
510            })
511        );
512
513        macro_rules! ensure_min_length_buffer (
514            ($required:expr) => ({
515                let required: usize = $required;
516                if buf.len() >= required && self.unused_internal_buffer_len == 0 {
517                    (required, &buf[..required])
518                } else {
519                    let has = usize::from(self.unused_internal_buffer_len);
520                    let mut consumed = 0;
521                    if has < required {
522                        let to_copy = buf.len().min(required - has);
523                        let new_len = has + to_copy;
524                        self.internal_buffer[has .. new_len].copy_from_slice(&buf[..to_copy]);
525                        consumed += to_copy;
526                        if new_len < required {
527                            self.unused_internal_buffer_len = new_len as u8;
528                            return Ok((consumed, Decoded::Nothing));
529                        } else {
530                            self.unused_internal_buffer_len = 0;
531                        }
532                    }
533                    (consumed, &self.internal_buffer[..required])
534                }
535            })
536        );
537
538        let b = *buf.first().ok_or(io::ErrorKind::UnexpectedEof)?;
539
540        match self.state {
541            Magic => {
542                let (consumed, version) = ensure_min_length_buffer!(6);
543
544                self.version = match version {
545                    b"GIF87a" => Version::V87a,
546                    b"GIF89a" => Version::V89a,
547                    _ => return Err(DecodingError::format("malformed GIF header")),
548                };
549
550                goto!(consumed, ScreenDescriptor)
551            },
552            ScreenDescriptor => {
553                let (consumed, desc) = ensure_min_length_buffer!(7);
554
555                self.width = u16::from_le_bytes(desc[..2].try_into().unwrap());
556                self.height = u16::from_le_bytes(desc[2..4].try_into().unwrap());
557                let global_flags = desc[4];
558                let background_color = desc[5];
559
560                let global_table = global_flags & 0x80 != 0;
561                let table_size = if global_table {
562                    let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize);
563                    self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::ErrorKind::OutOfMemory)?;
564                    table_size
565                } else {
566                    0usize
567                };
568
569                goto!(
570                    consumed,
571                    GlobalPalette(table_size),
572                    emit Decoded::BackgroundColor(background_color)
573                )
574            },
575            ImageBlockStart => {
576                let (consumed, header) = ensure_min_length_buffer!(9);
577
578                let frame = self.current.as_mut().ok_or_else(|| DecodingError::format("bad state"))?;
579                frame.left = u16::from_le_bytes(header[..2].try_into().unwrap());
580                frame.top = u16::from_le_bytes(header[2..4].try_into().unwrap());
581                frame.width = u16::from_le_bytes(header[4..6].try_into().unwrap());
582                frame.height = u16::from_le_bytes(header[6..8].try_into().unwrap());
583
584                let flags = header[8];
585                frame.interlaced = (flags & 0b0100_0000) != 0;
586
587                if self.check_frame_consistency {
588                    // Consistency checks.
589                    if self.width.checked_sub(frame.width) < Some(frame.left)
590                        || self.height.checked_sub(frame.height) < Some(frame.top)
591                    {
592                        return Err(DecodingError::format("frame descriptor is out-of-bounds"));
593                    }
594                }
595
596                let local_table = (flags & 0b1000_0000) != 0;
597                if local_table {
598                    let table_size = flags & 0b0000_0111;
599                    let pal_len = PLTE_CHANNELS * (1 << (table_size + 1));
600                    frame.palette.get_or_insert_with(Vec::new)
601                        .try_reserve_exact(pal_len).map_err(|_| io::ErrorKind::OutOfMemory)?;
602                    goto!(consumed, LocalPalette(pal_len))
603                } else {
604                    goto!(consumed, LocalPalette(0))
605                }
606            },
607            GlobalPalette(left) => {
608                // the global_color_table is guaranteed to have the exact capacity required
609                if left > 0 {
610                    let n = cmp::min(left, buf.len());
611                    if n <= self.global_color_table.capacity() - self.global_color_table.len() {
612                        self.global_color_table.extend_from_slice(&buf[..n]);
613                    }
614                    goto!(n, GlobalPalette(left - n))
615                } else {
616                    goto!(BlockStart(b), emit Decoded::GlobalPalette(
617                        mem::take(&mut self.global_color_table).into_boxed_slice()
618                    ))
619                }
620            }
621            BlockStart(type_) => {
622                if !self.header_end_reached && type_ != Block::Extension as u8 {
623                    self.header_end_reached = true;
624                    return goto!(0, BlockStart(type_), emit Decoded::HeaderEnd);
625                }
626
627                match Block::from_u8(type_) {
628                    Some(Block::Image) => {
629                        self.add_frame();
630                        goto!(0, ImageBlockStart, emit Decoded::BlockStart(Block::Image))
631                    }
632                    Some(Block::Extension) => {
633                        self.ext.data.clear();
634                        self.ext.id = AnyExtension(b);
635                        if self.ext.id.into_known().is_none() {
636                            return Err(DecodingError::format("unknown block type encountered"));
637                        }
638                        goto!(ExtensionBlockStart, emit Decoded::BlockStart(Block::Extension))
639                    }
640                    Some(Block::Trailer) => {
641                        // The `Trailer` is the final state, and isn't reachable without extraneous data after the end of file
642                        goto!(Trailer, emit Decoded::BlockStart(Block::Trailer))
643                    }
644                    None => {
645                        if self.allow_unknown_blocks {
646                            goto!(ExtensionDataBlock(b as usize))
647                        } else {
648                            Err(DecodingError::format("unknown block type encountered"))
649                        }
650                    }
651                }
652            },
653            BlockEnd => {
654                if b == Block::Trailer as u8 {
655                    // can't consume yet, because the trailer is not a real block,
656                    // and won't have futher data for BlockStart
657                    goto!(0, BlockStart(b))
658                } else {
659                    goto!(BlockStart(b))
660                }
661            }
662            ExtensionBlockStart => {
663                self.ext.data.push(b);
664                goto!(ExtensionDataBlock(b as usize))
665            }
666            ExtensionDataBlock(left) => {
667                if left > 0 {
668                    let n = cmp::min(left, buf.len());
669                    self.memory_limit.check_size(self.ext.data.len() + n)?;
670                    self.ext.data.try_reserve(n).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
671                    self.ext.data.extend_from_slice(&buf[..n]);
672                    goto!(n, ExtensionDataBlock(left - n))
673                } else if b == 0 {
674                    self.ext.is_block_end = true;
675                    match self.ext.id.into_known() {
676                        Some(Extension::Application) => {
677                            goto!(0, ApplicationExtension, emit Decoded::BlockFinished(self.ext.id))
678                        }
679                        Some(Extension::Control) => {
680                            self.read_control_extension()?;
681                            goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id))
682                        },
683                        _ => {
684                            goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id))
685                        }
686                    }
687                } else {
688                    self.ext.is_block_end = false;
689                    goto!(ExtensionDataBlock(b as usize), emit Decoded::SubBlockFinished(self.ext.id))
690                }
691            }
692            ApplicationExtension => {
693                debug_assert_eq!(0, b);
694                // the parser removes sub-block lenghts, so app name and data are concatenated
695                if self.ext.data.len() >= 15 && &self.ext.data[1..13] == b"NETSCAPE2.0\x01" {
696                    let repeat = &self.ext.data[13..15];
697                    let repeat = u16::from(repeat[0]) | u16::from(repeat[1]) << 8;
698                    goto!(BlockEnd, emit Decoded::Repetitions(if repeat == 0 { Repeat::Infinite } else { Repeat::Finite(repeat) }))
699                } else {
700                    goto!(BlockEnd)
701                }
702            }
703            LocalPalette(left) => {
704                if left > 0 {
705                    let n = cmp::min(left, buf.len());
706                    let src = &buf[..n];
707                    if let Some(pal) = self.try_current_frame()?.palette.as_mut() {
708                        // capacity has already been reserved in ImageBlockStart
709                        if pal.capacity() - pal.len() >= src.len() {
710                            pal.extend_from_slice(src);
711                        }
712                    }
713                    goto!(n, LocalPalette(left - n))
714                } else {
715                    goto!(LzwInit(b))
716                }
717            }
718            LzwInit(min_code_size) => {
719                if !self.skip_frame_decoding {
720                    // Reset validates the min code size
721                    self.lzw_reader.reset(min_code_size)?;
722                    goto!(DecodeSubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Pixels))
723                } else {
724                    LzwReader::check_code_size(min_code_size)?;
725                    goto!(CopySubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Lzw { min_code_size }))
726                }
727            }
728            CopySubBlock(left) => {
729                debug_assert!(self.skip_frame_decoding);
730                if left > 0 {
731                    let n = cmp::min(left, buf.len());
732                    let (consumed, copied) = write_into.append(&buf[..n], &self.memory_limit)?;
733                    goto!(consumed, CopySubBlock(left - consumed), emit Decoded::LzwDataCopied(copied))
734                } else if b != 0 {
735                    goto!(CopySubBlock(b as usize))
736                } else {
737                    goto!(0, FrameDecoded)
738                }
739            }
740            DecodeSubBlock(left) => {
741                debug_assert!(!self.skip_frame_decoding);
742                if left > 0 {
743                    let n = cmp::min(left, buf.len());
744                    if self.lzw_reader.has_ended() || matches!(write_into, OutputBuffer::None) {
745                        return goto!(n, DecodeSubBlock(left - n), emit Decoded::Nothing);
746                    }
747
748                    let (mut consumed, bytes_len) = self.lzw_reader.decode_bytes(&buf[..n], write_into)?;
749
750                    // skip if can't make progress (decode would fail if check_for_end_code was set)
751                    if consumed == 0 && bytes_len == 0 {
752                        consumed = n;
753                    }
754
755                    let decoded = if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
756                        Decoded::BytesDecoded(bytes_len)
757                    } else {
758                        Decoded::Nothing
759                    };
760                    goto!(consumed, DecodeSubBlock(left - consumed), emit decoded)
761                } else if b != 0 {
762                    // decode next sub-block
763                    goto!(DecodeSubBlock(b as usize))
764                } else {
765                    let (_, bytes_len) = self.lzw_reader.decode_bytes(&[], write_into)?;
766
767                    if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
768                        goto!(0, DecodeSubBlock(0), emit Decoded::BytesDecoded(bytes_len))
769                    } else {
770                        goto!(0, FrameDecoded)
771                    }
772                }
773            }
774            FrameDecoded => {
775                // end of image data reached
776                self.current = None;
777                debug_assert_eq!(0, b);
778                goto!(BlockEnd, emit Decoded::DataEnd)
779            }
780            Trailer => goto!(0, Trailer, emit Decoded::Nothing),
781        }
782    }
783
784    fn read_control_extension(&mut self) -> Result<(), DecodingError> {
785        if self.ext.data.len() != 5 {
786            return Err(DecodingError::format("control extension has wrong length"));
787        }
788        let control = &self.ext.data[1..];
789
790        let frame = self.current.get_or_insert_with(Frame::default);
791        let control_flags = control[0];
792        frame.needs_user_input = control_flags & 0b10 != 0;
793        frame.dispose = match DisposalMethod::from_u8((control_flags & 0b11100) >> 2) {
794            Some(method) => method,
795            None => DisposalMethod::Any,
796        };
797        frame.delay = u16::from_le_bytes(control[1..3].try_into().unwrap());
798        frame.transparent = (control_flags & 1 != 0).then_some(control[3]);
799        Ok(())
800    }
801
802    fn add_frame(&mut self) {
803        if self.current.is_none() {
804            self.current = Some(Frame::default());
805        }
806    }
807}
808
809#[test]
810fn error_cast() {
811    let _ : Box<dyn error::Error> = DecodingError::format("testing").into();
812}