-
Notifications
You must be signed in to change notification settings - Fork 5
/
compress.go
106 lines (93 loc) · 1.65 KB
/
compress.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package utils
import (
"bytes"
"compress/gzip"
"io/ioutil"
"sync"
)
var (
writerPool = newGzipWriterPool()
readerPool = sync.Pool{
New: func() interface{} {
return new(gzip.Reader)
},
}
bufferPool = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(nil)
},
}
)
func Zip(data []byte) ([]byte, error) {
return ZipLevel(data, gzip.BestSpeed)
}
func ZipLevel(data []byte, level int) (dst []byte, err error) {
buf := bufferPool.Get().(*bytes.Buffer)
idx := getWriterPoolIndex(level)
zw := writerPool[idx].Get().(*gzip.Writer)
zw.Reset(buf)
defer func() {
buf.Reset()
bufferPool.Put(buf)
writerPool[idx].Put(zw)
}()
_, err = zw.Write(data)
if err != nil {
return
}
err = zw.Flush()
if err != nil {
return
}
err = zw.Close()
if err != nil {
return
}
dst = buf.Bytes()
return
}
func Unzip(data []byte) (src []byte, err error) {
buf := bufferPool.Get().(*bytes.Buffer)
defer func() {
buf.Reset()
bufferPool.Put(buf)
}()
_, err = buf.Write(data)
if err != nil {
return
}
zr := readerPool.Get().(*gzip.Reader)
defer func() {
readerPool.Put(zr)
}()
err = zr.Reset(buf)
if err != nil {
return
}
defer func() {
_ = zr.Close()
}()
src, err = ioutil.ReadAll(zr)
if err != nil {
return
}
return
}
func newGzipWriterPool() (pools []*sync.Pool) {
for i := 0; i < 12; i++ {
level := i - 2
pools = append(pools, &sync.Pool{
New: func() interface{} {
zw, _ := gzip.NewWriterLevel(nil, level)
return zw
},
})
}
return
}
func getWriterPoolIndex(level int) int {
if level < gzip.HuffmanOnly || level > gzip.BestCompression {
level = gzip.DefaultCompression
}
return level + 2
}