-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcomp.go
93 lines (83 loc) · 2.32 KB
/
comp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package squashfs
import (
"bytes"
"compress/zlib"
"fmt"
"io"
)
type Compression uint16
const (
GZip Compression = iota + 1
LZMA
LZO
XZ
LZ4
ZSTD
)
type Decompressor func(buf []byte) ([]byte, error)
var decompressHandler = map[Compression]Decompressor{GZip: MakeDecompressorErr(zlib.NewReader)}
func (s Compression) String() string {
switch s {
case GZip:
return "GZip"
case LZMA:
return "LZMA"
case LZO:
return "LZO"
case XZ:
return "XZ"
case LZ4:
return "LZ4"
case ZSTD:
return "ZSTD"
}
return fmt.Sprintf("Compression(%d)", s)
}
func (s Compression) decompress(buf []byte) ([]byte, error) {
if f, ok := decompressHandler[s]; ok {
return f(buf)
}
return nil, fmt.Errorf("unsupported compression format %s", s.String())
}
// RegisterDecompressor can be used to register a decompressor for squashfs.
// By default GZip is supported. The method shall take a buffer and return a
// decompressed buffer.
func RegisterDecompressor(method Compression, dcomp Decompressor) {
decompressHandler[method] = dcomp
}
// MakeDecompressor allows using a decompressor made for archive/zip with
// SquashFs. It has some overhead as instead of simply dealing with buffer this
// uses the reader/writer API, but should allow to easily handle some formats.
//
// Example use:
// * squashfs.RegisterDecompressor(squashfs.ZSTD, squashfs.MakeDecompressor(zstd.ZipDecompressor()))
// * squashfs.RegisterDecompressor(squashfs.LZ4, squashfs.MakeDecompressor(lz4.NewReader)))
func MakeDecompressor(dec func(r io.Reader) io.ReadCloser) Decompressor {
return func(buf []byte) ([]byte, error) {
r := bytes.NewReader(buf)
p := dec(r)
defer p.Close()
w := &bytes.Buffer{}
_, err := io.Copy(w, p)
return w.Bytes(), err
}
}
// MakeDecompressorErr is similar to MakeDecompressor but the factory method also
// returns an error.
//
// Example use:
// * squashfs.RegisterDecompressor(squashfs.LZMA, squashfs.MakeDecompressorErr(lzma.NewReader))
// * squashfs.RegisterDecompressor(squashfs.XZ, squashfs.MakeDecompressorErr(xz.NewReader))
func MakeDecompressorErr(dec func(r io.Reader) (io.ReadCloser, error)) Decompressor {
return func(buf []byte) ([]byte, error) {
r := bytes.NewReader(buf)
p, err := dec(r)
if err != nil {
return nil, err
}
defer p.Close()
w := &bytes.Buffer{}
_, err = io.Copy(w, p)
return w.Bytes(), err
}
}