statsig_rust/hashing/
hash_util.rs1use serde::{de::Error, Deserialize, Deserializer};
2
3use super::{djb2::djb2, memo_sha_256::MemoSha256};
4use std::fmt::Display;
5
6#[derive(Eq, PartialEq)]
7pub enum HashAlgorithm {
8 Djb2,
9 None,
10 Sha256,
11}
12
13impl HashAlgorithm {
14 #[must_use]
15 pub fn from_string(input: &str) -> Option<Self> {
16 match input {
17 "sha256" | "SHA256" | "Sha256" => Some(HashAlgorithm::Sha256),
18 "djb2" | "DJB2" | "Djb2" => Some(HashAlgorithm::Djb2),
19 "none" | "NONE" | "None" => Some(HashAlgorithm::None),
20 _ => None,
21 }
22 }
23}
24
25impl<'de> Deserialize<'de> for HashAlgorithm {
26 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
27 where
28 D: Deserializer<'de>,
29 {
30 let s = String::deserialize(deserializer)?;
31 HashAlgorithm::from_string(&s).ok_or_else(|| D::Error::custom("Invalid hash algorithm"))
32 }
33}
34
35impl Display for HashAlgorithm {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 match self {
38 HashAlgorithm::Djb2 => write!(f, "djb2"),
39 HashAlgorithm::None => write!(f, "none"),
40 HashAlgorithm::Sha256 => write!(f, "sha256"),
41 }
42 }
43}
44
45pub struct HashUtil {
46 sha_hasher: MemoSha256,
47}
48
49impl Default for HashUtil {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl HashUtil {
56 #[must_use]
57 pub fn new() -> Self {
58 Self {
59 sha_hasher: MemoSha256::new(),
60 }
61 }
62
63 pub fn hash(&self, input: &str, hash_algorithm: &HashAlgorithm) -> String {
64 match hash_algorithm {
65 HashAlgorithm::Sha256 => self.sha_hasher.hash_string(input),
66 HashAlgorithm::Djb2 => djb2(input),
67 HashAlgorithm::None => input.to_string(),
68 }
69 }
70
71 pub fn sha256(&self, input: &str) -> String {
72 self.sha_hasher.hash_string(input)
73 }
74
75 pub fn sha256_to_u64(&self, input: &str) -> u64 {
76 let hash = self.sha_hasher.hash_string(input);
77
78 let mut hasher_bytes = [0u8; 8];
79 hasher_bytes.copy_from_slice(&hash.as_bytes()[0..8]);
80
81 u64::from_be_bytes(hasher_bytes)
82 }
83
84 pub fn evaluation_hash(&self, input: &String) -> Option<u64> {
85 self.sha_hasher.compute_hash(input)
86 }
87}