rustfs_erasure_codec/core/
verify.rs1extern crate alloc;
2
3use alloc::vec;
4use alloc::vec::Vec;
5
6use smallvec::SmallVec;
7
8use crate::Field;
9use crate::errors::Error;
10
11use super::{ReedSolomon, VERIFY_INLINE_SCRATCH_ELEMS, VerifyWorkspace};
12
13impl<F: Field> ReedSolomon<F> {
14 fn check_some_slices_with_buffer<T, U>(
15 &self,
16 matrix_rows: &[&[F::Elem]],
17 inputs: &[T],
18 to_check: &[T],
19 buffer: &mut [U],
20 ) -> bool
21 where
22 T: AsRef<[F::Elem]>,
23 U: AsRef<[F::Elem]> + AsMut<[F::Elem]>,
24 {
25 self.code_some_slices(matrix_rows, inputs, buffer);
26
27 for (expected_parity_shard, actual_parity_shard) in buffer.iter().zip(to_check.iter()) {
28 if expected_parity_shard.as_ref() != actual_parity_shard.as_ref() {
29 return false;
30 }
31 }
32 true
33 }
34
35 fn check_some_slices_with_buffer_raw<T: AsRef<[F::Elem]>>(
36 &self,
37 matrix_rows: &[&[F::Elem]],
38 inputs: &[T],
39 to_check: &[T],
40 buffer: &mut [&mut [F::Elem]],
41 ) -> bool {
42 self.code_some_slices(matrix_rows, inputs, buffer);
43
44 for (expected_parity_shard, actual_parity_shard) in buffer.iter().zip(to_check.iter()) {
45 if *expected_parity_shard != actual_parity_shard.as_ref() {
46 return false;
47 }
48 }
49 true
50 }
51
52 fn verify_leopard_with_buffer<T, U>(
53 &self,
54 slices: &[T],
55 parity: &mut [U],
56 ) -> Result<bool, Error>
57 where
58 T: AsRef<[F::Elem]>,
59 U: AsRef<[F::Elem]> + AsMut<[F::Elem]>,
60 {
61 let data = &slices[0..self.data_shard_count];
62 let to_check = &slices[self.data_shard_count..];
63 if self.is_leopard_gf8_family() {
64 self.encode_leopard_gf8_sep(data, parity)?;
65 } else {
66 self.encode_leopard_gf16_sep(data, parity)?;
67 }
68
69 for (expected, actual) in parity.iter().zip(to_check.iter()) {
70 if expected.as_ref() != actual.as_ref() {
71 return Ok(false);
72 }
73 }
74 Ok(true)
75 }
76
77 fn verify_leopard<T: AsRef<[F::Elem]>>(&self, slices: &[T]) -> Result<bool, Error> {
79 let slice_len = slices[0].as_ref().len();
80 let mut parity_bufs: Vec<Vec<F::Elem>> = (0..self.parity_shard_count)
81 .map(|_| vec![F::zero(); slice_len])
82 .collect();
83 self.verify_leopard_with_buffer(slices, &mut parity_bufs)
84 }
85
86 pub fn verify<T: AsRef<[F::Elem]>>(&self, slices: &[T]) -> Result<bool, Error> {
90 self.ensure_classic_family_execution()?;
91 check_piece_count!(all => self, slices);
92 check_slices!(multi => slices);
93
94 if self.is_leopard_gf8_family() || self.is_leopard_gf16_family() {
95 return self.verify_leopard(slices);
96 }
97
98 let slice_len = slices[0].as_ref().len();
99 let data = &slices[0..self.data_shard_count];
100 let to_check = &slices[self.data_shard_count..];
101
102 if self.fast_one_parity_enabled() {
103 let mut buffer = vec![F::zero(); slice_len];
104 self.encode_fast_one_parity(data, core::slice::from_mut(&mut buffer));
105 return Ok(buffer.as_slice() == to_check[0].as_ref());
106 }
107
108 let parity_rows = self.get_parity_rows();
109 let scratch_len = self.parity_shard_count * slice_len;
110 let mut scratch: SmallVec<[F::Elem; VERIFY_INLINE_SCRATCH_ELEMS]> =
111 SmallVec::with_capacity(scratch_len);
112 scratch.resize(scratch_len, F::zero());
113 let mut buffer_views: SmallVec<[&mut [F::Elem]; 32]> =
114 scratch.chunks_mut(slice_len).collect();
115
116 Ok(self.check_some_slices_with_buffer_raw(&parity_rows, data, to_check, &mut buffer_views))
117 }
118
119 pub fn verify_with_workspace<T>(
121 &self,
122 slices: &[T],
123 workspace: &mut VerifyWorkspace<F>,
124 ) -> Result<bool, Error>
125 where
126 T: AsRef<[F::Elem]>,
127 {
128 self.ensure_classic_family_execution()?;
129 check_piece_count!(all => self, slices);
130 check_slices!(multi => slices);
131
132 let slice_len = slices[0].as_ref().len();
133 if self.is_leopard_gf8_family() || self.is_leopard_gf16_family() {
134 workspace.prepare(self, slice_len);
135 return self.verify_leopard_with_buffer(slices, workspace.as_mut_shards());
136 }
137
138 workspace.prepare(self, slice_len);
139 self.verify_with_buffer(slices, workspace.as_mut_shards())
140 }
141
142 pub fn verify_with_buffer<T, U>(&self, slices: &[T], buffer: &mut [U]) -> Result<bool, Error>
144 where
145 T: AsRef<[F::Elem]>,
146 U: AsRef<[F::Elem]> + AsMut<[F::Elem]>,
147 {
148 self.ensure_classic_family_execution()?;
149 check_piece_count!(all => self, slices);
150 check_piece_count!(parity_buf => self, buffer);
151 check_slices!(multi => slices, multi => buffer);
152
153 if self.is_leopard_gf8_family() || self.is_leopard_gf16_family() {
154 return self.verify_leopard_with_buffer(slices, buffer);
155 }
156
157 let data = &slices[0..self.data_shard_count];
158 let to_check = &slices[self.data_shard_count..];
159
160 if self.fast_one_parity_enabled() {
161 self.encode_fast_one_parity(data, buffer);
162 return Ok(buffer[0].as_ref() == to_check[0].as_ref());
163 }
164
165 let parity_rows = self.get_parity_rows();
166 Ok(self.check_some_slices_with_buffer(&parity_rows, data, to_check, buffer))
167 }
168
169 #[cfg(feature = "std")]
171 pub fn verify_with_buffer_par<T, U>(
172 &self,
173 slices: &[T],
174 buffer: &mut [U],
175 ) -> Result<bool, Error>
176 where
177 F::Elem: Send + Sync,
178 T: AsRef<[F::Elem]> + Sync,
179 U: AsRef<[F::Elem]> + AsMut<[F::Elem]> + Send,
180 {
181 self.ensure_classic_family_execution()?;
182 check_piece_count!(all => self, slices);
183 check_piece_count!(parity_buf => self, buffer);
184 check_slices!(multi => slices, multi => buffer);
185
186 if self.is_leopard_gf8_family() || self.is_leopard_gf16_family() {
187 return self.verify_leopard_with_buffer(slices, buffer);
188 }
189
190 let data = &slices[0..self.data_shard_count];
191 let to_check = &slices[self.data_shard_count..];
192
193 if self.fast_one_parity_enabled() {
194 self.encode_fast_one_parity(data, buffer);
195 return Ok(buffer[0].as_ref() == to_check[0].as_ref());
196 }
197
198 self.encode_sep_par(data, buffer)?;
199
200 Ok(buffer
201 .iter()
202 .zip(to_check.iter())
203 .all(|(expected, actual)| expected.as_ref() == actual.as_ref()))
204 }
205
206 #[cfg(feature = "std")]
208 pub fn verify_par<T>(&self, slices: &[T]) -> Result<bool, Error>
209 where
210 F::Elem: Send + Sync,
211 T: AsRef<[F::Elem]> + Sync,
212 {
213 self.ensure_classic_family_execution()?;
214 check_piece_count!(all => self, slices);
215 check_slices!(multi => slices);
216
217 if self.is_leopard_gf8_family() || self.is_leopard_gf16_family() {
218 return self.verify_leopard(slices);
219 }
220
221 let slice_len = slices[0].as_ref().len();
222 let scratch_len = self.parity_shard_count * slice_len;
223 let mut scratch: SmallVec<[F::Elem; VERIFY_INLINE_SCRATCH_ELEMS]> =
224 SmallVec::with_capacity(scratch_len);
225 scratch.resize(scratch_len, F::zero());
226 let mut buffer_views: SmallVec<[&mut [F::Elem]; 32]> =
227 scratch.chunks_mut(slice_len).collect();
228
229 self.verify_with_buffer_par(slices, &mut buffer_views)
230 }
231}