...
1
18
19
20
21
22
23
24
25
26 package gzip
27
28 import (
29 "compress/gzip"
30 "encoding/binary"
31 "fmt"
32 "io"
33 "sync"
34
35 "google.golang.org/grpc/encoding"
36 )
37
38
39 const Name = "gzip"
40
41 func init() {
42 c := &compressor{}
43 c.poolCompressor.New = func() any {
44 return &writer{Writer: gzip.NewWriter(io.Discard), pool: &c.poolCompressor}
45 }
46 encoding.RegisterCompressor(c)
47 }
48
49 type writer struct {
50 *gzip.Writer
51 pool *sync.Pool
52 }
53
54
55
56
57
58
59 func SetLevel(level int) error {
60 if level < gzip.DefaultCompression || level > gzip.BestCompression {
61 return fmt.Errorf("grpc: invalid gzip compression level: %d", level)
62 }
63 c := encoding.GetCompressor(Name).(*compressor)
64 c.poolCompressor.New = func() any {
65 w, err := gzip.NewWriterLevel(io.Discard, level)
66 if err != nil {
67 panic(err)
68 }
69 return &writer{Writer: w, pool: &c.poolCompressor}
70 }
71 return nil
72 }
73
74 func (c *compressor) Compress(w io.Writer) (io.WriteCloser, error) {
75 z := c.poolCompressor.Get().(*writer)
76 z.Writer.Reset(w)
77 return z, nil
78 }
79
80 func (z *writer) Close() error {
81 defer z.pool.Put(z)
82 return z.Writer.Close()
83 }
84
85 type reader struct {
86 *gzip.Reader
87 pool *sync.Pool
88 }
89
90 func (c *compressor) Decompress(r io.Reader) (io.Reader, error) {
91 z, inPool := c.poolDecompressor.Get().(*reader)
92 if !inPool {
93 newZ, err := gzip.NewReader(r)
94 if err != nil {
95 return nil, err
96 }
97 return &reader{Reader: newZ, pool: &c.poolDecompressor}, nil
98 }
99 if err := z.Reset(r); err != nil {
100 c.poolDecompressor.Put(z)
101 return nil, err
102 }
103 return z, nil
104 }
105
106 func (z *reader) Read(p []byte) (n int, err error) {
107 n, err = z.Reader.Read(p)
108 if err == io.EOF {
109 z.pool.Put(z)
110 }
111 return n, err
112 }
113
114
115
116
117 func (c *compressor) DecompressedSize(buf []byte) int {
118 last := len(buf)
119 if last < 4 {
120 return -1
121 }
122 return int(binary.LittleEndian.Uint32(buf[last-4 : last]))
123 }
124
125 func (c *compressor) Name() string {
126 return Name
127 }
128
129 type compressor struct {
130 poolCompressor sync.Pool
131 poolDecompressor sync.Pool
132 }
133
View as plain text