github.com/wfusion/gofusion@v1.1.14/common/utils/compress/decode.go (about)

     1  package compress
     2  
     3  import (
     4  	"io"
     5  
     6  	"github.com/wfusion/gofusion/common/utils"
     7  )
     8  
     9  type decodable interface {
    10  	io.Reader
    11  	Reset(r io.Reader) error
    12  }
    13  
    14  func DecodeBytesFunc(algo Algorithm) func(src []byte) (dst []byte, err error) {
    15  	return func(src []byte) (dst []byte, err error) {
    16  		var (
    17  			dec      decodable
    18  			recycles []func()
    19  		)
    20  		defer func() {
    21  			for _, cb := range recycles {
    22  				if cb != nil {
    23  					cb()
    24  				}
    25  			}
    26  		}()
    27  
    28  		srcBuffer, bufferCb := utils.BytesBufferPool.Get(nil)
    29  		recycles = append(recycles, bufferCb)
    30  		srcBuffer.Write(src)
    31  		_, err = utils.Catch(func() {
    32  			var cb func()
    33  			dec, cb = getDecoder(algo, srcBuffer)
    34  			recycles = append(recycles, cb)
    35  		})
    36  		if err != nil || dec == nil {
    37  			return
    38  		}
    39  
    40  		dstBuffer, bufferCb := utils.BytesBufferPool.Get(nil)
    41  		recycles = append(recycles, bufferCb)
    42  		if _, err = io.Copy(dstBuffer, dec); err != nil {
    43  			if err = utils.ErrIgnore(err, eofErrs...); err != nil {
    44  				return
    45  			}
    46  		}
    47  		dst = make([]byte, dstBuffer.Len())
    48  		copy(dst, dstBuffer.Bytes())
    49  		return
    50  	}
    51  }
    52  
    53  func DecodeStreamFunc(algo Algorithm) func(dst io.Writer, src io.Reader) (err error) {
    54  	return func(dst io.Writer, src io.Reader) (err error) {
    55  		var (
    56  			dec decodable
    57  			cb  func()
    58  		)
    59  		defer func() {
    60  			if cb != nil {
    61  				cb()
    62  			}
    63  		}()
    64  
    65  		if _, err = utils.Catch(func() { dec, cb = getDecoder(algo, src) }); err != nil {
    66  			return
    67  		}
    68  
    69  		_, err = io.Copy(dst, dec)
    70  		return utils.ErrIgnore(err, eofErrs...)
    71  	}
    72  }
    73  
    74  func getDecoder(algo Algorithm, src io.Reader) (dec decodable, recycle func()) {
    75  	p, ok := decoderPools[algo]
    76  	if !algo.IsValid() || !ok {
    77  		panic(ErrUnknownAlgorithm)
    78  	}
    79  
    80  	sealer, recycle := p.Get(src)
    81  	dec = sealer.decodable
    82  	return
    83  }
    84  
    85  type decoder struct {
    86  	dec decodable
    87  	r   io.Reader
    88  	cb  func()
    89  }
    90  
    91  func NewDecFunc(algo Algorithm) func(r io.Reader) io.ReadCloser {
    92  	return func(r io.Reader) io.ReadCloser {
    93  		dec, cb := getDecoder(algo, r)
    94  		return &decoder{
    95  			dec: dec,
    96  			r:   r,
    97  			cb:  cb,
    98  		}
    99  	}
   100  }
   101  
   102  func (e *decoder) Reset(r io.Reader) error          { return e.dec.Reset(r) }
   103  func (e *decoder) Read(p []byte) (n int, err error) { return e.dec.Read(p) }
   104  func (e *decoder) Close() (err error)               { defer e.cb(); utils.CloseAnyway(e.r); return }