initial commit
This commit is contained in:
commit
0d02e98749
|
@ -0,0 +1,3 @@
|
|||
/target
|
||||
/Cargo.lock
|
||||
*.swp
|
|
@ -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