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
14pub struct MdbxCursor<'txn, K: TransactionKind, T: Table> {
17 cursor: libmdbx::Cursor<'txn, K>,
18 _table: PhantomData<T>,
19}
20pub type MdbxReadCursor<'txn, T> = MdbxCursor<'txn, RO, T>;
22pub 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
282pub 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}