Adding upstream version 0.31.1.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
091495b2f3
commit
5d4914ed7f
61 changed files with 30627 additions and 0 deletions
223
encoding.go
Normal file
223
encoding.go
Normal file
|
@ -0,0 +1,223 @@
|
|||
package meilisearch
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"compress/zlib"
|
||||
"encoding/json"
|
||||
"github.com/andybalholm/brotli"
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type encoder interface {
|
||||
Encode(rc io.Reader) (*bytes.Buffer, error)
|
||||
Decode(data []byte, vPtr interface{}) error
|
||||
}
|
||||
|
||||
func newEncoding(ce ContentEncoding, level EncodingCompressionLevel) encoder {
|
||||
switch ce {
|
||||
case GzipEncoding:
|
||||
return &gzipEncoder{
|
||||
gzWriterPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
w, err := gzip.NewWriterLevel(io.Discard, level.Int())
|
||||
return &gzipWriter{
|
||||
writer: w,
|
||||
err: err,
|
||||
}
|
||||
},
|
||||
},
|
||||
bufferPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
}
|
||||
case DeflateEncoding:
|
||||
return &flateEncoder{
|
||||
flWriterPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
w, err := zlib.NewWriterLevel(io.Discard, level.Int())
|
||||
return &flateWriter{
|
||||
writer: w,
|
||||
err: err,
|
||||
}
|
||||
},
|
||||
},
|
||||
bufferPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
}
|
||||
case BrotliEncoding:
|
||||
return &brotliEncoder{
|
||||
brWriterPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return brotli.NewWriterLevel(io.Discard, level.Int())
|
||||
},
|
||||
},
|
||||
bufferPool: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return new(bytes.Buffer)
|
||||
},
|
||||
},
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type gzipEncoder struct {
|
||||
gzWriterPool *sync.Pool
|
||||
bufferPool *sync.Pool
|
||||
}
|
||||
|
||||
type gzipWriter struct {
|
||||
writer *gzip.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
func (g *gzipEncoder) Encode(rc io.Reader) (*bytes.Buffer, error) {
|
||||
w := g.gzWriterPool.Get().(*gzipWriter)
|
||||
defer g.gzWriterPool.Put(w)
|
||||
|
||||
if w.err != nil {
|
||||
return nil, w.err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = w.writer.Close()
|
||||
}()
|
||||
|
||||
buf := g.bufferPool.Get().(*bytes.Buffer)
|
||||
defer g.bufferPool.Put(buf)
|
||||
|
||||
buf.Reset()
|
||||
w.writer.Reset(buf)
|
||||
|
||||
if _, err := copyZeroAlloc(w.writer, rc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (g *gzipEncoder) Decode(data []byte, vPtr interface{}) error {
|
||||
r, err := gzip.NewReader(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = r.Close()
|
||||
}()
|
||||
|
||||
if err := json.NewDecoder(r).Decode(vPtr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type flateEncoder struct {
|
||||
flWriterPool *sync.Pool
|
||||
bufferPool *sync.Pool
|
||||
}
|
||||
|
||||
type flateWriter struct {
|
||||
writer *zlib.Writer
|
||||
err error
|
||||
}
|
||||
|
||||
func (d *flateEncoder) Encode(rc io.Reader) (*bytes.Buffer, error) {
|
||||
w := d.flWriterPool.Get().(*flateWriter)
|
||||
defer d.flWriterPool.Put(w)
|
||||
|
||||
if w.err != nil {
|
||||
return nil, w.err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = w.writer.Close()
|
||||
}()
|
||||
|
||||
buf := d.bufferPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
w.writer.Reset(buf)
|
||||
|
||||
if _, err := copyZeroAlloc(w.writer, rc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (d *flateEncoder) Decode(data []byte, vPtr interface{}) error {
|
||||
r, err := zlib.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
_ = r.Close()
|
||||
}()
|
||||
|
||||
if err := json.NewDecoder(r).Decode(vPtr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type brotliEncoder struct {
|
||||
brWriterPool *sync.Pool
|
||||
bufferPool *sync.Pool
|
||||
}
|
||||
|
||||
func (b *brotliEncoder) Encode(rc io.Reader) (*bytes.Buffer, error) {
|
||||
w := b.brWriterPool.Get().(*brotli.Writer)
|
||||
defer func() {
|
||||
_ = w.Close()
|
||||
b.brWriterPool.Put(w)
|
||||
}()
|
||||
|
||||
buf := b.bufferPool.Get().(*bytes.Buffer)
|
||||
buf.Reset()
|
||||
w.Reset(buf)
|
||||
|
||||
if _, err := copyZeroAlloc(w, rc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (b *brotliEncoder) Decode(data []byte, vPtr interface{}) error {
|
||||
r := brotli.NewReader(bytes.NewBuffer(data))
|
||||
if err := json.NewDecoder(r).Decode(vPtr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var copyBufPool = sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 4096)
|
||||
},
|
||||
}
|
||||
|
||||
func copyZeroAlloc(w io.Writer, r io.Reader) (int64, error) {
|
||||
if wt, ok := r.(io.WriterTo); ok {
|
||||
return wt.WriteTo(w)
|
||||
}
|
||||
if rt, ok := w.(io.ReaderFrom); ok {
|
||||
return rt.ReadFrom(r)
|
||||
}
|
||||
vbuf := copyBufPool.Get()
|
||||
buf := vbuf.([]byte)
|
||||
n, err := io.CopyBuffer(w, r, buf)
|
||||
copyBufPool.Put(vbuf)
|
||||
return n, err
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue