hematite/catalog/
cursor.rs1use super::record::StoredRow;
4
5#[derive(Debug, Clone)]
6pub struct TableCursor {
7 rows: Vec<StoredRow>,
8 position: Option<usize>,
9}
10
11impl TableCursor {
12 pub fn new(mut rows: Vec<StoredRow>) -> Self {
13 rows.sort_by_key(|row| row.row_id);
14 Self {
15 rows,
16 position: None,
17 }
18 }
19
20 pub fn first(&mut self) -> bool {
21 if self.rows.is_empty() {
22 self.position = None;
23 return false;
24 }
25 self.position = Some(0);
26 true
27 }
28
29 pub fn next(&mut self) -> bool {
30 let Some(position) = self.position else {
31 return false;
32 };
33 let next = position + 1;
34 if next < self.rows.len() {
35 self.position = Some(next);
36 true
37 } else {
38 self.position = None;
39 false
40 }
41 }
42
43 pub fn seek_rowid(&mut self, rowid: u64) -> bool {
44 let found = self
45 .rows
46 .binary_search_by_key(&rowid, |row| row.row_id)
47 .ok();
48 self.position = found;
49 found.is_some()
50 }
51
52 pub fn current(&self) -> Option<&StoredRow> {
53 self.position.and_then(|index| self.rows.get(index))
54 }
55
56 pub fn is_valid(&self) -> bool {
57 self.current().is_some()
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct IndexEntry {
63 pub key: Vec<u8>,
64 pub row_id: u64,
65}
66
67#[derive(Debug, Clone)]
68pub struct IndexCursor {
69 entries: Vec<IndexEntry>,
70 position: Option<usize>,
71}
72
73impl IndexCursor {
74 pub fn new(mut entries: Vec<IndexEntry>) -> Self {
75 entries.sort_by(|l, r| l.key.cmp(&r.key).then(l.row_id.cmp(&r.row_id)));
76 Self {
77 entries,
78 position: None,
79 }
80 }
81
82 pub fn first(&mut self) -> bool {
83 if self.entries.is_empty() {
84 self.position = None;
85 return false;
86 }
87 self.position = Some(0);
88 true
89 }
90
91 pub fn next(&mut self) -> bool {
92 let Some(position) = self.position else {
93 return false;
94 };
95 let next = position + 1;
96 if next < self.entries.len() {
97 self.position = Some(next);
98 true
99 } else {
100 self.position = None;
101 false
102 }
103 }
104
105 pub fn seek_key(&mut self, key: &[u8]) -> bool {
106 let mut left = 0usize;
107 let mut right = self.entries.len();
108
109 while left < right {
110 let mid = left + (right - left) / 2;
111 if self.entries[mid].key.as_slice() < key {
112 left = mid + 1;
113 } else {
114 right = mid;
115 }
116 }
117
118 let found = self
119 .entries
120 .get(left)
121 .filter(|entry| entry.key.as_slice() == key)
122 .map(|_| left);
123 self.position = found;
124 found.is_some()
125 }
126
127 pub fn current(&self) -> Option<&IndexEntry> {
128 self.position.and_then(|index| self.entries.get(index))
129 }
130
131 pub fn is_valid(&self) -> bool {
132 self.current().is_some()
133 }
134}