pub const EMOJI: [&str; 64] = [
"๐ต", "๐ถ", "๐บ", "๐ฆ", "๐ฑ", "๐ฆ", "๐ฏ", "๐ด", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฎ", "๐ท", "๐", "๐ญ", "๐น",
"๐ฐ", "๐ป", "๐ผ", "๐จ", "๐ธ", "๐ฒ", "๐", "๐ง", "๐ฆ", "๐ฆ
", "๐ฆ", "๐ฆ", "๐ข", "๐", "๐ฆ", "๐",
"๐ณ", "๐ฌ", "๐", "๐ ", "๐ก", "๐ฆ", "๐", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐ฆ", "๐", "๐", "๐", "๐",
"๐ฆ", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐", "๐ฅ", "๐", "๐ฅฅ", "๐ฅ", "๐ฝ",
];
pub const LABELS: [&str; 64] = [
"monkey",
"dog",
"wolf",
"fox",
"cat",
"lion",
"tiger",
"horse",
"unicorn",
"zebra",
"deer",
"cow",
"pig",
"boar",
"mouse",
"hamster",
"rabbit",
"bear",
"panda",
"koala",
"frog",
"dragon",
"chicken",
"penguin",
"duck",
"eagle",
"owl",
"bat",
"turtle",
"snake",
"lizard",
"crocodile",
"whale",
"dolphin",
"fish",
"tropical-fish",
"blowfish",
"shark",
"octopus",
"squid",
"crab",
"lobster",
"shrimp",
"butterfly",
"snail",
"lady-beetle",
"bee",
"ant",
"scorpion",
"apple",
"pear",
"orange",
"lemon",
"banana",
"watermelon",
"grapes",
"strawberry",
"cherries",
"pineapple",
"kiwi",
"peach",
"coconut",
"carrot",
"corn",
];
pub const ALPHABET_SIZE: usize = 64;
pub fn emoji_indices(data: &[u8], length: usize) -> Vec<usize> {
let wanted = length.max(1);
let nbytes = (wanted * 6).div_ceil(8);
let mut digest = vec![0u8; nbytes];
blake3::Hasher::new()
.update(data)
.finalize_xof()
.fill(&mut digest);
let mut out = Vec::with_capacity(wanted);
let mut acc: u64 = 0;
let mut bits: u32 = 0;
for byte in digest {
acc = (acc << 8) | u64::from(byte);
bits += 8;
while bits >= 6 && out.len() < wanted {
bits -= 6;
out.push(((acc >> bits) & 0x3f) as usize);
}
acc &= (1u64 << bits) - 1; }
out.truncate(wanted);
out
}
pub fn emojihash(data: &[u8], length: usize) -> String {
emoji_indices(data, length)
.into_iter()
.map(|i| EMOJI[i])
.collect::<Vec<_>>()
.join(" ")
}
pub fn emojihash_labels(data: &[u8], length: usize) -> String {
emoji_indices(data, length)
.into_iter()
.map(|i| LABELS[i])
.collect::<Vec<_>>()
.join(" ")
}