forked from malaire/reed-solomon-16
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathencoder_result.rs
134 lines (113 loc) · 3.72 KB
/
encoder_result.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use crate::rate::EncoderWork;
// ======================================================================
// EncoderResult - PUBLIC
/// Result of encoding. Contains the generated recovery shards.
///
/// This struct is created by [`ReedSolomonEncoder::encode`]
/// and [`RateEncoder::encode`].
///
/// [`RateEncoder::encode`]: crate::rate::RateEncoder::encode
/// [`ReedSolomonEncoder::encode`]: crate::ReedSolomonEncoder::encode
pub struct EncoderResult<'a> {
work: &'a mut EncoderWork,
}
impl EncoderResult<'_> {
/// Returns recovery shard with given `index`
/// or `None` if `index >= recovery_count`.
///
/// Recovery shards have indexes `0..recovery_count`
/// and these same indexes must be used when decoding.
pub fn recovery(&self, index: usize) -> Option<&[u8]> {
self.work.recovery(index)
}
/// Returns iterator over all recovery shards ordered by their indexes.
///
/// Recovery shards have indexes `0..recovery_count`
/// and these same indexes must be used when decoding.
pub fn recovery_iter(&self) -> Recovery {
Recovery::new(self.work)
}
}
// ======================================================================
// EncoderResult - CRATE
impl<'a> EncoderResult<'a> {
pub(crate) fn new(work: &'a mut EncoderWork) -> Self {
Self { work }
}
}
// ======================================================================
// EncoderResult - IMPL DROP
impl Drop for EncoderResult<'_> {
fn drop(&mut self) {
self.work.reset_received();
}
}
// ======================================================================
// Recovery - PUBLIC
/// Iterator over generated recovery shards.
///
/// This struct is created by [`EncoderResult::recovery_iter`].
pub struct Recovery<'a> {
ended: bool,
next_index: usize,
work: &'a EncoderWork,
}
// ======================================================================
// Recovery - IMPL Iterator
impl<'a> Iterator for Recovery<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<&'a [u8]> {
if self.ended {
None
} else if let Some(next) = self.work.recovery(self.next_index) {
self.next_index += 1;
Some(next)
} else {
self.ended = true;
None
}
}
}
// ======================================================================
// Recovery - CRATE
impl<'a> Recovery<'a> {
pub(crate) fn new(work: &'a EncoderWork) -> Self {
Self {
ended: false,
next_index: 0,
work,
}
}
}
// ======================================================================
// TESTS
#[cfg(test)]
mod tests {
use super::*;
use crate::{test_util, ReedSolomonEncoder};
#[test]
// EncoderResult::recovery
// EncoderResult::recovery_iter
// Recovery
fn encoder_result() {
let original = test_util::generate_original(2, 1024, 123);
let mut encoder = ReedSolomonEncoder::new(2, 3, 1024).unwrap();
for original in &original {
encoder.add_original_shard(original).unwrap();
}
let result: EncoderResult = encoder.encode().unwrap();
let mut all = Vec::new();
all.push(result.recovery(0).unwrap());
all.push(result.recovery(1).unwrap());
all.push(result.recovery(2).unwrap());
assert!(result.recovery(3).is_none());
test_util::assert_hash(all, test_util::LOW_2_3);
let mut iter: Recovery = result.recovery_iter();
let mut all = Vec::new();
all.push(iter.next().unwrap());
all.push(iter.next().unwrap());
all.push(iter.next().unwrap());
assert!(iter.next().is_none());
test_util::assert_hash(all, test_util::LOW_2_3);
}
}