use core::{cmp, marker::PhantomData, mem, slice};
use dbutils::{
buffer::VacantBuffer,
equivalent::Comparable,
types::{KeyRef, Type, TypeRef},
};
use crate::types::EntryFlags;
const PTR_SIZE: usize = mem::size_of::<usize>();
const U32_SIZE: usize = mem::size_of::<u32>();
pub struct ValuePointer<V: ?Sized> {
ptr: *const u8,
len: usize,
_m: PhantomData<V>,
}
unsafe impl<V: ?Sized> Send for ValuePointer<V> {}
unsafe impl<V: ?Sized> Sync for ValuePointer<V> {}
impl<V: ?Sized> core::fmt::Debug for ValuePointer<V> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ValuePointer")
.field("ptr", &self.ptr)
.field("value", &self.as_slice())
.finish()
}
}
impl<V: ?Sized> Clone for ValuePointer<V> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<V: ?Sized> Copy for ValuePointer<V> {}
impl<V: ?Sized> ValuePointer<V> {
#[inline]
pub(crate) fn new(len: usize, ptr: *const u8) -> Self {
Self {
ptr,
len,
_m: PhantomData,
}
}
#[inline]
pub(crate) fn as_slice<'a>(&self) -> &'a [u8] {
if self.len == 0 {
return &[];
}
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
impl<V> Type for ValuePointer<V>
where
V: ?Sized,
{
type Ref<'a> = Self;
type Error = ();
#[inline]
fn encoded_len(&self) -> usize {
const SIZE: usize = PTR_SIZE + U32_SIZE;
SIZE
}
#[inline]
fn encode_to_buffer(&self, buf: &mut VacantBuffer<'_>) -> Result<usize, Self::Error> {
let val_len = self.len as u32;
let ptr = self.ptr as usize;
buf.set_len(self.encoded_len());
buf[0..PTR_SIZE].copy_from_slice(&ptr.to_le_bytes());
buf[PTR_SIZE..PTR_SIZE + U32_SIZE].copy_from_slice(&val_len.to_le_bytes());
Ok(PTR_SIZE + U32_SIZE)
}
}
impl<'a, V: ?Sized> TypeRef<'a> for ValuePointer<V> {
unsafe fn from_slice(src: &'a [u8]) -> Self {
let ptr = usize_to_addr(usize::from_le_bytes((&src[..PTR_SIZE]).try_into().unwrap()));
let len =
u32::from_le_bytes((&src[PTR_SIZE..PTR_SIZE + U32_SIZE]).try_into().unwrap()) as usize;
Self::new(len, ptr)
}
}
#[doc(hidden)]
pub struct KeyPointer<K: ?Sized> {
flag: EntryFlags,
ptr: *const u8,
len: usize,
_m: PhantomData<K>,
}
unsafe impl<K: ?Sized> Send for KeyPointer<K> {}
unsafe impl<K: ?Sized> Sync for KeyPointer<K> {}
impl<K: ?Sized> core::fmt::Debug for KeyPointer<K> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("KeyPointer")
.field("ptr", &self.ptr)
.field("flag", &self.flag)
.field("key", &self.as_slice())
.finish()
}
}
impl<K: ?Sized> Clone for KeyPointer<K> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<K: ?Sized> Copy for KeyPointer<K> {}
impl<K: ?Sized> KeyPointer<K> {
#[inline]
pub(crate) fn new(flag: EntryFlags, len: usize, ptr: *const u8) -> Self {
Self {
ptr,
flag,
len,
_m: PhantomData,
}
}
#[inline]
pub(crate) fn as_slice<'a>(&self) -> &'a [u8] {
if self.len == 0 {
return &[];
}
unsafe { slice::from_raw_parts(self.ptr, self.len) }
}
}
impl<K: Type + ?Sized> PartialEq for KeyPointer<K> {
fn eq(&self, other: &Self) -> bool {
self.as_slice() == other.as_slice()
}
}
impl<K: Type + ?Sized> Eq for KeyPointer<K> {}
impl<'a, K> PartialOrd for KeyPointer<K>
where
K: Type + Ord + ?Sized,
K::Ref<'a>: KeyRef<'a, K>,
{
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<'a, K> Ord for KeyPointer<K>
where
K: Type + Ord + ?Sized,
K::Ref<'a>: KeyRef<'a, K>,
{
fn cmp(&self, other: &Self) -> cmp::Ordering {
unsafe { <K::Ref<'_> as KeyRef<K>>::compare_binary(self.as_slice(), other.as_slice()) }
}
}
impl<K> Type for KeyPointer<K>
where
K: ?Sized,
{
type Ref<'a> = Self;
type Error = ();
#[inline]
fn encoded_len(&self) -> usize {
const SIZE: usize = PTR_SIZE + U32_SIZE + mem::size_of::<EntryFlags>();
SIZE
}
#[inline]
fn encode_to_buffer(&self, buf: &mut VacantBuffer<'_>) -> Result<usize, Self::Error> {
let key_len = self.len as u32;
let ptr = self.ptr as usize;
buf.set_len(self.encoded_len());
buf[0..PTR_SIZE].copy_from_slice(&ptr.to_le_bytes());
let mut offset = PTR_SIZE;
buf[offset] = self.flag.bits();
offset += 1;
buf[offset..offset + U32_SIZE].copy_from_slice(&key_len.to_le_bytes());
Ok(offset + U32_SIZE)
}
}
impl<'a, K: ?Sized> TypeRef<'a> for KeyPointer<K> {
unsafe fn from_slice(src: &'a [u8]) -> Self {
let ptr = usize_to_addr(usize::from_le_bytes((&src[..PTR_SIZE]).try_into().unwrap()));
let mut offset = PTR_SIZE;
let flag = EntryFlags::from_bits_retain(src[offset]);
offset += 1;
let key_len =
u32::from_le_bytes((&src[offset..offset + U32_SIZE]).try_into().unwrap()) as usize;
Self::new(flag, key_len, ptr)
}
}
impl<'a, K> KeyRef<'a, Self> for KeyPointer<K>
where
K: Type + Ord + ?Sized,
K::Ref<'a>: KeyRef<'a, K>,
{
#[inline]
fn compare<Q>(&self, a: &Q) -> cmp::Ordering
where
Q: ?Sized + Ord + Comparable<Self>,
{
Comparable::compare(a, self).reverse()
}
#[inline]
unsafe fn compare_binary(a: &[u8], b: &[u8]) -> cmp::Ordering {
<K::Ref<'_> as KeyRef<K>>::compare_binary(a, b)
}
}
#[inline]
const fn usize_to_addr<T>(addr: usize) -> *const T {
addr as *const T
}