1use std::{
2 fmt,
3 ops::{Bound, RangeBounds},
4};
5
6use crate::{
7 common::{IterPairResult, PairResult, ValueOnlyResult},
8 table::{DupSort, Table, TableRow},
9 DatabaseError,
10};
11
12pub trait DbCursorRO<T: Table> {
14 fn first(&mut self) -> PairResult<T>;
16
17 fn seek_exact(&mut self, key: T::Key) -> PairResult<T>;
19
20 fn seek(&mut self, key: T::Key) -> PairResult<T>;
22
23 fn next(&mut self) -> PairResult<T>;
25
26 fn prev(&mut self) -> PairResult<T>;
28
29 fn last(&mut self) -> PairResult<T>;
31
32 fn current(&mut self) -> PairResult<T>;
34
35 fn walk(&mut self, start_key: Option<T::Key>) -> Result<Walker<'_, T, Self>, DatabaseError>
40 where
41 Self: Sized;
42
43 fn walk_range(
45 &mut self,
46 range: impl RangeBounds<T::Key>,
47 ) -> Result<RangeWalker<'_, T, Self>, DatabaseError>
48 where
49 Self: Sized;
50
51 fn walk_back(
56 &mut self,
57 start_key: Option<T::Key>,
58 ) -> Result<ReverseWalker<'_, T, Self>, DatabaseError>
59 where
60 Self: Sized;
61}
62
63pub trait DbDupCursorRO<T: DupSort> {
65 fn prev_dup(&mut self) -> PairResult<T>;
67
68 fn next_dup(&mut self) -> PairResult<T>;
70
71 fn last_dup(&mut self) -> ValueOnlyResult<T>;
73
74 fn next_no_dup(&mut self) -> PairResult<T>;
76
77 fn next_dup_val(&mut self) -> ValueOnlyResult<T>;
79
80 fn seek_by_key_subkey(&mut self, key: T::Key, subkey: T::SubKey) -> ValueOnlyResult<T>;
87
88 fn walk_dup(
100 &mut self,
101 key: Option<T::Key>,
102 subkey: Option<T::SubKey>,
103 ) -> Result<DupWalker<'_, T, Self>, DatabaseError>
104 where
105 Self: Sized;
106}
107
108pub trait DbCursorRW<T: Table> {
110 fn upsert(&mut self, key: T::Key, value: &T::Value) -> Result<(), DatabaseError>;
113
114 fn insert(&mut self, key: T::Key, value: &T::Value) -> Result<(), DatabaseError>;
117
118 fn append(&mut self, key: T::Key, value: &T::Value) -> Result<(), DatabaseError>;
123
124 fn delete_current(&mut self) -> Result<(), DatabaseError>;
126}
127
128pub trait DbDupCursorRW<T: DupSort> {
130 fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError>;
132
133 fn append_dup(&mut self, key: T::Key, value: T::Value) -> Result<(), DatabaseError>;
137}
138
139pub struct Walker<'cursor, T: Table, CURSOR: DbCursorRO<T>> {
141 cursor: &'cursor mut CURSOR,
143 start: IterPairResult<T>,
145}
146
147impl<T, CURSOR> fmt::Debug for Walker<'_, T, CURSOR>
148where
149 T: Table,
150 CURSOR: DbCursorRO<T> + fmt::Debug,
151{
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 f.debug_struct("Walker").field("cursor", &self.cursor).field("start", &self.start).finish()
154 }
155}
156
157impl<T: Table, CURSOR: DbCursorRO<T>> Iterator for Walker<'_, T, CURSOR> {
158 type Item = Result<TableRow<T>, DatabaseError>;
159 fn next(&mut self) -> Option<Self::Item> {
160 self.start.take().or_else(|| self.cursor.next().transpose())
161 }
162}
163
164impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> Walker<'cursor, T, CURSOR> {
165 pub const fn new(cursor: &'cursor mut CURSOR, start: IterPairResult<T>) -> Self {
167 Self { cursor, start }
168 }
169
170 pub fn rev(self) -> ReverseWalker<'cursor, T, CURSOR> {
172 let start = self.cursor.current().transpose();
173 ReverseWalker::new(self.cursor, start)
174 }
175}
176
177impl<T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> Walker<'_, T, CURSOR> {
178 pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
180 self.start.take();
181 self.cursor.delete_current()
182 }
183}
184
185pub struct ReverseWalker<'cursor, T: Table, CURSOR: DbCursorRO<T>> {
188 cursor: &'cursor mut CURSOR,
190 start: IterPairResult<T>,
192}
193
194impl<T, CURSOR> fmt::Debug for ReverseWalker<'_, T, CURSOR>
195where
196 T: Table,
197 CURSOR: DbCursorRO<T> + fmt::Debug,
198{
199 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200 f.debug_struct("ReverseWalker")
201 .field("cursor", &self.cursor)
202 .field("start", &self.start)
203 .finish()
204 }
205}
206
207impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> ReverseWalker<'cursor, T, CURSOR> {
208 pub const fn new(cursor: &'cursor mut CURSOR, start: IterPairResult<T>) -> Self {
210 Self { cursor, start }
211 }
212
213 pub fn forward(self) -> Walker<'cursor, T, CURSOR> {
215 let start = self.cursor.current().transpose();
216 Walker::new(self.cursor, start)
217 }
218}
219
220impl<T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> ReverseWalker<'_, T, CURSOR> {
221 pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
223 self.start.take();
224 self.cursor.delete_current()
225 }
226}
227
228impl<T: Table, CURSOR: DbCursorRO<T>> Iterator for ReverseWalker<'_, T, CURSOR> {
229 type Item = Result<TableRow<T>, DatabaseError>;
230
231 fn next(&mut self) -> Option<Self::Item> {
232 let start = self.start.take();
233 if start.is_some() {
234 return start
235 }
236
237 self.cursor.prev().transpose()
238 }
239}
240
241pub struct RangeWalker<'cursor, T: Table, CURSOR: DbCursorRO<T>> {
244 cursor: &'cursor mut CURSOR,
246 start: IterPairResult<T>,
248 end_key: Bound<T::Key>,
250 is_done: bool,
252}
253
254impl<T, CURSOR> fmt::Debug for RangeWalker<'_, T, CURSOR>
255where
256 T: Table,
257 CURSOR: DbCursorRO<T> + fmt::Debug,
258{
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 f.debug_struct("RangeWalker")
261 .field("cursor", &self.cursor)
262 .field("start", &self.start)
263 .field("end_key", &self.end_key)
264 .field("is_done", &self.is_done)
265 .finish()
266 }
267}
268
269impl<T: Table, CURSOR: DbCursorRO<T>> Iterator for RangeWalker<'_, T, CURSOR> {
270 type Item = Result<TableRow<T>, DatabaseError>;
271
272 fn next(&mut self) -> Option<Self::Item> {
273 if self.is_done {
274 return None
275 }
276
277 let next_item = self.start.take().or_else(|| self.cursor.next().transpose());
278
279 match next_item {
280 Some(Ok((key, value))) => match &self.end_key {
281 Bound::Included(end_key) if &key <= end_key => Some(Ok((key, value))),
282 Bound::Excluded(end_key) if &key < end_key => Some(Ok((key, value))),
283 Bound::Unbounded => Some(Ok((key, value))),
284 _ => {
285 self.is_done = true;
286 None
287 }
288 },
289 Some(res @ Err(_)) => Some(res),
290 None => {
291 self.is_done = matches!(self.end_key, Bound::Unbounded);
292 None
293 }
294 }
295 }
296}
297
298impl<'cursor, T: Table, CURSOR: DbCursorRO<T>> RangeWalker<'cursor, T, CURSOR> {
299 pub fn new(
301 cursor: &'cursor mut CURSOR,
302 start: IterPairResult<T>,
303 end_key: Bound<T::Key>,
304 ) -> Self {
305 let is_done = match start {
307 Some(Ok((ref start_key, _))) => match &end_key {
308 Bound::Included(end_key) if start_key > end_key => true,
309 Bound::Excluded(end_key) if start_key >= end_key => true,
310 _ => false,
311 },
312 None => true,
313 _ => false,
314 };
315 Self { cursor, start, end_key, is_done }
316 }
317}
318
319impl<T: Table, CURSOR: DbCursorRW<T> + DbCursorRO<T>> RangeWalker<'_, T, CURSOR> {
320 pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
322 self.start.take();
323 self.cursor.delete_current()
324 }
325}
326
327impl<T: DupSort, CURSOR: DbDupCursorRW<T> + DbCursorRO<T>> RangeWalker<'_, T, CURSOR> {
328 pub fn delete_current_duplicates(&mut self) -> Result<(), DatabaseError> {
330 self.start.take();
331 self.cursor.delete_current_duplicates()
332 }
333}
334
335pub struct DupWalker<'cursor, T: DupSort, CURSOR: DbDupCursorRO<T>> {
341 pub cursor: &'cursor mut CURSOR,
343 pub start: IterPairResult<T>,
345}
346
347impl<T, CURSOR> fmt::Debug for DupWalker<'_, T, CURSOR>
348where
349 T: DupSort,
350 CURSOR: DbDupCursorRO<T> + fmt::Debug,
351{
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 f.debug_struct("DupWalker")
354 .field("cursor", &self.cursor)
355 .field("start", &self.start)
356 .finish()
357 }
358}
359
360impl<T: DupSort, CURSOR: DbCursorRW<T> + DbDupCursorRO<T>> DupWalker<'_, T, CURSOR> {
361 pub fn delete_current(&mut self) -> Result<(), DatabaseError> {
363 self.start.take();
364 self.cursor.delete_current()
365 }
366}
367
368impl<T: DupSort, CURSOR: DbDupCursorRO<T>> Iterator for DupWalker<'_, T, CURSOR> {
369 type Item = Result<TableRow<T>, DatabaseError>;
370 fn next(&mut self) -> Option<Self::Item> {
371 let start = self.start.take();
372 if start.is_some() {
373 return start
374 }
375 self.cursor.next_dup().transpose()
376 }
377}