use core::borrow::Borrow;
use core::hash::Hash;
use crate::buf::{Bindable, Buf, Visit};
use crate::endian::{ByteOrder, Native};
use crate::error::Error;
use crate::phf::hashing::HashKey;
use crate::phf::Entry;
use crate::pointer::{DefaultSize, Ref, Size};
use crate::{Endian, ZeroCopy};
pub struct Set<'a, T> {
key: HashKey,
entries: &'a [T],
displacements: &'a [Entry<u32, u32>],
buf: &'a Buf,
}
impl<T> Set<'_, T>
where
T: ZeroCopy,
{
pub fn contains<Q>(&self, key: &Q) -> Result<bool, Error>
where
Q: ?Sized + Visit,
Q::Target: Eq + Hash,
T: Visit,
T::Target: Borrow<Q::Target>,
{
if self.displacements.is_empty() {
return Ok(false);
}
let hashes = crate::phf::hashing::hash(self.buf, key, &self.key)?;
let index =
crate::phf::hashing::get_index(&hashes, self.displacements, self.entries.len())?;
let Some(e) = self.entries.get(index) else {
return Ok(false);
};
key.visit(self.buf, |b| e.visit(self.buf, |a| a.borrow() == b))?
}
}
impl<T, E, O> Bindable for SetRef<T, E, O>
where
T: ZeroCopy,
E: ByteOrder,
O: Size,
{
type Bound<'a>
= Set<'a, T>
where
Self: 'a;
#[inline]
fn bind(self, buf: &Buf) -> Result<Self::Bound<'_>, Error> {
Ok(Set {
key: self.key.to_ne(),
entries: buf.load(self.entries)?,
displacements: buf.load(self.displacements)?,
buf,
})
}
}
#[derive(Debug, ZeroCopy)]
#[repr(C)]
#[zero_copy(crate)]
pub struct SetRef<T, E = Native, O = DefaultSize>
where
T: ZeroCopy,
E: ByteOrder,
O: Size,
{
key: Endian<HashKey, E>,
entries: Ref<[T], E, O>,
displacements: Ref<[Entry<u32, u32>], E, O>,
}
impl<T, E, O> SetRef<T, E, O>
where
T: ZeroCopy,
E: ByteOrder,
O: Size,
{
#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn new(
key: HashKey,
entries: Ref<[T], E, O>,
displacements: Ref<[Entry<u32, u32>], E, O>,
) -> Self {
Self {
key: Endian::new(key),
entries,
displacements,
}
}
}
impl<T, E, O> SetRef<T, E, O>
where
T: ZeroCopy,
E: ByteOrder,
O: Size,
{
pub fn contains<Q>(&self, buf: &Buf, key: &Q) -> Result<bool, Error>
where
Q: ?Sized + Visit,
Q::Target: Eq + Hash,
T: Visit,
T::Target: Borrow<Q::Target>,
{
if self.displacements.is_empty() {
return Ok(false);
}
let hashes = crate::phf::hashing::hash(buf, key, &self.key.to_ne())?;
let displacements = |index| match self.displacements.get(index) {
Some(entry) => Ok(Some(buf.load(entry)?)),
None => Ok(None),
};
let index = crate::phf::hashing::get_custom_index(
&hashes,
displacements,
self.displacements.len(),
self.entries.len(),
)?;
let Some(e) = self.entries.get(index) else {
return Ok(false);
};
let e = buf.load(e)?;
key.visit(buf, |b| e.visit(buf, |a| a.borrow() == b))?
}
}