use h3o::{CellIndex, Resolution};
const SIZE: usize = 16;
#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Key([u8; SIZE]);
impl Key {
#[expect(clippy::cast_possible_truncation, reason = "len is in [0; 15]")]
const fn len(self) -> u8 {
(15 - (u128::from_be_bytes(self.0).trailing_ones() / 8)) as u8
}
}
impl From<CellIndex> for Key {
fn from(value: CellIndex) -> Self {
let mut key = [0xff; SIZE];
key[0] = value.base_cell().into();
for res in Resolution::range(Resolution::One, value.resolution()) {
key[res as usize] =
value.direction_at(res).expect("resolution in range").into();
}
Self(key)
}
}
impl AsRef<[u8]> for Key {
fn as_ref(&self) -> &[u8] {
&self.0[..=usize::from(self.len())]
}
}
impl From<Key> for CellIndex {
#[expect(
clippy::cast_possible_truncation,
reason = "resolution is in [0; 15]"
)]
fn from(value: Key) -> Self {
let res = value.len();
let key = value.0;
let mut index = 0x8001fffffffffff;
index |= u64::from(res) << 52;
index |= u64::from(key[0]) << 45;
for (i, direction) in key[1..=usize::from(res)].iter().enumerate() {
let direction = u64::from(*direction);
let resolution = (i + 1) as u8;
let offset = (15 - resolution) * 3;
index = (index & !(0b111 << offset)) | (direction << offset);
}
Self::try_from(index).expect("valid cell index")
}
}
impl From<&[u8]> for Key {
fn from(value: &[u8]) -> Self {
let mut key = [0xff; SIZE];
let len = std::cmp::min(SIZE, value.len());
key[..len].copy_from_slice(&value[..len]);
Self(key)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from() {
let index = CellIndex::try_from(0x8f2a1072b598641).expect("valid cell");
let key = Key::from(index);
assert_eq!(index, CellIndex::from(key));
}
}