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.
14 // A Compressor returns a new compressing writer, writing to w.
15 // The WriteCloser's Close method must be used to flush pending data to w.
16 // The Compressor itself must be safe to invoke from multiple goroutines
17 // simultaneously, but each returned writer will be used only by
18 // one goroutine at a time.
19 type Compressor
func(w io
.Writer
) (io
.WriteCloser
, error
)
21 // A Decompressor returns a new decompressing reader, reading from r.
22 // The ReadCloser's Close method must be used to release associated resources.
23 // The Decompressor itself must be safe to invoke from multiple goroutines
24 // simultaneously, but each returned reader will be used only by
25 // one goroutine at a time.
26 type Decompressor
func(r io
.Reader
) io
.ReadCloser
28 var flateWriterPool sync
.Pool
30 func newFlateWriter(w io
.Writer
) io
.WriteCloser
{
31 fw
, ok
:= flateWriterPool
.Get().(*flate
.Writer
)
35 fw
, _
= flate
.NewWriter(w
, 5)
37 return &pooledFlateWriter
{fw
: fw
}
40 type pooledFlateWriter
struct {
41 mu sync
.Mutex
// guards Close and Write
45 func (w
*pooledFlateWriter
) Write(p
[]byte) (n
int, err error
) {
49 return 0, errors
.New("Write after Close")
54 func (w
*pooledFlateWriter
) Close() error
{
60 flateWriterPool
.Put(w
.fw
)
66 var flateReaderPool sync
.Pool
68 func newFlateReader(r io
.Reader
) io
.ReadCloser
{
69 fr
, ok
:= flateReaderPool
.Get().(io
.ReadCloser
)
71 fr
.(flate
.Resetter
).Reset(r
, nil)
73 fr
= flate
.NewReader(r
)
75 return &pooledFlateReader
{fr
: fr
}
78 type pooledFlateReader
struct {
79 mu sync
.Mutex
// guards Close and Read
83 func (r
*pooledFlateReader
) Read(p
[]byte) (n
int, err error
) {
87 return 0, errors
.New("Read after Close")
92 func (r
*pooledFlateReader
) Close() error
{
98 flateReaderPool
.Put(r
.fr
)
105 compressors sync
.Map
// map[uint16]Compressor
106 decompressors sync
.Map
// map[uint16]Decompressor
110 compressors
.Store(Store
, Compressor(func(w io
.Writer
) (io
.WriteCloser
, error
) { return &nopCloser
{w
}, nil }))
111 compressors
.Store(Deflate
, Compressor(func(w io
.Writer
) (io
.WriteCloser
, error
) { return newFlateWriter(w
), nil }))
113 decompressors
.Store(Store
, Decompressor(io
.NopCloser
))
114 decompressors
.Store(Deflate
, Decompressor(newFlateReader
))
117 // RegisterDecompressor allows custom decompressors for a specified method ID.
118 // The common methods Store and Deflate are built in.
119 func RegisterDecompressor(method
uint16, dcomp Decompressor
) {
120 if _
, dup
:= decompressors
.LoadOrStore(method
, dcomp
); dup
{
121 panic("decompressor already registered")
125 // RegisterCompressor registers custom compressors for a specified method ID.
126 // The common methods Store and Deflate are built in.
127 func RegisterCompressor(method
uint16, comp Compressor
) {
128 if _
, dup
:= compressors
.LoadOrStore(method
, comp
); dup
{
129 panic("compressor already registered")
133 func compressor(method
uint16) Compressor
{
134 ci
, ok
:= compressors
.Load(method
)
138 return ci
.(Compressor
)
141 func decompressor(method
uint16) Decompressor
{
142 di
, ok
:= decompressors
.Load(method
)
146 return di
.(Decompressor
)