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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//! Reed-Solomon BCH encoder and decoder suitable for `no_std` environment.
//!
//! This library implements block encoder and decoder: error correction code is appended to original data.
//!
//! # Example
//! ```rust
//! extern crate reed_solomon;
//!
//! use reed_solomon::Encoder;
//! use reed_solomon::Decoder;
//!
//! fn main() {
//!     let data = b"Hello World!";
//!
//!     // Length of error correction code
//!     let ecc_len = 8;
//!
//!     // Create encoder and decoder with
//!     let enc = Encoder::new(ecc_len);
//!     let dec = Decoder::new(ecc_len);
//!
//!     // Encode data
//!     let encoded = enc.encode(&data[..]);
//!
//!     // Simulate some transmission errors
//!     let mut corrupted = *encoded;
//!     for i in 0..4 {
//!         corrupted[i] = 0x0;
//!     }
//!
//!     // Try to recover data
//!     let known_erasures = [0];
//!     let recovered = dec.correct(&mut corrupted, Some(&known_erasures)).unwrap();
//!
//!     let orig_str = std::str::from_utf8(data).unwrap();
//!     let recv_str = std::str::from_utf8(recovered.data()).unwrap();
//!
//!     println!("message:               {:?}", orig_str);
//!     println!("original data:         {:?}", data);
//!     println!("error correction code: {:?}", encoded.ecc());
//!     println!("corrupted:             {:?}", corrupted);
//!     println!("repaired:              {:?}", recv_str);
//! }
//! ```
//!
//! # Unsafe
//! This library uses some slices indexind that is boundary checked.
//!
//! You can disable checks with library feature `unsafe_indexing`, 
//! then unsafe `Slice::get_inchecked()` would be utilized to improve speed where unchecked indexing
//! is considered safe and LLVM cannot drop boundary checks.
//!
//! # Bandwidth
//! Software implementation is relatively slow because general purpose processors do not support
//! Galois field arithmetic operations. For example, Galois field multiply requires test for 0,
//! two table look-ups, modulo add, and anti-log table look-up.
//!
//! Besides this performance bound, current implementation is not very optimal
//! and performs some unnecessary memcpys.
//!
//! Encoder bandwidth using one Sandy Bridge core operating on 2.8 `GHz`:
//! <style type="text/css">
//! .tg  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}
//! .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}
//! .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}
//! .tg .tg-baqh{text-align:center;vertical-align:top}
//! </style>
//! <table class="tg">
//!   <tr>
//!     <th class="tg-baqh">data<br></th>
//!     <th class="tg-baqh">ecc</th>
//!     <th class="tg-baqh">bandwidth<br></th>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh">251</td>
//!     <td class="tg-baqh">4</td>
//!     <td class="tg-baqh">115.20 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh">239</td>
//!     <td class="tg-baqh">16</td>
//!     <td class="tg-baqh">37.76 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh">223</td>
//!     <td class="tg-baqh">32</td>
//!     <td class="tg-baqh">19.59 MB/s<br></td>
//!   </tr>
//! </table>
//!
//! Decoder bandwidth using one Sandy Bridge core operating on 2.8 `GHz`:
//! <style type="text/css">
//! .tg  {border-collapse:collapse;border-spacing:0;border-color:#ccc;}
//! .tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#fff;}
//! .tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;border-color:#ccc;color:#333;background-color:#f0f0f0;}
//! .tg .tg-uqo3{background-color:#efefef;text-align:center;vertical-align:top}
//! .tg .tg-baqh{text-align:center;vertical-align:top}
//! </style>
//! <table class="tg">
//!   <tr>
//!     <th class="tg-baqh">data<br></th>
//!     <th class="tg-baqh">ecc</th>
//!     <th class="tg-baqh">errors</th>
//!     <th class="tg-baqh">bandwidth</th>
//!   </tr>
//!   <tr>
//!     <td class="tg-uqo3">251</td>
//!     <td class="tg-uqo3">4</td>
//!     <td class="tg-uqo3">0<br></td>
//!     <td class="tg-uqo3">49 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"><br></td>
//!     <td class="tg-baqh"><br></td>
//!     <td class="tg-baqh">1</td>
//!     <td class="tg-baqh">16.91 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"><br></td>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh">2</td>
//!     <td class="tg-baqh">15.90 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-uqo3">239</td>
//!     <td class="tg-uqo3">16</td>
//!     <td class="tg-uqo3">0</td>
//!     <td class="tg-uqo3">10.75 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh">1</td>
//!     <td class="tg-baqh">4.86 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh">8</td>
//!     <td class="tg-baqh">3.81 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-uqo3">223</td>
//!     <td class="tg-uqo3">32</td>
//!     <td class="tg-uqo3">0</td>
//!     <td class="tg-uqo3">4.80 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh">1</td>
//!     <td class="tg-baqh">2.32 MB/s<br></td>
//!   </tr>
//!   <tr>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh"></td>
//!     <td class="tg-baqh">16</td>
//!     <td class="tg-baqh">1.82 MB/s<br></td>
//!   </tr>
//! </table>

#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![warn(missing_docs, missing_debug_implementations,
        trivial_casts, trivial_numeric_casts,
        unstable_features)]

#![no_std]

const POLYNOMIAL_MAX_LENGTH: usize = 256;

#[macro_use]
mod macros;
mod gf;
mod encoder;
mod decoder;
mod buffer;

pub use encoder::Encoder;
pub use decoder::Decoder;
pub use decoder::DecoderError;
pub use buffer::Buffer;