Skip to main content

embed_collections/btree/
cursor.rs

1use super::iter::{IterBackward, IterForward};
2use super::*;
3use core::marker::PhantomData;
4
5/// A read-only cursor for navigating through entries in a BTreeMap.
6///
7/// The cursor provides bidirectional navigation using leaf node sibling pointers,
8/// you can change where the direction goes at any time.
9///
10/// `Cursor` is lighter than [Iter] (without the cost of DoubleEndedIterator trait) and more customizable.
11///
12/// # Example
13///
14/// ```
15/// use embed_collections::BTreeMap;
16///
17/// let mut map = BTreeMap::new();
18/// map.insert(1, "a");
19/// map.insert(3, "b");
20/// map.insert(5, "c");
21///
22/// // Create cursor at key 2
23/// let mut cursor = map.cursor(&1);
24/// assert_eq!(cursor.next(), Some((&1, &"a")));
25/// assert_eq!(cursor.next(), Some((&3, &"b")));
26/// assert_eq!(cursor.next(), Some((&5, &"c")));
27/// assert_eq!(cursor.next(), None);
28///
29/// let mut cursor = map.cursor(&2);
30/// // return next existing key
31/// assert_eq!(cursor.next(), Some((&3, &"b")));
32/// assert_eq!(cursor.next(), Some((&5, &"c")));
33///
34/// // Peek without moving
35/// assert_eq!(cursor.peek_forward(), None);
36/// assert_eq!(cursor.peek_backward(), Some((&5, &"c")));
37/// assert_eq!(cursor.next(), None);
38///
39/// // Rewind
40/// assert_eq!(cursor.previous(), Some((&5, &"c")));
41///
42/// // Iterate from the back
43/// let mut cursor = map.last_cursor();
44/// assert_eq!(cursor.previous(), Some((&5, &"c")));
45/// assert_eq!(cursor.previous(), Some((&3, &"b")));
46/// assert_eq!(cursor.previous(), Some((&1, &"a")));
47/// assert_eq!(cursor.previous(), None);
48/// ```
49pub struct Cursor<'a, K: Ord + Clone + Sized, V: Sized> {
50    pub(super) leaf: Option<LeafNode<K, V>>,
51    pub(super) idx: u32,
52    pub(super) is_exist: bool,
53    pub(super) _marker: PhantomData<&'a ()>,
54}
55
56impl<'a, K: Ord + Clone + Sized + 'a, V: Sized + 'a> Iterator for Cursor<'a, K, V> {
57    type Item = (&'a K, &'a V);
58
59    /// Returns the key-value pair at current position, then move the cursor forward.
60    ///
61    /// # Example
62    ///
63    /// ```
64    /// use embed_collections::btree::BTreeMap;
65    /// let mut map = BTreeMap::new();
66    /// map.insert(1, "a");
67    /// map.insert(3, "b");
68    /// map.insert(5, "c");
69    ///
70    /// let mut cursor = map.first_cursor();
71    /// assert_eq!(cursor.next(), Some((&1, &"a")));
72    /// assert_eq!(cursor.next(), Some((&3, &"b")));
73    /// assert_eq!(cursor.next(), Some((&5, &"c")));
74    /// assert_eq!(cursor.next(), None);
75
76    ///
77    /// // existing key
78    /// let mut cursor = map.cursor(&3);
79    /// assert_eq!(cursor.next(), Some((&3, &"b")));
80    /// assert_eq!(cursor.next(), Some((&5, &"c")));
81    /// assert_eq!(cursor.next(), None);
82    ///
83    /// // non existing key
84    /// let mut cursor = map.cursor(&2);
85    /// assert_eq!(cursor.next(), Some((&3, &"b")));
86    /// assert_eq!(cursor.next(), Some((&5, &"c")));
87    /// assert_eq!(cursor.next(), None);
88    /// ```
89    #[inline]
90    fn next(&mut self) -> Option<(&'a K, &'a V)> {
91        unsafe {
92            loop {
93                let leaf = self.leaf.as_ref()?;
94                let idx = self.idx;
95                if self.is_exist {
96                    let (_k, _v) = leaf.get_raw_pair_unchecked(idx);
97                    let res = Some((&*_k, &*_v));
98                    if idx + 1 < leaf.key_count() {
99                        self.idx = idx + 1;
100                    } else {
101                        if let Some(right) = leaf.get_right_node() {
102                            self.leaf.replace(right);
103                            self.idx = 0;
104                        } else {
105                            self.is_exist = false;
106                            self.idx = idx + 1;
107                        }
108                    }
109                    return res;
110                } else {
111                    if self.idx < leaf.key_count() {
112                        self.is_exist = true;
113                    } else if let Some(right) = leaf.get_right_node() {
114                        _ = leaf;
115                        self.leaf.replace(right);
116                        self.idx = 0;
117                        self.is_exist = true;
118                    } else {
119                        return None;
120                    }
121                }
122            }
123        }
124    }
125}
126
127impl<'a, K: Ord + Clone + Sized, V: Sized> Cursor<'a, K, V> {
128    #[inline(always)]
129    pub fn is_exist(&self) -> bool {
130        self.is_exist
131    }
132
133    /// returns the key-value pair and move the cursor to previous position
134    /// Returns `None` if already at the beginning.
135    ///
136    /// # Example
137    ///
138    /// ```
139    /// use embed_collections::btree::BTreeMap;
140    ///
141    /// let mut map = BTreeMap::new();
142    /// map.insert(1, "a");
143    /// map.insert(3, "b");
144    /// map.insert(5, "c");
145    ///
146    /// // Iterate from the back
147    /// let mut cursor = map.last_cursor();
148    /// assert_eq!(cursor.previous(), Some((&5, &"c")));
149    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
150    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
151    ///
152    /// // non-existing key
153    /// let mut cursor = map.cursor(&4);
154    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
155    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
156    ///
157    /// // existing key
158    ///
159    /// let mut cursor = map.cursor(&3);
160    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
161    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
162    /// ```
163    #[inline]
164    pub fn previous(&mut self) -> Option<(&K, &V)> {
165        let leaf = self.leaf.as_ref()?;
166        let idx = self.idx;
167        unsafe {
168            if self.idx > 0 {
169                self.idx -= 1;
170                if self.is_exist && idx < leaf.key_count() {
171                    let (_k, _v) = leaf.get_raw_pair_unchecked(idx);
172                    return Some((&*_k, &*_v));
173                } else {
174                    let (_k, _v) = leaf.get_raw_pair_unchecked(self.idx);
175                    return Some((&*_k, &*_v));
176                }
177            }
178            if self.is_exist {
179                let (_k, _v) = leaf.get_raw_pair_unchecked(0);
180                let res = Some((&*_k, &*_v));
181                if let Some(prev) = leaf.get_left_node() {
182                    let count = prev.key_count();
183                    debug_assert!(count > 0);
184                    self.idx = count - 1;
185                    self.leaf.replace(prev);
186                } else {
187                    self.is_exist = false;
188                }
189                return res;
190            }
191            if let Some(prev) = leaf.get_left_node() {
192                let count = prev.key_count();
193                debug_assert!(count > 0);
194                self.leaf.replace(prev.clone());
195                if count > 1 {
196                    self.idx = count - 2;
197                    self.is_exist = true;
198                } else {
199                    self.idx = 0;
200                    self.is_exist = false;
201                }
202                let (_k, _v) = prev.get_raw_pair_unchecked(count - 1);
203                Some((&*_k, &*_v))
204            } else {
205                None
206            }
207        }
208    }
209
210    /// Peeks at the previous entry without moving the cursor.
211    /// Returns `None` if there is no previous entry.
212    ///
213    /// # Example
214    ///
215    /// ```
216    /// use embed_collections::BTreeMap;
217    ///
218    /// let mut map = BTreeMap::new();
219    /// map.insert(1, "a");
220    /// map.insert(3, "b");
221    /// map.insert(5, "c");
222    ///
223    /// // non-existing key
224    /// let mut cursor = map.cursor(&2);
225    /// assert_eq!(cursor.peek_backward(), Some((&1, &"a")));
226    ///
227    /// // existing key
228    /// let mut cursor = map.cursor(&3);
229    /// assert_eq!(cursor.peek_backward(), Some((&1, &"a")));
230    #[inline]
231    pub fn peek_backward(&self) -> Option<(&K, &V)> {
232        let leaf = self.leaf.as_ref()?;
233        let mut cursor = IterBackward { back_leaf: leaf.clone(), back_idx: self.idx };
234        unsafe {
235            if let Some((k, v)) = cursor.prev_pair() {
236                return Some((&*k, &*v));
237            }
238        }
239        None
240    }
241
242    /// Peeks at the next entry without moving the cursor.
243    /// Returns `None` if there is no next entry.
244    ///
245    /// # Example
246    ///
247    /// ```
248    /// use embed_collections::BTreeMap;
249    ///
250    /// let mut map = BTreeMap::new();
251    /// map.insert(1, "a");
252    /// map.insert(3, "b");
253    /// map.insert(5, "c");
254    /// // non-existing key
255    /// let cursor = map.cursor(&2);
256    /// assert_eq!(cursor.peek_forward(), Some((&3, &"b")));
257    ///
258    /// // existing key
259    /// let cursor = map.cursor(&1);
260    /// assert_eq!(cursor.peek_forward(), Some((&3, &"b")));
261    ///
262    ///    #[inline]
263    pub fn peek_forward(&self) -> Option<(&K, &V)> {
264        let leaf = self.leaf.as_ref()?;
265        unsafe {
266            if self.is_exist {
267                let mut cursor = IterForward { front_leaf: leaf.clone(), idx: self.idx + 1 };
268                if let Some((k, v)) = cursor.next_pair() {
269                    return Some((&*k, &*v));
270                }
271            } else {
272                if let Some((k, v)) = leaf.get_raw_pair(self.idx) {
273                    // get_raw_pair will validate idx
274                    return Some((&*k, &*v));
275                }
276                if let Some(right) = leaf.get_right_node() {
277                    if let Some((k, v)) = right.get_raw_pair(0) {
278                        return Some((&*k, &*v));
279                    }
280                }
281            }
282        }
283        None
284    }
285}
286
287/*
288impl<'a, K: Ord + Clone + Sized + fmt::Debug, V: Sized + fmt::Debug> fmt::Debug
289    for Cursor<'a, K, V>
290{
291    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
292        if let Some((k, v)) = self.peek_forward() {
293            f.debug_struct("Cursor").field("key", k).field("value", v).finish()
294        } else {
295            f.debug_struct("Cursor").field("key", &"<end>").field("value", &"<end>").finish()
296        }
297    }
298}
299*/