From a61676c80d41440771211397a662a7db2b43c2f9 Mon Sep 17 00:00:00 2001 From: Don MacAskill Date: Mon, 11 Aug 2025 22:27:56 -0700 Subject: [PATCH 1/2] Add state flexbiliity Enables retrieving the current state, and starting a new Digest with a starting initial state. This enables more hashing workloads, including across operations. --- libcrc_fast.h | 11 ++++++++ src/ffi.rs | 23 +++++++++++++++++ src/lib.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) diff --git a/libcrc_fast.h b/libcrc_fast.h index f720caa..918e8d6 100644 --- a/libcrc_fast.h +++ b/libcrc_fast.h @@ -77,6 +77,12 @@ extern "C" { */ struct CrcFastDigestHandle *crc_fast_digest_new(enum CrcFastAlgorithm algorithm); +/** + * Creates a new Digest with a custom initial state + */ +struct CrcFastDigestHandle *crc_fast_digest_new_with_init_state(enum CrcFastAlgorithm algorithm, + uint64_t init_state); + /** * Creates a new Digest to compute CRC checksums using custom parameters */ @@ -118,6 +124,11 @@ void crc_fast_digest_combine(struct CrcFastDigestHandle *handle1, */ uint64_t crc_fast_digest_get_amount(struct CrcFastDigestHandle *handle); +/** + * Gets the current state of the Digest + */ +uint64_t crc_fast_digest_get_state(struct CrcFastDigestHandle *handle); + /** * Helper method to calculate a CRC checksum directly for a string using algorithm */ diff --git a/src/ffi.rs b/src/ffi.rs index 9299d1d..611a2f4 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -219,6 +219,17 @@ pub extern "C" fn crc_fast_digest_new(algorithm: CrcFastAlgorithm) -> *mut CrcFa Box::into_raw(handle) } +/// Creates a new Digest with a custom initial state +#[no_mangle] +pub extern "C" fn crc_fast_digest_new_with_init_state( + algorithm: CrcFastAlgorithm, + init_state: u64, +) -> *mut CrcFastDigestHandle { + let digest = Box::new(Digest::new_with_init_state(algorithm.into(), init_state)); + let handle = Box::new(CrcFastDigestHandle(Box::into_raw(digest))); + Box::into_raw(handle) +} + /// Creates a new Digest to compute CRC checksums using custom parameters #[no_mangle] pub extern "C" fn crc_fast_digest_new_with_params( @@ -333,6 +344,18 @@ pub extern "C" fn crc_fast_digest_get_amount(handle: *mut CrcFastDigestHandle) - } } +/// Gets the current state of the Digest +#[no_mangle] +pub extern "C" fn crc_fast_digest_get_state(handle: *mut CrcFastDigestHandle) -> u64 { + if handle.is_null() { + return 0; + } + unsafe { + let digest = &*(*handle).0; + digest.get_state() + } +} + /// Helper method to calculate a CRC checksum directly for a string using algorithm #[no_mangle] pub extern "C" fn crc_fast_checksum( diff --git a/src/lib.rs b/src/lib.rs index 4dfb283..3d53e69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -376,6 +376,18 @@ impl DynDigest for Digest { impl Digest { /// Creates a new `Digest` instance for the specified CRC algorithm. + /// + /// # Examples + /// + /// ```rust + /// use crc_fast::{Digest, CrcAlgorithm::Crc32IsoHdlc}; + /// + /// let mut digest = Digest::new(Crc32IsoHdlc); + /// digest.update(b"123456789"); + /// let checksum = digest.finalize(); + /// + /// assert_eq!(checksum, 0xcbf43926); + /// ``` #[inline(always)] pub fn new(algorithm: CrcAlgorithm) -> Self { let (calculator, params) = get_calculator_params(algorithm); @@ -388,6 +400,42 @@ impl Digest { } } + /// Creates a new `Digest` instance for the specified CRC algorithm with a custom initial state. + /// + /// # Examples + /// + /// ```rust + /// use crc_fast::{Digest, CrcAlgorithm::Crc32IsoHdlc}; + /// + /// // CRC-32/ISO-HDLC with initial state of 0x00000000, instead of the default initial state + /// // of 0xffffffff, + /// let mut digest = Digest::new_with_init_state(Crc32IsoHdlc, 0x00000000); + /// digest.update(b"123456789"); + /// let checksum = digest.finalize(); + /// + /// // different initial state, so checksum will be different + /// assert_eq!(checksum, 0xd202d277); + /// + /// let mut digest = Digest::new_with_init_state(Crc32IsoHdlc, 0xffffffff); + /// digest.update(b"123456789"); + /// let checksum = digest.finalize(); + /// + /// // same initial state as the default, so checksum will be the same + /// assert_eq!(checksum, 0xcbf43926); + /// ``` + #[inline(always)] + pub fn new_with_init_state(algorithm: CrcAlgorithm, init_state: u64) -> Self { + let (calculator, params) = get_calculator_params(algorithm); + + Self { + state: init_state, + amount: 0, + params, + calculator, + } + } + + /// Creates a new `Digest` instance with custom CRC parameters. /// /// # Examples @@ -474,6 +522,27 @@ impl Digest { pub fn get_amount(&self) -> u64 { self.amount } + + /// Gets the current CRC state. + /// + /// # Examples + /// ```rust + /// use crc_fast::{Digest, CrcAlgorithm::Crc32IsoHdlc}; + /// + /// let mut digest = Digest::new(Crc32IsoHdlc); + /// digest.update(b"123456789"); + /// let state = digest.get_state(); + /// + /// // non-finalized state, so it won't match the final checksum + /// assert_eq!(state, 0x340bc6d9); + /// + /// // finalized state will match the checksum + /// assert_eq!(digest.finalize(), 0xcbf43926); + /// ``` + #[inline(always)] + pub fn get_state(&self) -> u64 { + self.state + } } impl Write for Digest { From 02febc8eb602f587718c9a0ebe40da257b0489ad Mon Sep 17 00:00:00 2001 From: Don MacAskill Date: Mon, 1 Sep 2025 10:25:06 -0700 Subject: [PATCH 2/2] Fix formatting --- src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3d53e69..21c4935 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,7 +435,6 @@ impl Digest { } } - /// Creates a new `Digest` instance with custom CRC parameters. /// /// # Examples