Skip to main content

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}