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  }