use xxhash_rust::const_xxh32::xxh32;
const XXH32_SEED: u32 = 0;
pub type Key = u32;
pub struct KeyComposer;
impl KeyComposer {
pub const fn concat(left: Key, right: Key) -> Key {
match (left, right) {
(0, 0) => 0,
(0, _) => right,
(_, 0) => left,
(left, right) => xxh32(&(left ^ right).to_be_bytes(), XXH32_SEED),
}
}
pub const fn from_str(str: &str) -> Key {
Self::from_bytes(str.as_bytes())
}
pub const fn from_bytes(bytes: &[u8]) -> Key {
if bytes.is_empty() {
return 0
}
xxh32(bytes, XXH32_SEED)
}
pub fn compute_key(
struct_name: &str,
variant_name: &str,
field_name: &str,
) -> Result<Key, Error> {
if struct_name.is_empty() {
return Err(Error::StructNameIsEmpty)
}
if field_name.is_empty() {
return Err(Error::FieldNameIsEmpty)
}
let separator = &b"::"[..];
let composed_key = if !variant_name.is_empty() {
[
struct_name.as_bytes(),
variant_name.as_bytes(),
field_name.as_bytes(),
]
.join(separator)
} else {
[struct_name.as_bytes(), field_name.as_bytes()].join(separator)
};
Ok(Self::from_bytes(composed_key.as_slice()))
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum Error {
StructNameIsEmpty,
FieldNameIsEmpty,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn concat_works_correct() {
assert_eq!(KeyComposer::concat(0, 13), 13);
assert_eq!(KeyComposer::concat(31, 0), 31);
assert_eq!(KeyComposer::concat(31, 13), 0x9ab19a67);
assert_eq!(KeyComposer::concat(0, 0), 0);
}
#[test]
fn from_str_works_correct() {
assert_eq!(KeyComposer::from_str(""), 0);
assert_eq!(KeyComposer::from_str("123"), 0xb6855437);
assert_eq!(KeyComposer::from_str("Hello world"), 0x9705d437);
}
#[test]
fn from_bytes_works_correct() {
assert_eq!(KeyComposer::from_bytes(b""), 0);
assert_eq!(KeyComposer::from_bytes(b"123"), 0xb6855437);
assert_eq!(KeyComposer::from_bytes(b"Hello world"), 0x9705d437);
}
#[test]
fn compute_key_works_correct() {
assert_eq!(
KeyComposer::compute_key("Contract", "", "balances"),
Ok(0xf820ff02)
);
assert_eq!(
KeyComposer::compute_key("Enum", "Variant", "0"),
Ok(0x14786b51)
);
assert_eq!(
KeyComposer::compute_key("", "Variant", "0"),
Err(Error::StructNameIsEmpty)
);
assert_eq!(
KeyComposer::compute_key("Enum", "Variant", ""),
Err(Error::FieldNameIsEmpty)
);
}
}