github.com/sandwich-go/boost@v1.3.29/xcompress/gzip.go (about)

     1  package xcompress
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"fmt"
     7  	"github.com/sandwich-go/boost"
     8  	"io/ioutil"
     9  	"sync"
    10  )
    11  
    12  type gzipCompressor struct {
    13  	level                        int
    14  	spWriter, spReader, spBuffer sync.Pool
    15  }
    16  
    17  func newGzipCompressor(level int) (Compressor, error) {
    18  	c := &gzipCompressor{level: level}
    19  	err := c.init()
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	return c, nil
    24  }
    25  
    26  func (c *gzipCompressor) init() error {
    27  	if c.level < HuffmanOnly || c.level > BestCompression {
    28  		return fmt.Errorf("gzip: invalid compression level: %d", c.level)
    29  	}
    30  	c.spWriter = sync.Pool{New: func() interface{} { w, _ := gzip.NewWriterLevel(nil, c.level); return w }}
    31  	c.spReader = sync.Pool{New: func() interface{} { return new(gzip.Reader) }}
    32  	c.spBuffer = sync.Pool{New: func() interface{} { return bytes.NewBuffer(nil) }}
    33  	return nil
    34  }
    35  
    36  func (c *gzipCompressor) Flat(data []byte) ([]byte, error) {
    37  	if len(data) == 0 {
    38  		return data, nil
    39  	}
    40  	buf := c.spBuffer.Get().(*bytes.Buffer)
    41  	w := c.spWriter.Get().(*gzip.Writer)
    42  	w.Reset(buf)
    43  
    44  	defer func() {
    45  		buf.Reset()
    46  		c.spBuffer.Put(buf)
    47  		boost.LogErrorAndEatError(w.Close())
    48  		c.spWriter.Put(w)
    49  	}()
    50  	_, err := w.Write(data)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	err = w.Flush()
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	err = w.Close()
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	dec := buf.Bytes()
    63  	bs := make([]byte, len(dec))
    64  	copy(bs, dec)
    65  	return bs, nil
    66  }
    67  
    68  func (c *gzipCompressor) Inflate(data []byte) ([]byte, error) {
    69  	if len(data) == 0 {
    70  		return data, nil
    71  	}
    72  	buf := c.spBuffer.Get().(*bytes.Buffer)
    73  	defer func() {
    74  		buf.Reset()
    75  		c.spBuffer.Put(buf)
    76  	}()
    77  
    78  	_, err := buf.Write(data)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	gr := c.spReader.Get().(*gzip.Reader)
    84  	defer func() {
    85  		c.spReader.Put(gr)
    86  	}()
    87  	err = gr.Reset(buf)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  	defer func() {
    92  		boost.LogErrorAndEatError(gr.Close())
    93  	}()
    94  	return ioutil.ReadAll(gr)
    95  }