github.com/bodgit/sevenzip@v1.5.1/internal/deflate/reader.go (about)

     1  package deflate
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  	"sync"
     7  
     8  	"github.com/bodgit/sevenzip/internal/util"
     9  	"github.com/klauspost/compress/flate"
    10  )
    11  
    12  //nolint:gochecknoglobals
    13  var flateReaderPool sync.Pool
    14  
    15  type readCloser struct {
    16  	c  io.Closer
    17  	fr io.ReadCloser
    18  }
    19  
    20  func (rc *readCloser) Close() error {
    21  	var err error
    22  
    23  	if rc.c != nil {
    24  		if err = rc.fr.Close(); err != nil {
    25  			return err
    26  		}
    27  
    28  		flateReaderPool.Put(rc.fr)
    29  		err = rc.c.Close()
    30  		rc.c, rc.fr = nil, nil
    31  	}
    32  
    33  	return err
    34  }
    35  
    36  func (rc *readCloser) Read(p []byte) (int, error) {
    37  	if rc.fr == nil {
    38  		return 0, errors.New("deflate: Read after Close")
    39  	}
    40  
    41  	return rc.fr.Read(p)
    42  }
    43  
    44  // NewReader returns a new DEFLATE io.ReadCloser.
    45  func NewReader(_ []byte, _ uint64, readers []io.ReadCloser) (io.ReadCloser, error) {
    46  	if len(readers) != 1 {
    47  		return nil, errors.New("deflate: need exactly one reader")
    48  	}
    49  
    50  	fr, ok := flateReaderPool.Get().(io.ReadCloser)
    51  	if ok {
    52  		frf, ok := fr.(flate.Resetter)
    53  		if ok {
    54  			if err := frf.Reset(util.ByteReadCloser(readers[0]), nil); err != nil {
    55  				return nil, err
    56  			}
    57  		}
    58  	} else {
    59  		fr = flate.NewReader(util.ByteReadCloser(readers[0]))
    60  	}
    61  
    62  	return &readCloser{
    63  		c:  readers[0],
    64  		fr: fr,
    65  	}, nil
    66  }