@@ -14,15 +14,22 @@ import (
14
14
15
15
var (
16
16
flateWriterPool = sync.Pool {}
17
+ flateReaderPool = sync.Pool {}
17
18
)
18
19
19
- func decompressNoContextTakeover (r io.Reader ) io.Reader {
20
+ func decompressNoContextTakeover (r io.Reader ) io.ReadCloser {
20
21
const tail =
21
22
// Add four bytes as specified in RFC
22
23
"\x00 \x00 \xff \xff " +
23
24
// Add final block to squelch unexpected EOF error from flate reader.
24
25
"\x01 \x00 \x00 \xff \xff "
25
- return flate .NewReader (io .MultiReader (r , strings .NewReader (tail )))
26
+
27
+ i := flateReaderPool .Get ()
28
+ if i == nil {
29
+ i = flate .NewReader (nil )
30
+ }
31
+ i .(flate.Resetter ).Reset (io .MultiReader (r , strings .NewReader (tail )), nil )
32
+ return & flateReadWrapper {i .(io.ReadCloser )}
26
33
}
27
34
28
35
func compressNoContextTakeover (w io.WriteCloser ) (io.WriteCloser , error ) {
@@ -36,7 +43,7 @@ func compressNoContextTakeover(w io.WriteCloser) (io.WriteCloser, error) {
36
43
fw = i .(* flate.Writer )
37
44
fw .Reset (tw )
38
45
}
39
- return & flateWrapper {fw : fw , tw : tw }, err
46
+ return & flateWriteWrapper {fw : fw , tw : tw }, err
40
47
}
41
48
42
49
// truncWriter is an io.Writer that writes all but the last four bytes of the
@@ -75,19 +82,19 @@ func (w *truncWriter) Write(p []byte) (int, error) {
75
82
return n + nn , err
76
83
}
77
84
78
- type flateWrapper struct {
85
+ type flateWriteWrapper struct {
79
86
fw * flate.Writer
80
87
tw * truncWriter
81
88
}
82
89
83
- func (w * flateWrapper ) Write (p []byte ) (int , error ) {
90
+ func (w * flateWriteWrapper ) Write (p []byte ) (int , error ) {
84
91
if w .fw == nil {
85
92
return 0 , errWriteClosed
86
93
}
87
94
return w .fw .Write (p )
88
95
}
89
96
90
- func (w * flateWrapper ) Close () error {
97
+ func (w * flateWriteWrapper ) Close () error {
91
98
if w .fw == nil {
92
99
return errWriteClosed
93
100
}
@@ -103,3 +110,31 @@ func (w *flateWrapper) Close() error {
103
110
}
104
111
return err2
105
112
}
113
+
114
+ type flateReadWrapper struct {
115
+ fr io.ReadCloser
116
+ }
117
+
118
+ func (r * flateReadWrapper ) Read (p []byte ) (int , error ) {
119
+ if r .fr == nil {
120
+ return 0 , io .ErrClosedPipe
121
+ }
122
+ n , err := r .fr .Read (p )
123
+ if err == io .EOF {
124
+ // Preemptively place the reader back in the pool. This helps with
125
+ // scenarios where the application does not call NextReader() soon after
126
+ // this final read.
127
+ r .Close ()
128
+ }
129
+ return n , err
130
+ }
131
+
132
+ func (r * flateReadWrapper ) Close () error {
133
+ if r .fr == nil {
134
+ return io .ErrClosedPipe
135
+ }
136
+ err := r .fr .Close ()
137
+ flateReaderPool .Put (r .fr )
138
+ r .fr = nil
139
+ return err
140
+ }
0 commit comments