folly: replace old-style header guards with "pragma once"
[folly.git] / folly / io / Compression.h
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <cstdint>
20 #include <limits>
21 #include <memory>
22
23 #include <folly/io/IOBuf.h>
24
25 /**
26  * Compression / decompression over IOBufs
27  */
28
29 namespace folly { namespace io {
30
31 enum class CodecType {
32   /**
33    * This codec type is not defined; getCodec() will throw an exception
34    * if used. Useful if deriving your own classes from Codec without
35    * going through the getCodec() interface.
36    */
37   USER_DEFINED = 0,
38
39   /**
40    * Use no compression.
41    * Levels supported: 0
42    */
43   NO_COMPRESSION = 1,
44
45   /**
46    * Use LZ4 compression.
47    * Levels supported: 1 = fast, 2 = best; default = 1
48    */
49   LZ4 = 2,
50
51   /**
52    * Use Snappy compression.
53    * Levels supported: 1
54    */
55   SNAPPY = 3,
56
57   /**
58    * Use zlib compression.
59    * Levels supported: 0 = no compression, 1 = fast, ..., 9 = best; default = 6
60    */
61   ZLIB = 4,
62
63   /**
64    * Use LZ4 compression, prefixed with size (as Varint).
65    */
66   LZ4_VARINT_SIZE = 5,
67
68   /**
69    * Use LZMA2 compression.
70    * Levels supported: 0 = no compression, 1 = fast, ..., 9 = best; default = 6
71    */
72   LZMA2 = 6,
73   LZMA2_VARINT_SIZE = 7,
74
75   /**
76    * Use ZSTD_BETA compression.
77    * This format is not yet final; please do not rely on it for anything other
78    * than testing purposes yet.
79    */
80   ZSTD_BETA = 8,
81
82   /**
83    * Use gzip compression.  This is the same compression algorithm as ZLIB but
84    * gzip-compressed files tend to be easier to work with from the command line.
85    * Levels supported: 0 = no compression, 1 = fast, ..., 9 = best; default = 6
86    */
87   GZIP = 9,
88
89   NUM_CODEC_TYPES = 10,
90 };
91
92 class Codec {
93  public:
94   virtual ~Codec() { }
95
96   /**
97    * Return the maximum length of data that may be compressed with this codec.
98    * NO_COMPRESSION and ZLIB support arbitrary lengths;
99    * LZ4 supports up to 1.9GiB; SNAPPY supports up to 4GiB.
100    * May return UNLIMITED_UNCOMPRESSED_LENGTH if unlimited.
101    */
102   uint64_t maxUncompressedLength() const;
103
104   /**
105    * Return the codec's type.
106    */
107   CodecType type() const { return type_; }
108
109   /**
110    * Does this codec need the exact uncompressed length on decompression?
111    */
112   bool needsUncompressedLength() const;
113
114   /**
115    * Compress data, returning an IOBuf (which may share storage with data).
116    * Throws std::invalid_argument if data is larger than
117    * maxUncompressedLength().
118    *
119    * Regardless of the behavior of the underlying compressor, compressing
120    * an empty IOBuf chain will return an empty IOBuf chain.
121    */
122   std::unique_ptr<IOBuf> compress(const folly::IOBuf* data);
123
124   /**
125    * Uncompress data. Throws std::runtime_error on decompression error.
126    *
127    * Some codecs (LZ4) require the exact uncompressed length; this is indicated
128    * by needsUncompressedLength().
129    *
130    * For other codes (zlib), knowing the exact uncompressed length ahead of
131    * time might be faster.
132    *
133    * Regardless of the behavior of the underlying compressor, uncompressing
134    * an empty IOBuf chain will return an empty IOBuf chain.
135    */
136   static constexpr uint64_t UNKNOWN_UNCOMPRESSED_LENGTH = uint64_t(-1);
137   static constexpr uint64_t UNLIMITED_UNCOMPRESSED_LENGTH = uint64_t(-2);
138
139   std::unique_ptr<IOBuf> uncompress(
140       const IOBuf* data,
141       uint64_t uncompressedLength = UNKNOWN_UNCOMPRESSED_LENGTH);
142
143  protected:
144   explicit Codec(CodecType type);
145
146  private:
147   // default: no limits (save for special value UNKNOWN_UNCOMPRESSED_LENGTH)
148   virtual uint64_t doMaxUncompressedLength() const;
149   // default: doesn't need uncompressed length
150   virtual bool doNeedsUncompressedLength() const;
151   virtual std::unique_ptr<IOBuf> doCompress(const folly::IOBuf* data) = 0;
152   virtual std::unique_ptr<IOBuf> doUncompress(const folly::IOBuf* data,
153                                               uint64_t uncompressedLength) = 0;
154
155   CodecType type_;
156 };
157
158 constexpr int COMPRESSION_LEVEL_FASTEST = -1;
159 constexpr int COMPRESSION_LEVEL_DEFAULT = -2;
160 constexpr int COMPRESSION_LEVEL_BEST = -3;
161
162 /**
163  * Return a codec for the given type. Throws on error.  The level
164  * is a non-negative codec-dependent integer indicating the level of
165  * compression desired, or one of the following constants:
166  *
167  * COMPRESSION_LEVEL_FASTEST is fastest (uses least CPU / memory,
168  *   worst compression)
169  * COMPRESSION_LEVEL_DEFAULT is the default (likely a tradeoff between
170  *   FASTEST and BEST)
171  * COMPRESSION_LEVEL_BEST is the best compression (uses most CPU / memory,
172  *   best compression)
173  *
174  * When decompressing, the compression level is ignored. All codecs will
175  * decompress all data compressed with the a codec of the same type, regardless
176  * of compression level.
177  */
178 std::unique_ptr<Codec> getCodec(CodecType type,
179                                 int level = COMPRESSION_LEVEL_DEFAULT);
180
181 }}  // namespaces