#![doc(
html_favicon_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon.ico?raw=true"
)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon-logo.png?raw=true"
)]
#![warn(missing_docs)]
pub mod cookbook;
mod cursor;
mod databases;
mod envs;
pub mod iteration_method;
mod iterator;
mod mdb;
mod reserved_space;
mod txn;
use std::ffi::CStr;
use std::{error, fmt, io, mem, result};
pub use byteorder;
use heed_traits as traits;
pub use heed_types as types;
use self::cursor::{RoCursor, RwCursor};
pub use self::databases::{Database, DatabaseOpenOptions, DatabaseStat};
#[cfg(master3)]
pub use self::databases::{EncryptedDatabase, EncryptedDatabaseOpenOptions};
#[cfg(master3)]
pub use self::envs::EncryptedEnv;
pub use self::envs::{
env_closing_event, CompactionOption, DefaultComparator, Env, EnvClosingEvent, EnvInfo,
EnvOpenOptions, FlagSetMode, IntegerComparator,
};
pub use self::iterator::{
RoIter, RoPrefix, RoRange, RoRevIter, RoRevPrefix, RoRevRange, RwIter, RwPrefix, RwRange,
RwRevIter, RwRevPrefix, RwRevRange,
};
pub use self::mdb::error::Error as MdbError;
use self::mdb::ffi::{from_val, into_val};
pub use self::mdb::flags::{DatabaseFlags, EnvFlags, PutFlags};
pub use self::reserved_space::ReservedSpace;
pub use self::traits::{BoxedError, BytesDecode, BytesEncode, Comparator, LexicographicComparator};
pub use self::txn::{AnyTls, RoTxn, RwTxn, TlsUsage, WithTls, WithoutTls};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LmdbVersion {
pub string: &'static str,
pub major: i32,
pub minor: i32,
pub patch: i32,
}
pub fn lmdb_version() -> LmdbVersion {
let mut major = mem::MaybeUninit::uninit();
let mut minor = mem::MaybeUninit::uninit();
let mut patch = mem::MaybeUninit::uninit();
unsafe {
let string_ptr =
mdb::ffi::mdb_version(major.as_mut_ptr(), minor.as_mut_ptr(), patch.as_mut_ptr());
LmdbVersion {
string: CStr::from_ptr(string_ptr).to_str().unwrap(),
major: major.assume_init(),
minor: minor.assume_init(),
patch: patch.assume_init(),
}
}
}
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Mdb(MdbError),
Encoding(BoxedError),
Decoding(BoxedError),
EnvAlreadyOpened,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Error::Io(error) => write!(f, "{error}"),
Error::Mdb(error) => write!(f, "{error}"),
Error::Encoding(error) => write!(f, "error while encoding: {error}"),
Error::Decoding(error) => write!(f, "error while decoding: {error}"),
Error::EnvAlreadyOpened => f.write_str(
"environment already open in this program; \
close it to be able to open it again with different options",
),
}
}
}
impl error::Error for Error {}
impl From<MdbError> for Error {
fn from(error: MdbError) -> Error {
match error {
MdbError::Other(e) => Error::Io(io::Error::from_raw_os_error(e)),
_ => Error::Mdb(error),
}
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Error {
Error::Io(error)
}
}
pub type Result<T> = result::Result<T, Error>;
pub enum Unspecified {}
macro_rules! assert_eq_env_db_txn {
($database:ident, $txn:ident) => {
assert!(
$database.env_ident == unsafe { $txn.env_mut_ptr().as_mut() as *mut _ as usize },
"The database environment doesn't match the transaction's environment"
);
};
}
macro_rules! assert_eq_env_txn {
($env:expr, $txn:ident) => {
assert!(
$env.env_mut_ptr() == $txn.env_mut_ptr(),
"The environment doesn't match the transaction's environment"
);
};
}
pub(crate) use assert_eq_env_db_txn;
pub(crate) use assert_eq_env_txn;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_is_send_sync() {
fn give_me_send_sync<T: Send + Sync>(_: T) {}
let error = Error::Encoding(Box::from("There is an issue, you know?"));
give_me_send_sync(error);
}
}