@@ -298,6 +298,14 @@ const (
298298 huffmanGenericReader
299299)
300300
301+ // flushMode tells decompressor when to return data
302+ type flushMode uint8
303+
304+ const (
305+ syncFlush flushMode = iota // return data after sync flush block
306+ partialFlush // return data after each block
307+ )
308+
301309// Decompress state.
302310type decompressor struct {
303311 // Input source.
@@ -332,6 +340,8 @@ type decompressor struct {
332340
333341 nb uint
334342 final bool
343+
344+ flushMode flushMode
335345}
336346
337347func (f * decompressor ) nextBlock () {
@@ -618,7 +628,10 @@ func (f *decompressor) dataBlock() {
618628 }
619629
620630 if n == 0 {
621- f .toRead = f .dict .readFlush ()
631+ if f .flushMode == syncFlush {
632+ f .toRead = f .dict .readFlush ()
633+ }
634+
622635 f .finishBlock ()
623636 return
624637 }
@@ -657,8 +670,12 @@ func (f *decompressor) finishBlock() {
657670 if f .dict .availRead () > 0 {
658671 f .toRead = f .dict .readFlush ()
659672 }
673+
660674 f .err = io .EOF
675+ } else if f .flushMode == partialFlush && f .dict .availRead () > 0 {
676+ f .toRead = f .dict .readFlush ()
661677 }
678+
662679 f .step = nextBlock
663680}
664681
@@ -789,15 +806,25 @@ func (f *decompressor) Reset(r io.Reader, dict []byte) error {
789806 return nil
790807}
791808
792- // NewReader returns a new ReadCloser that can be used
793- // to read the uncompressed version of r.
794- // If r does not also implement io.ByteReader,
795- // the decompressor may read more data than necessary from r.
796- // It is the caller's responsibility to call Close on the ReadCloser
797- // when finished reading.
798- //
799- // The ReadCloser returned by NewReader also implements Resetter.
800- func NewReader (r io.Reader ) io.ReadCloser {
809+ type ReaderOpt func (* decompressor )
810+
811+ // WithPartialBlock tells decompressor to return after each block,
812+ // so it can read data written with partial flush
813+ func WithPartialBlock () ReaderOpt {
814+ return func (f * decompressor ) {
815+ f .flushMode = partialFlush
816+ }
817+ }
818+
819+ // WithDict initializes the reader with a preset dictionary
820+ func WithDict (dict []byte ) ReaderOpt {
821+ return func (f * decompressor ) {
822+ f .dict .init (maxMatchOffset , dict )
823+ }
824+ }
825+
826+ // NewReaderOpts returns new reader with provided options
827+ func NewReaderOpts (r io.Reader , opts ... ReaderOpt ) io.ReadCloser {
801828 fixedHuffmanDecoderInit ()
802829
803830 var f decompressor
@@ -806,9 +833,26 @@ func NewReader(r io.Reader) io.ReadCloser {
806833 f .codebits = new ([numCodes ]int )
807834 f .step = nextBlock
808835 f .dict .init (maxMatchOffset , nil )
836+
837+ for _ , opt := range opts {
838+ opt (& f )
839+ }
840+
809841 return & f
810842}
811843
844+ // NewReader returns a new ReadCloser that can be used
845+ // to read the uncompressed version of r.
846+ // If r does not also implement io.ByteReader,
847+ // the decompressor may read more data than necessary from r.
848+ // It is the caller's responsibility to call Close on the ReadCloser
849+ // when finished reading.
850+ //
851+ // The ReadCloser returned by NewReader also implements Resetter.
852+ func NewReader (r io.Reader ) io.ReadCloser {
853+ return NewReaderOpts (r )
854+ }
855+
812856// NewReaderDict is like NewReader but initializes the reader
813857// with a preset dictionary. The returned Reader behaves as if
814858// the uncompressed data stream started with the given dictionary,
@@ -817,13 +861,5 @@ func NewReader(r io.Reader) io.ReadCloser {
817861//
818862// The ReadCloser returned by NewReader also implements Resetter.
819863func NewReaderDict (r io.Reader , dict []byte ) io.ReadCloser {
820- fixedHuffmanDecoderInit ()
821-
822- var f decompressor
823- f .r = makeReader (r )
824- f .bits = new ([maxNumLit + maxNumDist ]int )
825- f .codebits = new ([numCodes ]int )
826- f .step = nextBlock
827- f .dict .init (maxMatchOffset , dict )
828- return & f
864+ return NewReaderOpts (r , WithDict (dict ))
829865}
0 commit comments