1
2
3
4
5
24 package zlib
25
26 import (
27 "bufio"
28 "compress/flate"
29 "errors"
30 "hash"
31 "hash/adler32"
32 "io"
33 )
34
35 const zlibDeflate = 8
36
37 var (
38
39 ErrChecksum = errors.New("zlib: invalid checksum")
40
41 ErrDictionary = errors.New("zlib: invalid dictionary")
42
43 ErrHeader = errors.New("zlib: invalid header")
44 )
45
46 type reader struct {
47 r flate.Reader
48 decompressor io.ReadCloser
49 digest hash.Hash32
50 err error
51 scratch [4]byte
52 }
53
54
55
56
57 type Resetter interface {
58
59
60 Reset(r io.Reader, dict []byte) error
61 }
62
63
64
65
66
67
68
69
70 func NewReader(r io.Reader) (io.ReadCloser, error) {
71 return NewReaderDict(r, nil)
72 }
73
74
75
76
77
78
79 func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
80 z := new(reader)
81 err := z.Reset(r, dict)
82 if err != nil {
83 return nil, err
84 }
85 return z, nil
86 }
87
88 func (z *reader) Read(p []byte) (int, error) {
89 if z.err != nil {
90 return 0, z.err
91 }
92
93 var n int
94 n, z.err = z.decompressor.Read(p)
95 z.digest.Write(p[0:n])
96 if z.err != io.EOF {
97
98 return n, z.err
99 }
100
101
102 if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
103 if err == io.EOF {
104 err = io.ErrUnexpectedEOF
105 }
106 z.err = err
107 return n, z.err
108 }
109
110 checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
111 if checksum != z.digest.Sum32() {
112 z.err = ErrChecksum
113 return n, z.err
114 }
115 return n, io.EOF
116 }
117
118
119
120
121 func (z *reader) Close() error {
122 if z.err != nil && z.err != io.EOF {
123 return z.err
124 }
125 z.err = z.decompressor.Close()
126 return z.err
127 }
128
129 func (z *reader) Reset(r io.Reader, dict []byte) error {
130 *z = reader{decompressor: z.decompressor}
131 if fr, ok := r.(flate.Reader); ok {
132 z.r = fr
133 } else {
134 z.r = bufio.NewReader(r)
135 }
136
137
138 _, z.err = io.ReadFull(z.r, z.scratch[0:2])
139 if z.err != nil {
140 if z.err == io.EOF {
141 z.err = io.ErrUnexpectedEOF
142 }
143 return z.err
144 }
145 h := uint(z.scratch[0])<<8 | uint(z.scratch[1])
146 if (z.scratch[0]&0x0f != zlibDeflate) || (h%31 != 0) {
147 z.err = ErrHeader
148 return z.err
149 }
150 haveDict := z.scratch[1]&0x20 != 0
151 if haveDict {
152 _, z.err = io.ReadFull(z.r, z.scratch[0:4])
153 if z.err != nil {
154 if z.err == io.EOF {
155 z.err = io.ErrUnexpectedEOF
156 }
157 return z.err
158 }
159 checksum := uint32(z.scratch[0])<<24 | uint32(z.scratch[1])<<16 | uint32(z.scratch[2])<<8 | uint32(z.scratch[3])
160 if checksum != adler32.Checksum(dict) {
161 z.err = ErrDictionary
162 return z.err
163 }
164 }
165
166 if z.decompressor == nil {
167 if haveDict {
168 z.decompressor = flate.NewReaderDict(z.r, dict)
169 } else {
170 z.decompressor = flate.NewReader(z.r)
171 }
172 } else {
173 z.decompressor.(flate.Resetter).Reset(z.r, dict)
174 }
175 z.digest = adler32.New()
176 return nil
177 }
178
View as plain text