1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
1.6 KiB
Go

package snapshot
import (
"bytes"
"compress/gzip"
"encoding/binary"
"fmt"
"io"
"math"
)
// V1Encoder creates a new V1 snapshot.
type V1Encoder struct {
data []byte
}
// NewV1Encoder returns an initialized V1 encoder
func NewV1Encoder(b []byte) *V1Encoder {
return &V1Encoder{
data: b,
}
}
// WriteTo writes the snapshot to the given writer.
func (v *V1Encoder) WriteTo(w io.Writer) (int64, error) {
var totalN int64
// Indicate that the data is compressed by writing max uint64 value first.
if err := binary.Write(w, binary.LittleEndian, uint64(math.MaxUint64)); err != nil {
return 0, fmt.Errorf("failed to write max uint64: %w", err)
}
totalN += 8 // 8 bytes for uint64
// Get compressed copy of data.
cdata, err := v.compressedData()
if err != nil {
return 0, fmt.Errorf("failed to get compressed data: %w", err)
}
// Write size of compressed data.
if err := binary.Write(w, binary.LittleEndian, uint64(len(cdata))); err != nil {
return 0, fmt.Errorf("failed to write compressed data size: %w", err)
}
totalN += 8 // 8 bytes for uint64
if len(cdata) != 0 {
// Write compressed data.
n, err := w.Write(cdata)
if err != nil {
return 0, fmt.Errorf("failed to write compressed data: %w", err)
}
totalN += int64(n)
}
return totalN, nil
}
func (v *V1Encoder) compressedData() ([]byte, error) {
if v.data == nil {
return nil, nil
}
var buf bytes.Buffer
gz, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
if err != nil {
return nil, err
}
if _, err := gz.Write(v.data); err != nil {
return nil, err
}
if err := gz.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}