Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
R
rust-rocksdb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
fangzongwu
rust-rocksdb
Commits
747a9438
Commit
747a9438
authored
Jul 18, 2015
by
David Greenberg
Browse files
Options
Browse Files
Download
Plain Diff
Fixed tests and merged
parents
bf0c2b3b
cd1037a5
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
95 additions
and
96 deletions
+95
-96
Cargo.toml
Cargo.toml
+1
-1
README.md
README.md
+11
-15
comparator.rs
src/comparator.rs
+7
-5
ffi.rs
src/ffi.rs
+3
-3
lib.rs
src/lib.rs
+4
-20
merge_operator.rs
src/merge_operator.rs
+26
-14
rocksdb.rs
src/rocksdb.rs
+17
-13
rocksdb_options.rs
src/rocksdb_options.rs
+8
-11
test_iterator.rs
test/test_iterator.rs
+18
-14
No files found.
Cargo.toml
View file @
747a9438
...
...
@@ -2,7 +2,7 @@
name
=
"rocksdb"
description
=
"A Rust wrapper for Facebook's RocksDB embeddable database."
version
=
"0.0.
6
"
version
=
"0.0.
7
"
authors
=
[
"Tyler Neely <t@jujit.su>"
,
"David Greenberg <dsg123456789@gmail.com>"
]
license
=
"Apache-2.0"
exclude
=
[
...
...
README.md
View file @
747a9438
...
...
@@ -2,7 +2,7 @@ rust-rocksdb
============
[

](https://travis-ci.org/spacejam/rust-rocksdb)
This library has been tested against RocksDB 3.8.1 on linux and OSX. The 0.0.
6 crate should work with the Rust nightly release as of 7/12
/15.
This library has been tested against RocksDB 3.8.1 on linux and OSX. The 0.0.
7 crate should work with the Rust nightly release as of 7/16
/15.
### status
-
[
x
]
basic open/put/get/delete/close
...
...
@@ -12,7 +12,7 @@ This library has been tested against RocksDB 3.8.1 on linux and OSX. The 0.0.6
-
[
x
]
LRU cache
-
[
x
]
destroy/repair
-
[
x
]
iterator
-
[
]
comparator
-
[
x
]
comparator
-
[
x
]
snapshot
-
[
]
column family operations
-
[
]
slicetransform
...
...
@@ -31,12 +31,12 @@ sudo make install
###### Cargo.toml
```
rust
[
dependencies
]
rocksdb
=
"~0.0.
6
"
rocksdb
=
"~0.0.
7
"
```
###### Code
```
rust
extern
crate
rocksdb
;
use
rocksdb
::
RocksDB
;
use
rocksdb
::
{
RocksDB
,
Writable
}
;
fn
main
()
{
let
mut
db
=
RocksDB
::
open_default
(
"/path/for/rocksdb/storage"
)
.unwrap
();
...
...
@@ -107,7 +107,7 @@ fn main() {
###### Rustic Merge Operator
```
rust
extern
crate
rocksdb
;
use
rocksdb
::{
RocksDBOptions
,
RocksDB
,
MergeOperands
};
use
rocksdb
::{
Options
,
RocksDB
,
MergeOperands
,
Writable
};
fn
concat_merge
(
new_key
:
&
[
u8
],
existing_val
:
Option
<&
[
u8
]
>
,
operands
:
&
mut
MergeOperands
)
->
Vec
<
u8
>
{
...
...
@@ -121,10 +121,10 @@ fn concat_merge(new_key: &[u8], existing_val: Option<&[u8]>,
fn
main
()
{
let
path
=
"/path/to/rocksdb"
;
let
opts
=
RocksDB
Options
::
new
();
let
mut
opts
=
Options
::
new
();
opts
.create_if_missing
(
true
);
opts
.add_merge_operator
(
"test operator"
,
concat_merge
);
let
mut
db
=
RocksDB
::
open
(
opts
,
path
)
.unwrap
();
let
mut
db
=
RocksDB
::
open
(
&
opts
,
path
)
.unwrap
();
let
p
=
db
.put
(
b
"k1"
,
b
"a"
);
db
.merge
(
b
"k1"
,
b
"b"
);
db
.merge
(
b
"k1"
,
b
"c"
);
...
...
@@ -138,14 +138,13 @@ fn main() {
###### Apply Some Tunings
Please read
[
the official tuning guide
](
https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide
)
, and most importantly, measure performance under realistic workloads with realistic hardware.
```
rust
use
rocksdb
::{
RocksDBOptions
,
RocksDB
,
new_bloom_filter
};
use
rocksdb
::{
Options
,
RocksDB
};
use
rocksdb
::
RocksDBCompactionStyle
::
RocksDBUniversalCompaction
;
fn
tuned_for_somebody_elses_disk
()
->
RocksDB
{
fn
badly_
tuned_for_somebody_elses_disk
()
->
RocksDB
{
let
path
=
"_rust_rocksdb_optimizetest"
;
let
opts
=
RocksDB
Options
::
new
();
let
mut
opts
=
Options
::
new
();
opts
.create_if_missing
(
true
);
opts
.set_block_size
(
524288
);
opts
.set_max_open_files
(
10000
);
opts
.set_use_fsync
(
false
);
opts
.set_bytes_per_sync
(
8388608
);
...
...
@@ -164,10 +163,7 @@ fn tuned_for_somebody_elses_disk() -> RocksDB {
opts
.set_filter_deletes
(
false
);
opts
.set_disable_auto_compactions
(
true
);
let
filter
=
new_bloom_filter
(
10
);
opts
.set_filter
(
filter
);
RocksDB
::
open
(
opts
,
path
)
.unwrap
()
RocksDB
::
open
(
&
opts
,
path
)
.unwrap
()
}
```
src/comparator.rs
View file @
747a9438
...
...
@@ -25,7 +25,7 @@ use rocksdb::RocksDB;
pub
struct
ComparatorCallback
{
pub
name
:
CString
,
pub
f
:
fn
(
&
[
u8
],
&
[
u8
])
->
i32
,
pub
f
:
fn
(
&
[
u8
],
&
[
u8
])
->
i32
,
}
pub
extern
"C"
fn
destructor_callback
(
raw_cb
:
*
mut
c_void
)
{
...
...
@@ -42,10 +42,12 @@ pub extern "C" fn name_callback(raw_cb: *mut c_void) -> *const c_char {
}
}
pub
extern
"C"
fn
compare_callback
(
raw_cb
:
*
mut
c_void
,
a_raw
:
*
const
c_char
,
a_len
:
size_t
,
b_raw
:
*
const
c_char
,
b_len
:
size_t
)
->
c_int
{
pub
extern
"C"
fn
compare_callback
(
raw_cb
:
*
mut
c_void
,
a_raw
:
*
const
c_char
,
a_len
:
size_t
,
b_raw
:
*
const
c_char
,
b_len
:
size_t
)
->
c_int
{
unsafe
{
let
cb
:
&
mut
ComparatorCallback
=
&
mut
*
(
raw_cb
as
*
mut
ComparatorCallback
);
...
...
src/ffi.rs
View file @
747a9438
...
...
@@ -76,20 +76,20 @@ pub enum RocksDBCompressionType {
RocksDBZlibCompression
=
2
,
RocksDBBz2Compression
=
3
,
RocksDBLz4Compression
=
4
,
RocksDBLz4hcCompression
=
5
RocksDBLz4hcCompression
=
5
,
}
#[repr(C)]
pub
enum
RocksDBCompactionStyle
{
RocksDBLevelCompaction
=
0
,
RocksDBUniversalCompaction
=
1
,
RocksDBFifoCompaction
=
2
RocksDBFifoCompaction
=
2
,
}
#[repr(C)]
pub
enum
RocksDBUniversalCompactionStyle
{
rocksdb_similar_size_compaction_stop_style
=
0
,
rocksdb_total_size_compaction_stop_style
=
1
rocksdb_total_size_compaction_stop_style
=
1
,
}
//TODO audit the use of boolean arguments, b/c I think they need to be u8 instead...
...
...
src/lib.rs
View file @
747a9438
...
...
@@ -21,26 +21,10 @@
#
!
[
feature
(
raw
)]
pub
use
ffi
as
rocksdb_ffi
;
pub
use
ffi
::{
new_bloom_filter
,
RocksDBCompactionStyle
,
RocksDBComparator
,
};
pub
use
rocksdb
::{
RocksDB
,
RocksDBResult
,
RocksDBVector
,
WriteBatch
,
Writable
,
Direction
,
};
pub
use
rocksdb_options
::{
Options
,
BlockBasedOptions
,
};
pub
use
merge_operator
::{
MergeOperands
,
};
pub
use
ffi
::{
new_bloom_filter
,
RocksDBCompactionStyle
,
RocksDBComparator
};
pub
use
rocksdb
::{
RocksDB
,
RocksDBResult
,
RocksDBVector
,
WriteBatch
,
Writable
,
Direction
};
pub
use
rocksdb_options
::{
Options
,
BlockBasedOptions
};
pub
use
merge_operator
::
MergeOperands
;
pub
mod
rocksdb
;
pub
mod
ffi
;
pub
mod
rocksdb_options
;
...
...
src/merge_operator.rs
View file @
747a9438
...
...
@@ -20,12 +20,12 @@ use std::mem;
use
std
::
ptr
;
use
std
::
slice
;
use
rocksdb_options
::
{
Options
}
;
use
rocksdb_options
::
Options
;
use
rocksdb
::{
RocksDB
,
RocksDBResult
,
RocksDBVector
,
Writable
};
pub
struct
MergeOperatorCallback
{
pub
name
:
CString
,
pub
merge_fn
:
fn
(
&
[
u8
],
Option
<&
[
u8
]
>
,
&
mut
MergeOperands
)
->
Vec
<
u8
>
,
pub
merge_fn
:
fn
(
&
[
u8
],
Option
<&
[
u8
]
>
,
&
mut
MergeOperands
)
->
Vec
<
u8
>
,
}
pub
extern
"C"
fn
destructor_callback
(
raw_cb
:
*
mut
c_void
)
{
...
...
@@ -43,12 +43,17 @@ pub extern "C" fn name_callback(raw_cb: *mut c_void) -> *const c_char {
}
}
pub
extern
"C"
fn
full_merge_callback
(
raw_cb
:
*
mut
c_void
,
raw_key
:
*
const
c_char
,
key_len
:
size_t
,
existing_value
:
*
const
c_char
,
existing_value_len
:
size_t
,
operands_list
:
*
const
*
const
c_char
,
operands_list_len
:
*
const
size_t
,
pub
extern
"C"
fn
full_merge_callback
(
raw_cb
:
*
mut
c_void
,
raw_key
:
*
const
c_char
,
key_len
:
size_t
,
existing_value
:
*
const
c_char
,
existing_value_len
:
size_t
,
operands_list
:
*
const
*
const
c_char
,
operands_list_len
:
*
const
size_t
,
num_operands
:
c_int
,
success
:
*
mut
u8
,
new_value_length
:
*
mut
size_t
)
->
*
const
c_char
{
success
:
*
mut
u8
,
new_value_length
:
*
mut
size_t
)
->
*
const
c_char
{
unsafe
{
let
cb
:
&
mut
MergeOperatorCallback
=
&
mut
*
(
raw_cb
as
*
mut
MergeOperatorCallback
);
...
...
@@ -72,11 +77,15 @@ pub extern "C" fn full_merge_callback(
}
}
pub
extern
"C"
fn
partial_merge_callback
(
raw_cb
:
*
mut
c_void
,
raw_key
:
*
const
c_char
,
key_len
:
size_t
,
operands_list
:
*
const
*
const
c_char
,
operands_list_len
:
*
const
size_t
,
pub
extern
"C"
fn
partial_merge_callback
(
raw_cb
:
*
mut
c_void
,
raw_key
:
*
const
c_char
,
key_len
:
size_t
,
operands_list
:
*
const
*
const
c_char
,
operands_list_len
:
*
const
size_t
,
num_operands
:
c_int
,
success
:
*
mut
u8
,
new_value_length
:
*
mut
size_t
)
->
*
const
c_char
{
success
:
*
mut
u8
,
new_value_length
:
*
mut
size_t
)
->
*
const
c_char
{
unsafe
{
let
cb
:
&
mut
MergeOperatorCallback
=
&
mut
*
(
raw_cb
as
*
mut
MergeOperatorCallback
);
...
...
@@ -107,7 +116,8 @@ pub struct MergeOperands {
impl
MergeOperands
{
fn
new
(
operands_list
:
*
const
*
const
c_char
,
operands_list_len
:
*
const
size_t
,
num_operands
:
c_int
)
->
MergeOperands
{
num_operands
:
c_int
)
->
MergeOperands
{
assert
!
(
num_operands
>=
0
);
MergeOperands
{
operands_list
:
operands_list
,
...
...
@@ -148,8 +158,10 @@ impl<'a> Iterator for &'a mut MergeOperands {
}
}
fn
test_provided_merge
(
new_key
:
&
[
u8
],
existing_val
:
Option
<&
[
u8
]
>
,
mut
operands
:
&
mut
MergeOperands
)
->
Vec
<
u8
>
{
fn
test_provided_merge
(
new_key
:
&
[
u8
],
existing_val
:
Option
<&
[
u8
]
>
,
mut
operands
:
&
mut
MergeOperands
)
->
Vec
<
u8
>
{
let
nops
=
operands
.size_hint
()
.
0
;
let
mut
result
:
Vec
<
u8
>
=
Vec
::
with_capacity
(
nops
);
match
existing_val
{
...
...
src/rocksdb.rs
View file @
747a9438
...
...
@@ -46,14 +46,16 @@ pub struct Snapshot<'a> {
}
pub
struct
DBIterator
{
//TODO: should have a reference to DB to enforce scope, but it's trickier than I thought to add
// TODO: should have a reference to DB to enforce scope, but it's trickier than I
// thought to add
inner
:
rocksdb_ffi
::
RocksDBIterator
,
direction
:
Direction
,
just_seeked
:
bool
just_seeked
:
bool
,
}
pub
enum
Direction
{
forward
,
reverse
forward
,
reverse
,
}
pub
struct
SubDBIterator
<
'a
>
{
...
...
@@ -106,7 +108,7 @@ impl DBIterator {
unsafe
{
rocksdb_ffi
::
rocksdb_iter_seek_to_first
(
self
.inner
);
};
SubDBIterator
{
iter
:
self
,
direction
:
Direction
::
forward
,
}
SubDBIterator
{
iter
:
self
,
direction
:
Direction
::
forward
}
}
pub
fn
from_end
(
&
mut
self
)
->
SubDBIterator
{
...
...
@@ -114,7 +116,7 @@ impl DBIterator {
unsafe
{
rocksdb_ffi
::
rocksdb_iter_seek_to_last
(
self
.inner
);
};
SubDBIterator
{
iter
:
self
,
direction
:
Direction
::
reverse
,
}
SubDBIterator
{
iter
:
self
,
direction
:
Direction
::
reverse
}
}
pub
fn
from
(
&
mut
self
,
key
:
&
[
u8
],
dir
:
Direction
)
->
SubDBIterator
{
...
...
@@ -122,7 +124,7 @@ impl DBIterator {
unsafe
{
rocksdb_ffi
::
rocksdb_iter_seek
(
self
.inner
,
key
.as_ptr
(),
key
.len
()
as
size_t
);
}
SubDBIterator
{
iter
:
self
,
direction
:
dir
,
}
SubDBIterator
{
iter
:
self
,
direction
:
dir
}
}
}
...
...
@@ -137,7 +139,7 @@ impl Drop for DBIterator {
impl
<
'a
>
Snapshot
<
'a
>
{
pub
fn
new
(
db
:
&
RocksDB
)
->
Snapshot
{
let
snapshot
=
unsafe
{
rocksdb_ffi
::
rocksdb_create_snapshot
(
db
.inner
)
};
Snapshot
{
db
:
db
,
inner
:
snapshot
}
Snapshot
{
db
:
db
,
inner
:
snapshot
}
}
pub
fn
iterator
(
&
self
)
->
DBIterator
{
...
...
@@ -181,7 +183,8 @@ impl RocksDB {
pub
fn
open
(
opts
:
&
Options
,
path
:
&
str
)
->
Result
<
RocksDB
,
String
>
{
let
cpath
=
match
CString
::
new
(
path
.as_bytes
())
{
Ok
(
c
)
=>
c
,
Err
(
_
)
=>
return
Err
(
"Failed to convert path to CString when opening rocksdb"
.to_string
()),
Err
(
_
)
=>
return
Err
(
"Failed to convert path to CString when opening rocksdb"
.to_string
()),
};
let
cpath_ptr
=
cpath
.as_ptr
();
...
...
@@ -208,7 +211,7 @@ impl RocksDB {
if
db_ptr
.is_null
()
{
return
Err
(
"Could not initialize database."
.to_string
());
}
Ok
(
RocksDB
{
inner
:
db
})
Ok
(
RocksDB
{
inner
:
db
})
}
pub
fn
destroy
(
opts
:
&
Options
,
path
:
&
str
)
->
Result
<
(),
String
>
{
...
...
@@ -358,7 +361,7 @@ impl WriteBatch {
WriteBatch
{
inner
:
unsafe
{
rocksdb_ffi
::
rocksdb_writebatch_create
()
}
}
,
}
}
}
...
...
@@ -419,8 +422,9 @@ impl ReadOptions {
ReadOptions
{
inner
:
rocksdb_ffi
::
rocksdb_readoptions_create
()}
}
}
//TODO add snapshot setting here
//TODO add snapshot wrapper structs with proper destructors; that struct needs an "iterator" impl too.
// TODO add snapshot setting here
// TODO add snapshot wrapper structs with proper destructors;
// that struct needs an "iterator" impl too.
fn
fill_cache
(
&
mut
self
,
v
:
bool
)
{
unsafe
{
rocksdb_ffi
::
rocksdb_readoptions_set_fill_cache
(
self
.inner
,
v
);
...
...
@@ -505,7 +509,7 @@ impl <T, E> RocksDBResult<T, E> {
}
}
pub
fn
on_absent
<
F
:
FnOnce
()
->
()
>
(
self
,
f
:
F
)
->
RocksDBResult
<
T
,
E
>
{
pub
fn
on_absent
<
F
:
FnOnce
()
->
()
>
(
self
,
f
:
F
)
->
RocksDBResult
<
T
,
E
>
{
match
self
{
RocksDBResult
::
Some
(
x
)
=>
RocksDBResult
::
Some
(
x
),
RocksDBResult
::
None
=>
{
...
...
src/rocksdb_options.rs
View file @
747a9438
...
...
@@ -19,8 +19,8 @@ use std::ffi::CString;
use
std
::
mem
;
use
rocksdb_ffi
;
use
merge_operator
::{
self
,
MergeOperatorCallback
,
MergeOperands
,
full_merge_callback
,
partial_merge_callback
};
use
merge_operator
::{
self
,
MergeOperatorCallback
,
MergeOperands
,
full_merge_callback
,
partial_merge_callback
};
use
comparator
::{
self
,
ComparatorCallback
,
compare_callback
};
pub
struct
BlockBasedOptions
{
...
...
@@ -54,7 +54,7 @@ impl BlockBasedOptions {
if
opt_ptr
.is_null
()
{
panic!
(
"Could not create rocksdb block based options"
.to_string
());
}
BlockBasedOptions
{
inner
:
block_opts
,
}
BlockBasedOptions
{
inner
:
block_opts
}
}
pub
fn
set_block_size
(
&
mut
self
,
size
:
u64
)
{
...
...
@@ -107,8 +107,7 @@ impl Options {
}
}
pub
fn
optimize_level_style_compaction
(
&
mut
self
,
memtable_memory_budget
:
i32
)
{
pub
fn
optimize_level_style_compaction
(
&
mut
self
,
memtable_memory_budget
:
i32
)
{
unsafe
{
rocksdb_ffi
::
rocksdb_options_optimize_level_style_compaction
(
self
.inner
,
memtable_memory_budget
);
...
...
@@ -122,8 +121,9 @@ impl Options {
}
}
pub
fn
add_merge_operator
<
'a
>
(
&
mut
self
,
name
:
&
str
,
merge_fn
:
fn
(
&
[
u8
],
Option
<&
[
u8
]
>
,
&
mut
MergeOperands
)
->
Vec
<
u8
>
)
{
pub
fn
add_merge_operator
<
'a
>
(
&
mut
self
,
name
:
&
str
,
merge_fn
:
fn
(
&
[
u8
],
Option
<&
[
u8
]
>
,
&
mut
MergeOperands
)
->
Vec
<
u8
>
)
{
let
cb
=
Box
::
new
(
MergeOperatorCallback
{
name
:
CString
::
new
(
name
.as_bytes
())
.unwrap
(),
merge_fn
:
merge_fn
,
...
...
@@ -258,8 +258,7 @@ impl Options {
}
}
pub
fn
set_compaction_style
(
&
mut
self
,
style
:
rocksdb_ffi
::
RocksDBCompactionStyle
)
{
pub
fn
set_compaction_style
(
&
mut
self
,
style
:
rocksdb_ffi
::
RocksDBCompactionStyle
)
{
unsafe
{
rocksdb_ffi
::
rocksdb_options_set_compaction_style
(
self
.inner
,
style
);
...
...
@@ -306,5 +305,3 @@ impl Options {
}
}
}
test/test_iterator.rs
View file @
747a9438
use
rocksdb
::{
Options
,
RocksDB
,
Writable
,
Direction
};
use
std
;
fn
cba
(
input
:
&
Box
<
[
u8
]
>
)
->
Box
<
[
u8
]
>
{
input
.iter
()
.cloned
()
.collect
::
<
Vec
<
_
>>
()
.into_boxed_slice
()
}
#[test]
pub
fn
test_iterator
()
{
...
...
@@ -22,7 +25,7 @@ pub fn test_iterator() {
let
p
=
db
.put
(
&*
k3
,
&*
v3
);
assert
!
(
p
.is_ok
());
let
mut
view1
=
db
.iterator
();
let
expected
=
vec!
[(
k1
,
v1
),
(
k2
,
v2
),
(
k3
,
v3
)];
let
expected
=
vec!
[(
cba
(
&
k1
),
cba
(
&
v1
)),
(
cba
(
&
k2
),
cba
(
&
v2
)),
(
cba
(
&
k3
),
cba
(
&
v3
)
)];
{
let
mut
iterator1
=
view1
.from_start
();
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected
);
...
...
@@ -82,26 +85,27 @@ pub fn test_iterator() {
}
let
mut
view2
=
db
.iterator
();
let
p
=
db
.put
(
k4
,
v4
);
let
p
=
db
.put
(
&*
k4
,
&*
v4
);
assert
!
(
p
.is_ok
());
let
mut
view3
=
db
.iterator
();
let
expected2
=
vec!
[(
k1
,
v1
),
(
k2
,
v2
),
(
k3
,
v3
),
(
k4
,
v4
)];
let
expected2
=
vec!
[(
cba
(
&
k1
),
cba
(
&
v1
)),
(
cba
(
&
k2
),
cba
(
&
v2
)),
(
cba
(
&
k3
),
cba
(
&
v3
)),
(
cba
(
&
k4
),
cba
(
&
v4
)
)];
{
let
mut
iterator1
=
view1
.from_start
();
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected
2
);
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected
);
}
//TODO continue implementing tests!
println!
(
"See the output of the third iter"
);
for
(
k
,
v
)
in
view3
.from_start
()
{
//println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
{
let
mut
iterator1
=
view3
.from_start
();
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected2
);
}
println!
(
"now the 3rd iter from k2 fwd"
);
for
(
k
,
v
)
in
view3
.from
(
b
"k2"
,
Direction
::
forward
)
{
//println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
{
let
mut
iterator1
=
view3
.from
(
b
"k2"
,
Direction
::
forward
);
let
expected
=
vec!
[(
cba
(
&
k2
),
cba
(
&
v2
)),
(
cba
(
&
k3
),
cba
(
&
v3
)),
(
cba
(
&
k4
),
cba
(
&
v4
))];
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected
);
}
println!
(
"now the 3rd iter from k2 and back"
);
for
(
k
,
v
)
in
view3
.from
(
b
"k2"
,
Direction
::
reverse
)
{
//println!("Hello {}: {}", std::str::from_utf8(k).unwrap(), std::str::from_utf8(v).unwrap());
{
let
mut
iterator1
=
view3
.from
(
b
"k2"
,
Direction
::
reverse
);
let
expected
=
vec!
[(
cba
(
&
k2
),
cba
(
&
v2
)),
(
cba
(
&
k1
),
cba
(
&
v1
))];
assert_eq!
(
iterator1
.collect
::
<
Vec
<
_
>>
(),
expected
);
}
}
let
opts
=
Options
::
new
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment