Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated dependency db-key to version 0.1 #52

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ name = "leveldb"

[dependencies]

db-key = "0.0.5"
db-key = "0.1"
libc = "0.2.4"

[dependencies.leveldb-sys]
Expand Down
109 changes: 59 additions & 50 deletions src/database/batch.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
//! Module providing write batches

use super::error::Error;
use super::Database;
use database::key::Key;
use leveldb_sys::*;
use libc::{c_char, size_t, c_void};
use libc::{c_char, c_void, size_t};
use options::{c_writeoptions, WriteOptions};
use std::marker::PhantomData;
use database::key::Key;
use database::key::from_u8;
use std::slice;
use options::{WriteOptions, c_writeoptions};
use super::error::Error;
use std::ptr;
use super::Database;
use std::slice;

#[allow(missing_docs)]
struct RawWritebatch {
Expand All @@ -25,28 +24,30 @@ impl Drop for RawWritebatch {
}

#[allow(missing_docs)]
pub struct Writebatch<K: Key> {
pub struct Writebatch<'a, K: Key<'a>> {
#[allow(dead_code)]
writebatch: RawWritebatch,
marker: PhantomData<K>,
marker: PhantomData<&'a K>,
}

/// Batch access to the database
pub trait Batch<K: Key> {
pub trait Batch<'a, K: Key<'a>> {
/// Write a batch to the database, ensuring success for all items or an error
fn write(&self, options: WriteOptions, batch: &Writebatch<K>) -> Result<(), Error>;
fn write(&self, options: WriteOptions, batch: &Writebatch<'a, K>) -> Result<(), Error>;
}

impl<K: Key> Batch<K> for Database<K> {
fn write(&self, options: WriteOptions, batch: &Writebatch<K>) -> Result<(), Error> {
impl<'a, K: Key<'a>> Batch<'a, K> for Database<'a, K> {
fn write(&self, options: WriteOptions, batch: &Writebatch<'a, K>) -> Result<(), Error> {
unsafe {
let mut error = ptr::null_mut();
let c_writeoptions = c_writeoptions(options);

leveldb_write(self.database.ptr,
c_writeoptions,
batch.writebatch.ptr,
&mut error);
leveldb_write(
self.database.ptr,
c_writeoptions,
batch.writebatch.ptr,
&mut error,
);
leveldb_writeoptions_destroy(c_writeoptions);

if error == ptr::null_mut() {
Expand All @@ -58,11 +59,11 @@ impl<K: Key> Batch<K> for Database<K> {
}
}

impl<K: Key> Writebatch<K> {
impl<'a, K: Key<'a>> Writebatch<'a, K> {
/// Create a new writebatch
pub fn new() -> Writebatch<K> {
pub fn new() -> Writebatch<'a, K> {
let ptr = unsafe { leveldb_writebatch_create() };
let raw = RawWritebatch { ptr: ptr };
let raw = RawWritebatch { ptr };
Writebatch {
writebatch: raw,
marker: PhantomData,
Expand All @@ -77,44 +78,48 @@ impl<K: Key> Writebatch<K> {
/// Batch a put operation
pub fn put(&mut self, key: K, value: &[u8]) {
unsafe {
key.as_slice(|k| {
leveldb_writebatch_put(self.writebatch.ptr,
k.as_ptr() as *mut c_char,
k.len() as size_t,
value.as_ptr() as *mut c_char,
value.len() as size_t);
})
let k = key.as_ref();
leveldb_writebatch_put(
self.writebatch.ptr,
k.as_ptr() as *mut c_char,
k.len() as size_t,
value.as_ptr() as *mut c_char,
value.len() as size_t,
);
}
}

/// Batch a delete operation
pub fn delete(&mut self, key: K) {
unsafe {
key.as_slice(|k| {
leveldb_writebatch_delete(self.writebatch.ptr,
k.as_ptr() as *mut c_char,
k.len() as size_t);
})
let k = key.as_ref();
leveldb_writebatch_delete(
self.writebatch.ptr,
k.as_ptr() as *mut c_char,
k.len() as size_t,
);
}
}

/// Iterate over the writebatch, returning the resulting iterator
pub fn iterate<T: WritebatchIterator<K = K>>(&mut self, iterator: Box<T>) -> Box<T> {
pub fn iterate<T: WritebatchIterator<'a, K = K>>(&mut self, iterator: Box<T>) -> Box<T> {
unsafe {
let iter = Box::into_raw(iterator);
leveldb_writebatch_iterate(self.writebatch.ptr,
iter as *mut c_void,
put_callback::<K, T>,
deleted_callback::<K, T>);
leveldb_writebatch_iterate(
self.writebatch.ptr,
iter as *mut c_void,
put_callback::<K, T>,
deleted_callback::<K, T>,
);
Box::from_raw(iter)
}
}
}

/// A trait for iterators to iterate over written batches and check their validity.
pub trait WritebatchIterator {
/// The database key type this iterates over
type K: Key;
pub trait WritebatchIterator<'a> {
/// The database Key<'a> type this iterates over
type K: Key<'a>;

/// Callback for put items
fn put(&mut self, key: Self::K, value: &[u8]);
Expand All @@ -123,27 +128,31 @@ pub trait WritebatchIterator {
fn deleted(&mut self, key: Self::K);
}

extern "C" fn put_callback<K: Key, T: WritebatchIterator<K = K>>(state: *mut c_void,
key: *const c_char,
keylen: size_t,
val: *const c_char,
vallen: size_t) {
extern "C" fn put_callback<'a, K: Key<'a>, T: WritebatchIterator<'a, K = K>>(
state: *mut c_void,
key: *const c_char,
keylen: size_t,
val: *const c_char,
vallen: size_t,
) {
unsafe {
let iter: &mut T = &mut *(state as *mut T);
let key_slice = slice::from_raw_parts::<u8>(key as *const u8, keylen as usize);
let val_slice = slice::from_raw_parts::<u8>(val as *const u8, vallen as usize);
let k = from_u8::<<T as WritebatchIterator>::K>(key_slice);
let k = <<T as WritebatchIterator>::K>::from(key_slice);
iter.put(k, val_slice);
}
}

extern "C" fn deleted_callback<K: Key, T: WritebatchIterator<K = K>>(state: *mut c_void,
key: *const c_char,
keylen: size_t) {
extern "C" fn deleted_callback<'a, K: Key<'a>, T: WritebatchIterator<'a, K = K>>(
state: *mut c_void,
key: *const c_char,
keylen: size_t,
) {
unsafe {
let iter: &mut T = &mut *(state as *mut T);
let key_slice = slice::from_raw_parts::<u8>(key as *const u8, keylen as usize);
let k = from_u8::<<T as WritebatchIterator>::K>(key_slice);
let k = <<T as WritebatchIterator>::K>::from(key_slice);
iter.deleted(k);
}
}
4 changes: 2 additions & 2 deletions src/database/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ impl Bytes {
} else {
Some(Bytes {
bytes: &mut *ptr,
size: size,
size,
_marker: Default::default(),
})
}
Expand All @@ -33,7 +33,7 @@ impl Bytes {
pub unsafe fn from_raw_unchecked(ptr: *mut u8, size: usize) -> Self {
Bytes {
bytes: &mut *ptr,
size: size,
size,
_marker: Default::default(),
}
}
Expand Down
24 changes: 12 additions & 12 deletions src/database/compaction.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
//! Compaction
use super::Database;
use super::key::Key;
use super::Database;
use leveldb_sys::leveldb_compact_range;
use libc::{c_char, size_t};

pub trait Compaction<'a, K: Key + 'a> {
pub trait Compaction<'a, K: Key<'a> + 'a> {
fn compact(&self, start: &'a K, limit: &'a K);
}

impl<'a, K: Key + 'a> Compaction<'a, K> for Database<K> {
impl<'a, K: Key<'a> + 'a> Compaction<'a, K> for Database<'a, K> {
fn compact(&self, start: &'a K, limit: &'a K) {
unsafe {
start.as_slice(|s| {
limit.as_slice(|l| {
leveldb_compact_range(self.database.ptr,
s.as_ptr() as *mut c_char,
s.len() as size_t,
l.as_ptr() as *mut c_char,
l.len() as size_t);
});
});
let s = start.as_ref();
let l = limit.as_ref();
leveldb_compact_range(
self.database.ptr,
s.as_ptr() as *mut c_char,
s.len() as size_t,
l.as_ptr() as *mut c_char,
l.len() as size_t,
);
}
}
}
72 changes: 38 additions & 34 deletions src/database/comparator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@
//! Comparators allow to override this comparison.
//! The ordering of keys introduced by the compartor influences iteration order.
//! Databases written with one Comparator cannot be opened with another.
use database::key::Key;
use leveldb_sys::*;
use libc::{size_t, c_void, c_char};
use std::slice;
use libc::{c_char, c_void, size_t};
use std::cmp::Ordering;
use database::key::Key;
use database::key::from_u8;
use std::marker::PhantomData;
use std::slice;

/// A comparator has two important functions:
///
/// * the name function returns a fixed name to detect errors when
/// opening databases with a different name
/// * The comparison implementation
pub trait Comparator {
pub trait Comparator<'a> {
/// The type that the comparator compares.
type K: Key;
type K: Key<'a>;

/// Return the name of the Comparator
fn name(&self) -> *const c_char;
Expand All @@ -31,15 +30,15 @@ pub trait Comparator {
}
}

/// OrdComparator is a comparator comparing Keys that implement `Ord`
pub struct OrdComparator<K: Key + Ord> {
/// OrdComparator is a comparator comparing Key<'a>s that implement `Ord`
pub struct OrdComparator<'a, K: Key<'a> + Ord> {
name: String,
marker: PhantomData<K>,
marker: PhantomData<&'a K>,
}

impl<K: Key + Ord> OrdComparator<K> {
impl<'a, K: Key<'a> + Ord> OrdComparator<'a, K> {
/// Create a new OrdComparator
pub fn new(name: &str) -> OrdComparator<K> {
pub fn new(name: &str) -> OrdComparator<'a, K> {
OrdComparator {
marker: PhantomData,
name: name.to_string(),
Expand All @@ -48,28 +47,31 @@ impl<K: Key + Ord> OrdComparator<K> {
}

/// DefaultComparator is the a stand in for "no comparator set"
#[derive(Copy,Clone)]
#[derive(Copy, Clone)]
pub struct DefaultComparator;

unsafe trait InternalComparator : Comparator where Self: Sized {

unsafe trait InternalComparator<'a>: Comparator<'a>
where
Self: Sized,
{
extern "C" fn name(state: *mut c_void) -> *const c_char {
let x = unsafe { &*(state as *mut Self) };
x.name()
}

extern "C" fn compare(state: *mut c_void,
a: *const c_char,
a_len: size_t,
b: *const c_char,
b_len: size_t)
-> i32 {
extern "C" fn compare(
state: *mut c_void,
a: *const c_char,
a_len: size_t,
b: *const c_char,
b_len: size_t,
) -> i32 {
unsafe {
let a_slice = slice::from_raw_parts::<u8>(a as *const u8, a_len as usize);
let b_slice = slice::from_raw_parts::<u8>(b as *const u8, b_len as usize);
let x = &*(state as *mut Self);
let a_key = from_u8::<<Self as Comparator>::K>(a_slice);
let b_key = from_u8::<<Self as Comparator>::K>(b_slice);
let a_key = <<Self as Comparator>::K>::from(a_slice);
let b_key = <<Self as Comparator>::K>::from(b_slice);
match x.compare(&a_key, &b_key) {
Ordering::Less => -1,
Ordering::Equal => 0,
Expand All @@ -80,24 +82,26 @@ unsafe trait InternalComparator : Comparator where Self: Sized {

extern "C" fn destructor(state: *mut c_void) {
let _x: Box<Self> = unsafe { Box::from_raw(state as *mut Self) };
// let the Box fall out of scope and run the T's destructor
// let the Box fall out of scope and run the T's destructor
}
}

unsafe impl<C: Comparator> InternalComparator for C {}
unsafe impl<'a, C: Comparator<'a>> InternalComparator<'a> for C {}

#[allow(missing_docs)]
pub fn create_comparator<T: Comparator>(x: Box<T>) -> *mut leveldb_comparator_t {
pub fn create_comparator<'a, T: Comparator<'a>>(x: Box<T>) -> *mut leveldb_comparator_t {
unsafe {
leveldb_comparator_create(Box::into_raw(x) as *mut c_void,
<T as InternalComparator>::destructor,
<T as InternalComparator>::compare,
<T as InternalComparator>::name)
leveldb_comparator_create(
Box::into_raw(x) as *mut c_void,
<T as InternalComparator>::destructor,
<T as InternalComparator>::compare,
<T as InternalComparator>::name,
)
}
}

impl<K: Key + Ord> Comparator for OrdComparator<K> {
type K = K;
impl<'a, K: Key<'a> + Ord> Comparator<'a> for OrdComparator<'a, K> {
type K = K;

fn name(&self) -> *const c_char {
let slice: &str = self.name.as_ref();
Expand All @@ -109,14 +113,14 @@ impl<K: Key + Ord> Comparator for OrdComparator<K> {
}
}

impl Comparator for DefaultComparator {
type K = i32;
impl<'a> Comparator<'a> for DefaultComparator {
type K = &'a [u8];

fn name(&self) -> *const c_char {
"default_comparator".as_ptr() as *const c_char
}

fn compare(&self, _a: &i32, _b: &i32) -> Ordering {
fn compare(&self, _a: &&'a [u8], _b: &&'a [u8]) -> Ordering {
Ordering::Equal
}

Expand Down
Loading