Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove custom error type #7

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use std::hash::Hasher;

fn main() {
// Method 1: Direct hashing
let hash = chibi_hash64(b"yellow world", 42).expect("Failed to hash");
let hash = chibi_hash64(b"yellow world", 42);
println!("Direct hash: {:016x}", hash);

// Method 2: Using Hasher trait
Expand Down
77 changes: 13 additions & 64 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,18 @@
//! // Direct hashing
//! let key = b"Hello, World!";
//! let seed = 1337;
//! let hash = chibi_hash64(key, seed).unwrap_or(0);
//! let hash = chibi_hash64(key, seed);
//! println!("Hash of '{}' is: {:016x}", String::from_utf8_lossy(key), hash);
//!
//! // Using the Hasher trait
//! let mut hasher = ChibiHasher::new(seed);
//! hasher.write(key);
//! println!("{:016x}", hasher.finish());
//! ```
//!
//! # Safety and Performance
//!
//! This implementation is safe for inputs up to `usize::MAX / 2` bytes in length.
//! Attempting to hash larger inputs will result in an error.

use std::hash::{Hash, Hasher};

pub fn chibi_hash64(key: &[u8], seed: u64) -> Result<u64, ChibiHashError> {
pub fn chibi_hash64(key: &[u8], seed: u64) -> u64 {
const P1: u64 = 0x2B7E151628AED2A5;
const P2: u64 = 0x9E3793492EEDC3F7;
const P3: u64 = 0x3243F6A8885A308D;
Expand All @@ -38,13 +33,6 @@ pub fn chibi_hash64(key: &[u8], seed: u64) -> Result<u64, ChibiHashError> {
let len = key.len();
let mut k = key;

if key.len() > usize::MAX / 2 {
return Err(ChibiHashError::InputTooLarge {
size: key.len(),
max_supported: usize::MAX / 2,
});
}

// Process 32-byte chunks
while k.len() >= 32 {
for i in 0..4 {
Expand Down Expand Up @@ -101,46 +89,14 @@ pub fn chibi_hash64(key: &[u8], seed: u64) -> Result<u64, ChibiHashError> {
x = x.wrapping_mul(0x1C69B3F74AC4AE35);
x ^= x >> 27;

Ok(x)
x
}

#[inline(always)]
fn load_u64_le(bytes: &[u8]) -> u64 {
u64::from_le_bytes(bytes[..8].try_into().unwrap())
}

/// Error type for hash computation failures
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ChibiHashError {
/// Input is too large to hash safely
InputTooLarge {
/// Size of the input that caused the error
size: usize,
/// Maximum safe size for input
max_supported: usize,
},
}

impl std::fmt::Display for ChibiHashError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InputTooLarge {
size,
max_supported,
} => {
write!(
f,
"Input size {} exceeds maximum supported size {}",
size, max_supported
)
}
}
}
}

impl std::error::Error for ChibiHashError {}

/// Configuration for the hash function
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ChibiHasher {
Expand All @@ -156,16 +112,15 @@ impl ChibiHasher {
}
}

pub fn hash(&self, input: &[u8]) -> Result<u64, ChibiHashError> {
pub fn hash(&self, input: &[u8]) -> u64 {
chibi_hash64(input, self.seed)
}
}

impl Hasher for ChibiHasher {
fn finish(&self) -> u64 {
// Hash the accumulated bytes with our chibi_hash64 function
// If there's an error, fall back to a simple value
chibi_hash64(&self.buffer, self.seed).unwrap_or(self.seed)
chibi_hash64(&self.buffer, self.seed)
}

fn write(&mut self, bytes: &[u8]) {
Expand Down Expand Up @@ -196,24 +151,18 @@ mod tests {
// Tested against a Github comment from the original ChibiHash author
// See https://github.com/N-R-K/ChibiHash/issues/1#issuecomment-2486086163
fn test_real_world_examples() {
assert_eq!(chibi_hash64(b"", 0).unwrap_or(0), 0x9EA80F3B18E26CFB);
assert_eq!(chibi_hash64(b"", 55555).unwrap_or(0), 0x2EED9399FC4AC7E5);
assert_eq!(chibi_hash64(b"hi", 0).unwrap_or(0), 0xAF98F3924F5C80D6);
assert_eq!(chibi_hash64(b"123", 0).unwrap_or(0), 0x893A5CCA05B0A883);
assert_eq!(
chibi_hash64(b"abcdefgh", 0).unwrap_or(0),
0x8F922660063E3E75
);
assert_eq!(
chibi_hash64(b"Hello, world!", 0).unwrap_or(0),
0x5AF920D8C0EBFE9F
);
assert_eq!(chibi_hash64(b"", 0), 0x9EA80F3B18E26CFB);
assert_eq!(chibi_hash64(b"", 55555), 0x2EED9399FC4AC7E5);
assert_eq!(chibi_hash64(b"hi", 0), 0xAF98F3924F5C80D6);
assert_eq!(chibi_hash64(b"123", 0), 0x893A5CCA05B0A883);
assert_eq!(chibi_hash64(b"abcdefgh", 0), 0x8F922660063E3E75);
assert_eq!(chibi_hash64(b"Hello, world!", 0), 0x5AF920D8C0EBFE9F);
assert_eq!(
chibi_hash64(b"qwertyuiopasdfghjklzxcvbnm123456", 0).unwrap_or(0),
chibi_hash64(b"qwertyuiopasdfghjklzxcvbnm123456", 0),
0x2EF296DB634F6551
);
assert_eq!(
chibi_hash64(b"qwertyuiopasdfghjklzxcvbnm123456789", 0).unwrap_or(0),
chibi_hash64(b"qwertyuiopasdfghjklzxcvbnm123456789", 0),
0x0F56CF3735FFA943
);
}
Expand Down
7 changes: 3 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use chibihash::{chibi_hash64, ChibiHashError, ChibiHasher};
use chibihash::{chibi_hash64, ChibiHasher};
use std::hash::Hasher;

fn main() -> Result<(), ChibiHashError> {
fn main() {
let key = b"Hello, World!";
let seed = 1337;
let hash = chibi_hash64(key, seed)?;
let hash = chibi_hash64(key, seed);
println!(
"Hash of '{}' is: {:016x}",
String::from_utf8_lossy(key),
Expand All @@ -14,5 +14,4 @@ fn main() -> Result<(), ChibiHashError> {
let mut hasher = ChibiHasher::new(seed);
hasher.write(key);
println!("{:016x}", hasher.finish());
Ok(())
}