use base_encode::to_string;
use xxhash_rust::xxh3::xxh3_128;
use crate::base64::to_url_safe_base64;
pub fn xxhash_base64_url(input: &[u8]) -> String {
let hash = xxh3_128(input).to_le_bytes();
to_url_safe_base64(hash)
}
const CHARACTERS_BASE64: &[u8] =
b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
const CHARACTERS_BASE16: &[u8] = b"0123456789abcdef";
#[inline]
pub fn xxhash_with_base(input: &[u8], base: u8) -> String {
encode_hash_with_base(&xxh3_128(input).to_le_bytes(), base)
}
pub fn encode_hash_with_base(hash: &[u8; 16], base: u8) -> String {
let chars = match base {
64 => CHARACTERS_BASE64,
36 => &CHARACTERS_BASE64[26..(26 + 36)],
16 => CHARACTERS_BASE16,
_ => {
unreachable!()
}
};
let result = to_string(hash, base, chars).unwrap();
let pad_len = 21usize.saturating_sub(result.len());
if pad_len > 0 {
let mut padded = String::with_capacity(21);
padded.extend(std::iter::repeat_n(chars[0] as char, pad_len));
padded.push_str(&result);
padded
} else {
result
}
}
#[test]
fn test_xxhash_with_base() {
assert_eq!(&xxhash_with_base(b"hello", 64), "YOFJeqs95x38-Gwetwem1");
assert_eq!(&xxhash_with_base(b"hello", 36), "bpwli5k6mqm0gij09mxrh9npj");
assert_eq!(&xxhash_with_base(b"hello", 16), "1838525eaacf79c77f3e1b07adc1e9b5");
}
#[test]
fn test_encode_hash_with_base_padding() {
let input = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1u8];
let raw = to_string(&input, 64, CHARACTERS_BASE64).unwrap();
assert_eq!(raw.len(), 16);
let hash = encode_hash_with_base(&input, 64);
assert_eq!(hash.len(), 21);
}