use std::borrow::Borrow;
use crate::func::shard_edge::ShardEdge;
use crate::traits::bit_field_slice::*;
use crate::utils::*;
use crate::{bits::BitFieldVec, func::VFunc};
use mem_dbg::*;
use num_primitive::PrimitiveNumber;
use value_traits::slices::SliceByValue;
#[derive(Debug, MemDbg, MemSize)]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SignedVFunc<F, H: SliceByValue> {
pub(crate) func: F,
pub(crate) hashes: H,
}
impl<
T: ?Sized + ToSig<S>,
W: Word + BinSafe,
D: SliceByValue<Value = W>,
S: Sig,
E: ShardEdge<S, 3>,
H: SliceByValue,
> SignedVFunc<VFunc<T, W, D, S, E>, H>
where
H::Value: PrimitiveNumber,
{
#[inline]
pub fn get_by_sig(&self, sig: S) -> Option<W> {
const {
assert!(
size_of::<H::Value>() <= size_of::<u64>(),
"Hash value type must fit in u64 without truncation"
);
}
let index = self.func.get_by_sig(sig);
let shard_edge = &self.func.shard_edge;
if self
.hashes
.get_value(index.as_to::<usize>())?
.as_to::<u64>()
== crate::func::mix64(shard_edge.edge_hash(shard_edge.local_sig(sig)))
{
Some(index)
} else {
None
}
}
#[inline(always)]
pub fn get(&self, key: impl Borrow<T>) -> Option<W> {
self.get_by_sig(T::to_sig(key.borrow(), self.func.seed))
}
pub const fn len(&self) -> usize {
self.func.num_keys
}
pub const fn is_empty(&self) -> bool {
self.func.num_keys == 0
}
}
#[derive(Debug, MemDbg, MemSize)]
#[cfg_attr(feature = "epserde", derive(epserde::Epserde))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BitSignedVFunc<F, H: SliceByValue> {
pub(crate) func: F,
pub(crate) hashes: H,
pub(crate) hash_mask: u64,
}
impl<
T: ?Sized + ToSig<S>,
W: Word + BinSafe,
D: SliceByValue<Value = W>,
S: Sig,
E: ShardEdge<S, 3>,
H: SliceByValue,
> BitSignedVFunc<VFunc<T, W, D, S, E>, H>
where
H::Value: PrimitiveNumber,
{
#[inline]
pub fn get_by_sig(&self, sig: S) -> Option<W> {
const {
assert!(
size_of::<H::Value>() <= size_of::<u64>(),
"Hash value type must fit in u64 without truncation"
);
}
let index = self.func.get_by_sig(sig);
let shard_edge = &self.func.shard_edge;
if self
.hashes
.get_value(index.as_to::<usize>())?
.as_to::<u64>()
== (crate::func::mix64(shard_edge.edge_hash(shard_edge.local_sig(sig)))
& self.hash_mask)
{
Some(index)
} else {
None
}
}
#[inline(always)]
pub fn get(&self, key: impl Borrow<T>) -> Option<W> {
self.get_by_sig(T::to_sig(key.borrow(), self.func.seed))
}
pub const fn len(&self) -> usize {
self.func.num_keys
}
pub const fn is_empty(&self) -> bool {
self.func.num_keys == 0
}
}
impl<T: ?Sized + ToSig<S>, W: Word + BinSafe, S: Sig, E: ShardEdge<S, 3>, H: SliceByValue>
BitSignedVFunc<VFunc<T, W, BitFieldVec<W>, S, E>, H>
where
H::Value: PrimitiveNumber,
{
#[inline]
pub fn get_by_sig_unaligned(&self, sig: S) -> Option<W> {
const {
assert!(
size_of::<H::Value>() <= size_of::<u64>(),
"Hash value type must fit in u64 without truncation"
);
}
let index = self.func.get_by_sig_unaligned(sig);
let shard_edge = &self.func.shard_edge;
if self
.hashes
.get_value(index.as_to::<usize>())?
.as_to::<u64>()
== (crate::func::mix64(shard_edge.edge_hash(shard_edge.local_sig(sig)))
& self.hash_mask)
{
Some(index)
} else {
None
}
}
#[inline(always)]
pub fn get_unaligned(&self, key: impl Borrow<T>) -> Option<W> {
self.get_by_sig_unaligned(T::to_sig(key.borrow(), self.func.seed))
}
}