//! Key-Value semantics.
use super::Database;
use super::bytes::Bytes;
use super::error::Error;
use leveldb_sys::*;
use libc::{c_char, size_t};
use options::{c_readoptions, c_writeoptions, ReadOptions, WriteOptions};
use std::borrow::Borrow;
use std::ptr;
/// Key-Value-Access to the leveldb database, providing
/// a basic interface.
pub trait KV {
/// get a value from the database.
///
/// The passed key will be compared using the comparator.
fn get<'a>(&self, options: ReadOptions<'a>, key: &[u8]) -> Result<Option<Vec<u8>>, Error>;
/// get a value from the database.
///
/// The passed key will be compared using the comparator.
///
/// This version returns bytes allocated by leveldb without converting to `Vec<u8>`, which may
/// lead to better performance.
fn get_bytes<'a>(&self, options: ReadOptions<'a>, key: &[u8]) -> Result<Option<Bytes>, Error>;
/// put a binary value into the database.
///
/// If the key is already present in the database, it will be overwritten.
///
/// The passed key will be compared using the comparator.
///
/// The database will be synced to disc if `options.sync == true`. This is
/// NOT the default.
fn put(&self, options: WriteOptions, key: &[u8], value: &[u8]) -> Result<(), Error>;
/// delete a value from the database.
///
/// The passed key will be compared using the comparator.
///
/// The database will be synced to disc if `options.sync == true`. This is
/// NOT the default.
fn delete(&self, options: WriteOptions, key: &[u8]) -> Result<(), Error>;
}
impl KV for Database {
/// put a binary value into the database.
///
/// If the key is already present in the database, it will be overwritten.
///
/// The passed key will be compared using the comparator.
///
/// The database will be synced to disc if `options.sync == true`. This is
/// NOT the default.
fn put(&self, options: WriteOptions, key: &[u8], value: &[u8]) -> Result<(), Error> {
unsafe {
let mut error = ptr::null_mut();
let c_writeoptions = c_writeoptions(options);
leveldb_put(
self.0.database.ptr,
c_writeoptions,
key.borrow().as_ptr() as *mut c_char,
key.borrow().len() as size_t,
value.as_ptr() as *mut c_char,
value.len() as size_t,
&mut error,
);
leveldb_writeoptions_destroy(c_writeoptions);
if error.is_null() {
Ok(())
} else {
Err(Error::new_from_char(error))
}
}
}
/// delete a value from the database.
///
/// The passed key will be compared using the comparator.
///
/// The database will be synced to disc if `options.sync == true`. This is
/// NOT the default.
fn delete(&self, options: WriteOptions, key: &[u8]) -> Result<(), Error> {
unsafe {
let mut error = ptr::null_mut();
let c_writeoptions = c_writeoptions(options);
leveldb_delete(
self.0.database.ptr,
c_writeoptions,
key.borrow().as_ptr() as *mut c_char,
key.borrow().len() as size_t,
&mut error,
);
leveldb_writeoptions_destroy(c_writeoptions);
if error.is_null() {
Ok(())
} else {
Err(Error::new_from_char(error))
}
}
}
fn get_bytes<'a>(&self, options: ReadOptions<'a>, key: &[u8]) -> Result<Option<Bytes>, Error> {
unsafe {
let mut error = ptr::null_mut();
let mut length: size_t = 0;
let c_readoptions = c_readoptions(&options);
let result = leveldb_get(
self.0.database.ptr,
c_readoptions,
key.borrow().as_ptr() as *mut c_char,
key.borrow().len() as size_t,
&mut length,
&mut error,
);
leveldb_readoptions_destroy(c_readoptions);
if error.is_null() {
Ok(Bytes::from_raw(result as *mut u8, length))
} else {
Err(Error::new_from_char(error))
}
}
}
fn get<'a>(&self, options: ReadOptions<'a>, key: &[u8]) -> Result<Option<Vec<u8>>, Error> {
self.get_bytes(options, key).map(|val| val.map(Into::into))
}
}