1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::old_io;
use std::old_io::IoResult;
use super::hash::Adler32;
use super::deflate::Inflater;
enum ZlibState {
Start,
CompressedData,
End
}
pub struct ZlibDecoder<R> {
inflate: Inflater<R>,
adler: Adler32,
state: ZlibState,
}
impl<R: Reader> ZlibDecoder<R> {
pub fn new(r: R) -> ZlibDecoder<R> {
ZlibDecoder {
inflate: Inflater::new(r),
adler: Adler32::new(),
state: ZlibState::Start,
}
}
pub fn inner(&mut self) -> &mut R {
self.inflate.inner()
}
fn read_header(&mut self) -> IoResult<()> {
let cmf = try!(self.inner().read_u8());
let _cm = cmf & 0x0F;
let _cinfo = cmf >> 4;
let flg = try!(self.inner().read_u8());
let fdict = (flg & 0b100000) != 0;
if fdict {
let _dictid = try!(self.inner().read_be_u32());
panic!("invalid png: zlib detected fdict true")
}
assert!((cmf as u16 * 256 + flg as u16) % 31 == 0);
Ok(())
}
fn read_checksum(&mut self) -> IoResult<()> {
let stream_adler32 = try!(self.inner().read_be_u32());
let adler32 = self.adler.checksum();
assert!(adler32 == stream_adler32);
self.adler.reset();
Ok(())
}
}
impl<R: Reader> Reader for ZlibDecoder<R> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
match self.state {
ZlibState::CompressedData => {
match self.inflate.read(buf) {
Ok(n) => {
self.adler.update(&buf[..n]);
if self.inflate.eof() {
let _ = try!(self.read_checksum());
self.state = ZlibState::End;
}
Ok(n)
}
e => e
}
}
ZlibState::Start => {
let _ = try!(self.read_header());
self.state = ZlibState::CompressedData;
self.read(buf)
}
ZlibState::End => Err(old_io::standard_error(old_io::EndOfFile))
}
}
}