rustfs_erasure_codec/
lib.rs1#![allow(dead_code)]
11#![cfg_attr(not(feature = "std"), no_std)]
12
13#[cfg(test)]
14#[macro_use]
15extern crate quickcheck;
16
17#[cfg(test)]
18extern crate rand;
19
20extern crate smallvec;
21
22#[cfg(any(
23 feature = "simd-neon",
24 feature = "simd-ssse3",
25 feature = "simd-avx2",
26 feature = "simd-avx512",
27 feature = "simd-gfni",
28))]
29extern crate libc;
30
31use ::core::iter::FromIterator;
32
33#[macro_use]
34mod macros;
35
36mod core;
37mod errors;
38mod matrix;
39
40#[cfg(test)]
41mod tests;
42
43pub mod galois_16;
44pub mod galois_8;
45
46pub use crate::errors::Error;
47pub use crate::errors::SBSError;
48
49pub use crate::core::CodecFamily;
50pub use crate::core::CodecOptions;
51#[cfg(feature = "std")]
52pub use crate::core::LeopardGf8ProfileStats;
53pub use crate::core::MatrixMode;
54#[cfg(feature = "std")]
55pub use crate::core::PARALLEL_POLICY_VERSION;
56#[cfg(feature = "std")]
57pub use crate::core::ParallelDecision;
58#[cfg(feature = "std")]
59pub use crate::core::ParallelPolicy;
60#[cfg(feature = "std")]
61pub use crate::core::ReconstructionCacheAnalysis;
62#[cfg(feature = "std")]
63pub use crate::core::ReconstructionCacheStats;
64pub use crate::core::ReedSolomon;
65#[cfg(feature = "std")]
66pub use crate::core::RuntimeProfileStats;
67pub use crate::core::ShardByShard;
68pub use crate::core::VerifyWorkspace;
69#[cfg(feature = "std")]
70pub use crate::core::stream;
71
72#[cfg(feature = "std")]
73pub fn leopard_gf8_profile_stats() -> LeopardGf8ProfileStats {
74 crate::core::leopard_gf8_profile_stats()
75}
76
77#[cfg(feature = "std")]
78pub fn reset_leopard_gf8_profile_stats() {
79 crate::core::reset_leopard_gf8_profile_stats()
80}
81
82#[cfg(not(feature = "std"))]
84use libm::log2f as log2;
85#[cfg(feature = "std")]
86fn log2(n: f32) -> f32 {
87 n.log2()
88}
89
90pub trait Field: Sized {
92 const ORDER: usize;
95
96 type Elem: Default + Clone + Copy + PartialEq + ::core::fmt::Debug;
98
99 fn add(a: Self::Elem, b: Self::Elem) -> Self::Elem;
101
102 fn mul(a: Self::Elem, b: Self::Elem) -> Self::Elem;
104
105 fn div(a: Self::Elem, b: Self::Elem) -> Self::Elem;
107
108 fn exp(a: Self::Elem, n: usize) -> Self::Elem;
110
111 fn zero() -> Self::Elem;
113
114 fn one() -> Self::Elem;
116
117 fn nth_internal(n: usize) -> Self::Elem;
118
119 fn nth_checked(n: usize) -> Option<Self::Elem> {
121 if n >= Self::ORDER {
122 None
123 } else {
124 Some(Self::nth_internal(n))
125 }
126 }
127
128 fn nth(n: usize) -> Self::Elem {
134 Self::nth_checked(n).unwrap_or_else(|| {
135 debug_assert!(
136 false,
137 "Field::nth received out-of-range index: {} for GF(2^{}) order {}",
138 n,
139 log2(Self::ORDER as f32) as usize,
140 Self::ORDER
141 );
142 let fallback_n = n % Self::ORDER.max(1);
143 Self::nth_internal(fallback_n)
144 })
145 }
146
147 fn mul_slice(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
152 assert_eq!(input.len(), out.len());
153
154 for (i, o) in input.iter().zip(out) {
155 *o = Self::mul(elem, *i)
156 }
157 }
158
159 fn mul_slice_add(elem: Self::Elem, input: &[Self::Elem], out: &mut [Self::Elem]) {
165 assert_eq!(input.len(), out.len());
166
167 for (i, o) in input.iter().zip(out) {
168 *o = Self::add(*o, Self::mul(elem, *i))
169 }
170 }
171}
172
173pub type ReconstructInitResult<'a, F> =
174 Result<&'a mut [<F as Field>::Elem], Result<&'a mut [<F as Field>::Elem], Error>>;
175
176#[derive(Clone, Debug, PartialEq, Eq)]
182pub struct ShardSlot<T> {
183 data: T,
184 present: bool,
185}
186
187impl<T> ShardSlot<T> {
188 pub fn new_present(data: T) -> Self {
190 Self {
191 data,
192 present: true,
193 }
194 }
195
196 pub fn new_missing(data: T) -> Self {
198 Self {
199 data,
200 present: false,
201 }
202 }
203
204 pub fn with_present(data: T, present: bool) -> Self {
206 Self { data, present }
207 }
208
209 pub fn is_present(&self) -> bool {
211 self.present
212 }
213
214 pub fn mark_present(&mut self) {
216 self.present = true;
217 }
218
219 pub fn mark_missing(&mut self) {
221 self.present = false;
222 }
223
224 pub fn as_inner(&self) -> &T {
226 &self.data
227 }
228
229 pub fn as_inner_mut(&mut self) -> &mut T {
231 &mut self.data
232 }
233
234 pub fn into_inner(self) -> T {
236 self.data
237 }
238}
239
240pub trait ReconstructShard<F: Field> {
245 fn len(&self) -> Option<usize>;
247
248 fn is_empty(&self) -> bool {
249 self.len().is_none()
250 }
251
252 fn get(&mut self) -> Option<&mut [F::Elem]>;
254
255 fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F>;
258}
259
260impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]> + FromIterator<F::Elem>> ReconstructShard<F>
261 for Option<T>
262{
263 fn len(&self) -> Option<usize> {
264 self.as_ref().map(|x| x.as_ref().len())
265 }
266
267 fn get(&mut self) -> Option<&mut [F::Elem]> {
268 self.as_mut().map(|x| x.as_mut())
269 }
270
271 fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
272 let is_some = self.is_some();
273 let x = self
274 .get_or_insert_with(|| ::core::iter::repeat_n(F::zero(), len).collect())
275 .as_mut();
276
277 if is_some { Ok(x) } else { Err(Ok(x)) }
278 }
279}
280
281impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]>> ReconstructShard<F> for (T, bool) {
282 fn len(&self) -> Option<usize> {
283 if !self.1 {
284 None
285 } else {
286 Some(self.0.as_ref().len())
287 }
288 }
289
290 fn get(&mut self) -> Option<&mut [F::Elem]> {
291 if !self.1 { None } else { Some(self.0.as_mut()) }
292 }
293
294 fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
295 let x = self.0.as_mut();
296 if x.len() == len {
297 if self.1 {
298 Ok(x)
299 } else {
300 self.1 = true;
301 Err(Ok(x))
302 }
303 } else {
304 Err(Err(Error::IncorrectShardSize))
305 }
306 }
307}
308
309impl<F: Field, T: AsRef<[F::Elem]> + AsMut<[F::Elem]>> ReconstructShard<F> for ShardSlot<T> {
310 fn len(&self) -> Option<usize> {
311 if self.present {
312 Some(self.data.as_ref().len())
313 } else {
314 None
315 }
316 }
317
318 fn get(&mut self) -> Option<&mut [F::Elem]> {
319 if self.present {
320 Some(self.data.as_mut())
321 } else {
322 None
323 }
324 }
325
326 fn get_or_initialize(&mut self, len: usize) -> ReconstructInitResult<'_, F> {
327 let x = self.data.as_mut();
328 if x.len() == len {
329 if self.present {
330 Ok(x)
331 } else {
332 self.present = true;
333 Err(Ok(x))
334 }
335 } else {
336 Err(Err(Error::IncorrectShardSize))
337 }
338 }
339}