reed_solomon_simd/engine/
shards.rs1#[cfg(not(feature = "std"))]
2use alloc::vec::Vec;
3use core::ops::{Bound, Index, IndexMut, Range, RangeBounds};
4
5pub(crate) struct Shards {
9 shard_count: usize,
10 shard_len_64: usize,
12
13 data: Vec<[u8; 64]>,
15}
16
17impl Shards {
18 pub(crate) fn as_ref_mut(&mut self) -> ShardsRefMut<'_> {
19 ShardsRefMut::new(self.shard_count, self.shard_len_64, self.data.as_mut())
20 }
21
22 pub(crate) fn new() -> Self {
23 Self {
24 shard_count: 0,
25 shard_len_64: 0,
26 data: Vec::new(),
27 }
28 }
29
30 pub(crate) fn resize(&mut self, shard_count: usize, shard_len_64: usize) {
31 self.shard_count = shard_count;
32 self.shard_len_64 = shard_len_64;
33
34 self.data
35 .resize(self.shard_count * self.shard_len_64, [0; 64]);
36 }
37
38 pub(crate) fn insert(&mut self, index: usize, shard: &[u8]) {
39 debug_assert_eq!(shard.len() % 2, 0);
40
41 let whole_chunk_count = shard.len() / 64;
42 let tail_len = shard.len() % 64;
43
44 let (src_chunks, src_tail) = shard.split_at(shard.len() - tail_len);
45
46 let dst = &mut self[index];
47 dst[..whole_chunk_count]
48 .as_flattened_mut()
49 .copy_from_slice(src_chunks);
50
51 if tail_len > 0 {
54 let (src_lo, src_hi) = src_tail.split_at(tail_len / 2);
55 let (dst_lo, dst_hi) = dst[whole_chunk_count].split_at_mut(32);
56 dst_lo[..src_lo.len()].copy_from_slice(src_lo);
57 dst_hi[..src_hi.len()].copy_from_slice(src_hi);
58 }
59 }
60
61 pub(crate) fn undo_last_chunk_encoding(&mut self, shard_bytes: usize, range: Range<usize>) {
63 let whole_chunk_count = shard_bytes / 64;
64 let tail_len = shard_bytes % 64;
65
66 if tail_len == 0 {
67 return;
68 }
69
70 for idx in range {
71 let last_chunk = &mut self[idx][whole_chunk_count];
72 last_chunk.copy_within(32..32 + tail_len / 2, tail_len / 2);
73 }
74 }
75}
76
77impl Index<usize> for Shards {
81 type Output = [[u8; 64]];
82 fn index(&self, index: usize) -> &Self::Output {
83 &self.data[index * self.shard_len_64..(index + 1) * self.shard_len_64]
84 }
85}
86
87impl IndexMut<usize> for Shards {
91 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
92 &mut self.data[index * self.shard_len_64..(index + 1) * self.shard_len_64]
93 }
94}
95
96pub struct ShardsRefMut<'a> {
101 shard_count: usize,
102 shard_len_64: usize,
103
104 data: &'a mut [[u8; 64]],
105}
106
107impl<'a> ShardsRefMut<'a> {
108 pub fn dist2_mut(
118 &mut self,
119 mut pos: usize,
120 mut dist: usize,
121 ) -> (&mut [[u8; 64]], &mut [[u8; 64]]) {
122 pos *= self.shard_len_64;
123 dist *= self.shard_len_64;
124
125 let (a, b) = self.data[pos..].split_at_mut(dist);
126 (&mut a[..self.shard_len_64], &mut b[..self.shard_len_64])
127 }
128
129 #[allow(clippy::type_complexity)]
141 pub fn dist4_mut(
142 &mut self,
143 mut pos: usize,
144 mut dist: usize,
145 ) -> (
146 &mut [[u8; 64]],
147 &mut [[u8; 64]],
148 &mut [[u8; 64]],
149 &mut [[u8; 64]],
150 ) {
151 pos *= self.shard_len_64;
152 dist *= self.shard_len_64;
153
154 let (ab, cd) = self.data[pos..].split_at_mut(dist * 2);
155 let (a, b) = ab.split_at_mut(dist);
156 let (c, d) = cd.split_at_mut(dist);
157
158 (
159 &mut a[..self.shard_len_64],
160 &mut b[..self.shard_len_64],
161 &mut c[..self.shard_len_64],
162 &mut d[..self.shard_len_64],
163 )
164 }
165
166 pub fn is_empty(&self) -> bool {
168 self.shard_count == 0
169 }
170
171 pub fn len(&self) -> usize {
173 self.shard_count
174 }
175
176 pub fn new(shard_count: usize, shard_len_64: usize, data: &'a mut [[u8; 64]]) -> Self {
182 assert!(data.len() >= shard_count * shard_len_64);
183
184 Self {
185 shard_count,
186 shard_len_64,
187 data: &mut data[..shard_count * shard_len_64],
188 }
189 }
190
191 pub fn split_at_mut(&mut self, mid: usize) -> (ShardsRefMut<'_>, ShardsRefMut<'_>) {
194 let (a, b) = self.data.split_at_mut(mid * self.shard_len_64);
195
196 (
197 ShardsRefMut::new(mid, self.shard_len_64, a),
198 ShardsRefMut::new(self.shard_count - mid, self.shard_len_64, b),
199 )
200 }
201
202 pub fn zero<R: RangeBounds<usize>>(&mut self, range: R) {
204 let start = match range.start_bound() {
205 Bound::Included(start) => start * self.shard_len_64,
206 Bound::Excluded(start) => (start + 1) * self.shard_len_64,
207 Bound::Unbounded => 0,
208 };
209
210 let end = match range.end_bound() {
211 Bound::Included(end) => (end + 1) * self.shard_len_64,
212 Bound::Excluded(end) => end * self.shard_len_64,
213 Bound::Unbounded => self.shard_count * self.shard_len_64,
214 };
215
216 self.data[start..end].fill([0; 64]);
217 }
218}
219
220impl Index<usize> for ShardsRefMut<'_> {
224 type Output = [[u8; 64]];
225 fn index(&self, index: usize) -> &Self::Output {
226 &self.data[index * self.shard_len_64..(index + 1) * self.shard_len_64]
227 }
228}
229
230impl IndexMut<usize> for ShardsRefMut<'_> {
234 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
235 &mut self.data[index * self.shard_len_64..(index + 1) * self.shard_len_64]
236 }
237}
238
239impl ShardsRefMut<'_> {
243 pub(crate) fn copy_within(&mut self, mut src: usize, mut dest: usize, mut count: usize) {
244 src *= self.shard_len_64;
245 dest *= self.shard_len_64;
246 count *= self.shard_len_64;
247
248 self.data.copy_within(src..src + count, dest);
249 }
250
251 pub(crate) fn flat2_mut(
256 &mut self,
257 mut x: usize,
258 mut y: usize,
259 mut count: usize,
260 ) -> (&mut [[u8; 64]], &mut [[u8; 64]]) {
261 x *= self.shard_len_64;
262 y *= self.shard_len_64;
263 count *= self.shard_len_64;
264
265 if x < y {
266 let (head, tail) = self.data.split_at_mut(y);
267 (&mut head[x..x + count], &mut tail[..count])
268 } else {
269 let (head, tail) = self.data.split_at_mut(x);
270 (&mut tail[..count], &mut head[y..y + count])
271 }
272 }
273}