1 // Copyright 2010 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 // A Compressor returns a new compressing writer, writing to w.
16 // The WriteCloser's Close method must be used to flush pending data to w.
17 // The Compressor itself must be safe to invoke from multiple goroutines
18 // simultaneously, but each returned writer will be used only by
19 // one goroutine at a time.
20 type Compressor
func(w io
.Writer
) (io
.WriteCloser
, error
)
22 // A Decompressor returns a new decompressing reader, reading from r.
23 // The ReadCloser's Close method must be used to release associated resources.
24 // The Decompressor itself must be safe to invoke from multiple goroutines
25 // simultaneously, but each returned reader will be used only by
26 // one goroutine at a time.
27 type Decompressor
func(r io
.Reader
) io
.ReadCloser
29 var flateWriterPool sync
.Pool
31 func newFlateWriter(w io
.Writer
) io
.WriteCloser
{
32 fw
, ok
:= flateWriterPool
.Get().(*flate
.Writer
)
36 fw
, _
= flate
.NewWriter(w
, 5)
38 return &pooledFlateWriter
{fw
: fw
}
41 type pooledFlateWriter
struct {
42 mu sync
.Mutex
// guards Close and Write
46 func (w
*pooledFlateWriter
) Write(p
[]byte) (n
int, err error
) {
50 return 0, errors
.New("Write after Close")
55 func (w
*pooledFlateWriter
) Close() error
{
61 flateWriterPool
.Put(w
.fw
)
67 var flateReaderPool sync
.Pool
69 func newFlateReader(r io
.Reader
) io
.ReadCloser
{
70 fr
, ok
:= flateReaderPool
.Get().(io
.ReadCloser
)
72 fr
.(flate
.Resetter
).Reset(r
, nil)
74 fr
= flate
.NewReader(r
)
76 return &pooledFlateReader
{fr
: fr
}
79 type pooledFlateReader
struct {
80 mu sync
.Mutex
// guards Close and Read
84 func (r
*pooledFlateReader
) Read(p
[]byte) (n
int, err error
) {
88 return 0, errors
.New("Read after Close")
93 func (r
*pooledFlateReader
) Close() error
{
99 flateReaderPool
.Put(r
.fr
)
106 compressors sync
.Map
// map[uint16]Compressor
107 decompressors sync
.Map
// map[uint16]Decompressor
111 compressors
.Store(Store
, Compressor(func(w io
.Writer
) (io
.WriteCloser
, error
) { return &nopCloser
{w
}, nil }))
112 compressors
.Store(Deflate
, Compressor(func(w io
.Writer
) (io
.WriteCloser
, error
) { return newFlateWriter(w
), nil }))
114 decompressors
.Store(Store
, Decompressor(ioutil
.NopCloser
))
115 decompressors
.Store(Deflate
, Decompressor(newFlateReader
))
118 // RegisterDecompressor allows custom decompressors for a specified method ID.
119 // The common methods Store and Deflate are built in.
120 func RegisterDecompressor(method
uint16, dcomp Decompressor
) {
121 if _
, dup
:= decompressors
.LoadOrStore(method
, dcomp
); dup
{
122 panic("decompressor already registered")
126 // RegisterCompressor registers custom compressors for a specified method ID.
127 // The common methods Store and Deflate are built in.
128 func RegisterCompressor(method
uint16, comp Compressor
) {
129 if _
, dup
:= compressors
.LoadOrStore(method
, comp
); dup
{
130 panic("compressor already registered")
134 func compressor(method
uint16) Compressor
{
135 ci
, ok
:= compressors
.Load(method
)
139 return ci
.(Compressor
)
142 func decompressor(method
uint16) Decompressor
{
143 di
, ok
:= decompressors
.Load(method
)
147 return di
.(Decompressor
)