github.com/abemedia/appcast@v0.4.0/integrations/apt/compress.go (about) 1 package apt 2 3 import ( 4 "compress/gzip" 5 "io" 6 7 "github.com/dsnet/compress/bzip2" 8 "github.com/klauspost/compress/zstd" 9 "github.com/pierrec/lz4" 10 "github.com/ulikunitz/xz" 11 "github.com/ulikunitz/xz/lzma" 12 ) 13 14 type CompressionAlgo uint8 15 16 const ( 17 NoCompression CompressionAlgo = 1 << iota 18 GZIP 19 BZIP2 20 XZ 21 LZMA 22 LZ4 23 ZSTD 24 ) 25 26 func compressionExtensions(algo CompressionAlgo) []string { 27 if algo == 0 { 28 return []string{"", ".xz", ".gz"} // See https://wiki.debian.org/DebianRepository/Format#Compression_of_indices 29 } 30 31 a := []string{""} // Always start with blank string for uncompressed data. 32 for i := GZIP; i <= ZSTD; i <<= 1 { 33 if algo&i == 0 { 34 continue 35 } 36 switch i { 37 case NoCompression: 38 case GZIP: 39 a = append(a, ".gz") 40 case BZIP2: 41 a = append(a, ".bz2") 42 case XZ: 43 a = append(a, ".xz") 44 case LZMA: 45 a = append(a, ".lzma") 46 case LZ4: 47 a = append(a, ".lz4") 48 case ZSTD: 49 a = append(a, ".zst") 50 default: 51 panic("unknown compression algorithm") 52 } 53 } 54 return a 55 } 56 57 func compress(ext string) func(io.Writer) (io.WriteCloser, error) { 58 switch ext { 59 case ".gz": 60 return func(r io.Writer) (io.WriteCloser, error) { 61 return gzip.NewWriter(r), nil 62 } 63 case ".bz2": 64 return func(r io.Writer) (io.WriteCloser, error) { 65 return bzip2.NewWriter(r, nil) 66 } 67 case ".xz": 68 return func(r io.Writer) (io.WriteCloser, error) { 69 return xz.NewWriter(r) 70 } 71 case ".lzma": 72 return func(r io.Writer) (io.WriteCloser, error) { 73 return lzma.NewWriter(r) 74 } 75 case ".lz4": 76 return func(r io.Writer) (io.WriteCloser, error) { 77 return lz4.NewWriter(r), nil 78 } 79 case ".zst": 80 return func(r io.Writer) (io.WriteCloser, error) { 81 return zstd.NewWriter(r) 82 } 83 default: 84 return func(r io.Writer) (io.WriteCloser, error) { 85 return writeCloser{r}, nil 86 } 87 } 88 } 89 90 func decompress(ext string) func(io.Reader) (io.ReadCloser, error) { 91 switch ext { 92 case ".gz": 93 return func(r io.Reader) (io.ReadCloser, error) { 94 return gzip.NewReader(r) 95 } 96 case ".bz2": 97 return func(r io.Reader) (io.ReadCloser, error) { 98 return bzip2.NewReader(r, nil) 99 } 100 case ".xz": 101 return func(r io.Reader) (io.ReadCloser, error) { 102 rd, err := xz.NewReader(r) 103 return io.NopCloser(rd), err 104 } 105 case ".lzma": 106 return func(r io.Reader) (io.ReadCloser, error) { 107 rd, err := lzma.NewReader(r) 108 return io.NopCloser(rd), err 109 } 110 case ".lz4": 111 return func(r io.Reader) (io.ReadCloser, error) { 112 return io.NopCloser(lz4.NewReader(r)), nil 113 } 114 case ".zst": 115 return func(r io.Reader) (io.ReadCloser, error) { 116 rd, err := zstd.NewReader(r) 117 return readCloser{rd}, err 118 } 119 default: 120 return func(r io.Reader) (io.ReadCloser, error) { 121 return io.NopCloser(r), nil 122 } 123 } 124 } 125 126 type writeCloser struct { 127 io.Writer 128 } 129 130 func (c writeCloser) Close() error { 131 return nil 132 } 133 134 type rc interface { 135 io.Reader 136 Close() 137 } 138 139 type readCloser struct { 140 rc 141 } 142 143 func (c readCloser) Close() error { 144 c.rc.Close() 145 return nil 146 }