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 ended: bool,
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.ended {
69 None
70 } else {
71 let mut index = self.next_index;
72 while index < self.work.original_count() {
73 if let Some(original) = self.work.restored_original(index) {
74 self.next_index = index + 1;
75 return Some((index, original));
76 }
77 index += 1;
78 }
79 self.ended = true;
80 None
81 }
82 }
83}
84
85impl<'a> RestoredOriginal<'a> {
89 pub(crate) fn new(work: &'a DecoderWork) -> Self {
90 Self {
91 ended: false,
92 next_index: 0,
93 work,
94 }
95 }
96}
97
98#[cfg(test)]
102mod tests {
103 use super::*;
104 use crate::{test_util, ReedSolomonDecoder, ReedSolomonEncoder};
105
106 fn simple_roundtrip(shard_size: usize) {
107 let original = test_util::generate_original(3, shard_size, 0);
108
109 let mut encoder = ReedSolomonEncoder::new(3, 2, shard_size).unwrap();
110 let mut decoder = ReedSolomonDecoder::new(3, 2, shard_size).unwrap();
111
112 for original in &original {
113 encoder.add_original_shard(original).unwrap();
114 }
115
116 let result = encoder.encode().unwrap();
117 let recovery: Vec<_> = result.recovery_iter().collect();
118
119 assert!(recovery.iter().all(|slice| slice.len() == shard_size));
120
121 decoder.add_original_shard(1, &original[1]).unwrap();
122 decoder.add_recovery_shard(0, recovery[0]).unwrap();
123 decoder.add_recovery_shard(1, recovery[1]).unwrap();
124
125 let result: DecoderResult = decoder.decode().unwrap();
126
127 assert_eq!(result.restored_original(0).unwrap(), original[0]);
128 assert!(result.restored_original(1).is_none());
129 assert_eq!(result.restored_original(2).unwrap(), original[2]);
130 assert!(result.restored_original(3).is_none());
131
132 let mut iter: RestoredOriginal = result.restored_original_iter();
133 assert_eq!(iter.next(), Some((0, original[0].as_slice())));
134 assert_eq!(iter.next(), Some((2, original[2].as_slice())));
135 assert_eq!(iter.next(), None);
136 assert_eq!(iter.next(), None);
137 }
138
139 #[test]
140 fn decoder_result() {
144 simple_roundtrip(1024);
145 }
146
147 #[test]
148 fn shard_size_not_divisible_by_64() {
149 for shard_size in [2, 4, 6, 30, 32, 34, 62, 64, 66, 126, 128, 130] {
150 simple_roundtrip(shard_size);
151 }
152 }
153}