Make brotli behave like official compress/ packages

This commit is contained in:
Paolo Barbolini 2019-04-25 17:25:59 +02:00
parent f6e5ca9707
commit 7ad6b2e5b1
2 changed files with 45 additions and 6 deletions

View File

@ -20,13 +20,22 @@ var errReaderClosed = errors.New("brotli: Reader is closed")
// It is arbitrarily chosen to be equal to the constant used in io.Copy. // It is arbitrarily chosen to be equal to the constant used in io.Copy.
const readBufSize = 32 * 1024 const readBufSize = 32 * 1024
// NewReader initializes new Reader instance. // NewReader creates a new Reader reading the given reader.
func NewReader(src io.Reader) *Reader { func NewReader(src io.Reader) *Reader {
r := new(Reader) r := new(Reader)
r.Reset(src)
return r
}
// Reset discards the Reader's state and makes it equivalent to the result of
// its original state from NewReader, but writing to src instead.
// This permits reusing a Reader rather than allocating a new one.
// Error is always nil
func (r *Reader) Reset(src io.Reader) error {
decoderStateInit(r) decoderStateInit(r)
r.src = src r.src = src
r.buf = make([]byte, readBufSize) r.buf = make([]byte, readBufSize)
return r return nil
} }
func (r *Reader) Read(p []byte) (n int, err error) { func (r *Reader) Read(p []byte) (n int, err error) {

View File

@ -5,6 +5,12 @@ import (
"io" "io"
) )
const (
BestSpeed = 0
BestCompression = 11
DefaultCompression = 6
)
// WriterOptions configures Writer. // WriterOptions configures Writer.
type WriterOptions struct { type WriterOptions struct {
// Quality controls the compression-speed vs compression-density trade-offs. // Quality controls the compression-speed vs compression-density trade-offs.
@ -20,18 +26,42 @@ var (
errWriterClosed = errors.New("brotli: Writer is closed") errWriterClosed = errors.New("brotli: Writer is closed")
) )
// NewWriter initializes new Writer instance. // Writes to the returned writer are compressed and written to dst.
func NewWriter(dst io.Writer, options WriterOptions) *Writer { // It is the caller's responsibility to call Close on the Writer when done.
// Writes may be buffered and not flushed until Close.
func NewWriter(dst io.Writer) *Writer {
return NewWriterLevel(dst, DefaultCompression)
}
// NewWriterLevel is like NewWriter but specifies the compression level instead
// of assuming DefaultCompression.
// The compression level can be DefaultCompression or any integer value between
// BestSpeed and BestCompression inclusive.
func NewWriterLevel(dst io.Writer, level int) *Writer {
return NewWriterOptions(dst, WriterOptions{
Quality: level,
})
}
// NewWriterOptions is like NewWriter but specifies WriterOptions
func NewWriterOptions(dst io.Writer, options WriterOptions) *Writer {
w := new(Writer) w := new(Writer)
encoderInitState(w) w.Reset(dst)
w.params.quality = options.Quality w.params.quality = options.Quality
if options.LGWin > 0 { if options.LGWin > 0 {
w.params.lgwin = uint(options.LGWin) w.params.lgwin = uint(options.LGWin)
} }
w.dst = dst
return w return w
} }
// Reset discards the Writer's state and makes it equivalent to the result of
// its original state from NewWriter or NewWriterLevel, but writing to dst
// instead. This permits reusing a Writer rather than allocating a new one.
func (w *Writer) Reset(dst io.Writer) {
encoderInitState(w)
w.dst = dst
}
func (w *Writer) writeChunk(p []byte, op int) (n int, err error) { func (w *Writer) writeChunk(p []byte, op int) (n int, err error) {
if w.dst == nil { if w.dst == nil {
return 0, errWriterClosed return 0, errWriterClosed