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}