Skip to content

Commit

Permalink
archive/zip: clarify expectations of RegisterCompressor and RegisterD…
Browse files Browse the repository at this point in the history
…ecompressor

Clarify that Compressor and Decompressor callbacks must support being invoked
concurrently, but that the writer or reader returned need not be.

Updates #8359

Change-Id: Ia407b581dd124185f165c25f5701018a8ce4357a
Reviewed-on: https://go-review.googlesource.com/18627
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
  • Loading branch information
dsnet authored and bradfitz committed Jan 27, 2016
1 parent 1d901f5 commit c736280
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 27 deletions.
17 changes: 3 additions & 14 deletions src/archive/zip/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,17 @@ func ExampleReader() {
}

func ExampleWriter_RegisterCompressor() {
// Override the default Deflate compressor with a higher compression
// level.
// Override the default Deflate compressor with a higher compression level.

// Create a buffer to write our archive to.
buf := new(bytes.Buffer)

// Create a new zip archive.
w := zip.NewWriter(buf)

var fw *flate.Writer

// Register the deflator.
// Register a custom Deflate compressor.
w.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
var err error
if fw == nil {
// Creating a flate compressor for every file is
// expensive, create one and reuse it.
fw, err = flate.NewWriter(out, flate.BestCompression)
} else {
fw.Reset(out)
}
return fw, err
return flate.NewWriter(out, flate.BestCompression)
})

// Proceed to add files to w.
Expand Down
2 changes: 0 additions & 2 deletions src/archive/zip/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,6 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
// RegisterDecompressor registers or overrides a custom decompressor for a
// specific method ID. If a decompressor for a given method is not found,
// Reader will default to looking up the decompressor at the package level.
//
// Must not be called concurrently with Open on any Files in the Reader.
func (z *Reader) RegisterDecompressor(method uint16, dcomp Decompressor) {
if z.decompressors == nil {
z.decompressors = make(map[uint16]Decompressor)
Expand Down
27 changes: 16 additions & 11 deletions src/archive/zip/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,19 @@ import (
"sync"
)

// A Compressor returns a compressing writer, writing to the
// provided writer. On Close, any pending data should be flushed.
type Compressor func(io.Writer) (io.WriteCloser, error)

// Decompressor is a function that wraps a Reader with a decompressing Reader.
// The decompressed ReadCloser is returned to callers who open files from
// within the archive. These callers are responsible for closing this reader
// when they're finished reading.
type Decompressor func(io.Reader) io.ReadCloser
// 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.
type Compressor func(w io.Writer) (io.WriteCloser, error)

// 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

Expand Down Expand Up @@ -75,14 +79,15 @@ var (
)

// RegisterDecompressor allows custom decompressors for a specified method ID.
func RegisterDecompressor(method uint16, d Decompressor) {
// The common methods Store and Deflate are built in.
func RegisterDecompressor(method uint16, dcomp Decompressor) {
mu.Lock()
defer mu.Unlock()

if _, ok := decompressors[method]; ok {
panic("decompressor already registered")
}
decompressors[method] = d
decompressors[method] = dcomp
}

// RegisterCompressor registers custom compressors for a specified method ID.
Expand Down

0 comments on commit c736280

Please sign in to comment.