github.com/safing/portbase@v0.19.5/formats/dsd/compression.go (about) 1 package dsd 2 3 import ( 4 "bytes" 5 "compress/gzip" 6 "errors" 7 8 "github.com/safing/portbase/formats/varint" 9 ) 10 11 // DumpAndCompress stores the interface as a dsd formatted data structure and compresses the resulting data. 12 func DumpAndCompress(t interface{}, format uint8, compression uint8) ([]byte, error) { 13 // Check if compression format is valid. 14 compression, ok := ValidateCompressionFormat(compression) 15 if !ok { 16 return nil, ErrIncompatibleFormat 17 } 18 19 // Dump the given data with the given format. 20 data, err := Dump(t, format) 21 if err != nil { 22 return nil, err 23 } 24 25 // prepare writer 26 packetFormat := varint.Pack8(compression) 27 buf := bytes.NewBuffer(nil) 28 buf.Write(packetFormat) 29 30 // compress 31 switch compression { 32 case GZIP: 33 // create gzip writer 34 gzipWriter, err := gzip.NewWriterLevel(buf, gzip.BestCompression) 35 if err != nil { 36 return nil, err 37 } 38 39 // write data 40 n, err := gzipWriter.Write(data) 41 if err != nil { 42 return nil, err 43 } 44 if n != len(data) { 45 return nil, errors.New("failed to fully write to gzip compressor") 46 } 47 48 // flush and write gzip footer 49 err = gzipWriter.Close() 50 if err != nil { 51 return nil, err 52 } 53 default: 54 return nil, ErrIncompatibleFormat 55 } 56 57 return buf.Bytes(), nil 58 } 59 60 // DecompressAndLoad decompresses the data using the specified compression format and then loads the resulting data blob into the interface. 61 func DecompressAndLoad(data []byte, compression uint8, t interface{}) (format uint8, err error) { 62 // Check if compression format is valid. 63 _, ok := ValidateCompressionFormat(compression) 64 if !ok { 65 return 0, ErrIncompatibleFormat 66 } 67 68 // prepare reader 69 buf := bytes.NewBuffer(nil) 70 71 // decompress 72 switch compression { 73 case GZIP: 74 // create gzip reader 75 gzipReader, err := gzip.NewReader(bytes.NewBuffer(data)) 76 if err != nil { 77 return 0, err 78 } 79 80 // read uncompressed data 81 _, err = buf.ReadFrom(gzipReader) 82 if err != nil { 83 return 0, err 84 } 85 86 // flush and verify gzip footer 87 err = gzipReader.Close() 88 if err != nil { 89 return 0, err 90 } 91 default: 92 return 0, ErrIncompatibleFormat 93 } 94 95 // assign decompressed data 96 data = buf.Bytes() 97 98 format, read, err := loadFormat(data) 99 if err != nil { 100 return 0, err 101 } 102 return format, LoadAsFormat(data[read:], format, t) 103 }