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 }