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 }