99 lines
2.1 KiB
Go
99 lines
2.1 KiB
Go
package squish
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"encoding/base64"
|
|
"errors"
|
|
"io"
|
|
"sync"
|
|
)
|
|
|
|
var (
|
|
bufPool = &sync.Pool{
|
|
New: func() interface{} {
|
|
return &bytes.Buffer{}
|
|
},
|
|
}
|
|
|
|
gzipPool = &sync.Pool{
|
|
New: func() interface{} {
|
|
return gzip.NewWriter(nil)
|
|
},
|
|
}
|
|
)
|
|
|
|
// Gzip compresses as slice of bytes using gzip compression.
|
|
func Gzip(data []byte) []byte {
|
|
buf := bufPool.Get().(*bytes.Buffer)
|
|
gz := gzipPool.Get().(*gzip.Writer)
|
|
buf.Reset()
|
|
r, w := io.Pipe()
|
|
gz.Reset(w)
|
|
go func() {
|
|
_, _ = gz.Write(data)
|
|
_ = gz.Close()
|
|
_ = w.Close()
|
|
}()
|
|
n, _ := buf.ReadFrom(r)
|
|
buf.Truncate(int(n))
|
|
_ = r.Close()
|
|
res, _ := io.ReadAll(buf)
|
|
bufPool.Put(buf)
|
|
gzipPool.Put(gz)
|
|
return res
|
|
}
|
|
|
|
// Gunzip decompresses a gzip compressed slice of bytes.
|
|
func Gunzip(data []byte) (out []byte, err error) {
|
|
gz, err := gzip.NewReader(bytes.NewReader(data))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
buf := bufPool.Get().(*bytes.Buffer)
|
|
buf.Reset()
|
|
var n int64
|
|
n, _ = buf.ReadFrom(gz)
|
|
err = gz.Close()
|
|
buf.Truncate(int(n))
|
|
res, _ := io.ReadAll(buf)
|
|
bufPool.Put(buf)
|
|
return res, err
|
|
}
|
|
|
|
// B64e encodes the given slice of bytes into base64 standard encoding.
|
|
func B64e(in []byte) (out string) {
|
|
buf := bufPool.Get().(*bytes.Buffer)
|
|
buf.Reset()
|
|
buf.Grow(base64.StdEncoding.EncodedLen(len(in)))
|
|
b64 := base64.NewEncoder(base64.StdEncoding, buf)
|
|
_, _ = b64.Write(in)
|
|
_ = b64.Close()
|
|
res := buf.Bytes()
|
|
bufPool.Put(buf)
|
|
return string(res)
|
|
}
|
|
|
|
// B64d decodes the given string into the original slice of bytes.
|
|
// Do note that this is for non critical tasks, it has no error handling for purposes of clean code.
|
|
func B64d(str string) (data []byte) {
|
|
if len(str) == 0 {
|
|
return nil
|
|
}
|
|
data, _ = base64.StdEncoding.DecodeString(str)
|
|
return data
|
|
}
|
|
|
|
// UnpackStr UNsafely unpacks (usually banners) that have been base64'd and then gzip'd.
|
|
func UnpackStr(encoded string) (string, error) {
|
|
one := B64d(encoded)
|
|
if len(one) == 0 {
|
|
return "", errors.New("0 length base64 decoding result")
|
|
}
|
|
dcytes, err := Gunzip(one)
|
|
if err != nil && !errors.Is(err, io.EOF) {
|
|
return "", err
|
|
}
|
|
return string(dcytes), nil
|
|
}
|