Skip to main content

nimiq_database/mdbx/
cursor.rs

1use std::{borrow::Cow, cmp::Ordering, marker::PhantomData};
2
3use libmdbx::{TransactionKind, WriteFlags, RO, RW};
4use nimiq_database_value::{AsDatabaseBytes, FromDatabaseBytes};
5
6use super::{IntoIter, IntoIterProxy};
7use crate::traits::{
8    DupReadCursor, DupSubKey, DupTable, DupTableValue, DupWriteCursor, ReadCursor, Row, Table,
9    WriteCursor,
10};
11
12type DbKvPair<'a> = (Cow<'a, [u8]>, Cow<'a, [u8]>);
13
14/// A cursor for navigating the entries within a table.
15/// Wraps the libmdbx cursor so that we only expose our own methods.
16pub struct MdbxCursor<'txn, K: TransactionKind, T: Table> {
17    cursor: libmdbx::Cursor<'txn, K>,
18    _table: PhantomData<T>,
19}
20/// Instantiation of the `MdbxCursor` for read transactions.
21pub type MdbxReadCursor<'txn, T> = MdbxCursor<'txn, RO, T>;
22/// Instantiation of the `MdbxCursor` for write transactions.
23pub type MdbxWriteCursor<'txn, T> = MdbxCursor<'txn, RW, T>;
24
25impl<'txn, Kind: TransactionKind, T: Table> MdbxCursor<'txn, Kind, T> {
26    pub(crate) fn new(cursor: libmdbx::Cursor<'txn, Kind>) -> Self {
27        MdbxCursor {
28            cursor,
29            _table: PhantomData,
30        }
31    }
32}
33
34impl<Kind: TransactionKind, T: DupTable> MdbxCursor<'_, Kind, T>
35where
36    T::Value: DupTableValue,
37{
38    fn encode_subkey(subkey: &DupSubKey<T>) -> Cow<'_, [u8]> {
39        let enc_key = subkey.as_value_bytes();
40        if let Some(new_len) = T::Value::FIXED_SIZE {
41            let mut owned = enc_key.into_owned();
42            owned.resize(new_len, 0);
43            Cow::Owned(owned)
44        } else {
45            enc_key
46        }
47    }
48}
49
50impl<'txn, Kind: TransactionKind, T: Table> ReadCursor<'txn, T> for MdbxCursor<'txn, Kind, T> {
51    type IntoIter = IntoIter<'txn, Kind, T>;
52
53    fn first(&mut self) -> Option<Row<T>> {
54        let result: Option<DbKvPair> = self.cursor.first().unwrap();
55        let (key, value) = result?;
56        Some((
57            FromDatabaseBytes::from_key_bytes(&key),
58            FromDatabaseBytes::from_value_bytes(&value),
59        ))
60    }
61
62    fn last(&mut self) -> Option<Row<T>> {
63        let result: Option<DbKvPair> = self.cursor.last().unwrap();
64        let (key, value) = result?;
65        Some((
66            FromDatabaseBytes::from_key_bytes(&key),
67            FromDatabaseBytes::from_value_bytes(&value),
68        ))
69    }
70
71    fn next(&mut self) -> Option<Row<T>> {
72        let result: Option<DbKvPair> = self.cursor.next().unwrap();
73        let (key, value) = result?;
74        Some((
75            FromDatabaseBytes::from_key_bytes(&key),
76            FromDatabaseBytes::from_value_bytes(&value),
77        ))
78    }
79
80    fn prev(&mut self) -> Option<Row<T>> {
81        let result: Option<DbKvPair> = self.cursor.prev().unwrap();
82        let (key, value) = result?;
83        Some((
84            FromDatabaseBytes::from_key_bytes(&key),
85            FromDatabaseBytes::from_value_bytes(&value),
86        ))
87    }
88
89    fn get_current(&mut self) -> Option<Row<T>> {
90        let result: Option<DbKvPair> = self.cursor.get_current().unwrap();
91        let (key, value) = result?;
92        Some((
93            FromDatabaseBytes::from_key_bytes(&key),
94            FromDatabaseBytes::from_value_bytes(&value),
95        ))
96    }
97
98    fn set_key(&mut self, key: &T::Key) -> Option<T::Value> {
99        let key = AsDatabaseBytes::as_key_bytes(key);
100        let result: Option<Cow<[u8]>> = self.cursor.set(key.as_ref()).unwrap();
101        Some(FromDatabaseBytes::from_value_bytes(&result?))
102    }
103
104    fn set_lowerbound_key(&mut self, key: &T::Key) -> Option<Row<T>> {
105        let key = AsDatabaseBytes::as_key_bytes(key);
106        let result: Option<DbKvPair> = self.cursor.set_range(key.as_ref()).unwrap();
107        let (key, value) = result?;
108        Some((
109            FromDatabaseBytes::from_key_bytes(&key),
110            FromDatabaseBytes::from_value_bytes(&value),
111        ))
112    }
113
114    fn into_iter_start(self) -> Self::IntoIter {
115        Self::IntoIter {
116            iter: self.cursor.into_iter_start(),
117            _t: PhantomData,
118        }
119    }
120
121    fn into_iter_from(self, key: &T::Key) -> Self::IntoIter {
122        let key = AsDatabaseBytes::as_key_bytes(key);
123        Self::IntoIter {
124            iter: self.cursor.into_iter_from(key.as_ref()),
125            _t: PhantomData,
126        }
127    }
128}
129
130impl<'txn, Kind: TransactionKind, T: DupTable> DupReadCursor<'txn, T>
131    for MdbxCursor<'txn, Kind, T>
132{
133    fn first_duplicate(&mut self) -> Option<T::Value> {
134        let result: Option<Cow<[u8]>> = self.cursor.first_dup().unwrap();
135        Some(FromDatabaseBytes::from_value_bytes(&result?))
136    }
137
138    fn last_duplicate(&mut self) -> Option<T::Value> {
139        let result: Option<Cow<[u8]>> = self.cursor.last_dup().unwrap();
140        Some(FromDatabaseBytes::from_value_bytes(&result?))
141    }
142
143    fn next_duplicate(&mut self) -> Option<Row<T>> {
144        let result: Option<DbKvPair> = self.cursor.next_dup().unwrap();
145        let (key, value) = result?;
146        Some((
147            FromDatabaseBytes::from_key_bytes(&key),
148            FromDatabaseBytes::from_value_bytes(&value),
149        ))
150    }
151
152    fn next_no_duplicate(&mut self) -> Option<Row<T>> {
153        let result: Option<DbKvPair> = self.cursor.next_nodup().unwrap();
154        let (key, value) = result?;
155        Some((
156            FromDatabaseBytes::from_key_bytes(&key),
157            FromDatabaseBytes::from_value_bytes(&value),
158        ))
159    }
160
161    fn prev_duplicate(&mut self) -> Option<Row<T>> {
162        let result: Option<DbKvPair> = self.cursor.prev_dup().unwrap();
163        let (key, value) = result?;
164        Some((
165            FromDatabaseBytes::from_key_bytes(&key),
166            FromDatabaseBytes::from_value_bytes(&value),
167        ))
168    }
169
170    fn prev_no_duplicate(&mut self) -> Option<Row<T>> {
171        let result: Option<DbKvPair> = self.cursor.prev_nodup().unwrap();
172        let (key, value) = result?;
173        Some((
174            FromDatabaseBytes::from_key_bytes(&key),
175            FromDatabaseBytes::from_value_bytes(&value),
176        ))
177    }
178
179    fn set_subkey(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<T::Value>
180    where
181        T::Value: DupTableValue,
182    {
183        let value = self.set_lowerbound_subkey(key, subkey)?;
184        if value.subkey().cmp(subkey) == Ordering::Equal {
185            Some(value)
186        } else {
187            None
188        }
189    }
190
191    fn set_lowerbound_both(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<Row<T>>
192    where
193        T::Value: DupTableValue,
194    {
195        let key = AsDatabaseBytes::as_key_bytes(key);
196        let data = Self::encode_subkey(subkey);
197        let result: Option<(bool, Cow<[u8]>, Cow<[u8]>)> = self
198            .cursor
199            .set_lowerbound(key.as_ref(), Some(data.as_ref()))
200            .unwrap();
201        let (_exact_match, key, value) = result?;
202        Some((
203            FromDatabaseBytes::from_key_bytes(&key),
204            FromDatabaseBytes::from_value_bytes(&value),
205        ))
206    }
207
208    fn set_lowerbound_subkey(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<T::Value>
209    where
210        T::Value: DupTableValue,
211    {
212        let key = AsDatabaseBytes::as_key_bytes(key);
213        let data = Self::encode_subkey(subkey);
214        let result: Option<Cow<[u8]>> = self
215            .cursor
216            .get_both_range(key.as_ref(), data.as_ref())
217            .unwrap();
218        let value = result?;
219        Some(FromDatabaseBytes::from_value_bytes(&value))
220    }
221
222    fn count_duplicates(&mut self) -> usize {
223        let result: Option<DbKvPair> = self.cursor.get_current().unwrap();
224
225        if let Some((key, _)) = result {
226            self.cursor.iter_dup_of::<(), ()>(&key).count()
227        } else {
228            0_usize
229        }
230    }
231
232    fn into_iter_dup_of(self, key: &T::Key) -> Self::IntoIter {
233        let key = AsDatabaseBytes::as_key_bytes(key);
234        Self::IntoIter {
235            iter: self.cursor.into_iter_dup_of(key.as_ref()),
236            _t: PhantomData,
237        }
238    }
239}
240
241impl<Kind: TransactionKind, T: Table> Clone for MdbxCursor<'_, Kind, T> {
242    fn clone(&self) -> Self {
243        Self {
244            cursor: self.cursor.clone(),
245            _table: PhantomData,
246        }
247    }
248}
249
250impl<'txn, T: Table> WriteCursor<'txn, T> for MdbxWriteCursor<'txn, T> {
251    fn remove(&mut self) {
252        self.cursor.del(WriteFlags::empty()).unwrap();
253    }
254
255    fn append(&mut self, key: &T::Key, value: &T::Value) {
256        let key = AsDatabaseBytes::as_key_bytes(key);
257        let value = AsDatabaseBytes::as_value_bytes(value);
258        self.cursor.put(&key, &value, WriteFlags::APPEND).unwrap();
259    }
260
261    fn put(&mut self, key: &T::Key, value: &T::Value) {
262        let key = AsDatabaseBytes::as_key_bytes(key);
263        let value = AsDatabaseBytes::as_value_bytes(value);
264        self.cursor.put(&key, &value, WriteFlags::empty()).unwrap();
265    }
266}
267
268impl<'txn, T: DupTable> DupWriteCursor<'txn, T> for MdbxWriteCursor<'txn, T> {
269    fn append_dup(&mut self, key: &<T>::Key, value: &<T>::Value) {
270        let key = AsDatabaseBytes::as_key_bytes(key);
271        let value = AsDatabaseBytes::as_value_bytes(value);
272        self.cursor
273            .put(&key, &value, WriteFlags::APPEND_DUP)
274            .unwrap();
275    }
276
277    fn remove_all_dup(&mut self) {
278        self.cursor.del(WriteFlags::ALLDUPS).unwrap();
279    }
280}
281
282/// Proxy to abstract away the transaction kind.
283/// This is a read-only cursor.
284pub enum CursorProxy<'txn, T: Table> {
285    Read(MdbxCursor<'txn, RO, T>),
286    Write(MdbxCursor<'txn, RW, T>),
287}
288
289impl<T: Table> Clone for CursorProxy<'_, T> {
290    fn clone(&self) -> Self {
291        match self {
292            Self::Read(cursor) => Self::Read(cursor.clone()),
293            Self::Write(cursor) => Self::Write(cursor.clone()),
294        }
295    }
296}
297
298impl<'txn, T: Table> ReadCursor<'txn, T> for CursorProxy<'txn, T> {
299    type IntoIter = IntoIterProxy<'txn, T>;
300
301    fn first(&mut self) -> Option<Row<T>> {
302        match self {
303            Self::Read(cursor) => cursor.first(),
304            Self::Write(cursor) => cursor.first(),
305        }
306    }
307
308    fn last(&mut self) -> Option<Row<T>> {
309        match self {
310            Self::Read(cursor) => cursor.last(),
311            Self::Write(cursor) => cursor.last(),
312        }
313    }
314
315    fn next(&mut self) -> Option<Row<T>> {
316        match self {
317            Self::Read(cursor) => cursor.next(),
318            Self::Write(cursor) => cursor.next(),
319        }
320    }
321
322    fn prev(&mut self) -> Option<Row<T>> {
323        match self {
324            Self::Read(cursor) => cursor.prev(),
325            Self::Write(cursor) => cursor.prev(),
326        }
327    }
328
329    fn get_current(&mut self) -> Option<Row<T>> {
330        match self {
331            Self::Read(cursor) => cursor.get_current(),
332            Self::Write(cursor) => cursor.get_current(),
333        }
334    }
335
336    fn set_key(&mut self, key: &T::Key) -> Option<<T as Table>::Value> {
337        match self {
338            Self::Read(cursor) => cursor.set_key(key),
339            Self::Write(cursor) => cursor.set_key(key),
340        }
341    }
342
343    fn set_lowerbound_key(&mut self, key: &T::Key) -> Option<Row<T>> {
344        match self {
345            Self::Read(cursor) => cursor.set_lowerbound_key(key),
346            Self::Write(cursor) => cursor.set_lowerbound_key(key),
347        }
348    }
349
350    fn into_iter_start(self) -> Self::IntoIter {
351        match self {
352            Self::Read(cursor) => IntoIterProxy::Read(cursor.into_iter_start()),
353            Self::Write(cursor) => IntoIterProxy::Write(cursor.into_iter_start()),
354        }
355    }
356
357    fn into_iter_from(self, key: &T::Key) -> Self::IntoIter {
358        match self {
359            Self::Read(cursor) => IntoIterProxy::Read(cursor.into_iter_from(key)),
360            Self::Write(cursor) => IntoIterProxy::Write(cursor.into_iter_from(key)),
361        }
362    }
363}
364
365impl<'txn, T: DupTable> DupReadCursor<'txn, T> for CursorProxy<'txn, T> {
366    fn first_duplicate(&mut self) -> Option<T::Value> {
367        match self {
368            Self::Read(cursor) => cursor.first_duplicate(),
369            Self::Write(cursor) => cursor.first_duplicate(),
370        }
371    }
372
373    fn last_duplicate(&mut self) -> Option<T::Value> {
374        match self {
375            Self::Read(cursor) => cursor.last_duplicate(),
376            Self::Write(cursor) => cursor.last_duplicate(),
377        }
378    }
379
380    fn next_duplicate(&mut self) -> Option<Row<T>> {
381        match self {
382            Self::Read(cursor) => cursor.next_duplicate(),
383            Self::Write(cursor) => cursor.next_duplicate(),
384        }
385    }
386
387    fn next_no_duplicate(&mut self) -> Option<Row<T>> {
388        match self {
389            Self::Read(cursor) => cursor.next_no_duplicate(),
390            Self::Write(cursor) => cursor.next_no_duplicate(),
391        }
392    }
393
394    fn prev_duplicate(&mut self) -> Option<Row<T>> {
395        match self {
396            Self::Read(cursor) => cursor.prev_duplicate(),
397            Self::Write(cursor) => cursor.prev_duplicate(),
398        }
399    }
400
401    fn prev_no_duplicate(&mut self) -> Option<Row<T>> {
402        match self {
403            Self::Read(cursor) => cursor.prev_no_duplicate(),
404            Self::Write(cursor) => cursor.prev_no_duplicate(),
405        }
406    }
407
408    fn set_subkey(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<T::Value>
409    where
410        T::Value: DupTableValue,
411    {
412        match self {
413            Self::Read(cursor) => cursor.set_subkey(key, subkey),
414            Self::Write(cursor) => cursor.set_subkey(key, subkey),
415        }
416    }
417
418    fn set_lowerbound_both(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<Row<T>>
419    where
420        T::Value: DupTableValue,
421    {
422        match self {
423            Self::Read(cursor) => cursor.set_lowerbound_both(key, subkey),
424            Self::Write(cursor) => cursor.set_lowerbound_both(key, subkey),
425        }
426    }
427
428    fn set_lowerbound_subkey(&mut self, key: &T::Key, subkey: &DupSubKey<T>) -> Option<T::Value>
429    where
430        T::Value: DupTableValue,
431    {
432        match self {
433            Self::Read(cursor) => cursor.set_lowerbound_subkey(key, subkey),
434            Self::Write(cursor) => cursor.set_lowerbound_subkey(key, subkey),
435        }
436    }
437
438    fn count_duplicates(&mut self) -> usize {
439        match self {
440            Self::Read(cursor) => cursor.count_duplicates(),
441            Self::Write(cursor) => cursor.count_duplicates(),
442        }
443    }
444
445    fn into_iter_dup_of(self, key: &T::Key) -> Self::IntoIter {
446        match self {
447            Self::Read(cursor) => IntoIterProxy::Read(cursor.into_iter_dup_of(key)),
448            Self::Write(cursor) => IntoIterProxy::Write(cursor.into_iter_dup_of(key)),
449        }
450    }
451}