1use std::borrow::Cow;
2use std::default::Default;
3use std::error;
4use std::fmt;
5use std::io;
6use std::cmp::min;
7use std::convert::From;
8
9extern crate inflate;
10
11use self::inflate::InflateStream;
12use crc::Crc32;
13use traits::ReadBytesExt;
14use common::{ColorType, BitDepth, Info, Unit, PixelDimensions, AnimationControl, FrameControl};
15use chunk::{self, ChunkType, IHDR, IDAT, IEND};
16
17pub const CHUNCK_BUFFER_SIZE: usize = 32*1024;
19
20#[derive(Debug)]
21enum U32Value {
22 Length,
24 Type(u32),
25 Crc(ChunkType)
26}
27
28#[derive(Debug)]
29enum State {
30 Signature(u8, [u8; 7]),
31 U32Byte3(U32Value, u32),
32 U32Byte2(U32Value, u32),
33 U32Byte1(U32Value, u32),
34 U32(U32Value),
35 ReadChunk(ChunkType, bool),
36 PartialChunk(ChunkType),
37 DecodeData(ChunkType, usize),
38}
39
40#[derive(Debug)]
41pub enum Decoded {
43 Nothing,
45 Header(u32, u32, BitDepth, ColorType, bool),
46 ChunkBegin(u32, ChunkType),
47 ChunkComplete(u32, ChunkType),
48 PixelDimensions(PixelDimensions),
49 AnimationControl(AnimationControl),
50 FrameControl(FrameControl),
51 ImageData,
53 PartialChunk(ChunkType),
54 ImageEnd,
55}
56
57#[derive(Debug)]
58pub enum DecodingError {
59 IoError(io::Error),
60 Format(Cow<'static, str>),
61 InvalidSignature,
62 CrcMismatch {
63 recover: usize,
65 crc_val: u32,
67 crc_sum: u32,
69 chunk: ChunkType
70 },
71 Other(Cow<'static, str>),
72 CorruptFlateStream
73}
74
75impl error::Error for DecodingError {
76 fn description(&self) -> &str {
77 use self::DecodingError::*;
78 match *self {
79 IoError(ref err) => err.description(),
80 Format(ref desc) | Other(ref desc) => &desc,
81 InvalidSignature => "invalid signature",
82 CrcMismatch { .. } => "CRC error",
83 CorruptFlateStream => "compressed data stream corrupted"
84 }
85 }
86}
87
88impl fmt::Display for DecodingError {
89 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
90 write!(fmt, "{}", (self as &error::Error).description())
91 }
92}
93
94impl From<io::Error> for DecodingError {
95 fn from(err: io::Error) -> DecodingError {
96 DecodingError::IoError(err)
97 }
98}
99
100impl From<String> for DecodingError {
101 fn from(err: String) -> DecodingError {
102 DecodingError::Other(err.into())
103 }
104}
105
106impl From<DecodingError> for io::Error {
107 fn from(err: DecodingError) -> io::Error {
108 use std::error::Error;
109 match err {
110 DecodingError::IoError(err) => err,
111 err => io::Error::new(
112 io::ErrorKind::Other,
113 err.description()
114 )
115 }
116 }
117}
118
119pub struct StreamingDecoder {
121 state: Option<State>,
122 current_chunk: (Crc32, u32, Vec<u8>),
123 inflater: InflateStream,
124 info: Option<Info>,
125 current_seq_no: Option<u32>,
126 have_idat: bool,
127}
128
129impl StreamingDecoder {
130 pub fn new() -> StreamingDecoder {
134 StreamingDecoder {
135 state: Some(State::Signature(0, [0; 7])),
136 current_chunk: (Crc32::new(), 0, Vec::with_capacity(CHUNCK_BUFFER_SIZE)),
137 inflater: if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()},
138 info: None,
139 current_seq_no: None,
140 have_idat: false
141 }
142 }
143
144 pub fn reset(&mut self) {
146 self.state = Some(State::Signature(0, [0; 7]));
147 self.current_chunk.0 = Crc32::new();
148 self.current_chunk.1 = 0;
149 self.current_chunk.2.clear();
150 self.inflater = if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()};
151 self.info = None;
152 self.current_seq_no = None;
153 self.have_idat = false;
154 }
155
156 pub fn update(&mut self, mut buf: &[u8], image_data: &mut Vec<u8>)
162 -> Result<(usize, Decoded), DecodingError> {
163 let len = buf.len();
164 while buf.len() > 0 && self.state.is_some() {
165 match self.next_state(buf, image_data) {
166 Ok((bytes, Decoded::Nothing)) => {
167 buf = &buf[bytes..]
168 }
169 Ok((bytes, result)) => {
170 buf = &buf[bytes..];
171 return Ok((len-buf.len(), result));
172 }
173 Err(err) => return Err(err)
174 }
175 }
176 Ok((len-buf.len(), Decoded::Nothing))
177 }
178
179 fn next_state<'a>(&'a mut self, buf: &[u8], image_data: &mut Vec<u8>)
180 -> Result<(usize, Decoded), DecodingError> {
181 use self::State::*;
182
183 macro_rules! goto (
184 ($n:expr, $state:expr) => ({
185 self.state = Some($state);
186 Ok(($n, Decoded::Nothing))
187 });
188 ($state:expr) => ({
189 self.state = Some($state);
190 Ok((1, Decoded::Nothing))
191 });
192 ($n:expr, $state:expr, emit $res:expr) => ({
193 self.state = Some($state);
194 Ok(($n, $res))
195 });
196 ($state:expr, emit $res:expr) => ({
197 self.state = Some($state);
198 Ok((1, $res))
199 })
200 );
201
202 let current_byte = buf[0];
203
204 let state = self.state.take().unwrap();
206 match state {
209 Signature(i, mut signature) => if i < 7 {
210 signature[i as usize] = current_byte;
211 goto!(Signature(i+1, signature))
212 } else {
213 if signature == [137, 80, 78, 71, 13, 10, 26] && current_byte == 10 {
214 goto!(U32(U32Value::Length))
215 } else {
216 Err(DecodingError::InvalidSignature)
217 }
218 },
219 U32Byte3(type_, mut val) => {
220 use self::U32Value::*;
221 val |= current_byte as u32;
222 match type_ {
223 Length => goto!(U32(Type(val))),
224 Type(length) => {
225 let type_str = [
226 (val >> 24) as u8,
227 (val >> 16) as u8,
228 (val >> 8) as u8,
229 val as u8
230 ];
231 self.current_chunk.0.reset();
232 self.current_chunk.0.update(&type_str);
233 self.current_chunk.1 = length;
234 goto!(
235 ReadChunk(type_str, true),
236 emit Decoded::ChunkBegin(length, type_str)
237 )
238 },
239 Crc(type_str) => {
240 if cfg!(fuzzing) || val == self.current_chunk.0.checksum() {
241 goto!(
242 State::U32(U32Value::Length),
243 emit if type_str == IEND {
244 Decoded::ImageEnd
245 } else {
246 Decoded::ChunkComplete(val, type_str)
247 }
248 )
249 } else {
250 Err(DecodingError::CrcMismatch {
251 recover: 1,
252 crc_val: val,
253 crc_sum: self.current_chunk.0.checksum(),
254 chunk: type_str
255 })
256 }
257 },
258 }
259 },
260 U32Byte2(type_, val) => {
261 goto!(U32Byte3(type_, val | (current_byte as u32) << 8))
262 },
263 U32Byte1(type_, val) => {
264 goto!(U32Byte2(type_, val | (current_byte as u32) << 16))
265 },
266 U32(type_) => {
267 goto!(U32Byte1(type_, (current_byte as u32) << 24))
268 },
269 PartialChunk(type_str) => {
270 match type_str {
271 IDAT => {
272 self.have_idat = true;
273 goto!(
274 0,
275 DecodeData(type_str, 0),
276 emit Decoded::PartialChunk(type_str)
277 )
278 },
279 chunk::fdAT => {
280 if let Some(seq_no) = self.current_seq_no {
281 let mut buf = &self.current_chunk.2[..];
282 let next_seq_no = try!(buf.read_be());
283 if next_seq_no != seq_no + 1 {
284 return Err(DecodingError::Format(format!(
285 "Sequence is not in order, expected #{} got #{}.",
286 seq_no + 1,
287 next_seq_no
288 ).into()))
289 }
290 self.current_seq_no = Some(next_seq_no);
291 } else {
292 return Err(DecodingError::Format("fcTL chunk missing before fdAT chunk.".into()))
293 }
294 goto!(
295 0,
296 DecodeData(type_str, 4),
297 emit Decoded::PartialChunk(type_str)
298 )
299 },
300 _ => {
302 if self.current_chunk.1 == 0 { Ok((0, try!(self.parse_chunk(type_str))))
304 } else {
305 goto!(
306 0, ReadChunk(type_str, true),
307 emit Decoded::PartialChunk(type_str)
308 )
309 }
310 }
311 }
312
313 },
314 ReadChunk(type_str, clear) => {
315 if clear {
316 self.current_chunk.2.clear();
317 }
318 if self.current_chunk.1 > 0 {
319 let (ref mut crc, ref mut remaining, ref mut c_buf) = self.current_chunk;
320 let buf_avail = c_buf.capacity() - c_buf.len();
321 let bytes_avail = min(buf.len(), buf_avail);
322 let n = min(*remaining, bytes_avail as u32);
323 if buf_avail == 0 {
324 goto!(0, PartialChunk(type_str))
325 } else {
326 let buf = &buf[..n as usize];
327 crc.update(buf);
328 c_buf.extend(buf.iter().map(|&v| v));
329 *remaining -= n;
330 if *remaining == 0 {
331 goto!(n as usize, PartialChunk(type_str
332 ))
333 } else {
334 goto!(n as usize, ReadChunk(type_str, false))
335 }
336
337 }
338 } else {
339 goto!(0, U32(U32Value::Crc(type_str)))
340 }
341 }
342 DecodeData(type_str, mut n) => {
343 let chunk_len = self.current_chunk.2.len();
344 let (c, data) = try!(self.inflater.update(&self.current_chunk.2[n..]));
345 image_data.extend_from_slice(data);
346 n += c;
347 if n == chunk_len && data.len() == 0 && c == 0 {
348 goto!(
349 0,
350 ReadChunk(type_str, true),
351 emit Decoded::ImageData
352 )
353 } else {
354 goto!(
355 0,
356 DecodeData(type_str, n),
357 emit Decoded::ImageData
358 )
359 }
360 }
361 }
362 }
363
364 fn parse_chunk(&mut self, type_str: [u8; 4])
365 -> Result<Decoded, DecodingError> {
366 self.state = Some(State::U32(U32Value::Crc(type_str)));
367 if self.info.is_none() && type_str != IHDR {
368 return Err(DecodingError::Format(format!(
369 "{} chunk appeared before IHDR chunk", String::from_utf8_lossy(&type_str)
370 ).into()))
371 }
372 match match type_str {
373 IHDR => {
374 self.parse_ihdr()
375 }
376 chunk::PLTE => {
377 self.parse_plte()
378 }
379 chunk::tRNS => {
380 self.parse_trns()
381 }
382 chunk::pHYs => {
383 self.parse_phys()
384 }
385 chunk::acTL => {
386 self.parse_actl()
387 }
388 chunk::fcTL => {
389 self.parse_fctl()
390 }
391 _ => Ok(Decoded::PartialChunk(type_str))
392 } {
393 Err(err) =>{
394 self.state = None;
396 Err(err)
397 },
398 ok => ok
399 }
400 }
401
402 fn get_info_or_err(&self) -> Result<&Info, DecodingError> {
403 self.info.as_ref().ok_or(DecodingError::Format(
404 "IHDR chunk missing".into()
405 ))
406 }
407
408 fn parse_fctl(&mut self)
409 -> Result<Decoded, DecodingError> {
410 let mut buf = &self.current_chunk.2[..];
411 let next_seq_no = try!(buf.read_be());
412
413 self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
415 if next_seq_no != seq_no + 1 {
416 return Err(DecodingError::Format(format!(
417 "Sequence is not in order, expected #{} got #{}.",
418 seq_no + 1,
419 next_seq_no
420 ).into()))
421 }
422 next_seq_no
423 } else {
424 if next_seq_no != 0 {
425 return Err(DecodingError::Format(format!(
426 "Sequence is not in order, expected #{} got #{}.",
427 0,
428 next_seq_no
429 ).into()))
430 }
431 0
432 });
433 self.inflater = if cfg!(fuzzing) {InflateStream::from_zlib_no_checksum()} else {InflateStream::from_zlib()};
434 let fc = FrameControl {
435 sequence_number: next_seq_no,
436 width: try!(buf.read_be()),
437 height: try!(buf.read_be()),
438 x_offset: try!(buf.read_be()),
439 y_offset: try!(buf.read_be()),
440 delay_num: try!(buf.read_be()),
441 delay_den: try!(buf.read_be()),
442 dispose_op: try!(buf.read_be()),
443 blend_op : try!(buf.read_be()),
444 };
445 self.info.as_mut().unwrap().frame_control = Some(fc.clone());
446 Ok(Decoded::FrameControl(fc))
447 }
448
449 fn parse_actl(&mut self)
450 -> Result<Decoded, DecodingError> {
451 if self.have_idat {
452 Err(DecodingError::Format(
453 "acTL chunk appeared after first IDAT chunk".into()
454 ))
455 } else {
456 let mut buf = &self.current_chunk.2[..];
457 let actl = AnimationControl {
458 num_frames: try!(buf.read_be()),
459 num_plays: try!(buf.read_be())
460 };
461 self.info.as_mut().unwrap().animation_control = Some(actl);
462 Ok(Decoded::AnimationControl(actl))
463 }
464 }
465
466 fn parse_plte(&mut self)
467 -> Result<Decoded, DecodingError> {
468 let mut vec = Vec::new();
469 vec.extend(self.current_chunk.2.iter().map(|&v| v));
470 self.info.as_mut().map(
471 |info| info.palette = Some(vec)
472 );
473 Ok(Decoded::Nothing)
474 }
475
476 fn parse_trns(&mut self)
477 -> Result<Decoded, DecodingError> {
478 use common::ColorType::*;
479 let (color_type, bit_depth) = {
480 let info = try!(self.get_info_or_err());
481 (info.color_type, info.bit_depth as u8)
482 };
483 let mut vec = Vec::new();
484 vec.extend(self.current_chunk.2.iter().map(|&v| v));
485 let len = vec.len();
486 let info = match self.info {
487 Some(ref mut info) => info,
488 None => return Err(DecodingError::Format(
489 "tRNS chunk occured before IHDR chunk".into()
490 ))
491 };
492 info.trns = Some(vec);
493 let vec = info.trns.as_mut().unwrap();
494 match color_type {
495 Grayscale => {
496 if len < 2 {
497 return Err(DecodingError::Format(
498 "not enough palette entries".into()
499 ))
500 }
501 if bit_depth < 16 {
502 vec[0] = vec[1];
503 vec.truncate(1);
504 }
505 Ok(Decoded::Nothing)
506 },
507 RGB => {
508 if len < 6 {
509 return Err(DecodingError::Format(
510 "not enough palette entries".into()
511 ))
512 }
513 if bit_depth < 16 {
514 vec[0] = vec[1];
515 vec[1] = vec[3];
516 vec[2] = vec[5];
517 vec.truncate(3);
518 }
519 Ok(Decoded::Nothing)
520 },
521 Indexed => {
522 let _ = info.palette.as_ref().ok_or(DecodingError::Format(
523 "tRNS chunk occured before PLTE chunk".into()
524 ));
525 Ok(Decoded::Nothing)
526 },
527 c => Err(DecodingError::Format(
528 format!("tRNS chunk found for color type ({})", c as u8).into()
529 ))
530 }
531
532 }
533
534 fn parse_phys(&mut self)
535 -> Result<Decoded, DecodingError> {
536 if self.have_idat {
537 Err(DecodingError::Format(
538 "pHYs chunk appeared after first IDAT chunk".into()
539 ))
540 } else {
541 let mut buf = &self.current_chunk.2[..];
542 let xppu = try!(buf.read_be());
543 let yppu = try!(buf.read_be());
544 let unit = try!(buf.read_be());
545 let unit = match Unit::from_u8(unit) {
546 Some(unit) => unit,
547 None => return Err(DecodingError::Format(
548 format!("invalid unit ({})", unit).into()
549 ))
550 };
551 let pixel_dims = PixelDimensions {
552 xppu: xppu,
553 yppu: yppu,
554 unit: unit,
555 };
556 self.info.as_mut().unwrap().pixel_dims = Some(pixel_dims);
557 Ok(Decoded::PixelDimensions(pixel_dims))
558 }
559 }
560
561 fn parse_ihdr(&mut self)
562 -> Result<Decoded, DecodingError> {
563 let mut buf = &self.current_chunk.2[..];
565 let width = try!(buf.read_be());
566 let height = try!(buf.read_be());
567 let bit_depth = try!(buf.read_be());
568 let bit_depth = match BitDepth::from_u8(bit_depth) {
569 Some(bits) => bits,
570 None => return Err(DecodingError::Format(
571 format!("invalid bit depth ({})", bit_depth).into()
572 ))
573 };
574 let color_type = try!(buf.read_be());
575 let color_type = match ColorType::from_u8(color_type) {
576 Some(color_type) => color_type,
577 None => return Err(DecodingError::Format(
578 format!("invalid color type ({})", color_type).into()
579 ))
580 };
581 match try!(buf.read_be()) { 0u8 => (),
583 n => return Err(DecodingError::Format(
584 format!("unknown compression method ({})", n).into()
585 ))
586 }
587 match try!(buf.read_be()) { 0u8 => (),
589 n => return Err(DecodingError::Format(
590 format!("unknown filter method ({})", n).into()
591 ))
592 }
593 let interlaced = match try!(buf.read_be()) {
594 0u8 => false,
595 1 => {
596 true
597 },
598 n => return Err(DecodingError::Format(
599 format!("unknown interlace method ({})", n).into()
600 ))
601 };
602 let mut info = Info::default();
603
604 info.width = width;
605 info.height = height;
606 info.bit_depth = bit_depth;
607 info.color_type = color_type;
608 info.interlaced = interlaced;
609 self.info = Some(info);
610 Ok(Decoded::Header(
611 width,
612 height,
613 bit_depth,
614 color_type,
615 interlaced
616 ))
617 }
618}
619
620#[inline(always)]
621pub fn get_info(d: &StreamingDecoder) -> Option<&Info> {
622 d.info.as_ref()
623}