use crate::error::{PicanteError, PicanteResult};
use facet::Facet;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::sync::Arc;
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct QueryKindId(pub u32);
impl QueryKindId {
pub const fn as_u32(self) -> u32 {
self.0
}
pub const fn from_str(s: &str) -> Self {
let bytes = s.as_bytes();
let mut hash: u32 = 0x811c9dc5; let mut i = 0usize;
while i < bytes.len() {
hash ^= bytes[i] as u32;
hash = hash.wrapping_mul(0x0100_0193); i += 1;
}
QueryKindId(hash)
}
}
#[derive(Clone)]
pub struct Key {
bytes: Arc<[u8]>,
hash: u64,
}
impl Key {
pub fn encode_facet<T: Facet<'static>>(value: &T) -> PicanteResult<Self> {
let bytes = facet_postcard::to_vec(value).map_err(|e| {
Arc::new(PicanteError::Encode {
what: "key",
message: format!("{e:?}"),
})
})?;
Ok(Self::from_bytes(bytes))
}
pub fn decode_facet<T: Facet<'static>>(&self) -> PicanteResult<T> {
facet_postcard::from_slice(self.bytes()).map_err(|e| {
Arc::new(PicanteError::Decode {
what: "key",
message: format!("{e:?}"),
})
})
}
pub fn from_bytes(bytes: Vec<u8>) -> Self {
let hash = stable_hash(&bytes);
Self {
bytes: bytes.into(),
hash,
}
}
pub fn bytes(&self) -> &[u8] {
&self.bytes
}
pub fn hash(&self) -> u64 {
self.hash
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn is_empty(&self) -> bool {
self.bytes.is_empty()
}
}
impl PartialEq for Key {
fn eq(&self, other: &Self) -> bool {
self.bytes == other.bytes
}
}
impl Eq for Key {}
impl Hash for Key {
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.hash);
}
}
impl fmt::Debug for Key {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Key")
.field("hash", &format_args!("{:016x}", self.hash))
.field("len", &self.bytes.len())
.finish()
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct DynKey {
pub kind: QueryKindId,
pub key: Key,
}
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct Dep {
pub kind: QueryKindId,
pub key: Key,
}
fn stable_hash(bytes: &[u8]) -> u64 {
let mut hasher = std::collections::hash_map::DefaultHasher::new();
bytes.hash(&mut hasher);
hasher.finish()
}