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