use std::num::NonZeroU128;
use allocative::Allocative;
use dupe::Dupe;
#[derive(
Allocative,
Debug,
Eq,
PartialEq,
Clone,
Dupe,
Copy,
Hash,
bytemuck::NoUninit,
bytemuck::AnyBitPattern
)]
#[repr(transparent)]
pub struct DataKey(pub u128);
static_assertions::assert_eq_size!(DataKey, OptionalDataKey);
impl DataKey {
pub(crate) fn compute(arcs: usize, data: &[u8], more_data: &[u8]) -> Self {
let mut hasher = blake3::Hasher::new();
hasher.update(&arcs.to_le_bytes());
hasher.update(data);
hasher.update(more_data);
let hash = hasher.finalize();
let hash_bytes = hash.as_bytes();
let value = u128::from_le_bytes(hash_bytes[..16].try_into().unwrap());
if value == 0 {
return Self(1);
}
Self(value)
}
}
#[derive(Debug, Clone, Copy, Hash, Allocative)]
pub enum OptionalDataKey {
None,
Some(#[allocative(skip)] NonZeroU128),
}
impl OptionalDataKey {
pub fn unwrap(&self) -> DataKey {
match self {
Self::Some(nz) => DataKey(nz.get()),
Self::None => panic!("unwrap called on None"),
}
}
pub fn is_some(&self) -> bool {
matches!(self, Self::Some(_))
}
pub fn is_none(&self) -> bool {
matches!(self, Self::None)
}
}
impl From<DataKey> for OptionalDataKey {
fn from(key: DataKey) -> Self {
Self::Some(NonZeroU128::new(key.0).expect("DataKey should never be zero"))
}
}
pub struct PagableData {
pub data: Vec<u8>,
pub arcs: Vec<DataKey>,
}
impl PagableData {
pub(crate) fn compute_key(&self) -> DataKey {
DataKey::compute(
self.arcs.len(),
&self.data,
bytemuck::cast_slice(&self.arcs),
)
}
}