1#![doc(
2 html_favicon_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon.ico?raw=true"
3)]
4#![doc(
5 html_logo_url = "https://raw.githubusercontent.com/meilisearch/heed/main/assets/heed-pigeon-logo.png?raw=true"
6)]
7
8#![warn(missing_docs)]
64
65pub mod cookbook;
66mod cursor;
67mod database;
68mod env;
69pub mod iteration_method;
70mod iterator;
71mod mdb;
72mod reserved_space;
73mod txn;
74mod write_admission;
75
76use std::ffi::CStr;
77use std::{error, fmt, io, mem, result};
78
79use heed_traits as traits;
80pub use {byteorder, heed_types as types};
81
82use self::cursor::{RoCursor, RwCursor};
83pub use self::database::{Database, DatabaseOpenOptions, DatabaseStat};
84pub use self::env::{
85 env_closing_event, CompactionOption, DefaultComparator, Env, EnvClosingEvent, EnvInfo,
86 EnvOpenOptions, FlagSetMode, PinnedLmdbFileIdentity, PinnedLmdbIdentity,
87};
88pub use self::iterator::{
89 RoIter, RoPrefix, RoRange, RoRevIter, RoRevPrefix, RoRevRange, RwIter, RwPrefix, RwRange,
90 RwRevIter, RwRevPrefix, RwRevRange,
91};
92pub use self::mdb::error::Error as MdbError;
93use self::mdb::ffi::{from_val, into_val};
94pub use self::mdb::flags::{DatabaseFlags, EnvFlags, PutFlags};
95pub use self::reserved_space::ReservedSpace;
96pub use self::traits::{BoxedError, BytesDecode, BytesEncode, Comparator, LexicographicComparator};
97pub use self::txn::{RoTxn, RwTxn};
98pub use self::write_admission::WriteAdmission;
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
102pub struct LmdbVersion {
103 pub string: &'static str,
105 pub major: i32,
107 pub minor: i32,
109 pub patch: i32,
111}
112
113pub fn lmdb_version() -> LmdbVersion {
127 let mut major = mem::MaybeUninit::uninit();
128 let mut minor = mem::MaybeUninit::uninit();
129 let mut patch = mem::MaybeUninit::uninit();
130
131 unsafe {
132 let string_ptr =
133 mdb::ffi::mdb_version(major.as_mut_ptr(), minor.as_mut_ptr(), patch.as_mut_ptr());
134 LmdbVersion {
135 string: CStr::from_ptr(string_ptr).to_str().unwrap(),
136 major: major.assume_init(),
137 minor: minor.assume_init(),
138 patch: patch.assume_init(),
139 }
140 }
141}
142
143#[derive(Debug)]
145pub enum Error {
146 Io(io::Error),
148 Mdb(MdbError),
150 Encoding(BoxedError),
152 Decoding(BoxedError),
154 DatabaseClosing,
156 BadOpenOptions {
158 options: EnvOpenOptions,
160 env: Env,
162 },
163}
164
165impl fmt::Display for Error {
166 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167 match self {
168 Error::Io(error) => write!(f, "{}", error),
169 Error::Mdb(error) => write!(f, "{}", error),
170 Error::Encoding(error) => write!(f, "error while encoding: {}", error),
171 Error::Decoding(error) => write!(f, "error while decoding: {}", error),
172 Error::DatabaseClosing => {
173 f.write_str("database is in a closing phase, you can't open it at the same time")
174 }
175 Error::BadOpenOptions { .. } => {
176 f.write_str("an environment is already opened with different options")
177 }
178 }
179 }
180}
181
182impl error::Error for Error {}
183
184impl From<MdbError> for Error {
185 fn from(error: MdbError) -> Error {
186 match error {
187 MdbError::Other(e) => Error::Io(io::Error::from_raw_os_error(e)),
188 _ => Error::Mdb(error),
189 }
190 }
191}
192
193impl From<io::Error> for Error {
194 fn from(error: io::Error) -> Error {
195 Error::Io(error)
196 }
197}
198
199pub type Result<T> = result::Result<T, Error>;
201
202pub enum Unspecified {}
209
210macro_rules! assert_eq_env_db_txn {
211 ($database:ident, $txn:ident) => {
212 assert!(
213 $database.env_ident == $txn.env_mut_ptr() as usize,
214 "The database environment doesn't match the transaction's environment"
215 );
216 };
217}
218
219macro_rules! assert_eq_env_txn {
220 ($env:expr, $txn:ident) => {
221 assert!(
222 $env.env_mut_ptr() == $txn.env_mut_ptr(),
223 "The environment doesn't match the transaction's environment"
224 );
225 };
226}
227
228pub(crate) use {assert_eq_env_db_txn, assert_eq_env_txn};
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233
234 #[test]
235 fn error_is_send_sync() {
236 fn give_me_send_sync<T: Send + Sync>(_: T) {}
237
238 let error = Error::Encoding(Box::from("There is an issue, you know?"));
239 give_me_send_sync(error);
240 }
241}