OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / crypto / openpgp / packet / compressed.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package packet
6
7 import (
8         "compress/bzip2"
9         "compress/flate"
10         "compress/zlib"
11         "golang.org/x/crypto/openpgp/errors"
12         "io"
13         "strconv"
14 )
15
16 // Compressed represents a compressed OpenPGP packet. The decompressed contents
17 // will contain more OpenPGP packets. See RFC 4880, section 5.6.
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 // CompressionConfig contains compressor configuration settings.
30 type CompressionConfig struct {
31         // Level is the compression level to use. It must be set to
32         // between -1 and 9, with -1 causing the compressor to use the
33         // default compression level, 0 causing the compressor to use
34         // no compression and 1 to 9 representing increasing (better,
35         // slower) compression levels. If Level is less than -1 or
36         // more then 9, a non-nil error will be returned during
37         // encryption. See the constants above for convenient common
38         // settings for Level.
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 1:
51                 c.Body = flate.NewReader(r)
52         case 2:
53                 c.Body, err = zlib.NewReader(r)
54         case 3:
55                 c.Body = bzip2.NewReader(r)
56         default:
57                 err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
58         }
59
60         return err
61 }
62
63 // compressedWriterCloser represents the serialized compression stream
64 // header and the compressor. Its Close() method ensures that both the
65 // compressor and serialized stream header are closed. Its Write()
66 // method writes to the compressor.
67 type compressedWriteCloser struct {
68         sh io.Closer      // Stream Header
69         c  io.WriteCloser // Compressor
70 }
71
72 func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
73         return cwc.c.Write(p)
74 }
75
76 func (cwc compressedWriteCloser) Close() (err error) {
77         err = cwc.c.Close()
78         if err != nil {
79                 return err
80         }
81
82         return cwc.sh.Close()
83 }
84
85 // SerializeCompressed serializes a compressed data packet to w and
86 // returns a WriteCloser to which the literal data packets themselves
87 // can be written and which MUST be closed on completion. If cc is
88 // nil, sensible defaults will be used to configure the compression
89 // algorithm.
90 func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
91         compressed, err := serializeStreamHeader(w, packetTypeCompressed)
92         if err != nil {
93                 return
94         }
95
96         _, err = compressed.Write([]byte{uint8(algo)})
97         if err != nil {
98                 return
99         }
100
101         level := DefaultCompression
102         if cc != nil {
103                 level = cc.Level
104         }
105
106         var compressor io.WriteCloser
107         switch algo {
108         case CompressionZIP:
109                 compressor, err = flate.NewWriter(compressed, level)
110         case CompressionZLIB:
111                 compressor, err = zlib.NewWriterLevel(compressed, level)
112         default:
113                 s := strconv.Itoa(int(algo))
114                 err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
115         }
116         if err != nil {
117                 return
118         }
119
120         literaldata = compressedWriteCloser{compressed, compressor}
121
122         return
123 }