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}