1 module rocksdb.iterator;
2 
3 import std.conv : to;
4 import std.string : fromStringz, toStringz;
5 
6 import rocksdb.slice : Slice;
7 import rocksdb.options : ReadOptions, rocksdb_readoptions_t;
8 import rocksdb.database : Database, rocksdb_t;
9 
10 extern (C) {
11   struct rocksdb_iterator_t {};
12 
13   rocksdb_iterator_t* rocksdb_create_iterator(rocksdb_t*, rocksdb_readoptions_t*);
14   void rocksdb_iter_destroy(rocksdb_iterator_t*);
15   ubyte rocksdb_iter_valid(const rocksdb_iterator_t*);
16   void rocksdb_iter_seek_to_first(rocksdb_iterator_t*);
17   void rocksdb_iter_seek_to_last(rocksdb_iterator_t*);
18   void rocksdb_iter_seek(rocksdb_iterator_t*, const char*, size_t);
19   void rocksdb_iter_seek_for_prev(rocksdb_iterator_t*, const char*, size_t);
20   void rocksdb_iter_next(rocksdb_iterator_t*);
21   void rocksdb_iter_prev(rocksdb_iterator_t*);
22   immutable(char*) rocksdb_iter_key(const rocksdb_iterator_t*, size_t*);
23   immutable(char*) rocksdb_iter_value(const rocksdb_iterator_t*, size_t*);
24   void rocksdb_iter_get_error(const rocksdb_iterator_t*, char**);
25 }
26 
27 class Iterator {
28   rocksdb_iterator_t* iter;
29 
30   this(Database db) {
31     this(db, db.readOptions);
32   }
33 
34   this(Database db, ReadOptions opts) {
35     this.iter = rocksdb_create_iterator(db.db, opts.opts);
36     this.seekToFirst();
37   }
38 
39   ~this() {
40     rocksdb_iter_destroy(this.iter);
41   }
42 
43   void seekToFirst() {
44     rocksdb_iter_seek_to_first(this.iter);
45   }
46 
47   void seekToLast() {
48     rocksdb_iter_seek_to_last(this.iter);
49   }
50 
51   void seek(string key) {
52     rocksdb_iter_seek(this.iter, toStringz(key), key.length);
53   }
54 
55   void seekPrev(string key) {
56     rocksdb_iter_seek_for_prev(this.iter, toStringz(key), key.length);
57   }
58 
59   void next() {
60     rocksdb_iter_next(this.iter);
61   }
62 
63   void prev() {
64     rocksdb_iter_prev(this.iter);
65   }
66 
67   bool valid() {
68     return cast(bool)rocksdb_iter_valid(this.iter);
69   }
70 
71   string key() {
72     return this.keySlice().toString();
73   }
74 
75   Slice keySlice() {
76     size_t size;
77     immutable char* ckey = rocksdb_iter_key(this.iter, &size);
78     return Slice(size, ckey);
79   }
80 
81   string value() {
82     return this.valueSlice().toString();
83   }
84 
85   Slice valueSlice() {
86     size_t size;
87     immutable char* cvalue = rocksdb_iter_value(this.iter, &size);
88     return Slice(size, cvalue);
89   }
90 
91   int opApply(scope int delegate(ref string, ref string) dg) {
92     string key;
93     string value;
94     int result = 0;
95 
96     while (this.valid()) {
97       key = this.key();
98       value = this.value();
99 
100       result = dg(key, value);
101       if (result) break;
102       this.next();
103     }
104 
105     return result;
106   }
107 }