mrhooray / crc-rs

Rust implementation of CRC(16, 32, 64) with support of various standards
Apache License 2.0
187 stars 49 forks source link

Add a const fn version of digest update #70

Open benhall-7 opened 2 years ago

benhall-7 commented 2 years ago

So for context, I'm working on a library for a special type of hash which involves a CRC32, but the implementation takes every character and makes it lowercase (ascii_lowercase) before it's hashed. Since this is a const fn, I'm not able to create a new allocations for the lowercased version. I've tried const generics, but that requires always knowing the input length at compile time, which is too restrictive. I've found a way to do this, by adding a const fn version of the update function in Digest, which I've implemented in this PR. Here's an example using it:

pub struct Hash40(pub u64);

pub const fn new(string: &str) -> Hash40 {
    let bytes = string.as_bytes();
    let algo = Crc::<u32>::new(&CRC_32_CKSUM);
    let mut digest = algo.digest();
    let mut index = 0;
    while index < string.len() {
        digest = digest.updated(&[bytes[index]]);
        index += 1;
    }
    let crc = digest.finalize() as u64;
    let length_byte = (string.len() as u8 as u64) << 32;
    Hash40(crc | length_byte)
}

This is kind of an undesirable way to calculate the hash anyway, so if we can find some other way to write this, that would be cool too

akhilles commented 2 years ago

Is there a reason why we can't make the existing update function const?

benhall-7 commented 2 years ago

Is there a reason why we can't make the existing update function const?

This is because Rust doesn't allow &mut in const fn functions yet. The tracking issue for it is here: https://github.com/rust-lang/rust/issues/57349

akhilles commented 1 year ago

Sorry for the delayed response, but wdyt about making Crc::update public instead? Seems like exposing a single low-level API would address a lot of the edge cases without overburdening the high-level APIs.

EDIT: Actually, just update wouldn't be enough, finalize would also have to be exposed.