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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
//! RFC 8878 Zstandard decoder.
//!
//! The entry points:
//!
//! * [`StreamingDecoder`] — implements [`crate::io::Read`] over a compressed
//! byte stream, transparently parsing the frame header and concatenated
//! frames. The typical choice for application code.
//! * [`FrameDecoder`] — single-frame interface; use when the caller manages
//! the input buffer manually (zero-copy slices, network framing, etc).
//! * `workspace::WorkspaceDecoder` (feature `caller-workspace`): streaming
//! decoder over a byte slice the caller sizes and owns, with no allocation
//! and limits on window, output and work. For consumers that account their
//! memory themselves, such as browser bundles verifying a download.
//! * [`DictionaryHandle`] — pre-parsed dictionary handle. Parse the
//! dictionary bytes once with [`DictionaryHandle::decode_dict`] and reuse
//! the handle across every subsequent decode; saves the per-frame
//! dictionary parse cost when the same dictionary is used many times in a
//! row.
//!
//! Both decoders expose dictionary-aware constructors / methods,
//! though the exact naming differs:
//!
//! * [`StreamingDecoder::new_with_dictionary_handle`] /
//! [`StreamingDecoder::new_with_dictionary_bytes`]
//! * [`FrameDecoder::decode_all_with_dict_handle`] /
//! [`FrameDecoder::decode_all_with_dict_bytes`]
//!
//! The `_handle` variants reuse a previously parsed
//! [`DictionaryHandle`]; the `_bytes` variants parse the dictionary
//! per call (suitable for one-off decodes).
//!
//! Errors surface through [`errors::FrameDecoderError`] and the per-decoder
//! error types in the [`errors`] submodule.
pub use ;
pub use ;
/// Largest window a frame may declare before a decoder that holds the window
/// itself refuses it, unless [`FrameDecoder::set_max_window_size`] raised the
/// ceiling.
///
/// The bound is what makes decoding untrusted input safe: a frame header can
/// ask for a window far larger than the data behind it, and honouring that
/// would let a few bytes of input demand gigabytes of memory.
pub use crateMAXIMUM_ALLOWED_WINDOW_SIZE;
/// Largest window any decode accepts, the ceiling
/// [`FrameDecoder::set_max_window_size`] can be raised to.
pub use crateMAX_DECODER_WINDOW_SIZE;
pub use ;
pub use ;
/// Decompressed size a frame declares in its header, as read by
/// [`read_frame_content_size`] without decoding the frame body.
/// Read the decompressed size a frame declares in its header, without
/// decoding the frame body.
///
/// Parses only the leading frame header of `src`. Returns
/// [`FrameContentSize::Known`] when the header carries an explicit
/// `Frame_Content_Size`, or [`FrameContentSize::Unknown`] when it does not.
/// This backs the C `ZSTD_getFrameContentSize` entry point, where the two
/// variants map to a concrete size and `ZSTD_CONTENTSIZE_UNKNOWN`.
///
/// # Errors
/// Returns [`ReadFrameHeaderError`](errors::ReadFrameHeaderError) when `src`
/// is too short to hold a header, carries a bad magic number, or begins with
/// a skippable frame.
///
/// ```rust
/// use structured_zstd::encoding::{compress_slice_to_vec, CompressionLevel};
/// use structured_zstd::decoding::{read_frame_content_size, FrameContentSize};
/// let frame = compress_slice_to_vec(&[42u8; 100], CompressionLevel::Default);
/// assert_eq!(read_frame_content_size(&frame).unwrap(), FrameContentSize::Known(100));
/// ```
/// Error from [`find_frame_compressed_size`].
/// On-disk byte length of the FIRST frame in `src` — magic number, frame
/// header, every block, and the trailing content checksum when present —
/// computed by walking the block headers without decoding any block body.
///
/// For a skippable frame, returns its full `8 + Frame_Size` length. This backs
/// the C `ZSTD_findFrameCompressedSize` entry point; the returned value is the
/// offset at which a following concatenated frame would begin.
///
/// # Errors
/// [`FrameSizeError`] when the header is unreadable, the buffer is truncated
/// mid-frame, or a block uses the reserved type.
///
/// ```rust
/// use structured_zstd::encoding::{compress_slice_to_vec, CompressionLevel};
/// use structured_zstd::decoding::find_frame_compressed_size;
/// let frame = compress_slice_to_vec(&[5u8; 256], CompressionLevel::Default);
/// assert_eq!(find_frame_compressed_size(&frame).unwrap(), frame.len());
/// ```
/// Result of walking the block sequence of one frame (between the header and
/// the optional trailing checksum).
/// `Block_Maximum_Size` for the frame: `min(Window_Size, 128 KiB)`. Per RFC
/// 8878 §3.1.1.2 every block's `Block_Size` is bounded by this, and each block
/// regenerates at most this many bytes. Single-segment frames omit the
/// `Window_Descriptor`; their window equals the declared content size.
/// Walk the block headers of a single frame starting at `start` (the offset of
/// the first block header), validating each fits in `src` and declares a
/// `Block_Size` no larger than `max_block_size` (the frame's
/// `Block_Maximum_Size`). Does not consume the trailing content checksum.
/// Shared by [`find_frame_compressed_size`] and [`frame_decompressed_bound`] so
/// the on-disk-size and block-count views never diverge.
/// Upper bound on the decompressed size of the FIRST frame in `src`, without
/// decoding the body. Backs the C `ZSTD_decompressBound` (per-frame term).
///
/// Returns the exact size when the header declares `Frame_Content_Size`;
/// otherwise a valid (loose) bound of `block_count * block_size_max`, where
/// `block_size_max = min(window_size, 128 KiB)` — every block decompresses to
/// at most that many bytes. Skippable frames contribute `0`.
///
/// # Errors
/// [`FrameSizeError`] on an unreadable header, truncation, or a reserved block.
/// Frame header fields decoded by [`read_frame_header_info`], mirroring the
/// values the C `ZSTD_getFrameHeader` fills into a `ZSTD_FrameHeader`.
/// Length in bytes of the frame header at the start of `src`, including the
/// 4-byte magic number (the offset at which the first block begins). Backs the
/// C `ZSTD_frameHeaderSize`.
///
/// Only the magic number and the descriptor byte are needed: the length
/// follows from the descriptor alone, so a caller holding just that five-byte
/// prefix learns how much of the header is still to read. Upstream's
/// `ZSTD_frameHeaderSize` measures it the same way
/// (`zstd_decompress.c:416-429`), without looking at the descriptor's other
/// bits, so a header this library refuses to decode is still measured.
///
/// # Errors
/// [`ReadFrameHeaderError`](errors::ReadFrameHeaderError) when `src` is shorter
/// than five bytes, has a bad magic number, or is a skippable frame.
///
/// ```rust
/// use structured_zstd::decoding::frame_header_size;
/// // Magic number and a descriptor announcing a window byte only.
/// assert_eq!(frame_header_size(&[0x28, 0xB5, 0x2F, 0xFD, 0x00]).unwrap(), 6);
/// ```
/// Decode the leading frame header fields of `src` without decoding the body.
///
/// Backs the C `ZSTD_getFrameHeader`. When `magicless` is `true` the 4-byte
/// magic prefix is assumed absent (the `ZSTD_f_zstd1_magicless` format); the
/// caller must know out-of-band that the stream is magicless. The reported
/// [`FrameHeaderInfo::window_size`] is the raw value derived from the header
/// (no maximum-window policy applied here; that bound is enforced at decode
/// time), so callers see the frame's own declared window even when it exceeds
/// a decoder limit.
///
/// # Errors
/// As [`read_frame_content_size`].
///
/// ```rust
/// use structured_zstd::encoding::{compress_slice_to_vec, CompressionLevel};
/// use structured_zstd::decoding::{read_frame_header_info, FrameContentSize};
/// let frame = compress_slice_to_vec(&[7u8; 512], CompressionLevel::Default);
/// let info = read_frame_header_info(&frame, false).unwrap();
/// assert_eq!(info.content_size, FrameContentSize::Known(512));
/// assert!(info.window_size >= 512);
/// ```
pub
pub
pub
pub
pub
// FlatBuf is the compile-time-monomorphised "frame fits in window"
// backend selected via `DecodeBuffer<FlatBuf>`. `FrameDecoder`'s
// `DecoderScratchKind` picks it when the frame header has
// `Single_Segment_flag` set; the ring backend remains the default
// for multi-segment frames. See backlog item #132 for the wiring
// rationale.
pub
pub
pub
pub
pub
// Per-kernel monolithic sequence-section decoder entry points. Each
// kernel has its own self-contained function with the full pipeline
// (outer init, both arms, decode_one, execute_one) inlined inside one
// `#[target_feature]`-scoped body. The dispatcher in
// `sequence_section_decoder::decode_and_execute_sequences` selects the
// kernel ONCE per call via cached `detect_cpu_kernel`. aarch64 Neon
// and Sve still go through the K-generic
// `decode_and_execute_sequences_impl` shared body until their own
// monoliths land.
//
// The shared helpers (`decode_and_execute_sequences_impl`,
// `run_pipelined_sequence_loop`, `decode_one_sequence_inline`, the
// `execute_one_sequence_pipelined*` wrappers) live on aarch64
// (Neon/Sve dispatch arms in `decode_and_execute_sequences`) and in
// tests, but are orphan on x86_64 production builds where the
// per-kernel monoliths bypass them entirely. Each carries
// `#[allow(dead_code)]` so the `-D warnings` clippy gate stays green
// on x86_64 without losing the cross-arch reuse. The vestigial
// `_bmi2`/`_avx2`/`_vbmi2` variants are pre-R12 macro-dispatch
// helpers with no remaining callers; they should be cleaned up in
// a follow-up PR once the per-kernel monolithic shape is fully
// settled.
pub
pub
pub
pub
pub
pub
pub
/// Diagnostic-only re-export of the copy-shape histogram counters. Public
/// only when the `copy-shape-stats` feature is on (off in shipping builds).
pub use shape_stats;
// `UserSliceBackend` is the compile-time-monomorphised backend that
// writes directly into the caller's `&mut [u8]` output slice, used
// by the `FrameDecoder::decode_all` direct-decode path. It
// eliminates the `FlatBuf` drain copy + anonymous-page-fault cost
// on large literal sections. Wiring happens via
// `DecodeBuffer<UserSliceBackend<'a>>`; the lifetime binds the
// backend to the caller's slice for the call duration.
pub
pub use copy_bytes_overshooting_for_bench;