reed_solomon_simd/
decoder_result.rs1use crate::rate::DecoderWork;
2
3pub struct DecoderResult<'a> {
14 work: &'a mut DecoderWork,
15}
16
17impl DecoderResult<'_> {
18 pub fn restored_original(&self, index: usize) -> Option<&[u8]> {
22 self.work.restored_original(index)
23 }
24
25 pub fn restored_original_iter(&self) -> RestoredOriginal<'_> {
28 RestoredOriginal::new(self.work)
29 }
30}
31
32impl<'a> DecoderResult<'a> {
36 pub(crate) fn new(work: &'a mut DecoderWork) -> Self {
37 Self { work }
38 }
39}
40
41impl Drop for DecoderResult<'_> {
45 fn drop(&mut self) {
46 self.work.reset_received();
47 }
48}
49
50pub struct RestoredOriginal<'a> {
57 remaining: usize,
58 next_index: usize,
59 work: &'a DecoderWork,
60}
61
62impl<'a> Iterator for RestoredOriginal<'a> {
66 type Item = (usize, &'a [u8]);
67 fn next(&mut self) -> Option<(usize, &'a [u8])> {
68 if self.remaining == 0 {
69 return None;
70 }
71
72 let mut index = self.next_index;
73 while index < self.work.original_count() {
74 if let Some(original) = self.work.restored_original(index) {
75 self.next_index = index + 1;
76 self.remaining -= 1;
77 return Some((index, original));
78 }
79 index += 1;
80 }
81
82 debug_assert!(
83 false,
84 "Inconsistency in internal data structures. Please report."
85 );
86
87 None
88 }
89
90 fn size_hint(&self) -> (usize, Option<usize>) {
91 (self.remaining, Some(self.remaining))
92 }
93}
94
95impl ExactSizeIterator for RestoredOriginal<'_> {}
99
100impl<'a> RestoredOriginal<'a> {
104 pub(crate) fn new(work: &'a DecoderWork) -> Self {
105 Self {
106 remaining: work.missing_original_count(),
107 next_index: 0,
108 work,
109 }
110 }
111}
112
113#[cfg(test)]
117mod tests {
118 use super::*;
119 use crate::{test_util, ReedSolomonDecoder, ReedSolomonEncoder};
120
121 #[cfg(not(feature = "std"))]
122 use alloc::vec::Vec;
123
124 fn simple_roundtrip(shard_size: usize) {
125 let original = test_util::generate_original(3, shard_size, 0);
126
127 let mut encoder = ReedSolomonEncoder::new(3, 2, shard_size).unwrap();
128 let mut decoder = ReedSolomonDecoder::new(3, 2, shard_size).unwrap();
129
130 for original in &original {
131 encoder.add_original_shard(original).unwrap();
132 }
133
134 let result = encoder.encode().unwrap();
135 let recovery: Vec<_> = result.recovery_iter().collect();
136
137 assert!(recovery.iter().all(|slice| slice.len() == shard_size));
138
139 decoder.add_original_shard(1, &original[1]).unwrap();
140 decoder.add_recovery_shard(0, recovery[0]).unwrap();
141 decoder.add_recovery_shard(1, recovery[1]).unwrap();
142
143 let result: DecoderResult = decoder.decode().unwrap();
144
145 assert_eq!(result.restored_original(0).unwrap(), original[0]);
146 assert!(result.restored_original(1).is_none());
147 assert_eq!(result.restored_original(2).unwrap(), original[2]);
148 assert!(result.restored_original(3).is_none());
149
150 let mut iter: RestoredOriginal = result.restored_original_iter();
151 assert_eq!(iter.next(), Some((0, original[0].as_slice())));
152 assert_eq!(iter.next(), Some((2, original[2].as_slice())));
153 assert_eq!(iter.next(), None);
154 assert_eq!(iter.next(), None);
155 }
156
157 #[test]
158 fn decoder_result() {
162 simple_roundtrip(1024);
163 }
164
165 #[test]
166 fn shard_size_not_divisible_by_64() {
167 for shard_size in [2, 4, 6, 30, 32, 34, 62, 64, 66, 126, 128, 130] {
168 simple_roundtrip(shard_size);
169 }
170 }
171
172 #[test]
173 fn decoder_result_size_hint() {
174 let shard_size = 64;
175 let original = test_util::generate_original(3, shard_size, 0);
176
177 let mut encoder = ReedSolomonEncoder::new(3, 2, shard_size).unwrap();
178 let mut decoder = ReedSolomonDecoder::new(3, 2, shard_size).unwrap();
179
180 for original in &original {
181 encoder.add_original_shard(original).unwrap();
182 }
183
184 let result = encoder.encode().unwrap();
185 let recovery: Vec<_> = result.recovery_iter().collect();
186
187 decoder.add_original_shard(1, &original[1]).unwrap();
188 decoder.add_recovery_shard(0, recovery[0]).unwrap();
189 decoder.add_recovery_shard(1, recovery[1]).unwrap();
190
191 let result: DecoderResult = decoder.decode().unwrap();
192
193 let mut iter: RestoredOriginal = result.restored_original_iter();
194
195 assert_eq!(iter.len(), 2);
196
197 assert!(iter.next().is_some());
198 assert_eq!(iter.len(), 1);
199
200 assert!(iter.next().is_some());
201 assert_eq!(iter.len(), 0);
202
203 assert!(iter.next().is_none());
204 assert_eq!(iter.len(), 0);
205 }
206
207 #[test]
208 fn decoder_result_size_hint_no_missing() {
209 let shard_size = 64;
210 let original = test_util::generate_original(3, shard_size, 0);
211
212 let mut encoder = ReedSolomonEncoder::new(3, 2, shard_size).unwrap();
213 let mut decoder = ReedSolomonDecoder::new(3, 2, shard_size).unwrap();
214
215 for original in &original {
216 encoder.add_original_shard(original).unwrap();
217 }
218
219 let result = encoder.encode().unwrap();
220 let _recovery: Vec<_> = result.recovery_iter().collect();
221
222 decoder.add_original_shard(0, &original[0]).unwrap();
224 decoder.add_original_shard(1, &original[1]).unwrap();
225 decoder.add_original_shard(2, &original[2]).unwrap();
226
227 let result: DecoderResult = decoder.decode().unwrap();
228
229 let mut iter: RestoredOriginal = result.restored_original_iter();
230
231 assert_eq!(iter.len(), 0);
232
233 assert!(iter.next().is_none());
234 assert_eq!(iter.len(), 0);
235
236 assert!(iter.next().is_none());
237 assert_eq!(iter.len(), 0);
238 }
239}