Copyright 2010 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

package zip

import (
	
	
	
	
)
A Compressor returns a new compressing writer, writing to w. The WriteCloser's Close method must be used to flush pending data to w. The Compressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned writer will be used only by one goroutine at a time.
A Decompressor returns a new decompressing reader, reading from r. The ReadCloser's Close method must be used to release associated resources. The Decompressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned reader will be used only by one goroutine at a time.
type Decompressor func(r io.Reader) io.ReadCloser

var flateWriterPool sync.Pool

func ( io.Writer) io.WriteCloser {
	,  := flateWriterPool.Get().(*flate.Writer)
	if  {
		.Reset()
	} else {
		, _ = flate.NewWriter(, 5)
	}
	return &pooledFlateWriter{fw: }
}

type pooledFlateWriter struct {
	mu sync.Mutex // guards Close and Write
	fw *flate.Writer
}

func ( *pooledFlateWriter) ( []byte) ( int,  error) {
	.mu.Lock()
	defer .mu.Unlock()
	if .fw == nil {
		return 0, errors.New("Write after Close")
	}
	return .fw.Write()
}

func ( *pooledFlateWriter) () error {
	.mu.Lock()
	defer .mu.Unlock()
	var  error
	if .fw != nil {
		 = .fw.Close()
		flateWriterPool.Put(.fw)
		.fw = nil
	}
	return 
}

var flateReaderPool sync.Pool

func ( io.Reader) io.ReadCloser {
	,  := flateReaderPool.Get().(io.ReadCloser)
	if  {
		.(flate.Resetter).Reset(, nil)
	} else {
		 = flate.NewReader()
	}
	return &pooledFlateReader{fr: }
}

type pooledFlateReader struct {
	mu sync.Mutex // guards Close and Read
	fr io.ReadCloser
}

func ( *pooledFlateReader) ( []byte) ( int,  error) {
	.mu.Lock()
	defer .mu.Unlock()
	if .fr == nil {
		return 0, errors.New("Read after Close")
	}
	return .fr.Read()
}

func ( *pooledFlateReader) () error {
	.mu.Lock()
	defer .mu.Unlock()
	var  error
	if .fr != nil {
		 = .fr.Close()
		flateReaderPool.Put(.fr)
		.fr = nil
	}
	return 
}

var (
	compressors   sync.Map // map[uint16]Compressor
	decompressors sync.Map // map[uint16]Decompressor
)

func () {
	compressors.Store(Store, Compressor(func( io.Writer) (io.WriteCloser, error) { return &nopCloser{}, nil }))
	compressors.Store(Deflate, Compressor(func( io.Writer) (io.WriteCloser, error) { return newFlateWriter(), nil }))

	decompressors.Store(Store, Decompressor(io.NopCloser))
	decompressors.Store(Deflate, Decompressor(newFlateReader))
}
RegisterDecompressor allows custom decompressors for a specified method ID. The common methods Store and Deflate are built in.
func ( uint16,  Decompressor) {
	if ,  := decompressors.LoadOrStore(, );  {
		panic("decompressor already registered")
	}
}
RegisterCompressor registers custom compressors for a specified method ID. The common methods Store and Deflate are built in.
func ( uint16,  Compressor) {
	if ,  := compressors.LoadOrStore(, );  {
		panic("compressor already registered")
	}
}

func ( uint16) Compressor {
	,  := compressors.Load()
	if ! {
		return nil
	}
	return .(Compressor)
}

func ( uint16) Decompressor {
	,  := decompressors.Load()
	if ! {
		return nil
	}
	return .(Decompressor)