forked from jstrong/const-crc32
				
			commit
					0d02e98749
				
				 4 changed files with 130 additions and 0 deletions
			
			
		@ -0,0 +1,13 @@ | 
				
			|||||||
 | 
					[package] | 
				
			||||||
 | 
					name = "const-crc32" | 
				
			||||||
 | 
					version = "1.0.0" | 
				
			||||||
 | 
					edition = "2021" | 
				
			||||||
 | 
					authors = ["Jonathan Strong <jstrong@shipyard.rs>"] | 
				
			||||||
 | 
					license = "MIT" | 
				
			||||||
 | 
					description = "A `const fn` implementation of crc32 checksum algorithm" | 
				
			||||||
 | 
					repository = "https://git.shipyard.rs/jstrong/const-crc32" | 
				
			||||||
 | 
					keywords = ["checksum", "crc", "crc32", "const"] | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[dev-dependencies] | 
				
			||||||
 | 
					crc32fast = "1.2" | 
				
			||||||
 | 
					rand = "0.8" | 
				
			||||||
@ -0,0 +1,21 @@ | 
				
			|||||||
 | 
					MIT License | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Copyright (c) 2022 Jonathan Strong | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Permission is hereby granted, free of charge, to any person obtaining a copy | 
				
			||||||
 | 
					of this software and associated documentation files (the "Software"), to deal | 
				
			||||||
 | 
					in the Software without restriction, including without limitation the rights | 
				
			||||||
 | 
					to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
				
			||||||
 | 
					copies of the Software, and to permit persons to whom the Software is | 
				
			||||||
 | 
					furnished to do so, subject to the following conditions: | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The above copyright notice and this permission notice shall be included in all | 
				
			||||||
 | 
					copies or substantial portions of the Software. | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||||
 | 
					IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||||
 | 
					FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | 
				
			||||||
 | 
					AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
				
			||||||
 | 
					LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
				
			||||||
 | 
					OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 
				
			||||||
 | 
					SOFTWARE. | 
				
			||||||
@ -0,0 +1,93 @@ | 
				
			|||||||
 | 
					//! A `const fn` crc32 checksum implementation.
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! # Examples
 | 
				
			||||||
 | 
					//!
 | 
				
			||||||
 | 
					//! ```
 | 
				
			||||||
 | 
					//! const BYTES: &[u8] = "The quick brown fox jumps over the lazy dog".as_bytes();
 | 
				
			||||||
 | 
					//! assert_eq!(const_crc32::crc32(BYTES), 0x414fa339_u32);
 | 
				
			||||||
 | 
					//! ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// typically crc32 implementations set up a [u32; 256] lookup table. this computes
 | 
				
			||||||
 | 
					/// the table on demand for a given "index" `i`
 | 
				
			||||||
 | 
					const fn table_fn(i: u32) -> u32 { | 
				
			||||||
 | 
					    let mut out = i; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					    out = if out & 1 == 1 { 0xedb88320 ^ (out >> 1) } else { out >> 1 }; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    out | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// A `const fn` crc32 checksum implementation.
 | 
				
			||||||
 | 
					///
 | 
				
			||||||
 | 
					/// Note: this is a naive implementation that should be expected to have poor performance
 | 
				
			||||||
 | 
					/// if used on dynamic data at runtime. Usage should generally be restricted to declaring
 | 
				
			||||||
 | 
					/// `const` variables based on `static` or `const` data available at build time.
 | 
				
			||||||
 | 
					pub const fn crc32(buf: &[u8]) -> u32 { | 
				
			||||||
 | 
					    let mut out = !0u32; | 
				
			||||||
 | 
					    let mut i = 0; | 
				
			||||||
 | 
					    loop { | 
				
			||||||
 | 
					        if i >= buf.len() { break } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        out = (out >> 8) ^ table_fn((out & 0xff) ^ (buf[i] as u32)); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        i += 1; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    !out | 
				
			||||||
 | 
					} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[cfg(test)] | 
				
			||||||
 | 
					mod tests { | 
				
			||||||
 | 
					    use super::*; | 
				
			||||||
 | 
					    use rand::prelude::*; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn crc32_compute_table() -> [u32; 256] { | 
				
			||||||
 | 
					        let mut crc32_table = [0; 256]; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for n in 0..256 { | 
				
			||||||
 | 
					            crc32_table[n as usize] = (0..8).fold(n as u32, |acc, _| { | 
				
			||||||
 | 
					                match acc & 1 { | 
				
			||||||
 | 
					                    1 => 0xedb88320 ^ (acc >> 1), | 
				
			||||||
 | 
					                    _ => acc >> 1, | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            }); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        crc32_table | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test] | 
				
			||||||
 | 
					    fn check_table_fn_against_example_code() { | 
				
			||||||
 | 
					        let table = crc32_compute_table(); | 
				
			||||||
 | 
					        for i in 0..256{ | 
				
			||||||
 | 
					            assert_eq!(table[i], table_fn(i as u32)); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test] | 
				
			||||||
 | 
					    fn simple_test() { | 
				
			||||||
 | 
					        const BYTES: &[u8] = "The quick brown fox jumps over the lazy dog".as_bytes(); | 
				
			||||||
 | 
					        assert_eq!(crc32(BYTES), 0x414fa339_u32); | 
				
			||||||
 | 
					        assert_eq!(crc32(BYTES), crc32fast::hash(BYTES)); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test] | 
				
			||||||
 | 
					    fn check_random_inputs_against_crc32_fast() { | 
				
			||||||
 | 
					        const N_ITER: usize = 100; | 
				
			||||||
 | 
					        const BUFSIZE: usize = 4096; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut buf = [0u8; BUFSIZE]; | 
				
			||||||
 | 
					        let mut rng = thread_rng(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for _ in 0..N_ITER { | 
				
			||||||
 | 
					            rng.fill(&mut buf[..]); | 
				
			||||||
 | 
					            assert_eq!(crc32(&buf[..]), crc32fast::hash(&buf[..])); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
					Loading…
					
					
				
		Reference in new issue