use super::*;
use std::sync::Arc;
#[derive(Debug)]
#[repr(C)]
pub struct Entry<const KEY_LEN: usize, V = ()> {
ptr: NonNull<Leaf<KEY_LEN, V>>,
}
impl<const KEY_LEN: usize> Entry<KEY_LEN> {
pub fn new(key: &[u8; KEY_LEN]) -> Self {
unsafe {
let ptr = Leaf::<KEY_LEN, ()>::new(key, ());
Self { ptr }
}
}
}
impl<const KEY_LEN: usize, V> Entry<KEY_LEN, V> {
pub fn with_value(key: &[u8; KEY_LEN], value: V) -> Self {
unsafe {
let ptr = Leaf::<KEY_LEN, V>::new(key, value);
Self { ptr }
}
}
pub fn value(&self) -> &V {
unsafe { &self.ptr.as_ref().value }
}
pub(super) fn leaf<O: KeySchema<KEY_LEN>>(&self) -> Head<KEY_LEN, O, V> {
unsafe { Head::new(0, Leaf::rc_inc(self.ptr)) }
}
}
impl<const KEY_LEN: usize, V> Clone for Entry<KEY_LEN, V> {
fn clone(&self) -> Self {
unsafe {
Self {
ptr: Leaf::rc_inc(self.ptr),
}
}
}
}
impl<const KEY_LEN: usize, V> Drop for Entry<KEY_LEN, V> {
fn drop(&mut self) {
unsafe {
Leaf::rc_dec(self.ptr);
}
}
}
pub struct ArchiveEntry<'a, const KEY_LEN: usize> {
pub(super) ptr: NonNull<[u8; KEY_LEN]>,
pub(super) owner: &'a Arc<dyn ArchiveOwner>,
pub(super) hash: u128,
}
impl<'a, const KEY_LEN: usize> ArchiveEntry<'a, KEY_LEN> {
pub unsafe fn new(
ptr: NonNull<[u8; KEY_LEN]>,
owner: &'a Arc<dyn ArchiveOwner>,
) -> Self {
debug_assert_eq!(
ptr.as_ptr() as usize & 0x0f,
0,
"ArchiveEntry pointer must be 16-byte aligned"
);
let hash = unsafe {
use siphasher::sip128::SipHasher24;
use std::ptr::addr_of;
let key = *addr_of!(crate::patch::SIP_KEY);
SipHasher24::new_with_key(&key).hash(&ptr.as_ref()[..]).into()
};
Self { ptr, owner, hash }
}
pub(super) fn leaf<O: KeySchema<KEY_LEN>>(
&self,
) -> (Head<KEY_LEN, O, ()>, &'a Arc<dyn ArchiveOwner>, u128) {
unsafe { (Head::new_local_leaf(0, self.ptr), self.owner, self.hash) }
}
pub fn owner(&self) -> &'a Arc<dyn ArchiveOwner> {
self.owner
}
}
impl<'a, const KEY_LEN: usize> Copy for ArchiveEntry<'a, KEY_LEN> {}
impl<'a, const KEY_LEN: usize> Clone for ArchiveEntry<'a, KEY_LEN> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, const KEY_LEN: usize> core::fmt::Debug for ArchiveEntry<'a, KEY_LEN> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ArchiveEntry")
.field("ptr", &self.ptr)
.field("owner", &"<archive owner>")
.finish()
}
}