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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
use io;
use BufRead;
use ;
/// How much `decode_all` will reserve up front, at most.
///
/// The size comes out of the frame header, which is whatever the data claims
/// it is - so it is capped, or a few bytes of input could ask us for an
/// arbitrary amount of memory. Past this the output just grows as it goes,
/// which is what the whole function used to do; the reserve is only worth
/// anything for the first few megabytes anyway.
const MAX_RESERVED: usize = 32 * 1024 * 1024;
/// Reads the decompressed size out of the start of a frame, if it says.
///
/// Returns `None` if `data` does not begin with a zstd frame header, or if the
/// frame does not record its content size - which is normal for anything
/// produced by a streaming compressor that was not told the size in advance.
///
/// This is the size to reserve when decompressing into your own buffer:
///
/// ```
/// # fn main() -> std::io::Result<()> {
/// let frame = zstd::encode_all(&b"some data"[..], 3)?;
///
/// let mut output = match zstd::decompressed_size(&frame) {
/// Some(size) => Vec::with_capacity(size as usize),
/// None => Vec::new(),
/// };
/// zstd::stream::copy_decode(&frame[..], &mut output)?;
/// # assert_eq!(output, b"some data");
/// # Ok(())
/// # }
/// ```
/// Decompress from the given source as if using a `Decoder`.
///
/// The input data must be in the zstd frame format.
///
/// When the frame records its decompressed size, the returned `Vec` is sized
/// for it up front. That is worth about a factor of two over letting it grow,
/// so prefer this to driving a `Decoder` into a `Vec::new()` yourself. If you
/// are decompressing into a buffer you own, [`decompressed_size()`] gives you
/// the same number.
/// Decompress from the given source as if using a `Decoder`.
///
/// Decompressed data will be appended to `destination`.
/// Compress all data from the given source as if using an `Encoder`.
///
/// Result will be in the zstd frame format.
///
/// A level of `0` uses zstd's default (currently `3`).
///
/// Because the source is read as a stream, its length is not known in advance,
/// so the frame this produces does not record its decompressed size. Whoever
/// decompresses it cannot size their buffer up front, which costs them about a
/// factor of two - see [`decompressed_size()`]. Use [`crate::bulk::compress()`]
/// for a slice you already hold, [`compress_file()`] for a file, or
/// [`compress_sized()`] when you know the length some other way; all three
/// record it.
/// Compress everything from `source`, whose length you already know.
///
/// The length is recorded in the frame header, which is what lets whoever
/// decompresses it size their buffer up front - worth about a factor of two to
/// them. [`encode_all()`] cannot do this, because it has no way to know how
/// much is coming.
///
/// `size` must be exactly how many bytes `source` yields; zstd fails the frame
/// if it turns out to be wrong.
///
/// For data already in a slice, use [`crate::bulk::compress()`], which knows
/// the length without being told. For a file, [`compress_file()`].
///
/// ```
/// # fn main() -> std::io::Result<()> {
/// let data = b"the length of this is known up front";
///
/// let frame = zstd::compress_sized(&data[..], 3, data.len() as u64)?;
///
/// assert_eq!(zstd::decompressed_size(&frame), Some(data.len() as u64));
/// # assert_eq!(zstd::decode_all(&frame[..])?, data);
/// # Ok(())
/// # }
/// ```
/// Compress everything from `source`, whose length you already know, into
/// `destination`.
///
/// Like [`copy_encode()`], but the length is recorded in the frame header, so
/// whoever decompresses it can size their buffer up front - worth about a
/// factor of two to them.
///
/// Nothing larger than the compressor's own buffers is held in memory, so this
/// is the one to reach for when the data is too big to want a `Vec` of it.
///
/// `size` must be exactly how many bytes `source` yields; zstd fails the frame
/// if it turns out to be wrong.
///
/// ```no_run
/// # fn main() -> std::io::Result<()> {
/// let input = std::fs::File::open("input.txt")?;
/// let size = input.metadata()?.len();
/// let output = std::fs::File::create("input.txt.zst")?;
///
/// zstd::compress_sized_into(input, output, 3, size)?;
/// # Ok(())
/// # }
/// ```
/// Compress the contents of a file.
///
/// The file's length comes from its metadata and is recorded in the frame, so
/// whoever decompresses it can size their buffer up front. The contents are
/// streamed through the compressor rather than read into memory first, so only
/// the compressed result is held.
///
/// That result is still a `Vec`, so for a file large enough that you would
/// rather not have one, use [`compress_file_into()`] instead.
///
/// ```no_run
/// # fn main() -> std::io::Result<()> {
/// let frame = zstd::compress_file("input.txt", 3)?;
/// # Ok(())
/// # }
/// ```
/// Compress the contents of a file into `destination`.
///
/// Like [`compress_file()`], but writing rather than handing back a
/// `Vec` - so nothing beyond the compressor's own buffers is held, whatever
/// the size of the file.
///
/// ```no_run
/// # fn main() -> std::io::Result<()> {
/// let output = std::fs::File::create("input.txt.zst")?;
///
/// zstd::compress_file_into("input.txt", output, 3)?;
/// # Ok(())
/// # }
/// ```
/// Compress all data from the given source as if using an `Encoder`.
///
/// Compressed data will be appended to `destination`.
///
/// A level of `0` uses zstd's default (currently `3`).