1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Key-Value semantics.

use super::Database;

use options::{WriteOptions, ReadOptions, c_writeoptions, c_readoptions};
use super::error::Error;
use database::key::Key;
use std::ptr;
use std::slice::from_raw_parts;
use std::borrow::Borrow;
use libc::{c_char, size_t, c_void};
use leveldb_sys::*;

/// Key-Value-Access to the leveldb database, providing
/// a basic interface.
pub trait KV<K: Key> {
    /// get a value from the database.
    ///
    /// The passed key will be compared using the comparator.
    fn get<'a, BK: Borrow<K>>(&self, options: ReadOptions<'a, K>, key: BK) -> Result<Option<Vec<u8>>, 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<BK: Borrow<K>>(&self, options: WriteOptions, key: BK, 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<BK: Borrow<K>>(&self, options: WriteOptions, key: BK) -> Result<(), Error>;
}

impl<K: Key> KV<K> for Database<K> {
    /// 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<BK: Borrow<K>>(&self, options: WriteOptions, key: BK, value: &[u8]) -> Result<(), Error> {
        unsafe {
            key.borrow().as_slice(|k| {
                let mut error = ptr::null_mut();
                let c_writeoptions = c_writeoptions(options);
                leveldb_put(self.database.ptr,
                            c_writeoptions,
                            k.as_ptr() as *mut c_char,
                            k.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 == ptr::null_mut() {
                    Ok(())
                } else {
                    Err(Error::new_from_i8(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<BK: Borrow<K>>(&self, options: WriteOptions, key: BK) -> Result<(), Error> {
        unsafe {
            key.borrow().as_slice(|k| {
                let mut error = ptr::null_mut();
                let c_writeoptions = c_writeoptions(options);
                leveldb_delete(self.database.ptr,
                               c_writeoptions,
                               k.as_ptr() as *mut c_char,
                               k.len() as size_t,
                               &mut error);
                leveldb_writeoptions_destroy(c_writeoptions);
                if error == ptr::null_mut() {
                    Ok(())
                } else {
                    Err(Error::new_from_i8(error))
                }
            })
        }
    }

    /// get a value from the database.
    ///
    /// The passed key will be compared using the comparator.
    fn get<'a, BK: Borrow<K>>(&self, options: ReadOptions<'a, K>, key: BK) -> Result<Option<Vec<u8>>, Error> {
        unsafe {
            key.borrow().as_slice(|k| {
                let mut error = ptr::null_mut();
                let mut length: size_t = 0;
                let c_readoptions = c_readoptions(&options);
                let result = leveldb_get(self.database.ptr,
                                         c_readoptions,
                                         k.as_ptr() as *mut c_char,
                                         k.len() as size_t,
                                         &mut length,
                                         &mut error);
                leveldb_readoptions_destroy(c_readoptions);

                if error == ptr::null_mut() {
                    if result == ptr::null_mut() {
                        Ok(None)
                    } else {
                        let vec = from_raw_parts(result as *mut u8, length as usize).to_vec();
                        leveldb_free(result as *mut c_void);
                        Ok(Some(vec))
                    }
                } else {
                    Err(Error::new_from_i8(error))
                }
            })
        }
    }
}