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
17pub const PLTE_CHANNELS: usize = 3;
19
20#[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)]
41pub enum DecodingError {
43 Format(DecodingFormatError),
45 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) => d.fmt(fmt),
63 DecodingError::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 DecodingError::Format(ref err) => Some(err),
73 DecodingError::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 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#[derive(Debug, Copy, Clone)]
101pub enum FrameDataType {
102 Pixels,
104 Lzw {
106 min_code_size: u8,
108 },
109}
110
111#[derive(Debug)]
113#[non_exhaustive]
114pub enum Decoded {
115 Nothing,
117 GlobalPalette(Box<[u8]>),
119 BackgroundColor(u8),
121 Repetitions(Repeat),
123 HeaderEnd,
126 BlockStart(Block),
129 SubBlockFinished(AnyExtension),
136 BlockFinished(AnyExtension),
143 FrameMetadata(FrameDataType),
149 BytesDecoded(NonZeroUsize),
151 LzwDataCopied(usize),
153 DataEnd,
155}
156
157#[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 ExtensionDataBlock(usize),
170 ApplicationExtension,
171 LocalPalette(usize),
172 LzwInit(u8),
173 DecodeSubBlock(usize),
175 CopySubBlock(usize),
177 FrameDecoded,
178 Trailer,
179}
180use self::State::*;
181
182use super::converter::PixelConverter;
183
184#[derive(Debug, Copy, Clone)]
186enum U16Value {
187 ScreenWidth,
189 ScreenHeight,
191 Delay,
193 ImageLeft,
195 ImageTop,
197 ImageWidth,
199 ImageHeight,
201}
202
203#[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
215pub struct FrameDecoder {
217 lzw_reader: LzwReader,
218 pixel_converter: PixelConverter,
219}
220
221impl FrameDecoder {
222 #[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 #[inline]
234 pub fn set_global_palette(&mut self, palette: Vec<u8>) {
235 self.pixel_converter.set_global_palette(palette);
236 }
237
238 #[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 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 #[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 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 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
346pub 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: ExtensionData,
363 current: Option<Frame<'static>>,
365 header_end_reached: bool,
367}
368
369#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
371pub enum Version {
372 V87a,
374 V89a,
376}
377
378struct ExtensionData {
379 id: AnyExtension,
380 data: Vec<u8>,
381 is_block_end: bool,
382}
383
384pub enum OutputBuffer<'a> {
386 Slice(&'a mut [u8]),
388 Vec(&'a mut Vec<u8>),
390 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 OutputBuffer::None => (buf.len(), 0),
415 };
416 Ok((consumed, copied))
417 }
418}
419
420impl StreamingDecoder {
421 #[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), is_block_end: true,
445 },
446 current: None,
447 header_end_reached: false,
448 }
449 }
450
451 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 #[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 #[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 #[track_caller]
489 #[must_use]
490 pub fn current_frame(&self) -> &Frame<'static> {
491 self.current.as_ref().unwrap()
492 }
493
494 #[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 #[must_use]
502 pub fn width(&self) -> u16 {
503 self.width
504 }
505
506 #[must_use]
508 pub fn height(&self) -> u16 {
509 self.height
510 }
511
512 #[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 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 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 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 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 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 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 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 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 { 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 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("testing").into();
879}