#![deny(
missing_docs,
trivial_casts,
trivial_numeric_casts,
unused_import_braces,
unused_qualifications
)]
use thiserror::*;
mod environment;
pub use environment::{Commit, Env, MutTxn, RootDb, RootPage, Txn};
pub use sanakirja_core::{
btree, direct_repr, AllocPage, CowPage, LoadPage, MutPage, Page, Slice, Storable,
UnsizedStorable,
};
#[cfg(test)]
mod tests;
#[doc(hidden)]
pub mod debug;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
IO(#[from] std::io::Error),
#[error("Lock poisoning")]
Poison,
#[error("Version mismatch")]
VersionMismatch,
#[error(transparent)]
CRC(#[from] CRCError),
#[error("Corruption error: offset {0} is past the end of the file")]
Corrupt(u64),
}
#[derive(Debug, Error)]
#[error("CRC check failed")]
pub struct CRCError {}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct L64(pub u64);
impl std::fmt::Debug for L64 {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "L64({})", u64::from_le(self.0))
}
}
impl serde::Serialize for L64 {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u64(u64::from_le(self.0))
}
}
use serde::de::{self, Visitor};
struct L64Visitor;
impl<'de> Visitor<'de> for L64Visitor {
type Value = L64;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("an unsigned, little-endian integer")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
log::debug!("visit u64 {:?}", value);
Ok(L64(value.to_le()))
}
}
impl<'de> serde::Deserialize<'de> for L64 {
fn deserialize<D>(deserializer: D) -> Result<L64, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_u64(L64Visitor)
}
}
impl From<u64> for L64 {
fn from(u: u64) -> Self {
L64(u.to_le())
}
}
impl From<L64> for u64 {
fn from(u: L64) -> Self {
u64::from_le(u.0)
}
}
impl Ord for L64 {
fn cmp(&self, x: &Self) -> std::cmp::Ordering {
u64::from_le(self.0).cmp(&u64::from_le(x.0))
}
}
impl PartialOrd for L64 {
fn partial_cmp(&self, x: &Self) -> Option<std::cmp::Ordering> {
u64::from_le(self.0).partial_cmp(&u64::from_le(x.0))
}
}
impl From<usize> for L64 {
fn from(u: usize) -> Self {
L64((u as u64).to_le())
}
}
impl From<L64> for usize {
fn from(u: L64) -> Self {
u64::from_le(u.0) as usize
}
}
impl L64 {
pub fn as_u64(&self) -> u64 {
u64::from_le(self.0)
}
pub fn as_usize(&self) -> usize {
u64::from_le(self.0) as usize
}
}
impl std::fmt::Display for L64 {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
u64::from_le(self.0).fmt(fmt)
}
}
impl std::ops::Add<L64> for L64 {
type Output = Self;
fn add(self, x: L64) -> L64 {
L64((u64::from_le(self.0) + u64::from_le(x.0)).to_le())
}
}
impl std::ops::Add<usize> for L64 {
type Output = Self;
fn add(self, x: usize) -> L64 {
L64((u64::from_le(self.0) + x as u64).to_le())
}
}
impl std::ops::SubAssign<usize> for L64 {
fn sub_assign(&mut self, x: usize) {
self.0 = ((u64::from_le(self.0)) - x as u64).to_le()
}
}
#[allow(trivial_casts)]
impl L64 {
pub fn from_slice_le(s: &[u8]) -> Self {
let mut u = 0u64;
assert!(s.len() >= 8);
unsafe { std::ptr::copy_nonoverlapping(s.as_ptr(), &mut u as *mut u64 as *mut u8, 8) }
L64(u)
}
pub fn to_slice_le(&self, s: &mut [u8]) {
assert!(s.len() >= 8);
unsafe {
std::ptr::copy_nonoverlapping(&self.0 as *const u64 as *const u8, s.as_mut_ptr(), 8)
}
}
}
direct_repr!(L64);
impl debug::Check for L64 {}