tickv/
crc32.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! A standalone CRC32 implementation
6//!
7//! This is based on the CRC32 implementation
8//! from: crc-rs <https://github.com/mrhooray/crc-rs>
9//!
10//! This implemented the CRC-32 checksum
11//!     poly: 0x04c11db7
12//!     init: 0x00000000
13//!     refin: false
14//!     refout: false
15//!     xorout: 0xffffffff
16//!
17//! Licensed under either of:
18//!     Apache License, Version 2.0 (LICENSE-APACHE <http://www.apache.org/licenses/LICENSE-2.0>)
19//!     MIT License (LICENSE-MIT <http://opensource.org/licenses/MIT>)
20//! at your option.
21
22use core::cell::Cell;
23
24const CRC_TABLE: [u32; 256] = [
25    crc32(0x04c11db7, 0),
26    crc32(0x04c11db7, 1),
27    crc32(0x04c11db7, 2),
28    crc32(0x04c11db7, 3),
29    crc32(0x04c11db7, 4),
30    crc32(0x04c11db7, 5),
31    crc32(0x04c11db7, 6),
32    crc32(0x04c11db7, 7),
33    crc32(0x04c11db7, 8),
34    crc32(0x04c11db7, 9),
35    crc32(0x04c11db7, 10),
36    crc32(0x04c11db7, 11),
37    crc32(0x04c11db7, 12),
38    crc32(0x04c11db7, 13),
39    crc32(0x04c11db7, 14),
40    crc32(0x04c11db7, 15),
41    crc32(0x04c11db7, 16),
42    crc32(0x04c11db7, 17),
43    crc32(0x04c11db7, 18),
44    crc32(0x04c11db7, 19),
45    crc32(0x04c11db7, 20),
46    crc32(0x04c11db7, 21),
47    crc32(0x04c11db7, 22),
48    crc32(0x04c11db7, 23),
49    crc32(0x04c11db7, 24),
50    crc32(0x04c11db7, 25),
51    crc32(0x04c11db7, 26),
52    crc32(0x04c11db7, 27),
53    crc32(0x04c11db7, 28),
54    crc32(0x04c11db7, 29),
55    crc32(0x04c11db7, 30),
56    crc32(0x04c11db7, 31),
57    crc32(0x04c11db7, 32),
58    crc32(0x04c11db7, 33),
59    crc32(0x04c11db7, 34),
60    crc32(0x04c11db7, 35),
61    crc32(0x04c11db7, 36),
62    crc32(0x04c11db7, 37),
63    crc32(0x04c11db7, 38),
64    crc32(0x04c11db7, 39),
65    crc32(0x04c11db7, 40),
66    crc32(0x04c11db7, 41),
67    crc32(0x04c11db7, 42),
68    crc32(0x04c11db7, 43),
69    crc32(0x04c11db7, 44),
70    crc32(0x04c11db7, 45),
71    crc32(0x04c11db7, 46),
72    crc32(0x04c11db7, 47),
73    crc32(0x04c11db7, 48),
74    crc32(0x04c11db7, 49),
75    crc32(0x04c11db7, 50),
76    crc32(0x04c11db7, 51),
77    crc32(0x04c11db7, 52),
78    crc32(0x04c11db7, 53),
79    crc32(0x04c11db7, 54),
80    crc32(0x04c11db7, 55),
81    crc32(0x04c11db7, 56),
82    crc32(0x04c11db7, 57),
83    crc32(0x04c11db7, 58),
84    crc32(0x04c11db7, 59),
85    crc32(0x04c11db7, 60),
86    crc32(0x04c11db7, 61),
87    crc32(0x04c11db7, 62),
88    crc32(0x04c11db7, 63),
89    crc32(0x04c11db7, 64),
90    crc32(0x04c11db7, 65),
91    crc32(0x04c11db7, 66),
92    crc32(0x04c11db7, 67),
93    crc32(0x04c11db7, 68),
94    crc32(0x04c11db7, 69),
95    crc32(0x04c11db7, 70),
96    crc32(0x04c11db7, 71),
97    crc32(0x04c11db7, 72),
98    crc32(0x04c11db7, 73),
99    crc32(0x04c11db7, 74),
100    crc32(0x04c11db7, 75),
101    crc32(0x04c11db7, 76),
102    crc32(0x04c11db7, 77),
103    crc32(0x04c11db7, 78),
104    crc32(0x04c11db7, 79),
105    crc32(0x04c11db7, 80),
106    crc32(0x04c11db7, 81),
107    crc32(0x04c11db7, 82),
108    crc32(0x04c11db7, 83),
109    crc32(0x04c11db7, 84),
110    crc32(0x04c11db7, 85),
111    crc32(0x04c11db7, 86),
112    crc32(0x04c11db7, 87),
113    crc32(0x04c11db7, 88),
114    crc32(0x04c11db7, 89),
115    crc32(0x04c11db7, 90),
116    crc32(0x04c11db7, 91),
117    crc32(0x04c11db7, 92),
118    crc32(0x04c11db7, 93),
119    crc32(0x04c11db7, 94),
120    crc32(0x04c11db7, 95),
121    crc32(0x04c11db7, 96),
122    crc32(0x04c11db7, 97),
123    crc32(0x04c11db7, 98),
124    crc32(0x04c11db7, 99),
125    crc32(0x04c11db7, 100),
126    crc32(0x04c11db7, 101),
127    crc32(0x04c11db7, 102),
128    crc32(0x04c11db7, 103),
129    crc32(0x04c11db7, 104),
130    crc32(0x04c11db7, 105),
131    crc32(0x04c11db7, 106),
132    crc32(0x04c11db7, 107),
133    crc32(0x04c11db7, 108),
134    crc32(0x04c11db7, 109),
135    crc32(0x04c11db7, 110),
136    crc32(0x04c11db7, 111),
137    crc32(0x04c11db7, 112),
138    crc32(0x04c11db7, 113),
139    crc32(0x04c11db7, 114),
140    crc32(0x04c11db7, 115),
141    crc32(0x04c11db7, 116),
142    crc32(0x04c11db7, 117),
143    crc32(0x04c11db7, 118),
144    crc32(0x04c11db7, 119),
145    crc32(0x04c11db7, 120),
146    crc32(0x04c11db7, 121),
147    crc32(0x04c11db7, 122),
148    crc32(0x04c11db7, 123),
149    crc32(0x04c11db7, 124),
150    crc32(0x04c11db7, 125),
151    crc32(0x04c11db7, 126),
152    crc32(0x04c11db7, 127),
153    crc32(0x04c11db7, 128),
154    crc32(0x04c11db7, 129),
155    crc32(0x04c11db7, 130),
156    crc32(0x04c11db7, 131),
157    crc32(0x04c11db7, 132),
158    crc32(0x04c11db7, 133),
159    crc32(0x04c11db7, 134),
160    crc32(0x04c11db7, 135),
161    crc32(0x04c11db7, 136),
162    crc32(0x04c11db7, 137),
163    crc32(0x04c11db7, 138),
164    crc32(0x04c11db7, 139),
165    crc32(0x04c11db7, 140),
166    crc32(0x04c11db7, 141),
167    crc32(0x04c11db7, 142),
168    crc32(0x04c11db7, 143),
169    crc32(0x04c11db7, 144),
170    crc32(0x04c11db7, 145),
171    crc32(0x04c11db7, 146),
172    crc32(0x04c11db7, 147),
173    crc32(0x04c11db7, 148),
174    crc32(0x04c11db7, 149),
175    crc32(0x04c11db7, 150),
176    crc32(0x04c11db7, 151),
177    crc32(0x04c11db7, 152),
178    crc32(0x04c11db7, 153),
179    crc32(0x04c11db7, 154),
180    crc32(0x04c11db7, 155),
181    crc32(0x04c11db7, 156),
182    crc32(0x04c11db7, 157),
183    crc32(0x04c11db7, 158),
184    crc32(0x04c11db7, 159),
185    crc32(0x04c11db7, 160),
186    crc32(0x04c11db7, 161),
187    crc32(0x04c11db7, 162),
188    crc32(0x04c11db7, 163),
189    crc32(0x04c11db7, 164),
190    crc32(0x04c11db7, 165),
191    crc32(0x04c11db7, 166),
192    crc32(0x04c11db7, 167),
193    crc32(0x04c11db7, 168),
194    crc32(0x04c11db7, 169),
195    crc32(0x04c11db7, 170),
196    crc32(0x04c11db7, 171),
197    crc32(0x04c11db7, 172),
198    crc32(0x04c11db7, 173),
199    crc32(0x04c11db7, 174),
200    crc32(0x04c11db7, 175),
201    crc32(0x04c11db7, 176),
202    crc32(0x04c11db7, 177),
203    crc32(0x04c11db7, 178),
204    crc32(0x04c11db7, 179),
205    crc32(0x04c11db7, 180),
206    crc32(0x04c11db7, 181),
207    crc32(0x04c11db7, 182),
208    crc32(0x04c11db7, 183),
209    crc32(0x04c11db7, 184),
210    crc32(0x04c11db7, 185),
211    crc32(0x04c11db7, 186),
212    crc32(0x04c11db7, 187),
213    crc32(0x04c11db7, 188),
214    crc32(0x04c11db7, 189),
215    crc32(0x04c11db7, 190),
216    crc32(0x04c11db7, 191),
217    crc32(0x04c11db7, 192),
218    crc32(0x04c11db7, 193),
219    crc32(0x04c11db7, 194),
220    crc32(0x04c11db7, 195),
221    crc32(0x04c11db7, 196),
222    crc32(0x04c11db7, 197),
223    crc32(0x04c11db7, 198),
224    crc32(0x04c11db7, 199),
225    crc32(0x04c11db7, 200),
226    crc32(0x04c11db7, 201),
227    crc32(0x04c11db7, 202),
228    crc32(0x04c11db7, 203),
229    crc32(0x04c11db7, 204),
230    crc32(0x04c11db7, 205),
231    crc32(0x04c11db7, 206),
232    crc32(0x04c11db7, 207),
233    crc32(0x04c11db7, 208),
234    crc32(0x04c11db7, 209),
235    crc32(0x04c11db7, 210),
236    crc32(0x04c11db7, 211),
237    crc32(0x04c11db7, 212),
238    crc32(0x04c11db7, 213),
239    crc32(0x04c11db7, 214),
240    crc32(0x04c11db7, 215),
241    crc32(0x04c11db7, 216),
242    crc32(0x04c11db7, 217),
243    crc32(0x04c11db7, 218),
244    crc32(0x04c11db7, 219),
245    crc32(0x04c11db7, 220),
246    crc32(0x04c11db7, 221),
247    crc32(0x04c11db7, 222),
248    crc32(0x04c11db7, 223),
249    crc32(0x04c11db7, 224),
250    crc32(0x04c11db7, 225),
251    crc32(0x04c11db7, 226),
252    crc32(0x04c11db7, 227),
253    crc32(0x04c11db7, 228),
254    crc32(0x04c11db7, 229),
255    crc32(0x04c11db7, 230),
256    crc32(0x04c11db7, 231),
257    crc32(0x04c11db7, 232),
258    crc32(0x04c11db7, 233),
259    crc32(0x04c11db7, 234),
260    crc32(0x04c11db7, 235),
261    crc32(0x04c11db7, 236),
262    crc32(0x04c11db7, 237),
263    crc32(0x04c11db7, 238),
264    crc32(0x04c11db7, 239),
265    crc32(0x04c11db7, 240),
266    crc32(0x04c11db7, 241),
267    crc32(0x04c11db7, 242),
268    crc32(0x04c11db7, 243),
269    crc32(0x04c11db7, 244),
270    crc32(0x04c11db7, 245),
271    crc32(0x04c11db7, 246),
272    crc32(0x04c11db7, 247),
273    crc32(0x04c11db7, 248),
274    crc32(0x04c11db7, 249),
275    crc32(0x04c11db7, 250),
276    crc32(0x04c11db7, 251),
277    crc32(0x04c11db7, 252),
278    crc32(0x04c11db7, 253),
279    crc32(0x04c11db7, 254),
280    crc32(0x04c11db7, 255),
281];
282
283const fn reflect_8(mut b: u8) -> u8 {
284    b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
285    b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
286    b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
287    b
288}
289
290const fn reflect_32(mut b: u32) -> u32 {
291    b = (b & 0xFFFF0000) >> 16 | (b & 0x0000FFFF) << 16;
292    b = (b & 0xFF00FF00) >> 8 | (b & 0x00FF00FF) << 8;
293    b = (b & 0xF0F0F0F0) >> 4 | (b & 0x0F0F0F0F) << 4;
294    b = (b & 0xCCCCCCCC) >> 2 | (b & 0x33333333) << 2;
295    b = (b & 0xAAAAAAAA) >> 1 | (b & 0x55555555) << 1;
296    b
297}
298
299const fn crc32(poly: u32, mut byte: u8) -> u32 {
300    const fn poly_sum_crc32(poly: u32, value: u32) -> u32 {
301        (value << 1) ^ ((value >> 31) * poly)
302    }
303    byte = [byte, reflect_8(byte)][0];
304    let mut value = (byte as u32) << 24;
305    value = poly_sum_crc32(poly, value);
306    value = poly_sum_crc32(poly, value);
307    value = poly_sum_crc32(poly, value);
308    value = poly_sum_crc32(poly, value);
309    value = poly_sum_crc32(poly, value);
310    value = poly_sum_crc32(poly, value);
311    value = poly_sum_crc32(poly, value);
312    value = poly_sum_crc32(poly, value);
313    [value, reflect_32(value)][0]
314}
315
316/// Internal `Crc` implementation
317///
318/// This doesn't store any state, but just performs operations
319///
320/// This is called from the public `Crc32` struct and functions
321/// which store the state.
322///
323/// We keep this seperate to clearly show the CRC implementation
324/// details (such as initial state and xorout).
325#[derive(Default)]
326struct Crc {}
327
328impl Crc {
329    /// Create a new instance for performing CRC32 operations.
330    const fn new() -> Self {
331        Self {}
332    }
333
334    const fn init(&self) -> u32 {
335        0x00000000
336    }
337
338    const fn table_entry(&self, index: u32) -> u32 {
339        CRC_TABLE[(index & 0xFF) as usize]
340    }
341
342    const fn update(&self, mut crc: u32, bytes: &[u8]) -> u32 {
343        let mut i = 0;
344        while i < bytes.len() {
345            crc = self.table_entry(bytes[i] as u32 ^ (crc >> 24)) ^ (crc << 8);
346            i += 1;
347        }
348        crc
349    }
350
351    const fn finalise(&self, crc: u32) -> u32 {
352        crc ^ 0xffffffff
353    }
354}
355
356/// A standalone CRC32 implementation
357///
358/// This is based on the CRC32 implementation
359/// from: crc-rs <https://github.com/mrhooray/crc-rs>
360///
361/// This implemented the CRC-32 checksum
362///     poly: 0x04c11db7
363///     init: 0x00000000
364///     refin: false
365///     refout: false
366///     xorout: 0xffffffff
367pub struct Crc32 {
368    crc: Crc,
369    value: Cell<u32>,
370}
371
372impl Crc32 {
373    /// Create a new instance of the CRC implementation.
374    ///
375    /// This correctly initalises the CRC
376    pub const fn new() -> Self {
377        let crc = Crc::new();
378        let value = crc.init();
379        Crc32 {
380            crc,
381            value: Cell::new(value),
382        }
383    }
384
385    /// Update the CRC based on the data in `bytes`
386    pub fn update(&self, bytes: &[u8]) {
387        self.value.set(self.crc.update(self.value.get(), bytes));
388    }
389
390    /// Complete the CRC operation and return the final value
391    ///
392    /// This will reset the CRC instance in preperation for new data
393    pub fn finalise(self) -> u32 {
394        let ret = self.crc.finalise(self.value.get());
395
396        self.value.set(self.crc.init());
397
398        ret
399    }
400}