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) }