#[cfg(any(feature = "std", feature = "hashbrown"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "hashbrown"))))]
pub mod wiscask;
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Entry<D> {
pub(super) flag: EntryFlags,
pub(super) data: D,
}
impl<D> Entry<D> {
#[inline]
pub const fn creation(data: D) -> Self {
Self {
flag: EntryFlags::creation(),
data,
}
}
#[inline]
pub const fn deletion(data: D) -> Self {
Self {
flag: EntryFlags::deletion(),
data,
}
}
#[inline]
pub const fn creation_with_custom_flags(flag: CustomFlags, data: D) -> Self {
Self {
flag: EntryFlags::creation_with_custom_flag(flag),
data,
}
}
#[inline]
pub const fn deletion_with_custom_flags(flag: CustomFlags, data: D) -> Self {
Self {
flag: EntryFlags::deletion_with_custom_flag(flag),
data,
}
}
#[inline]
pub const fn flag(&self) -> EntryFlags {
self.flag
}
#[inline]
pub const fn data(&self) -> &D {
&self.data
}
#[inline]
pub(super) fn encode<C>(&self, data_encoded_len: usize, buf: &mut [u8]) -> Result<usize, D::Error>
where
C: Checksumer,
D: Data,
{
let mut cursor = 0;
buf[cursor] = self.flag.value;
cursor += 1;
buf[cursor..cursor + LEN_BUF_SIZE].copy_from_slice(&(data_encoded_len as u32).to_le_bytes());
cursor += LEN_BUF_SIZE;
let encoded = self.data.encode(&mut buf[cursor..])?;
cursor += encoded;
let cks = C::checksum(&buf[..cursor]).to_le_bytes();
buf[cursor..cursor + CHECKSUM_SIZE].copy_from_slice(&cks);
cursor += CHECKSUM_SIZE;
debug_assert_eq!(
cursor,
FIXED_MANIFEST_ENTRY_SIZE + data_encoded_len,
"invalid encoded size, expected {} got {}",
cursor,
FIXED_MANIFEST_ENTRY_SIZE + data_encoded_len
);
Ok(cursor)
}
#[inline]
pub(super) fn decode<C>(buf: &[u8]) -> Result<Self, Option<D::Error>>
where
C: Checksumer,
D: Data,
{
let flag = EntryFlags { value: buf[0] };
let mut cursor = 1;
let len = u32::from_le_bytes(buf[cursor..cursor + LEN_BUF_SIZE].try_into().unwrap());
cursor += LEN_BUF_SIZE;
let (read, data) = D::decode(&buf[cursor..cursor + len as usize]).map_err(Some)?;
debug_assert_eq!(
read, len as usize,
"invalid decoded size, expected {} got {}",
read, len
);
cursor += read;
let cks = C::checksum(&buf[..cursor]).to_le_bytes();
cursor += CHECKSUM_SIZE;
if cks != buf[cursor..cursor + CHECKSUM_SIZE] {
return Err(None);
}
Ok(Self { flag, data })
}
}
#[cfg(any(feature = "std", feature = "hashbrown"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "std", feature = "hashbrown"))))]
pub mod lsm;
use super::*;
pub trait Data: Sized {
#[cfg(feature = "std")]
type Error: std::error::Error;
#[cfg(not(feature = "std"))]
type Error: core::fmt::Debug + core::fmt::Display;
fn encoded_size(&self) -> usize;
fn encode(&self, buf: &mut [u8]) -> Result<usize, Self::Error>;
fn decode(buf: &[u8]) -> Result<(usize, Self), Self::Error>;
}
impl Data for () {
type Error = core::convert::Infallible;
#[inline]
fn encoded_size(&self) -> usize {
0
}
#[inline]
fn encode(&self, _buf: &mut [u8]) -> Result<usize, Self::Error> {
Ok(0)
}
#[inline]
fn decode(_buf: &[u8]) -> Result<(usize, Self), Self::Error> {
Ok((0, ()))
}
}
pub trait BackedManifest: Default {
type Data: Data;
#[cfg(feature = "std")]
type Error: std::error::Error;
#[cfg(not(feature = "std"))]
type Error: core::fmt::Debug + core::fmt::Display;
fn insert(&mut self, entry: Entry<Self::Data>) -> Result<(), Self::Error>;
fn into_iter(self) -> impl Iterator<Item = Entry<Self::Data>>;
fn deletions(&self) -> u64;
fn creations(&self) -> u64;
}