rustfs_erasure_codec/core/options.rs
1/// Selects the codec algorithm family for encoding and reconstruction.
2///
3/// - [`Classic`](CodecFamily::Classic): Standard Reed-Solomon over GF(2^8) using
4/// Vandermonde/Cauchy matrix multiplication. Supports all shard counts up to
5/// `Field::ORDER`, incremental `update`, and `encode_single`.
6///
7/// - [`LeopardGF8`](CodecFamily::LeopardGF8): FFT-based Leopard codec over GF(2^8).
8/// Uses Fermat-number FFT with Forney syndrome decoding. Requires shard lengths
9/// that are multiples of 64 bytes. Does **not** support `encode_single` or `update`.
10/// Supports up to 256 total shards (data + parity).
11///
12/// - [`LeopardGF16`](CodecFamily::LeopardGF16): FFT-based Leopard codec over GF(2^16).
13/// Supports up to 65536 total shards (data + parity).
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum CodecFamily {
16 Classic,
17 LeopardGF8,
18 LeopardGF16,
19}
20
21/// Controls optional automatic selection of a Leopard codec when the requested
22/// [`CodecFamily`] is [`Classic`](CodecFamily::Classic).
23///
24/// Auto-selection only takes effect on a byte-oriented field (where
25/// `size_of::<Field::Elem>() == 1`, i.e. the GF(2^8) field the Leopard codecs
26/// are built on); on any other field the mode is ignored and the codec stays
27/// Classic. When the caller sets an explicit non-Classic `codec_family`, this
28/// mode is likewise ignored — the explicit family wins.
29///
30/// The resolution, as a function of `total = data + parity` shards, mirrors the
31/// klauspost/reedsolomon `New()` behaviour:
32///
33/// | `total` | [`AsNeeded`](LeopardMode::AsNeeded) | [`PreferLeopard`](LeopardMode::PreferLeopard) | [`PreferGF16`](LeopardMode::PreferGF16) |
34/// |---------|-----------|---------------|------------|
35/// | ≤ 256 | Classic | LeopardGF8¹ | LeopardGF16 |
36/// | 257..=65536 | LeopardGF16 | LeopardGF16 | LeopardGF16 |
37///
38/// ¹ [`PreferLeopard`](LeopardMode::PreferLeopard) selects [`LeopardGF8`](CodecFamily::LeopardGF8)
39/// only when `total ≤ 256` **and** `parity ≤ 128`; otherwise it falls back to
40/// [`LeopardGF16`](CodecFamily::LeopardGF16).
41#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
42#[non_exhaustive]
43pub enum LeopardMode {
44 /// Never auto-select Leopard. The codec behaves exactly as an explicit
45 /// [`CodecFamily::Classic`] construction — byte-for-byte identical to
46 /// releases before auto-activation existed. This is the default.
47 #[default]
48 Disabled,
49 /// Use Classic while it can represent the configuration (`total ≤ 256`), and
50 /// automatically switch to [`LeopardGF16`](CodecFamily::LeopardGF16) once the
51 /// shard count exceeds what GF(2^8) can address.
52 AsNeeded,
53 /// Always use [`LeopardGF16`](CodecFamily::LeopardGF16) (for any supported
54 /// shard count up to 65536).
55 PreferGF16,
56 /// Prefer a Leopard codec whenever possible: [`LeopardGF8`](CodecFamily::LeopardGF8)
57 /// for small byte-friendly configurations (`total ≤ 256` and `parity ≤ 128`),
58 /// otherwise [`LeopardGF16`](CodecFamily::LeopardGF16).
59 PreferLeopard,
60}
61
62/// Selects the encoding matrix construction strategy for [`CodecFamily::Classic`].
63///
64/// This option is ignored for Leopard families (they use FFT-based encoding).
65///
66/// - [`Vandermonde`](MatrixMode::Vandermonde): Standard Vandermonde matrix.
67/// - [`Cauchy`](MatrixMode::Cauchy): Cauchy matrix construction.
68/// - [`JerasureLike`](MatrixMode::JerasureLike): Jerasure-compatible matrix layout.
69/// - [`Custom`](MatrixMode::Custom): User-supplied matrix via
70/// [`ReedSolomon::with_custom_matrix`](crate::ReedSolomon::with_custom_matrix).
71#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum MatrixMode {
73 Vandermonde,
74 Cauchy,
75 JerasureLike,
76 Custom,
77}
78
79/// Configuration options for constructing a [`ReedSolomon`](crate::ReedSolomon) codec.
80///
81/// Use `CodecOptions::default()` for sensible defaults, or the builder methods:
82///
83/// ```ignore
84/// use rustfs_erasure_codec::core::{CodecOptions, CodecFamily};
85///
86/// let opts = CodecOptions::builder()
87/// .codec_family(CodecFamily::LeopardGF8)
88/// .fast_one_parity(true)
89/// .build();
90/// ```
91///
92/// `CodecOptions` is `#[non_exhaustive]`: construct it from
93/// [`CodecOptions::default()`] (optionally with `..Default::default()` in a
94/// struct-update expression) or via the [`builder`](CodecOptions::builder), not
95/// with an exhaustive struct literal. This lets future fields be added without a
96/// breaking change.
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98#[non_exhaustive]
99pub struct CodecOptions {
100 /// When `true` and parity shard count is 1, use XOR-only fast path instead of
101 /// full matrix multiplication. Default: `false`.
102 pub fast_one_parity: bool,
103 /// When `true`, cache the inverted decode matrix for repeated reconstruction
104 /// with the same erasure pattern. Default: `true`.
105 pub inversion_cache: bool,
106 /// Capacity of the inversion cache (LRU). `0` means automatic sizing based on
107 /// shard counts. Default: `0`.
108 pub inversion_cache_capacity: usize,
109 /// The codec algorithm family to use. Default: [`CodecFamily::Classic`].
110 pub codec_family: CodecFamily,
111 /// Optional automatic Leopard selection when `codec_family` is
112 /// [`CodecFamily::Classic`]. Default: [`LeopardMode::Disabled`] (no
113 /// auto-selection; behaviour identical to prior releases). See [`LeopardMode`].
114 pub leopard_mode: LeopardMode,
115 /// The matrix construction strategy (only used for [`CodecFamily::Classic`]).
116 /// Default: [`MatrixMode::Vandermonde`].
117 pub matrix_mode: MatrixMode,
118 /// Maximum number of parallel jobs for encode/decode operations.
119 /// `0` means automatic (uses `available_parallelism()`). Default: `0`.
120 pub max_parallel_jobs: usize,
121}
122
123impl Default for CodecOptions {
124 fn default() -> Self {
125 Self {
126 fast_one_parity: false,
127 inversion_cache: true,
128 inversion_cache_capacity: 0,
129 codec_family: CodecFamily::Classic,
130 leopard_mode: LeopardMode::Disabled,
131 matrix_mode: MatrixMode::Vandermonde,
132 max_parallel_jobs: 0,
133 }
134 }
135}
136
137/// Builder for [`CodecOptions`].
138///
139/// Created via [`CodecOptions::builder()`]. All methods chain; call [`build()`](CodecOptionsBuilder::build) to obtain the final `CodecOptions`.
140#[derive(Debug, Clone, Copy)]
141pub struct CodecOptionsBuilder {
142 options: CodecOptions,
143}
144
145impl CodecOptions {
146 /// Create a new builder with default options.
147 pub fn builder() -> CodecOptionsBuilder {
148 CodecOptionsBuilder {
149 options: CodecOptions::default(),
150 }
151 }
152}
153
154impl CodecOptionsBuilder {
155 /// Set the codec algorithm family.
156 pub fn codec_family(mut self, family: CodecFamily) -> Self {
157 self.options.codec_family = family;
158 self
159 }
160
161 /// Set the optional automatic Leopard selection mode (see [`LeopardMode`]).
162 /// Only takes effect when [`codec_family`](CodecOptionsBuilder::codec_family)
163 /// is [`CodecFamily::Classic`] and the field is byte-oriented.
164 pub fn leopard_mode(mut self, mode: LeopardMode) -> Self {
165 self.options.leopard_mode = mode;
166 self
167 }
168
169 /// Set the matrix construction strategy.
170 pub fn matrix_mode(mut self, mode: MatrixMode) -> Self {
171 self.options.matrix_mode = mode;
172 self
173 }
174
175 /// Enable or disable the XOR-only fast path for single parity shards.
176 pub fn fast_one_parity(mut self, enabled: bool) -> Self {
177 self.options.fast_one_parity = enabled;
178 self
179 }
180
181 /// Enable or disable the inversion cache.
182 pub fn inversion_cache(mut self, enabled: bool) -> Self {
183 self.options.inversion_cache = enabled;
184 self
185 }
186
187 /// Set the inversion cache capacity. `0` for automatic sizing.
188 pub fn inversion_cache_capacity(mut self, capacity: usize) -> Self {
189 self.options.inversion_cache_capacity = capacity;
190 self
191 }
192
193 /// Set the maximum number of parallel jobs. `0` for automatic.
194 pub fn max_parallel_jobs(mut self, jobs: usize) -> Self {
195 self.options.max_parallel_jobs = jobs;
196 self
197 }
198
199 /// Build the final [`CodecOptions`].
200 pub fn build(self) -> CodecOptions {
201 self.options
202 }
203}