reed_solomon_16/rate.rs
1//! Advanced encoding/decoding using chosen [`Engine`] and [`Rate`].
2//!
3//! **This is an advanced module which is not needed for [simple usage] or [basic usage].**
4//!
5//! This module is relevant if you want to
6//! - encode/decode using other [`Engine`] than [`DefaultEngine`].
7//! - re-use working space of one encoder/decoder in another.
8//! - understand/benchmark/test high or low rate directly.
9//!
10//! # Rates
11//!
12//! See [algorithm > Rate] for details about high/low rate.
13//!
14//! - [`DefaultRate`], [`DefaultRateEncoder`], [`DefaultRateDecoder`]
15//! - Encoding/decoding using high or low rate as appropriate.
16//! - These are basically same as [`ReedSolomonEncoder`]
17//! and [`ReedSolomonDecoder`] except with slightly different API
18//! which allows specifying [`Engine`] and working space.
19//! - [`HighRate`], [`HighRateEncoder`], [`HighRateDecoder`]
20//! - Encoding/decoding using only high rate.
21//! - [`LowRate`], [`LowRateEncoder`], [`LowRateDecoder`]
22//! - Encoding/decoding using only low rate.
23//!
24//! [simple usage]: crate#simple-usage
25//! [basic usage]: crate#basic-usage
26//! [algorithm > Rate]: crate::algorithm#rate
27//! [`ReedSolomonEncoder`]: crate::ReedSolomonEncoder
28//! [`ReedSolomonDecoder`]: crate::ReedSolomonDecoder
29//! [`DefaultEngine`]: crate::engine::DefaultEngine
30
31use crate::{engine::Engine, DecoderResult, EncoderResult, Error};
32
33pub use self::{
34 decoder_work::DecoderWork,
35 encoder_work::EncoderWork,
36 rate_default::{DefaultRate, DefaultRateDecoder, DefaultRateEncoder},
37 rate_high::{HighRate, HighRateDecoder, HighRateEncoder},
38 rate_low::{LowRate, LowRateDecoder, LowRateEncoder},
39};
40
41mod decoder_work;
42mod encoder_work;
43mod rate_default;
44mod rate_high;
45mod rate_low;
46
47// ======================================================================
48// Rate - PUBLIC
49
50/// Reed-Solomon encoder/decoder generator using specific rate.
51pub trait Rate<E: Engine> {
52 // ============================================================
53 // REQUIRED
54
55 /// Encoder of this rate.
56 type RateEncoder: RateEncoder<E>;
57 /// Decoder of this rate.
58 type RateDecoder: RateDecoder<E>;
59
60 /// Returns `true` if given `original_count` / `recovery_count`
61 /// combination is supported.
62 fn supports(original_count: usize, recovery_count: usize) -> bool;
63
64 // ============================================================
65 // PROVIDED
66
67 /// Creates new encoder. This is same as [`RateEncoder::new`].
68 fn encoder(
69 original_count: usize,
70 recovery_count: usize,
71 shard_bytes: usize,
72 engine: E,
73 work: Option<EncoderWork>,
74 ) -> Result<Self::RateEncoder, Error> {
75 Self::RateEncoder::new(original_count, recovery_count, shard_bytes, engine, work)
76 }
77
78 /// Creates new decoder. This is same as [`RateDecoder::new`].
79 fn decoder(
80 original_count: usize,
81 recovery_count: usize,
82 shard_bytes: usize,
83 engine: E,
84 work: Option<DecoderWork>,
85 ) -> Result<Self::RateDecoder, Error> {
86 Self::RateDecoder::new(original_count, recovery_count, shard_bytes, engine, work)
87 }
88
89 /// Returns `Ok(())` if given `original_count` / `recovery_count`
90 /// combination is supported and given `shard_bytes` is valid.
91 fn validate(
92 original_count: usize,
93 recovery_count: usize,
94 shard_bytes: usize,
95 ) -> Result<(), Error> {
96 if !Self::supports(original_count, recovery_count) {
97 Err(Error::UnsupportedShardCount {
98 original_count,
99 recovery_count,
100 })
101 } else if shard_bytes == 0 || shard_bytes & 63 != 0 {
102 Err(Error::InvalidShardSize { shard_bytes })
103 } else {
104 Ok(())
105 }
106 }
107}
108
109// ======================================================================
110// RateEncoder - PUBLIC
111
112/// Reed-Solomon encoder using specific rate.
113pub trait RateEncoder<E: Engine>
114where
115 Self: Sized,
116{
117 // ============================================================
118 // REQUIRED
119
120 /// Rate of this encoder.
121 type Rate: Rate<E>;
122
123 /// Like [`ReedSolomonEncoder::add_original_shard`](crate::ReedSolomonEncoder::add_original_shard).
124 fn add_original_shard<T: AsRef<[u8]>>(&mut self, original_shard: T) -> Result<(), Error>;
125
126 /// Like [`ReedSolomonEncoder::encode`](crate::ReedSolomonEncoder::encode).
127 fn encode(&mut self) -> Result<EncoderResult, Error>;
128
129 /// Consumes this encoder returning its [`Engine`] and [`EncoderWork`]
130 /// so that they can be re-used by another encoder.
131 fn into_parts(self) -> (E, EncoderWork);
132
133 /// Like [`ReedSolomonEncoder::new`](crate::ReedSolomonEncoder::new)
134 /// with [`Engine`] to use and optional working space to be re-used.
135 fn new(
136 original_count: usize,
137 recovery_count: usize,
138 shard_bytes: usize,
139 engine: E,
140 work: Option<EncoderWork>,
141 ) -> Result<Self, Error>;
142
143 /// Like [`ReedSolomonEncoder::reset`](crate::ReedSolomonEncoder::reset).
144 fn reset(
145 &mut self,
146 original_count: usize,
147 recovery_count: usize,
148 shard_bytes: usize,
149 ) -> Result<(), Error>;
150
151 // ============================================================
152 // PROVIDED
153
154 /// Returns `true` if given `original_count` / `recovery_count`
155 /// combination is supported.
156 ///
157 /// This is same as [`Rate::supports`].
158 fn supports(original_count: usize, recovery_count: usize) -> bool {
159 Self::Rate::supports(original_count, recovery_count)
160 }
161
162 /// Returns `Ok(())` if given `original_count` / `recovery_count`
163 /// combination is supported and given `shard_bytes` is valid.
164 ///
165 /// This is same as [`Rate::validate`].
166 fn validate(
167 original_count: usize,
168 recovery_count: usize,
169 shard_bytes: usize,
170 ) -> Result<(), Error> {
171 Self::Rate::validate(original_count, recovery_count, shard_bytes)
172 }
173}
174
175// ======================================================================
176// RateDecoder - PUBLIC
177
178/// Reed-Solomon decoder using specific rate.
179pub trait RateDecoder<E: Engine>
180where
181 Self: Sized,
182{
183 // ============================================================
184 // REQUIRED
185
186 /// Rate of this decoder.
187 type Rate: Rate<E>;
188
189 /// Like [`ReedSolomonDecoder::add_original_shard`](crate::ReedSolomonDecoder::add_original_shard).
190 fn add_original_shard<T: AsRef<[u8]>>(
191 &mut self,
192 index: usize,
193 original_shard: T,
194 ) -> Result<(), Error>;
195
196 /// Like [`ReedSolomonDecoder::add_recovery_shard`](crate::ReedSolomonDecoder::add_recovery_shard).
197 fn add_recovery_shard<T: AsRef<[u8]>>(
198 &mut self,
199 index: usize,
200 recovery_shard: T,
201 ) -> Result<(), Error>;
202
203 /// Like [`ReedSolomonDecoder::decode`](crate::ReedSolomonDecoder::decode).
204 fn decode(&mut self) -> Result<DecoderResult, Error>;
205
206 /// Consumes this decoder returning its [`Engine`] and [`DecoderWork`]
207 /// so that they can be re-used by another decoder.
208 fn into_parts(self) -> (E, DecoderWork);
209
210 /// Like [`ReedSolomonDecoder::new`](crate::ReedSolomonDecoder::new)
211 /// with [`Engine`] to use and optional working space to be re-used.
212 fn new(
213 original_count: usize,
214 recovery_count: usize,
215 shard_bytes: usize,
216 engine: E,
217 work: Option<DecoderWork>,
218 ) -> Result<Self, Error>;
219
220 /// Like [`ReedSolomonDecoder::reset`](crate::ReedSolomonDecoder::reset).
221 fn reset(
222 &mut self,
223 original_count: usize,
224 recovery_count: usize,
225 shard_bytes: usize,
226 ) -> Result<(), Error>;
227
228 // ============================================================
229 // PROVIDED
230
231 /// Returns `true` if given `original_count` / `recovery_count`
232 /// combination is supported.
233 ///
234 /// This is same as [`Rate::supports`].
235 fn supports(original_count: usize, recovery_count: usize) -> bool {
236 Self::Rate::supports(original_count, recovery_count)
237 }
238
239 /// Returns `Ok(())` if given `original_count` / `recovery_count`
240 /// combination is supported and given `shard_bytes` is valid.
241 ///
242 /// This is same as [`Rate::validate`].
243 fn validate(
244 original_count: usize,
245 recovery_count: usize,
246 shard_bytes: usize,
247 ) -> Result<(), Error> {
248 Self::Rate::validate(original_count, recovery_count, shard_bytes)
249 }
250}