use super::*;
use std::sync::Arc;
#[derive(Debug)]
#[repr(C)]
pub struct Entry<const KEY_LEN: usize, V = (), H: PatchHash = XorSip128> {
ptr: NonNull<Leaf<KEY_LEN, V, H>>,
}
impl<const KEY_LEN: usize, H: PatchHash> Entry<KEY_LEN, (), H> {
pub fn new(key: &[u8; KEY_LEN]) -> Self {
unsafe {
let ptr = Leaf::<KEY_LEN, (), H>::new(key, ());
Self { ptr }
}
}
}
impl<const KEY_LEN: usize, V, H: PatchHash> Entry<KEY_LEN, V, H> {
pub fn with_value(key: &[u8; KEY_LEN], value: V) -> Self {
unsafe {
let ptr = Leaf::<KEY_LEN, V, H>::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, H> {
unsafe { Head::new(0, Leaf::rc_inc(self.ptr)) }
}
}
impl<const KEY_LEN: usize, V, H: PatchHash> Clone for Entry<KEY_LEN, V, H> {
fn clone(&self) -> Self {
unsafe {
Self {
ptr: Leaf::rc_inc(self.ptr),
}
}
}
}
impl<const KEY_LEN: usize, V, H: PatchHash> Drop for Entry<KEY_LEN, V, H> {
fn drop(&mut self) {
unsafe {
Leaf::rc_dec(self.ptr);
}
}
}
pub struct ArchiveEntry<'a, const KEY_LEN: usize, H: PatchHash = XorSip128> {
pub(super) ptr: NonNull<[u8; KEY_LEN]>,
pub(super) owner: &'a Arc<dyn ArchiveOwner>,
pub(super) hash: H::Digest,
}
impl<'a, const KEY_LEN: usize, H: PatchHash> ArchiveEntry<'a, KEY_LEN, H> {
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 { H::leaf(&ptr.as_ref()[..]) };
Self { ptr, owner, hash }
}
pub(super) fn leaf<O: KeySchema<KEY_LEN>>(
&self,
) -> (
Head<KEY_LEN, O, (), H>,
&'a Arc<dyn ArchiveOwner>,
H::Digest,
) {
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, H: PatchHash> Copy for ArchiveEntry<'a, KEY_LEN, H> {}
impl<'a, const KEY_LEN: usize, H: PatchHash> Clone for ArchiveEntry<'a, KEY_LEN, H> {
fn clone(&self) -> Self {
*self
}
}
impl<'a, const KEY_LEN: usize, H: PatchHash> core::fmt::Debug for ArchiveEntry<'a, KEY_LEN, H> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ArchiveEntry")
.field("ptr", &self.ptr)
.field("owner", &"<archive owner>")
.finish()
}
}