#![doc = include_str!("../README.md")]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(docsrs, allow(unused_attributes))]
#![deny(missing_docs, warnings)]
#![allow(clippy::type_complexity)]
#[cfg(not(any(feature = "std", feature = "alloc")))]
compile_error!("`aol` cannot be compiled when both `std` is disabled.");
#[cfg(not(feature = "std"))]
extern crate alloc as std;
#[cfg(feature = "std")]
extern crate std;
#[cfg(feature = "std")]
use core::mem;
mod types;
pub use types::*;
mod impls;
mod snapshot;
pub use snapshot::*;
pub use dbutils::{checksum, leb128};
pub use either;
pub mod buffer {
pub use dbutils::{buffer::VacantBuffer, error::*};
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
mod fs;
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
pub use fs::*;
#[cfg(feature = "std")]
const MAGIC_LEN: usize = mem::size_of::<u16>();
#[cfg(feature = "std")]
const MAGIC_TEXT: &[u8] = b"aol!";
#[cfg(feature = "std")]
const MAGIC_TEXT_LEN: usize = MAGIC_TEXT.len();
#[cfg(feature = "std")]
const MAGIC_VERSION_LEN: usize = mem::size_of::<u16>();
#[cfg(feature = "std")]
const ENTRY_HEADER_SIZE: usize = 1 + LEN_BUF_SIZE; #[cfg(feature = "std")]
const FIXED_ENTRY_LEN: usize = ENTRY_HEADER_SIZE + CHECKSUM_SIZE; #[cfg(feature = "std")]
const CHECKSUM_SIZE: usize = mem::size_of::<u64>();
#[cfg(feature = "std")]
const LEN_BUF_SIZE: usize = mem::size_of::<u32>();
#[cfg(feature = "std")]
const HEADER_SIZE: usize = MAGIC_TEXT_LEN + MAGIC_LEN + MAGIC_VERSION_LEN;
const DELETE_FLAG: u8 = 0b00000001;
const MASK: u8 = 0b11111110;
const CUSTOM_CORE_MASK: CustomFlagsCore = CustomFlagsCore::from_bits_retain(MASK);
bitflags::bitflags! {
#[derive(Default, PartialEq, Eq, Copy, Clone, Hash)]
struct CustomFlagsCore: u8 {
const BIT1 = 0b00000010;
const BIT2 = 0b00000100;
const BIT3 = 0b00001000;
const BIT4 = 0b00010000;
const BIT5 = 0b00100000;
const BIT6 = 0b01000000;
const BIT7 = 0b10000000;
}
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct CustomFlags(CustomFlagsCore);
impl core::fmt::Debug for CustomFlags {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("CustomFlags")
.field(&(self.0.bits() & MASK))
.finish()
}
}
impl core::fmt::Display for CustomFlags {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0.bits() & MASK)
}
}
macro_rules! bits_api {
($($num:literal), +$(,)?) => {
$(
paste::paste! {
#[doc = concat!("Set the bit", $num,)]
#[doc = concat!("flags.set_bit", $num, "();")]
#[inline]
pub fn [< set_bit $num >] (&mut self) {
self.0.insert(CustomFlagsCore::[< BIT $num >]);
}
#[doc = concat!("Set the bit", $num,)]
#[doc = concat!("let flags = flags.with_bit", $num, "();")]
#[doc = concat!("assert!(flags.bit", $num, "());")]
#[inline]
pub const fn [< with_bit $num >] (self) -> Self {
Self(self.0.union(CustomFlagsCore::[< BIT $num >]))
}
#[doc = concat!("Clear the bit", $num)]
#[doc = concat!("flags.clear_bit", $num, "();")]
#[doc = concat!("assert_eq!(flags.bit", $num, "(), false);")]
#[inline]
pub fn [< clear_bit $num >](&mut self) {
self.0.remove(CustomFlagsCore::[< BIT $num >]);
}
#[doc = concat!("Returns `true` if the bit", $num, " is set.")]
#[doc = concat!("assert_eq!(flags.bit", $num, "(), true);")]
#[inline]
pub const fn [< bit $num >](&self) -> bool {
self.0.contains(CustomFlagsCore::[< BIT $num >])
}
}
)*
};
}
macro_rules! flags_api {
($($name:ident: #[$doc:meta]), +$(,)?) => {
$(
paste::paste! {
#[$doc]
#[doc = "let flags = flags1." $name "(flags2);"]
#[inline]
pub const fn $name(&self, other: Self) -> Self {
Self(CustomFlagsCore::from_bits_retain((self.0.$name(other.0).bits() & MASK)))
}
}
)*
};
}
macro_rules! impl_bitwise_ops {
($($trait:ident, $method:ident, $assign_trait:ident, $assign_method:ident),+ $(,)?) => {
$(
impl core::ops::$trait for CustomFlags {
type Output = Self;
#[inline]
fn $method(self, rhs: Self) -> Self::Output {
#[allow(clippy::suspicious_arithmetic_impl)]
Self(self.0.$method(rhs.0) & CUSTOM_CORE_MASK)
}
}
impl core::ops::$assign_trait for CustomFlags {
#[inline]
#[allow(clippy::suspicious_op_assign_impl)]
fn $assign_method(&mut self, rhs: Self) {
self.0.$assign_method(rhs.0);
self.0 &= CUSTOM_CORE_MASK;
}
}
)*
};
}
impl core::ops::Not for CustomFlags {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
Self(self.0.not() & CUSTOM_CORE_MASK)
}
}
impl_bitwise_ops! {
BitAnd, bitand, BitAndAssign, bitand_assign,
BitOr, bitor, BitOrAssign, bitor_assign,
BitXor, bitxor, BitXorAssign, bitxor_assign,
}
impl CustomFlags {
#[inline]
pub const fn all() -> Self {
Self(CustomFlagsCore::from_bits_retain(
CustomFlagsCore::all().bits() & MASK,
))
}
#[inline]
pub const fn empty() -> Self {
Self(CustomFlagsCore::empty())
}
#[inline]
pub const fn contains(&self, other: Self) -> bool {
self.0.contains(other.0)
}
#[inline]
pub fn toggle(&mut self, other: Self) {
self.0.toggle(other.0);
self.0 &= CUSTOM_CORE_MASK;
}
#[inline]
pub const fn complement(&self) -> Self {
Self(CustomFlagsCore::from_bits_retain(
self.0.complement().bits() & MASK,
))
}
#[inline]
pub const fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub const fn is_all(&self) -> bool {
self.0.is_all()
}
flags_api! {
union: #[doc = "The bitwise intersection (`|`) of the bits in two flags values."],
intersection: #[doc = "The bitwise intersection (`&`) of the bits in two flags values."],
difference: #[doc = concat!("The intersection of a source flags value with the complement of a target flags value (`&!`).", "\n\n",
"This method is not equivalent to `self & !other` when `other` has unknown bits set. difference won't truncate other, but the `!` operator will.")],
symmetric_difference: #[doc = "The bitwise exclusive-or (`^`) of the bits in two flags values."],
}
bits_api!(1, 2, 3, 4, 5, 6, 7);
#[inline]
const fn bits(&self) -> u8 {
self.0.bits()
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
#[repr(transparent)]
pub struct EntryFlags {
value: u8,
}
impl core::fmt::Debug for EntryFlags {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("EntryFlags")
.field("custom_flag", &self.custom_flag())
.field(
"op",
if self.is_deletion() {
&"deletion"
} else {
&"creation"
},
)
.finish()
}
}
impl EntryFlags {
#[inline]
pub const fn creation() -> Self {
Self::creation_with_custom_flag(CustomFlags::empty())
}
#[inline]
pub const fn deletion() -> Self {
Self::deletion_with_custom_flag(CustomFlags::empty())
}
#[inline]
pub const fn deletion_with_custom_flag(flag: CustomFlags) -> Self {
let mut this = Self::new(flag);
this.value |= DELETE_FLAG;
this
}
#[inline]
pub const fn creation_with_custom_flag(flag: CustomFlags) -> Self {
let mut this = Self::new(flag);
this.value &= !DELETE_FLAG;
this
}
#[inline]
pub const fn custom_flag(&self) -> CustomFlags {
CustomFlags(CustomFlagsCore::from_bits_retain(self.value & MASK))
}
#[inline]
pub fn set_custom_flag(&mut self, flag: CustomFlags) {
self.value = (flag.bits() & MASK) | (self.value & DELETE_FLAG);
}
#[inline]
pub const fn is_deletion(&self) -> bool {
(self.value & DELETE_FLAG) != 0
}
#[inline]
pub const fn is_creation(&self) -> bool {
(self.value & DELETE_FLAG) == 0
}
#[inline]
pub const fn bits(&self) -> u8 {
self.value
}
#[inline]
const fn new(flag: CustomFlags) -> Self {
Self {
value: flag.bits() & MASK,
}
}
}