structured_zstd/decoding/mod.rs
1//! RFC 8878 Zstandard decoder.
2//!
3//! Three entry points are exposed, each with progressively lower-level
4//! control:
5//!
6//! * [`StreamingDecoder`] — implements [`crate::io::Read`] over a compressed
7//! byte stream, transparently parsing the frame header and concatenated
8//! frames. The typical choice for application code.
9//! * [`FrameDecoder`] — single-frame interface; use when the caller manages
10//! the input buffer manually (zero-copy slices, network framing, etc).
11//! * [`DictionaryHandle`] — pre-parsed dictionary handle. Parse the
12//! dictionary bytes once with [`DictionaryHandle::decode_dict`] and reuse
13//! the handle across every subsequent decode; saves the per-frame
14//! dictionary parse cost when the same dictionary is used many times in a
15//! row.
16//!
17//! Both decoders expose dictionary-aware constructors / methods,
18//! though the exact naming differs:
19//!
20//! * [`StreamingDecoder::new_with_dictionary_handle`] /
21//! [`StreamingDecoder::new_with_dictionary_bytes`]
22//! * [`FrameDecoder::decode_all_with_dict_handle`] /
23//! [`FrameDecoder::decode_all_with_dict_bytes`]
24//!
25//! The `_handle` variants reuse a previously parsed
26//! [`DictionaryHandle`]; the `_bytes` variants parse the dictionary
27//! per call (suitable for one-off decodes).
28//!
29//! Errors surface through [`errors::FrameDecoderError`] and the per-decoder
30//! error types in the [`errors`] submodule.
31
32pub mod errors;
33mod frame_decoder;
34mod streaming_decoder;
35
36pub use dictionary::{Dictionary, DictionaryHandle};
37pub use frame_decoder::{BlockDecodingStrategy, FrameDecoder};
38pub use streaming_decoder::StreamingDecoder;
39
40pub(crate) mod block_decoder;
41pub(crate) mod buffer_backend;
42pub(crate) mod decode_buffer;
43pub(crate) mod dictionary;
44pub(crate) mod exec_sequence_inline;
45// FlatBuf is the compile-time-monomorphised "frame fits in window"
46// backend selected via `DecodeBuffer<FlatBuf>`. `FrameDecoder`'s
47// `DecoderScratchKind` picks it when the frame header has
48// `Single_Segment_flag` set; the ring backend remains the default
49// for multi-segment frames. See backlog item #132 for the wiring
50// rationale.
51pub(crate) mod flat_buf;
52pub(crate) mod frame;
53pub(crate) mod literals_section_decoder;
54pub(crate) mod prefetch;
55mod ringbuffer;
56#[allow(dead_code)]
57pub(crate) mod scratch;
58// Per-kernel monolithic sequence-section decoder entry points. Each
59// kernel has its own self-contained function with the full pipeline
60// (outer init, both arms, decode_one, execute_one) inlined inside one
61// `#[target_feature]`-scoped body. The dispatcher in
62// `sequence_section_decoder::decode_and_execute_sequences` selects the
63// kernel ONCE per call via cached `detect_cpu_kernel`. aarch64 Neon
64// and Sve still go through the K-generic
65// `decode_and_execute_sequences_impl` shared body until their own
66// monoliths land.
67//
68// The shared helpers (`decode_and_execute_sequences_impl`,
69// `run_pipelined_sequence_loop`, `decode_one_sequence_inline`, the
70// `execute_one_sequence_pipelined*` wrappers) live on aarch64
71// (Neon/Sve dispatch arms in `decode_and_execute_sequences`) and in
72// tests, but are orphan on x86_64 production builds where the
73// per-kernel monoliths bypass them entirely. Each carries
74// `#[allow(dead_code)]` so the `-D warnings` clippy gate stays green
75// on x86_64 without losing the cross-arch reuse. The vestigial
76// `_bmi2`/`_avx2`/`_vbmi2` variants are pre-R12 macro-dispatch
77// helpers with no remaining callers; they should be cleaned up in
78// a follow-up PR once the per-kernel monolithic shape is fully
79// settled.
80#[cfg(target_arch = "x86_64")]
81pub(crate) mod seq_decoder_avx2;
82#[cfg(target_arch = "x86_64")]
83pub(crate) mod seq_decoder_bmi2;
84pub(crate) mod seq_decoder_scalar;
85#[cfg(target_arch = "x86_64")]
86pub(crate) mod seq_decoder_vbmi2;
87pub(crate) mod sequence_execution;
88pub(crate) mod sequence_section_decoder;
89pub(crate) mod simd_copy;
90/// Diagnostic-only re-export of the copy-shape histogram counters. Public
91/// only when the `copy_shape_stats` feature is on (off in shipping builds).
92#[cfg(feature = "copy_shape_stats")]
93pub use simd_copy::shape_stats;
94// `UserSliceBackend` is the compile-time-monomorphised backend that
95// writes directly into the caller's `&mut [u8]` output slice, used
96// by the `FrameDecoder::decode_all` direct-decode path. It
97// eliminates the `FlatBuf` drain copy + anonymous-page-fault cost
98// on large literal sections. Wiring happens via
99// `DecodeBuffer<UserSliceBackend<'a>>`; the lifetime binds the
100// backend to the caller's slice for the call duration.
101pub(crate) mod user_slice_buf;
102
103#[cfg(feature = "bench_internals")]
104pub(crate) use self::simd_copy::copy_bytes_overshooting_for_bench;