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    /// // existing key
77    /// let mut cursor = map.cursor(&3);
78    /// assert_eq!(cursor.next(), Some((&3, &"b")));
79    /// assert_eq!(cursor.next(), Some((&5, &"c")));
80    /// assert_eq!(cursor.next(), None);
81    ///
82    /// // non existing key
83    /// let mut cursor = map.cursor(&2);
84    /// assert_eq!(cursor.next(), Some((&3, &"b")));
85    /// assert_eq!(cursor.next(), Some((&5, &"c")));
86    /// assert_eq!(cursor.next(), None);
87    /// ```
88    #[inline]
89    fn next(&mut self) -> Option<(&'a K, &'a V)> {
90        unsafe {
91            loop {
92                let leaf = self.leaf.as_ref()?;
93                let idx = self.idx;
94                if self.is_exist {
95                    let (_k, _v) = leaf.get_raw_pair_unchecked(idx);
96                    let res = Some((&*_k, &*_v));
97                    if idx + 1 < leaf.key_count() {
98                        self.idx = idx + 1;
99                    } else {
100                        if let Some(right) = leaf.get_right_node() {
101                            self.leaf.replace(right);
102                            self.idx = 0;
103                        } else {
104                            self.is_exist = false;
105                            self.idx = idx + 1;
106                        }
107                    }
108                    return res;
109                } else {
110                    if self.idx < leaf.key_count() {
111                        self.is_exist = true;
112                    } else if let Some(right) = leaf.get_right_node() {
113                        _ = leaf;
114                        self.leaf.replace(right);
115                        self.idx = 0;
116                        self.is_exist = true;
117                    } else {
118                        return None;
119                    }
120                }
121            }
122        }
123    }
124}
125
126impl<'a, K: Ord + Clone + Sized, V: Sized> Cursor<'a, K, V> {
127    #[inline(always)]
128    pub fn is_exist(&self) -> bool {
129        self.is_exist
130    }
131
132    /// returns the key-value pair and move the cursor to previous position
133    /// Returns `None` if already at the beginning.
134    ///
135    /// # Example
136    ///
137    /// ```
138    /// use embed_collections::btree::BTreeMap;
139    ///
140    /// let mut map = BTreeMap::new();
141    /// map.insert(1, "a");
142    /// map.insert(3, "b");
143    /// map.insert(5, "c");
144    ///
145    /// // Iterate from the back
146    /// let mut cursor = map.last_cursor();
147    /// assert_eq!(cursor.previous(), Some((&5, &"c")));
148    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
149    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
150    ///
151    /// // non-existing key
152    /// let mut cursor = map.cursor(&4);
153    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
154    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
155    ///
156    /// // existing key
157    ///
158    /// let mut cursor = map.cursor(&3);
159    /// assert_eq!(cursor.previous(), Some((&3, &"b")));
160    /// assert_eq!(cursor.previous(), Some((&1, &"a")));
161    /// ```
162    #[inline]
163    pub fn previous(&mut self) -> Option<(&K, &V)> {
164        let leaf = self.leaf.as_ref()?;
165        let idx = self.idx;
166        unsafe {
167            if self.idx > 0 {
168                self.idx -= 1;
169                if self.is_exist && idx < leaf.key_count() {
170                    let (_k, _v) = leaf.get_raw_pair_unchecked(idx);
171                    return Some((&*_k, &*_v));
172                } else {
173                    let (_k, _v) = leaf.get_raw_pair_unchecked(self.idx);
174                    return Some((&*_k, &*_v));
175                }
176            }
177            if self.is_exist {
178                let (_k, _v) = leaf.get_raw_pair_unchecked(0);
179                let res = Some((&*_k, &*_v));
180                if let Some(prev) = leaf.get_left_node() {
181                    let count = prev.key_count();
182                    debug_assert!(count > 0);
183                    self.idx = count - 1;
184                    self.leaf.replace(prev);
185                } else {
186                    self.is_exist = false;
187                }
188                return res;
189            }
190            if let Some(prev) = leaf.get_left_node() {
191                let count = prev.key_count();
192                debug_assert!(count > 0);
193                self.leaf.replace(prev.clone());
194                if count > 1 {
195                    self.idx = count - 2;
196                    self.is_exist = true;
197                } else {
198                    self.idx = 0;
199                    self.is_exist = false;
200                }
201                let (_k, _v) = prev.get_raw_pair_unchecked(count - 1);
202                Some((&*_k, &*_v))
203            } else {
204                None
205            }
206        }
207    }
208
209    /// Peeks at the previous entry without moving the cursor.
210    /// Returns `None` if there is no previous entry.
211    ///
212    /// # Example
213    ///
214    /// ```
215    /// use embed_collections::BTreeMap;
216    ///
217    /// let mut map = BTreeMap::new();
218    /// map.insert(1, "a");
219    /// map.insert(3, "b");
220    /// map.insert(5, "c");
221    ///
222    /// // non-existing key
223    /// let mut cursor = map.cursor(&2);
224    /// assert_eq!(cursor.peek_backward(), Some((&1, &"a")));
225    ///
226    /// // existing key
227    /// let mut cursor = map.cursor(&3);
228    /// assert_eq!(cursor.peek_backward(), Some((&1, &"a")));
229    #[inline]
230    pub fn peek_backward(&self) -> Option<(&K, &V)> {
231        let leaf = self.leaf.as_ref()?;
232        let mut cursor = IterBackward { back_leaf: leaf.clone(), back_idx: self.idx };
233        unsafe {
234            if let Some((k, v)) = cursor.prev_pair() {
235                return Some((&*k, &*v));
236            }
237        }
238        None
239    }
240
241    /// Peeks at the next entry without moving the cursor.
242    /// Returns `None` if there is no next entry.
243    ///
244    /// # Example
245    ///
246    /// ```
247    /// use embed_collections::BTreeMap;
248    ///
249    /// let mut map = BTreeMap::new();
250    /// map.insert(1, "a");
251    /// map.insert(3, "b");
252    /// map.insert(5, "c");
253    /// // non-existing key
254    /// let cursor = map.cursor(&2);
255    /// assert_eq!(cursor.peek_forward(), Some((&3, &"b")));
256    ///
257    /// // existing key
258    /// let cursor = map.cursor(&1);
259    /// assert_eq!(cursor.peek_forward(), Some((&3, &"b")));
260    ///
261    ///    #[inline]
262    pub fn peek_forward(&self) -> Option<(&K, &V)> {
263        let leaf = self.leaf.as_ref()?;
264        unsafe {
265            if self.is_exist {
266                let mut cursor = IterForward { front_leaf: leaf.clone(), idx: self.idx + 1 };
267                if let Some((k, v)) = cursor.next_pair() {
268                    return Some((&*k, &*v));
269                }
270            } else {
271                if let Some((k, v)) = leaf.get_raw_pair(self.idx) {
272                    // get_raw_pair will validate idx
273                    return Some((&*k, &*v));
274                }
275                if let Some(right) = leaf.get_right_node()
276                    && let Some((k, v)) = right.get_raw_pair(0)
277                {
278                    return Some((&*k, &*v));
279                }
280            }
281        }
282        None
283    }
284}
285
286/*
287impl<'a, K: Ord + Clone + Sized + fmt::Debug, V: Sized + fmt::Debug> fmt::Debug
288    for Cursor<'a, K, V>
289{
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        if let Some((k, v)) = self.peek_forward() {
292            f.debug_struct("Cursor").field("key", k).field("value", v).finish()
293        } else {
294            f.debug_struct("Cursor").field("key", &"<end>").field("value", &"<end>").finish()
295        }
296    }
297}
298*/