use mountpoint_s3_crt_sys::aws_checksums_crc32;
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub struct Crc32(u32);
impl Crc32 {
pub fn new(value: u32) -> Crc32 {
Crc32(value)
}
}
pub fn checksum(buf: &[u8]) -> Crc32 {
let mut hasher = Hasher::new();
hasher.update(buf);
hasher.finalize()
}
#[derive(Debug, Clone)]
pub struct Hasher {
state: Crc32,
}
impl Hasher {
pub fn new() -> Self {
Self { state: Crc32(0) }
}
pub fn update(&mut self, buf: &[u8]) {
self.state = Hasher::crc32(buf, self.state);
}
pub fn finalize(self) -> Crc32 {
self.state
}
fn crc32(buf: &[u8], previous_checksum: Crc32) -> Crc32 {
assert!(buf.len() <= i32::MAX as usize);
let checksum = unsafe { aws_checksums_crc32(buf.as_ptr(), buf.len() as i32, previous_checksum.0) };
Crc32(checksum)
}
}
impl Default for Hasher {
fn default() -> Self {
Self::new()
}
}
impl std::hash::Hasher for Hasher {
fn finish(&self) -> u64 {
self.clone().finalize().0.into()
}
fn write(&mut self, bytes: &[u8]) {
self.update(bytes);
}
}
#[cfg(test)]
mod tests {
use crate::checksums::crc32::{self, Crc32};
#[test]
fn crc32_simple() {
let buf: &[u8] = b"123456789";
let crc = crc32::checksum(buf);
assert_eq!(crc, Crc32(0xcbf43926));
}
#[test]
fn crc32_append() {
let mut hasher = crc32::Hasher::new();
hasher.update(b"1234");
hasher.update(b"56789");
let crc = hasher.finalize();
assert_eq!(crc, Crc32(0xcbf43926));
}
}