noxu_db/get.rs
1//! Get operation types.
2//!
3
4/// Type of get operation for cursors and databases.
5///
6/// Specifies how to position the cursor or which record to retrieve.
7///
8/// Get operation types from the database engine.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10pub enum Get {
11 /// Get the record matching the key.
12 ///
13 /// Searches for a record with the specified key. For duplicate databases,
14 /// returns the first duplicate.
15 Search,
16
17 /// Get the record matching both key and data.
18 ///
19 /// For duplicate databases, searches for a record matching both the key
20 /// and the data. Returns an error if not found.
21 SearchBoth,
22
23 /// Get the record matching the key with data >= the specified data.
24 ///
25 /// For duplicate databases, positions the cursor at the first duplicate
26 /// of the specified key whose data is >= the supplied data slice.
27 /// Equivalent to BDB-JE's `Cursor.getSearchBothRange`.
28 SearchBothRange,
29
30 /// Get the record with the smallest key.
31 ///
32 /// Positions the cursor at the first record in the database.
33 First,
34
35 /// Get the record with the largest key.
36 ///
37 /// Positions the cursor at the last record in the database.
38 Last,
39
40 /// Get the next record.
41 ///
42 /// Moves the cursor to the next record in key order. For duplicate
43 /// databases, moves to the next duplicate of the current key, or the
44 /// first duplicate of the next key if at the last duplicate.
45 Next,
46
47 /// Get the previous record.
48 ///
49 /// Moves the cursor to the previous record in key order. For duplicate
50 /// databases, moves to the previous duplicate of the current key, or the
51 /// last duplicate of the previous key if at the first duplicate.
52 Prev,
53
54 /// Get the next record with a different key.
55 ///
56 /// Skips all duplicates of the current key and moves to the first
57 /// duplicate of the next key.
58 NextNoDup,
59
60 /// Get the previous record with a different key.
61 ///
62 /// Skips all duplicates of the current key and moves to the last
63 /// duplicate of the previous key.
64 PrevNoDup,
65
66 /// Get the current record.
67 ///
68 /// Returns the record at the current cursor position. Useful after
69 /// positioning the cursor to re-read the record.
70 Current,
71
72 /// Get the record with the smallest key greater than or equal to the specified key.
73 ///
74 /// Positions the cursor at the first record with a key greater than or
75 /// equal to the search key.
76 ///
77 /// Also known as `SearchRange` (the: `Cursor.getSearchKeyRange`).
78 SearchGte,
79
80 /// Alias for `SearchGte`. Matches the `SEARCH_RANGE`/`getSearchKeyRange` name.
81 SearchRange,
82
83 /// Get the record with the largest key less than or equal to the specified key.
84 ///
85 /// Positions the cursor at the last record with a key less than or
86 /// equal to the search key.
87 ///
88 /// **Not yet implemented.** `Cursor::get` returns
89 /// [`crate::error::NoxuError::Unsupported`] for this variant. Tracked
90 /// for a future sprint; see
91 /// `docs/src/internal/api-audit-2026-05-cursor.md` Finding 3.
92 SearchLte,
93
94 /// Get the first duplicate of the current key.
95 ///
96 /// For duplicate databases, positions at the first duplicate of the
97 /// current key. Has no effect if not positioned on a key.
98 ///
99 /// **Not yet implemented.** `Cursor::get` returns
100 /// [`crate::error::NoxuError::Unsupported`] for this variant. Tracked
101 /// for a future sprint; see
102 /// `docs/src/internal/api-audit-2026-05-cursor.md` Finding 3.
103 FirstDup,
104
105 /// Get the last duplicate of the current key.
106 ///
107 /// For duplicate databases, positions at the last duplicate of the
108 /// current key. Has no effect if not positioned on a key.
109 ///
110 /// **Not yet implemented.** `Cursor::get` returns
111 /// [`crate::error::NoxuError::Unsupported`] for this variant. Tracked
112 /// for a future sprint; see
113 /// `docs/src/internal/api-audit-2026-05-cursor.md` Finding 3.
114 LastDup,
115
116 /// Get the next duplicate of the current key.
117 ///
118 /// For duplicate databases, moves to the next duplicate of the current
119 /// key. Returns an error if at the last duplicate.
120 NextDup,
121
122 /// Get the previous duplicate of the current key.
123 ///
124 /// For duplicate databases, moves to the previous duplicate of the current
125 /// key. Returns an error if at the first duplicate.
126 PrevDup,
127}
128
129impl Get {
130 /// Returns whether this operation requires a key parameter.
131 pub fn requires_key(&self) -> bool {
132 matches!(
133 self,
134 Get::Search
135 | Get::SearchBoth
136 | Get::SearchBothRange
137 | Get::SearchGte
138 | Get::SearchLte
139 | Get::SearchRange
140 )
141 }
142
143 /// Returns whether this operation requires a data parameter.
144 pub fn requires_data(&self) -> bool {
145 matches!(self, Get::SearchBoth | Get::SearchBothRange)
146 }
147
148 /// Returns whether this operation is valid only for duplicate databases.
149 pub fn requires_duplicates(&self) -> bool {
150 matches!(
151 self,
152 Get::SearchBoth
153 | Get::SearchBothRange
154 | Get::FirstDup
155 | Get::LastDup
156 | Get::NextDup
157 | Get::PrevDup
158 )
159 }
160
161 /// Returns whether this operation moves the cursor position.
162 pub fn moves_cursor(&self) -> bool {
163 !matches!(self, Get::Current)
164 }
165
166 /// Returns whether this operation moves forward in key order.
167 pub fn moves_forward(&self) -> bool {
168 matches!(self, Get::Next | Get::NextDup | Get::NextNoDup)
169 }
170
171 /// Returns whether this operation moves backward in key order.
172 pub fn moves_backward(&self) -> bool {
173 matches!(self, Get::Prev | Get::PrevDup | Get::PrevNoDup)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_requires_key() {
183 assert!(Get::Search.requires_key());
184 assert!(Get::SearchBoth.requires_key());
185 assert!(Get::SearchBothRange.requires_key());
186 assert!(Get::SearchGte.requires_key());
187 assert!(Get::SearchLte.requires_key());
188 assert!(!Get::First.requires_key());
189 assert!(!Get::Next.requires_key());
190 }
191
192 #[test]
193 fn test_requires_data() {
194 assert!(Get::SearchBoth.requires_data());
195 assert!(Get::SearchBothRange.requires_data());
196 assert!(!Get::Search.requires_data());
197 assert!(!Get::First.requires_data());
198 }
199
200 #[test]
201 fn test_requires_duplicates() {
202 assert!(Get::SearchBoth.requires_duplicates());
203 assert!(Get::SearchBothRange.requires_duplicates());
204 assert!(Get::FirstDup.requires_duplicates());
205 assert!(Get::LastDup.requires_duplicates());
206 assert!(Get::NextDup.requires_duplicates());
207 assert!(Get::PrevDup.requires_duplicates());
208 assert!(!Get::First.requires_duplicates());
209 assert!(!Get::Next.requires_duplicates());
210 }
211
212 #[test]
213 fn test_moves_cursor() {
214 assert!(Get::First.moves_cursor());
215 assert!(Get::Next.moves_cursor());
216 assert!(!Get::Current.moves_cursor());
217 }
218
219 #[test]
220 fn test_moves_forward() {
221 assert!(Get::Next.moves_forward());
222 assert!(Get::NextDup.moves_forward());
223 assert!(Get::NextNoDup.moves_forward());
224 assert!(!Get::Prev.moves_forward());
225 assert!(!Get::First.moves_forward());
226 }
227
228 #[test]
229 fn test_moves_backward() {
230 assert!(Get::Prev.moves_backward());
231 assert!(Get::PrevDup.moves_backward());
232 assert!(Get::PrevNoDup.moves_backward());
233 assert!(!Get::Next.moves_backward());
234 assert!(!Get::Last.moves_backward());
235 }
236
237 #[test]
238 fn test_equality() {
239 assert_eq!(Get::First, Get::First);
240 assert_ne!(Get::First, Get::Last);
241 }
242
243 #[test]
244 fn test_clone() {
245 let get1 = Get::Search;
246 let get2 = get1;
247 assert_eq!(get1, get2);
248 }
249
250 #[test]
251 fn test_copy() {
252 let get1 = Get::Next;
253 let get2 = get1;
254 assert_eq!(get1, get2);
255 }
256
257 #[test]
258 fn test_debug() {
259 let get = Get::SearchBoth;
260 let debug = format!("{:?}", get);
261 assert_eq!(debug, "SearchBoth");
262 }
263}