...
1
2
3
4
5 package packet
6
7 import (
8 "compress/bzip2"
9 "compress/flate"
10 "compress/zlib"
11 "github.com/ProtonMail/go-crypto/openpgp/errors"
12 "io"
13 "strconv"
14 )
15
16
17
18 type Compressed struct {
19 Body io.Reader
20 }
21
22 const (
23 NoCompression = flate.NoCompression
24 BestSpeed = flate.BestSpeed
25 BestCompression = flate.BestCompression
26 DefaultCompression = flate.DefaultCompression
27 )
28
29
30 type CompressionConfig struct {
31
32
33
34
35
36
37
38
39 Level int
40 }
41
42 func (c *Compressed) parse(r io.Reader) error {
43 var buf [1]byte
44 _, err := readFull(r, buf[:])
45 if err != nil {
46 return err
47 }
48
49 switch buf[0] {
50 case 0:
51 c.Body = r
52 case 1:
53 c.Body = flate.NewReader(r)
54 case 2:
55 c.Body, err = zlib.NewReader(r)
56 case 3:
57 c.Body = bzip2.NewReader(r)
58 default:
59 err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
60 }
61
62 return err
63 }
64
65
66
67
68
69 type compressedWriteCloser struct {
70 sh io.Closer
71 c io.WriteCloser
72 }
73
74 func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
75 return cwc.c.Write(p)
76 }
77
78 func (cwc compressedWriteCloser) Close() (err error) {
79 err = cwc.c.Close()
80 if err != nil {
81 return err
82 }
83
84 return cwc.sh.Close()
85 }
86
87
88
89
90
91
92 func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
93 compressed, err := serializeStreamHeader(w, packetTypeCompressed)
94 if err != nil {
95 return
96 }
97
98 _, err = compressed.Write([]byte{uint8(algo)})
99 if err != nil {
100 return
101 }
102
103 level := DefaultCompression
104 if cc != nil {
105 level = cc.Level
106 }
107
108 var compressor io.WriteCloser
109 switch algo {
110 case CompressionZIP:
111 compressor, err = flate.NewWriter(compressed, level)
112 case CompressionZLIB:
113 compressor, err = zlib.NewWriterLevel(compressed, level)
114 default:
115 s := strconv.Itoa(int(algo))
116 err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
117 }
118 if err != nil {
119 return
120 }
121
122 literaldata = compressedWriteCloser{compressed, compressor}
123
124 return
125 }
126
View as plain text