mirror of
https://github.com/safing/structures
synced 2025-04-04 17:39:12 +00:00
103 lines
2.2 KiB
Go
103 lines
2.2 KiB
Go
package dsd
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"errors"
|
|
|
|
"github.com/safing/structures/varint"
|
|
)
|
|
|
|
// DumpAndCompress stores the interface as a dsd formatted data structure and compresses the resulting data.
|
|
func DumpAndCompress(t interface{}, format uint8, compression uint8) ([]byte, error) {
|
|
// Check if compression format is valid.
|
|
compression, ok := ValidateCompressionFormat(compression)
|
|
if !ok {
|
|
return nil, ErrIncompatibleFormat
|
|
}
|
|
|
|
// Dump the given data with the given format.
|
|
data, err := Dump(t, format)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// prepare writer
|
|
packetFormat := varint.Pack8(compression)
|
|
buf := bytes.NewBuffer(nil)
|
|
buf.Write(packetFormat)
|
|
|
|
// compress
|
|
switch compression {
|
|
case GZIP:
|
|
// create gzip writer
|
|
gzipWriter, err := gzip.NewWriterLevel(buf, gzip.BestCompression)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// write data
|
|
n, err := gzipWriter.Write(data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if n != len(data) {
|
|
return nil, errors.New("failed to fully write to gzip compressor")
|
|
}
|
|
|
|
// flush and write gzip footer
|
|
err = gzipWriter.Close()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
default:
|
|
return nil, ErrIncompatibleFormat
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// DecompressAndLoad decompresses the data using the specified compression format and then loads the resulting data blob into the interface.
|
|
func DecompressAndLoad(data []byte, compression uint8, t interface{}) (format uint8, err error) {
|
|
// Check if compression format is valid.
|
|
_, ok := ValidateCompressionFormat(compression)
|
|
if !ok {
|
|
return 0, ErrIncompatibleFormat
|
|
}
|
|
|
|
// prepare reader
|
|
buf := bytes.NewBuffer(nil)
|
|
|
|
// decompress
|
|
switch compression {
|
|
case GZIP:
|
|
// create gzip reader
|
|
gzipReader, err := gzip.NewReader(bytes.NewBuffer(data))
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// read uncompressed data
|
|
_, err = buf.ReadFrom(gzipReader)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
// flush and verify gzip footer
|
|
err = gzipReader.Close()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
default:
|
|
return 0, ErrIncompatibleFormat
|
|
}
|
|
|
|
// assign decompressed data
|
|
data = buf.Bytes()
|
|
|
|
format, read, err := loadFormat(data)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return format, LoadAsFormat(data[read:], format, t)
|
|
}
|