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, f: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 DecodingError::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 DecodingError::Format(ref d: &DecodingFormatError) => d.fmt(fmt),
63 DecodingError::Io(ref err: &Error) => 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 DecodingError::Format(ref err: &DecodingFormatError) => Some(err),
73 DecodingError::Io(ref err: &Error) => Some(err),
74 }
75 }
76}
77
78impl From<io::Error> for DecodingError {
79 #[inline]
80 fn from(err: io::Error) -> Self {
81 DecodingError::Io(err)
82 }
83}
84
85impl From<io::ErrorKind> for DecodingError {
86 #[cold]
87 fn from(err: io::ErrorKind) -> Self {
88 DecodingError::Io(io::Error::from(err))
89 }
90}
91
92impl From<DecodingFormatError> for DecodingError {
93 #[inline]
94 fn from(err: DecodingFormatError) -> Self {
95 DecodingError::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(u8, [u8; 6]),
161 U16Byte1(U16Value, u8),
162 U16(U16Value),
163 Byte(ByteValue),
164 GlobalPalette(usize),
165 BlockStart(u8),
166 BlockEnd,
167 ExtensionBlock(AnyExtension),
168 /// Collects data in ext.data
169 ExtensionDataBlock(usize),
170 ApplicationExtension,
171 LocalPalette(usize),
172 LzwInit(u8),
173 /// Decompresses LZW
174 DecodeSubBlock(usize),
175 /// Keeps LZW compressed
176 CopySubBlock(usize),
177 FrameDecoded,
178 Trailer,
179}
180use self::State::*;
181
182use super::converter::PixelConverter;
183
184/// U16 values that may occur in a GIF image
185#[derive(Debug, Copy, Clone)]
186enum U16Value {
187 /// Logical screen descriptor width
188 ScreenWidth,
189 /// Logical screen descriptor height
190 ScreenHeight,
191 /// Delay time
192 Delay,
193 /// Left frame offset
194 ImageLeft,
195 /// Top frame offset
196 ImageTop,
197 /// Frame width
198 ImageWidth,
199 /// Frame height
200 ImageHeight,
201}
202
203/// Single byte screen descriptor values
204#[derive(Debug, Copy, Clone)]
205enum ByteValue {
206 GlobalFlags,
207 Background { global_flags: u8 },
208 AspectRatio { global_flags: u8 },
209 ControlFlags,
210 ImageFlags,
211 TransparentIdx,
212 CodeSize,
213}
214
215/// Decoder for `Frame::make_lzw_pre_encoded`
216pub struct FrameDecoder {
217 lzw_reader: LzwReader,
218 pixel_converter: PixelConverter,
219}
220
221impl FrameDecoder {
222 /// See also `set_global_palette`
223 #[inline]
224 #[must_use]
225 pub fn new(options: DecodeOptions) -> Self {
226 Self {
227 lzw_reader: LzwReader::new(options.check_for_end_code),
228 pixel_converter: PixelConverter::new(options.color_output, options.memory_limit),
229 }
230 }
231
232 /// Palette used for RGBA conversion
233 #[inline]
234 pub fn set_global_palette(&mut self, palette: Vec<u8>) {
235 self.pixel_converter.set_global_palette(palette);
236 }
237
238 /// Converts the frame in-place, replacing its LZW buffer with pixels.
239 ///
240 /// If you get an error about invalid min code size, the buffer was probably pixels, not compressed data.
241 #[inline]
242 pub fn decode_lzw_encoded_frame(&mut self, frame: &mut Frame<'_>) -> Result<(), DecodingError> {
243 let pixel_bytes = self.pixel_converter.check_buffer_size(frame)?;
244 let mut vec = vec![0; pixel_bytes];
245 self.decode_lzw_encoded_frame_into_buffer(frame, &mut vec)?;
246 frame.buffer = Cow::Owned(vec);
247 frame.interlaced = false;
248 Ok(())
249 }
250
251 /// Converts into the given buffer. It must be [`buffer_size()`] bytes large.
252 ///
253 /// Pixels are always deinterlaced, so update `frame.interlaced` afterwards if you're putting the buffer back into the frame.
254 pub fn decode_lzw_encoded_frame_into_buffer(&mut self, frame: &Frame<'_>, buf: &mut [u8]) -> Result<(), DecodingError> {
255 let (&min_code_size, mut data) = frame.buffer.split_first().unwrap_or((&2, &[]));
256 self.lzw_reader.reset(min_code_size)?;
257 let lzw_reader = &mut self.lzw_reader;
258 self.pixel_converter.read_into_buffer(frame, buf, &mut move |out| {
259 loop {
260 let (bytes_read, bytes_written) = lzw_reader.decode_bytes(data, out)?;
261 data = &data.get(bytes_read..).unwrap_or_default();
262 if bytes_written > 0 || bytes_read == 0 || data.is_empty() {
263 return Ok(bytes_written)
264 }
265 }
266 })?;
267 Ok(())
268 }
269
270 /// Number of bytes required for `decode_lzw_encoded_frame_into_buffer`
271 #[inline]
272 #[must_use]
273 pub fn buffer_size(&self, frame: &Frame<'_>) -> usize {
274 self.pixel_converter.buffer_size(frame).unwrap()
275 }
276}
277
278struct LzwReader {
279 decoder: Option<LzwDecoder>,
280 min_code_size: u8,
281 check_for_end_code: bool,
282}
283
284impl LzwReader {
285 pub fn new(check_for_end_code: bool) -> Self {
286 Self {
287 decoder: None,
288 min_code_size: 0,
289 check_for_end_code,
290 }
291 }
292
293 pub fn check_code_size(min_code_size: u8) -> Result<(), DecodingError> {
294 // LZW spec: max 12 bits per code. This check helps catch confusion
295 // between LZW-compressed buffers and raw pixel data
296 if min_code_size > 11 || min_code_size < 1 {
297 return Err(DecodingError::format("invalid minimal code size"));
298 }
299 Ok(())
300 }
301
302 pub fn reset(&mut self, min_code_size: u8) -> Result<(), DecodingError> {
303 Self::check_code_size(min_code_size)?;
304
305 // The decoder can be reused if the code size stayed the same
306 if self.min_code_size != min_code_size || self.decoder.is_none() {
307 self.min_code_size = min_code_size;
308 self.decoder = Some(LzwDecoder::new(BitOrder::Lsb, min_code_size));
309 } else {
310 self.decoder.as_mut().ok_or_else(|| DecodingError::format("bad state"))?.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(&mut self, lzw_data: &[u8], decode_buffer: &mut OutputBuffer<'_>) -> io::Result<(usize, usize)> {
321 let decoder = self.decoder.as_mut().ok_or(io::ErrorKind::Unsupported)?;
322
323 let decode_buffer = match decode_buffer {
324 OutputBuffer::Slice(buf) => &mut **buf,
325 OutputBuffer::None => &mut [],
326 OutputBuffer::Vec(_) => return Err(io::Error::from(io::ErrorKind::Unsupported)),
327 };
328
329 let decoded = decoder.decode_bytes(lzw_data, decode_buffer);
330
331 match decoded.status {
332 Ok(LzwStatus::Done | LzwStatus::Ok) => {},
333 Ok(LzwStatus::NoProgress) => {
334 if self.check_for_end_code {
335 return Err(io::Error::new(io::ErrorKind::InvalidData, "no end code in lzw stream"));
336 }
337 },
338 Err(err @ LzwError::InvalidCode) => {
339 return Err(io::Error::new(io::ErrorKind::InvalidData, err));
340 }
341 }
342 Ok((decoded.consumed_in, decoded.consumed_out))
343 }
344}
345
346/// GIF decoder which emits [low-level events](Decoded) for items in the GIF file
347///
348/// To just get GIF frames, use [`crate::Decoder`] instead.
349pub struct StreamingDecoder {
350 state: State,
351 lzw_reader: LzwReader,
352 skip_frame_decoding: bool,
353 check_frame_consistency: bool,
354 allow_unknown_blocks: bool,
355 memory_limit: MemoryLimit,
356 version: Version,
357 width: u16,
358 height: u16,
359 global_color_table: Vec<u8>,
360 background_color: [u8; 4],
361 /// ext buffer
362 ext: ExtensionData,
363 /// Frame data
364 current: Option<Frame<'static>>,
365 /// Needs to emit `HeaderEnd` once
366 header_end_reached: bool,
367}
368
369/// One version number of the GIF standard.
370#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
371pub enum Version {
372 /// Version 87a, from May 1987.
373 V87a,
374 /// Version 89a, from July 1989.
375 V89a,
376}
377
378struct ExtensionData {
379 id: AnyExtension,
380 data: Vec<u8>,
381 is_block_end: bool,
382}
383
384/// Destination to write to for `StreamingDecoder::update`
385pub enum OutputBuffer<'a> {
386 /// Overwrite bytes
387 Slice(&'a mut [u8]),
388 /// Append LZW bytes
389 Vec(&'a mut Vec<u8>),
390 /// Discard bytes
391 None,
392}
393
394impl<'a> OutputBuffer<'a> {
395 fn append(&mut self, buf: &[u8], memory_limit: &MemoryLimit) -> Result<(usize, usize), DecodingError> {
396 let (consumed, copied) = match self {
397 OutputBuffer::Slice(slice) => {
398 let len = cmp::min(buf.len(), slice.len());
399 slice[..len].copy_from_slice(&buf[..len]);
400 (len, len)
401 },
402 OutputBuffer::Vec(vec) => {
403 let vec: &mut Vec<u8> = vec;
404 let len = buf.len();
405 memory_limit.check_size(vec.len() + len)?;
406 vec.try_reserve(len).map_err(|_| io::ErrorKind::OutOfMemory)?;
407 if vec.capacity() - vec.len() >= len {
408 vec.extend_from_slice(buf);
409 }
410 (len, len)
411 },
412 // It's valid that bytes are discarded. For example,
413 // when using next_frame_info() with skip_frame_decoding to only get metadata.
414 OutputBuffer::None => (buf.len(), 0),
415 };
416 Ok((consumed, copied))
417 }
418}
419
420impl StreamingDecoder {
421 /// Creates a new streaming decoder
422 #[must_use]
423 pub fn new() -> StreamingDecoder {
424 let options = DecodeOptions::new();
425 Self::with_options(&options)
426 }
427
428 pub(crate) fn with_options(options: &DecodeOptions) -> Self {
429 StreamingDecoder {
430 state: Magic(0, [0; 6]),
431 lzw_reader: LzwReader::new(options.check_for_end_code),
432 skip_frame_decoding: options.skip_frame_decoding,
433 check_frame_consistency: options.check_frame_consistency,
434 allow_unknown_blocks: options.allow_unknown_blocks,
435 memory_limit: options.memory_limit.clone(),
436 version: Version::V87a,
437 width: 0,
438 height: 0,
439 global_color_table: Vec::new(),
440 background_color: [0, 0, 0, 0xFF],
441 ext: ExtensionData {
442 id: AnyExtension(0),
443 data: Vec::with_capacity(256), // 0xFF + 1 byte length
444 is_block_end: true,
445 },
446 current: None,
447 header_end_reached: false,
448 }
449 }
450
451 /// Updates the internal state of the decoder.
452 ///
453 /// Returns the number of bytes consumed from the input buffer
454 /// and the last decoding result.
455 pub fn update<'a>(
456 &'a mut self,
457 mut buf: &[u8],
458 write_into: &mut OutputBuffer<'_>,
459 ) -> Result<(usize, Decoded), DecodingError> {
460 let len = buf.len();
461 while !buf.is_empty() {
462 let (bytes, decoded) = self.next_state(buf, write_into)?;
463 buf = buf.get(bytes..).unwrap_or_default();
464 match decoded {
465 Decoded::Nothing => {},
466 result => {
467 return Ok((len-buf.len(), result));
468 },
469 };
470 }
471 Ok((len - buf.len(), Decoded::Nothing))
472 }
473
474 /// Returns the data of the last extension that has been decoded.
475 #[must_use]
476 pub fn last_ext(&self) -> (AnyExtension, &[u8], bool) {
477 (self.ext.id, &self.ext.data, self.ext.is_block_end)
478 }
479
480 /// Current frame info as a mutable ref.
481 #[must_use]
482 #[track_caller]
483 pub fn current_frame_mut(&mut self) -> &mut Frame<'static> {
484 self.current.as_mut().unwrap()
485 }
486
487 /// Current frame info as a ref.
488 #[track_caller]
489 #[must_use]
490 pub fn current_frame(&self) -> &Frame<'static> {
491 self.current.as_ref().unwrap()
492 }
493
494 /// Current frame info as a mutable ref.
495 #[inline(always)]
496 fn try_current_frame(&mut self) -> Result<&mut Frame<'static>, DecodingError> {
497 self.current.as_mut().ok_or_else(|| DecodingError::format("bad state"))
498 }
499
500 /// Width of the image
501 #[must_use]
502 pub fn width(&self) -> u16 {
503 self.width
504 }
505
506 /// Height of the image
507 #[must_use]
508 pub fn height(&self) -> u16 {
509 self.height
510 }
511
512 /// The version number of the GIF standard used in this image.
513 ///
514 /// We suppose a minimum of `V87a` compatibility. This value will be reported until we have
515 /// read the version information in the magic header bytes.
516 #[must_use]
517 pub fn version(&self) -> Version {
518 self.version
519 }
520
521 #[inline]
522 fn next_state(&mut self, buf: &[u8], write_into: &mut OutputBuffer<'_>) -> Result<(usize, Decoded), DecodingError> {
523 macro_rules! goto (
524 ($n:expr, $state:expr) => ({
525 self.state = $state;
526 Ok(($n, Decoded::Nothing))
527 });
528 ($state:expr) => ({
529 self.state = $state;
530 Ok((1, Decoded::Nothing))
531 });
532 ($n:expr, $state:expr, emit $res:expr) => ({
533 self.state = $state;
534 Ok(($n, $res))
535 });
536 ($state:expr, emit $res:expr) => ({
537 self.state = $state;
538 Ok((1, $res))
539 })
540 );
541
542 let b = *buf.get(0).ok_or(io::ErrorKind::UnexpectedEof)?;
543
544 match self.state {
545 Magic(i, mut version) => if i < 6 {
546 version[i as usize] = b;
547 goto!(Magic(i+1, version))
548 } else if &version[..3] == b"GIF" {
549 self.version = match &version[3..] {
550 b"87a" => Version::V87a,
551 b"89a" => Version::V89a,
552 _ => return Err(DecodingError::format("malformed GIF header"))
553 };
554 goto!(U16Byte1(U16Value::ScreenWidth, b))
555 } else {
556 Err(DecodingError::format("malformed GIF header"))
557 },
558 Byte(value) => {
559 use self::ByteValue::*;
560 match value {
561 GlobalFlags => {
562 goto!(Byte(Background { global_flags: b }))
563 },
564 Background { global_flags } => {
565 goto!(
566 Byte(AspectRatio { global_flags }),
567 emit Decoded::BackgroundColor(b)
568 )
569 },
570 AspectRatio { global_flags } => {
571 let global_table = global_flags & 0x80 != 0;
572 let table_size = if global_table {
573 let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize);
574 self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::ErrorKind::OutOfMemory)?;
575 table_size
576 } else {
577 0usize
578 };
579 goto!(GlobalPalette(table_size))
580 },
581 ControlFlags => {
582 self.ext.data.push(b);
583 let frame = self.try_current_frame()?;
584 let control_flags = b;
585 if control_flags & 1 != 0 {
586 // Set to Some(...), gets overwritten later
587 frame.transparent = Some(0);
588 }
589 frame.needs_user_input =
590 control_flags & 0b10 != 0;
591 frame.dispose = match DisposalMethod::from_u8(
592 (control_flags & 0b11100) >> 2
593 ) {
594 Some(method) => method,
595 None => DisposalMethod::Any
596 };
597 goto!(U16(U16Value::Delay))
598 }
599 TransparentIdx => {
600 self.ext.data.push(b);
601 if let Some(ref mut idx) = self.try_current_frame()?.transparent {
602 *idx = b;
603 }
604 goto!(ExtensionDataBlock(0))
605 }
606 ImageFlags => {
607 let local_table = (b & 0b1000_0000) != 0;
608 let interlaced = (b & 0b0100_0000) != 0;
609 let table_size = b & 0b0000_0111;
610 let check_frame_consistency = self.check_frame_consistency;
611 let (width, height) = (self.width, self.height);
612
613 let frame = self.try_current_frame()?;
614
615 frame.interlaced = interlaced;
616 if check_frame_consistency {
617 // Consistency checks.
618 if width.checked_sub(frame.width) < Some(frame.left)
619 || height.checked_sub(frame.height) < Some(frame.top)
620 {
621 return Err(DecodingError::format("frame descriptor is out-of-bounds"))
622 }
623 }
624
625 if local_table {
626 let entries = PLTE_CHANNELS * (1 << (table_size + 1));
627 let mut pal = Vec::new();
628 pal.try_reserve_exact(entries).map_err(|_| io::ErrorKind::OutOfMemory)?;
629 frame.palette = Some(pal);
630 goto!(LocalPalette(entries))
631 } else {
632 goto!(Byte(CodeSize))
633 }
634 }
635 CodeSize => goto!(LzwInit(b)),
636 }
637 }
638 GlobalPalette(left) => {
639 let n = cmp::min(left, buf.len());
640 if left > 0 {
641 self.global_color_table.extend_from_slice(&buf[..n]);
642 goto!(n, GlobalPalette(left - n))
643 } else {
644 let idx = self.background_color[0];
645 match self.global_color_table.chunks_exact(PLTE_CHANNELS).nth(idx as usize) {
646 Some(chunk) => self.background_color[..PLTE_CHANNELS]
647 .copy_from_slice(&chunk[..PLTE_CHANNELS]),
648 None => self.background_color[0] = 0
649 }
650 goto!(BlockStart(b), emit Decoded::GlobalPalette(
651 mem::take(&mut self.global_color_table).into_boxed_slice()
652 ))
653 }
654 }
655 BlockStart(type_) => {
656 if !self.header_end_reached && type_ != Block::Extension as u8 {
657 self.header_end_reached = true;
658 return goto!(0, BlockStart(type_), emit Decoded::HeaderEnd);
659 }
660
661 match Block::from_u8(type_) {
662 Some(Block::Image) => {
663 self.add_frame();
664 goto!(U16Byte1(U16Value::ImageLeft, b), emit Decoded::BlockStart(Block::Image))
665 }
666 Some(Block::Extension) => {
667 goto!(ExtensionBlock(AnyExtension(b)), emit Decoded::BlockStart(Block::Extension))
668 }
669 Some(Block::Trailer) => {
670 // The `Trailer` is the final state, and isn't reachable without extraneous data after the end of file
671 goto!(Trailer, emit Decoded::BlockStart(Block::Trailer))
672 }
673 None => {
674 if self.allow_unknown_blocks {
675 goto!(ExtensionDataBlock(b as usize))
676 } else {
677 Err(DecodingError::format("unknown block type encountered"))
678 }
679 }
680 }
681 },
682 BlockEnd => {
683 if b == Block::Trailer as u8 {
684 // can't consume yet, because the trailer is not a real block,
685 // and won't have futher data for BlockStart
686 goto!(0, BlockStart(b))
687 } else {
688 goto!(BlockStart(b))
689 }
690 }
691 ExtensionBlock(id) => {
692 use Extension::*;
693 self.ext.id = id;
694 self.ext.data.clear();
695 self.ext.data.push(b);
696 if let Some(ext) = Extension::from_u8(id.0) {
697 match ext {
698 Control => {
699 goto!(self.read_control_extension(b)?)
700 }
701 Text | Comment | Application => {
702 goto!(ExtensionDataBlock(b as usize))
703 }
704 }
705 } else {
706 Err(DecodingError::format("unknown block type encountered"))
707 }
708 }
709 ExtensionDataBlock(left) => {
710 if left > 0 {
711 let n = cmp::min(left, buf.len());
712 self.memory_limit.check_size(self.ext.data.len() + n)?;
713 self.ext.data.try_reserve(n).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
714 self.ext.data.extend_from_slice(&buf[..n]);
715 goto!(n, ExtensionDataBlock(left - n))
716 } else if b == 0 {
717 self.ext.is_block_end = true;
718 if self.ext.id.into_known() == Some(Extension::Application) {
719 goto!(0, ApplicationExtension, emit Decoded::BlockFinished(self.ext.id))
720 } else {
721 goto!(BlockEnd, emit Decoded::BlockFinished(self.ext.id))
722 }
723 } else {
724 self.ext.is_block_end = false;
725 goto!(ExtensionDataBlock(b as usize), emit Decoded::SubBlockFinished(self.ext.id))
726 }
727 }
728 ApplicationExtension => {
729 debug_assert_eq!(0, b);
730 // the parser removes sub-block lenghts, so app name and data are concatenated
731 if self.ext.data.len() >= 15 && &self.ext.data[1..13] == b"NETSCAPE2.0\x01" {
732 let repeat = &self.ext.data[13..15];
733 let repeat = u16::from(repeat[0]) | u16::from(repeat[1]) << 8;
734 goto!(BlockEnd, emit Decoded::Repetitions(if repeat == 0 { Repeat::Infinite } else { Repeat::Finite(repeat) }))
735 } else {
736 goto!(BlockEnd)
737 }
738 }
739 LocalPalette(left) => {
740 let n = cmp::min(left, buf.len());
741 if left > 0 {
742 let src = &buf[..n];
743 if let Some(pal) = self.try_current_frame()?.palette.as_mut() {
744 // capacity has already been reserved in ImageFlags
745 if pal.capacity() - pal.len() >= src.len() {
746 pal.extend_from_slice(src);
747 }
748 }
749 goto!(n, LocalPalette(left - n))
750 } else {
751 goto!(LzwInit(b))
752 }
753 }
754 LzwInit(min_code_size) => {
755 if !self.skip_frame_decoding {
756 // Reset validates the min code size
757 self.lzw_reader.reset(min_code_size)?;
758 goto!(DecodeSubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Pixels))
759 } else {
760 LzwReader::check_code_size(min_code_size)?;
761 goto!(CopySubBlock(b as usize), emit Decoded::FrameMetadata(FrameDataType::Lzw { min_code_size }))
762 }
763 }
764 CopySubBlock(left) => {
765 debug_assert!(self.skip_frame_decoding);
766 if left > 0 {
767 let n = cmp::min(left, buf.len());
768 let (consumed, copied) = write_into.append(&buf[..n], &self.memory_limit)?;
769 goto!(consumed, CopySubBlock(left - consumed), emit Decoded::LzwDataCopied(copied))
770 } else if b != 0 {
771 goto!(CopySubBlock(b as usize))
772 } else {
773 goto!(0, FrameDecoded)
774 }
775 }
776 DecodeSubBlock(left) => {
777 debug_assert!(!self.skip_frame_decoding);
778 if left > 0 {
779 let n = cmp::min(left, buf.len());
780 if self.lzw_reader.has_ended() || matches!(write_into, OutputBuffer::None) {
781 return goto!(n, DecodeSubBlock(left - n), emit Decoded::Nothing);
782 }
783
784 let (mut consumed, bytes_len) = self.lzw_reader.decode_bytes(&buf[..n], write_into)?;
785
786 // skip if can't make progress (decode would fail if check_for_end_code was set)
787 if consumed == 0 && bytes_len == 0 {
788 consumed = n;
789 }
790
791 let decoded = if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
792 Decoded::BytesDecoded(bytes_len)
793 } else {
794 Decoded::Nothing
795 };
796 goto!(consumed, DecodeSubBlock(left - consumed), emit decoded)
797 } else if b != 0 { // decode next sub-block
798 goto!(DecodeSubBlock(b as usize))
799 } else {
800 let (_, bytes_len) = self.lzw_reader.decode_bytes(&[], write_into)?;
801
802 if let Some(bytes_len) = NonZeroUsize::new(bytes_len) {
803 goto!(0, DecodeSubBlock(0), emit Decoded::BytesDecoded(bytes_len))
804 } else {
805 goto!(0, FrameDecoded)
806 }
807 }
808 }
809 U16(next) => goto!(U16Byte1(next, b)),
810 U16Byte1(next, value) => {
811 goto!(self.read_second_byte(next, value, b)?)
812 }
813 FrameDecoded => {
814 // end of image data reached
815 self.current = None;
816 debug_assert_eq!(0, b);
817 goto!(BlockEnd, emit Decoded::DataEnd)
818 }
819 Trailer => goto!(0, Trailer, emit Decoded::Nothing),
820 }
821 }
822
823 fn read_second_byte(&mut self, next: U16Value, value: u8, b: u8) -> Result<State, DecodingError> {
824 use self::U16Value::*;
825 let value = (u16::from(b) << 8) | u16::from(value);
826 Ok(match (next, value) {
827 (ScreenWidth, width) => {
828 self.width = width;
829 U16(U16Value::ScreenHeight)
830 },
831 (ScreenHeight, height) => {
832 self.height = height;
833 Byte(ByteValue::GlobalFlags)
834 },
835 (Delay, delay) => {
836 self.try_current_frame()?.delay = delay;
837 self.ext.data.push(value as u8);
838 self.ext.data.push(b);
839 Byte(ByteValue::TransparentIdx)
840 },
841 (ImageLeft, left) => {
842 self.try_current_frame()?.left = left;
843 U16(U16Value::ImageTop)
844 },
845 (ImageTop, top) => {
846 self.try_current_frame()?.top = top;
847 U16(U16Value::ImageWidth)
848 },
849 (ImageWidth, width) => {
850 self.try_current_frame()?.width = width;
851 U16(U16Value::ImageHeight)
852 },
853 (ImageHeight, height) => {
854 self.try_current_frame()?.height = height;
855 Byte(ByteValue::ImageFlags)
856 }
857 })
858 }
859
860 fn read_control_extension(&mut self, b: u8) -> Result<State, DecodingError> {
861 self.add_frame();
862 self.ext.data.push(b);
863 if b != 4 {
864 return Err(DecodingError::format("control extension has wrong length"));
865 }
866 Ok(Byte(ByteValue::ControlFlags))
867 }
868
869 fn add_frame(&mut self) {
870 if self.current.is_none() {
871 self.current = Some(Frame::default());
872 }
873 }
874}
875
876#[test]
877fn error_cast() {
878 let _ : Box<dyn error::Error> = DecodingError::format(err:"testing").into();
879}
880