unc_sdk/store/tree_map/
entry.rs

1use borsh::{BorshDeserialize, BorshSerialize};
2
3use super::Tree;
4use crate::store::lookup_map as lm;
5
6/// A view into a single entry in the map, which can be vacant or occupied.
7pub enum Entry<'a, K: 'a, V: 'a>
8where
9    K: BorshSerialize,
10{
11    Occupied(OccupiedEntry<'a, K, V>),
12    Vacant(VacantEntry<'a, K, V>),
13}
14
15impl<'a, K, V> Entry<'a, K, V>
16where
17    K: BorshSerialize,
18{
19    pub(super) fn new(lm_entry: lm::Entry<'a, K, V>, keys: &'a mut Tree<K>) -> Self {
20        match lm_entry {
21            lm::Entry::Occupied(value_entry) => Self::Occupied(OccupiedEntry { value_entry, keys }),
22            lm::Entry::Vacant(value_entry) => Self::Vacant(VacantEntry { value_entry, keys }),
23        }
24    }
25}
26
27impl<'a, K, V> Entry<'a, K, V>
28where
29    K: BorshSerialize,
30{
31    /// Returns a reference to this entry's key.
32    ///
33    /// # Examples
34    ///
35    /// ```
36    /// use unc_sdk::store::TreeMap;
37    ///
38    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
39    /// assert_eq!(map.entry("poneyland".to_string()).key(), "poneyland");
40    /// ```
41    pub fn key(&self) -> &K {
42        match self {
43            Entry::Occupied(entry) => entry.key(),
44            Entry::Vacant(entry) => entry.key(),
45        }
46    }
47}
48
49impl<'a, K, V> Entry<'a, K, V>
50where
51    K: BorshSerialize + BorshDeserialize + Clone + Ord,
52{
53    /// Ensures a value is in the entry by inserting the default if empty, and returns
54    /// a mutable reference to the value in the entry.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use unc_sdk::store::TreeMap;
60    ///
61    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
62    ///
63    /// map.entry("poneyland".to_string()).or_insert(3);
64    /// assert_eq!(map["poneyland"], 3);
65    ///
66    /// *map.entry("poneyland".to_string()).or_insert(10) *= 2;
67    /// assert_eq!(map["poneyland"], 6);
68    /// ```
69    pub fn or_insert(self, default: V) -> &'a mut V {
70        self.or_insert_with(|| default)
71    }
72
73    /// Ensures a value is in the entry by inserting the result of the default function if empty,
74    /// and returns a mutable reference to the value in the entry.
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// use unc_sdk::store::TreeMap;
80    ///
81    /// let mut map: TreeMap<String, String> = TreeMap::new(b"m");
82    /// let s = "hoho".to_string();
83    ///
84    /// map.entry("poneyland".to_string()).or_insert_with(|| s);
85    ///
86    /// assert_eq!(map["poneyland"], "hoho".to_string());
87    /// ```
88    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
89        self.or_insert_with_key(|_| default())
90    }
91
92    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
93    /// This method allows for generating key-derived values for insertion by providing the default
94    /// function a reference to the key that was moved during the `.entry(key)` method call.
95    ///
96    /// The reference to the moved key is provided so that cloning or copying the key is
97    /// unnecessary, unlike with `.or_insert_with(|| ... )`.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use unc_sdk::store::TreeMap;
103    ///
104    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
105    ///
106    /// map.entry("poneyland".to_string()).or_insert_with_key(|key| key.chars().count() as u32);
107    ///
108    /// assert_eq!(map["poneyland"], 9);
109    /// ```
110    pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V
111    where
112        K: BorshDeserialize,
113    {
114        match self {
115            Self::Occupied(entry) => entry.into_mut(),
116            Self::Vacant(entry) => {
117                let value = default(entry.key());
118                entry.insert(value)
119            }
120        }
121    }
122
123    /// Ensures a value is in the entry by inserting the default value if empty,
124    /// and returns a mutable reference to the value in the entry.
125    ///
126    /// # Examples
127    ///
128    /// ```
129    /// # fn main() {
130    /// use unc_sdk::store::TreeMap;
131    ///
132    /// let mut map: TreeMap<String, Option<u32>> = TreeMap::new(b"m");
133    /// map.entry("poneyland".to_string()).or_default();
134    ///
135    /// assert_eq!(map["poneyland"], None);
136    /// # }
137    /// ```
138    pub fn or_default(self) -> &'a mut V
139    where
140        V: Default,
141    {
142        #[allow(clippy::unwrap_or_default)]
143        self.or_insert_with(Default::default)
144    }
145
146    /// Provides in-place mutable access to an occupied entry before any
147    /// potential inserts into the map.
148    ///
149    /// # Examples
150    ///
151    /// ```
152    /// use unc_sdk::store::TreeMap;
153    ///
154    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
155    ///
156    /// map.entry("poneyland".to_string())
157    ///    .and_modify(|e| { *e += 1 })
158    ///    .or_insert(42);
159    /// assert_eq!(map["poneyland"], 42);
160    ///
161    /// map.entry("poneyland".to_string())
162    ///    .and_modify(|e| { *e += 1 })
163    ///    .or_insert(42);
164    /// assert_eq!(map["poneyland"], 43);
165    /// ```
166    pub fn and_modify<F>(mut self, f: F) -> Self
167    where
168        F: FnOnce(&mut V),
169    {
170        if let Self::Occupied(entry) = &mut self {
171            f(entry.get_mut());
172        }
173        self
174    }
175}
176
177/// View into an occupied entry in a [`TreeMap`](super::TreeMap).
178/// This is part of the [`Entry`] enum.
179pub struct OccupiedEntry<'a, K, V>
180where
181    K: BorshSerialize,
182{
183    value_entry: lm::OccupiedEntry<'a, K, V>,
184    keys: &'a mut Tree<K>,
185}
186
187impl<'a, K, V> OccupiedEntry<'a, K, V>
188where
189    K: BorshSerialize,
190{
191    /// Gets a reference to the key in the entry.
192    pub fn key(&self) -> &K {
193        self.value_entry.key()
194    }
195
196    /// Take the ownership of the key and value from the map.
197    ///
198    /// # Examples
199    ///
200    /// ```
201    /// use unc_sdk::store::TreeMap;
202    /// use unc_sdk::store::tree_map::Entry;
203    ///
204    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
205    /// map.entry("poneyland".to_string()).or_insert(12);
206    ///
207    /// if let Entry::Occupied(o) = map.entry("poneyland".to_string()) {
208    ///     // We delete the entry from the map.
209    ///     o.remove_entry();
210    /// }
211    ///
212    /// assert_eq!(map.contains_key("poneyland"), false);
213    /// ```
214    pub fn remove_entry(self) -> (K, V)
215    where
216        K: BorshDeserialize + Ord + Clone,
217    {
218        let (key, value) = self.value_entry.remove_entry();
219        self.keys.do_remove(&key);
220        (key, value)
221    }
222
223    /// Gets a reference to the value in the entry.
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// use unc_sdk::store::TreeMap;
229    /// use unc_sdk::store::tree_map::Entry;
230    ///
231    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
232    /// map.entry("poneyland".to_string()).or_insert(12);
233    ///
234    /// if let Entry::Occupied(o) = map.entry("poneyland".to_string()) {
235    ///     assert_eq!(o.get(), &12);
236    /// }
237    /// ```
238    pub fn get(&self) -> &V {
239        self.value_entry.get()
240    }
241
242    /// Gets a mutable reference to the value in the entry.
243    ///
244    /// If you need a reference to the `OccupiedEntry` which may outlive the
245    /// destruction of the `Entry` value, see [`into_mut`].
246    ///
247    /// [`into_mut`]: Self::into_mut
248    ///
249    /// # Examples
250    ///
251    /// ```
252    /// use unc_sdk::store::TreeMap;
253    /// use unc_sdk::store::tree_map::Entry;
254    ///
255    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
256    /// map.entry("poneyland".to_string()).or_insert(12);
257    ///
258    /// assert_eq!(map["poneyland"], 12);
259    /// if let Entry::Occupied(mut o) = map.entry("poneyland".to_string()) {
260    ///     *o.get_mut() += 10;
261    ///     assert_eq!(*o.get(), 22);
262    ///
263    ///     // We can use the same Entry multiple times.
264    ///     *o.get_mut() += 2;
265    /// }
266    ///
267    /// assert_eq!(map["poneyland"], 24);
268    /// ```
269    pub fn get_mut(&mut self) -> &mut V {
270        self.value_entry.get_mut()
271    }
272
273    /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
274    /// with a lifetime bound to the map itself.
275    ///
276    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
277    ///
278    /// [`get_mut`]: Self::get_mut
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use unc_sdk::store::TreeMap;
284    /// use unc_sdk::store::tree_map::Entry;
285    ///
286    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
287    /// map.entry("poneyland".to_string()).or_insert(12);
288    ///
289    /// assert_eq!(map["poneyland"], 12);
290    /// if let Entry::Occupied(o) = map.entry("poneyland".to_string()) {
291    ///     *o.into_mut() += 10;
292    /// }
293    ///
294    /// assert_eq!(map["poneyland"], 22);
295    /// ```
296    pub fn into_mut(self) -> &'a mut V {
297        self.value_entry.into_mut()
298    }
299
300    /// Sets the value of the entry, and returns the entry's old value.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// use unc_sdk::store::TreeMap;
306    /// use unc_sdk::store::tree_map::Entry;
307    ///
308    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
309    /// map.entry("poneyland".to_string()).or_insert(12);
310    ///
311    /// if let Entry::Occupied(mut o) = map.entry("poneyland".to_string()) {
312    ///     assert_eq!(o.insert(15), 12);
313    /// }
314    ///
315    /// assert_eq!(map["poneyland"], 15);
316    /// ```
317    pub fn insert(&mut self, value: V) -> V {
318        core::mem::replace(self.value_entry.get_mut(), value)
319    }
320
321    /// Takes the value out of the entry, and returns it.
322    ///
323    /// # Examples
324    ///
325    /// ```
326    /// use unc_sdk::store::TreeMap;
327    /// use unc_sdk::store::tree_map::Entry;
328    ///
329    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
330    /// map.entry("poneyland".to_string()).or_insert(12);
331    ///
332    /// if let Entry::Occupied(o) = map.entry("poneyland".to_string()) {
333    ///     assert_eq!(o.remove(), 12);
334    /// }
335    ///
336    /// assert_eq!(map.contains_key("poneyland"), false);
337    /// ```
338    pub fn remove(self) -> V
339    where
340        K: BorshDeserialize + Ord + Clone,
341    {
342        self.remove_entry().1
343    }
344}
345
346/// View into a vacant entry in a [`TreeMap`](super::TreeMap).
347/// This is part of the [`Entry`] enum.
348pub struct VacantEntry<'a, K, V>
349where
350    K: BorshSerialize,
351{
352    value_entry: lm::VacantEntry<'a, K, V>,
353    keys: &'a mut Tree<K>,
354}
355
356impl<'a, K, V> VacantEntry<'a, K, V>
357where
358    K: BorshSerialize,
359{
360    /// Gets a reference to the key that would be used when inserting a value
361    /// through the `VacantEntry`.
362    pub fn key(&self) -> &K {
363        self.value_entry.key()
364    }
365
366    /// Take ownership of the key.
367    ///
368    /// # Examples
369    ///
370    /// ```
371    /// use unc_sdk::store::TreeMap;
372    /// use unc_sdk::store::tree_map::Entry;
373    ///
374    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
375    ///
376    /// if let Entry::Vacant(v) = map.entry("poneyland".to_string()) {
377    ///     v.into_key();
378    /// }
379    /// ```
380    pub fn into_key(self) -> K {
381        self.value_entry.into_key()
382    }
383
384    /// Sets the value of the entry with the `VacantEntry`'s key,
385    /// and returns a mutable reference to it.
386    ///
387    /// # Examples
388    ///
389    /// ```
390    /// use unc_sdk::store::TreeMap;
391    /// use unc_sdk::store::tree_map::Entry;
392    ///
393    /// let mut map: TreeMap<String, u32> = TreeMap::new(b"m");
394    ///
395    /// if let Entry::Vacant(o) = map.entry("poneyland".to_string()) {
396    ///     o.insert(37);
397    /// }
398    /// assert_eq!(map["poneyland"], 37);
399    /// ```
400    pub fn insert(self, value: V) -> &'a mut V
401    where
402        K: BorshDeserialize + Clone + Ord,
403    {
404        // Vacant entry so we know key doesn't exist
405        self.keys.internal_insert(self.key().to_owned());
406        self.value_entry.insert(value)
407    }
408}