prefix_trie/map/entry.rs
1//! Code for inserting elements and the entry pattern.
2
3use super::*;
4
5/// A mutable view into a single entry in a map, which may either be vacant or occupied.
6pub enum Entry<'a, P, T> {
7 /// The entry is not present in the tree.
8 Vacant(VacantEntry<'a, P, T>),
9 /// The entry is already present in the tree.
10 Occupied(OccupiedEntry<'a, P, T>),
11}
12
13/// A mutable view into a missing entry. The information within this structure describes a path
14/// towards that missing node, and how to insert it.
15pub struct VacantEntry<'a, P, T> {
16 pub(super) map: &'a mut PrefixMap<P, T>,
17 pub(super) prefix: P,
18 pub(super) idx: usize,
19 pub(super) direction: DirectionForInsert<P>,
20}
21
22/// A mutable view into an occupied entry. An occupied entry represents a node that is already
23/// present on the tree.
24pub struct OccupiedEntry<'a, P, T> {
25 pub(super) node: &'a mut Node<P, T>,
26 pub(super) prefix: P, // needed to replace the prefix on the thing if we perform insert.
27}
28
29impl<P, T> Entry<'_, P, T> {
30 /// Get the value if it exists
31 ///
32 /// ```
33 /// # use prefix_trie::*;
34 /// # #[cfg(feature = "ipnet")]
35 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
36 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
37 /// pm.insert("192.168.1.0/24".parse()?, 1);
38 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).get(), Some(&1));
39 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).get(), None);
40 /// # Ok(())
41 /// # }
42 /// # #[cfg(not(feature = "ipnet"))]
43 /// # fn main() {}
44 /// ```
45 pub fn get(&self) -> Option<&T> {
46 match self {
47 Entry::Vacant(_) => None,
48 Entry::Occupied(e) => e.node.value.as_ref(),
49 }
50 }
51
52 /// Get the value if it exists
53 ///
54 /// ```
55 /// # use prefix_trie::*;
56 /// # #[cfg(feature = "ipnet")]
57 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
58 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
59 /// pm.insert("192.168.1.0/24".parse()?, 1);
60 /// pm.entry("192.168.1.0/24".parse()?).get_mut().map(|x| *x += 1);
61 /// pm.entry("192.168.2.0/24".parse()?).get_mut().map(|x| *x += 1);
62 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
63 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), None);
64 /// # Ok(())
65 /// # }
66 /// # #[cfg(not(feature = "ipnet"))]
67 /// # fn main() {}
68 /// ```
69 pub fn get_mut(&mut self) -> Option<&mut T> {
70 match self {
71 Entry::Vacant(_) => None,
72 Entry::Occupied(e) => e.node.value.as_mut(),
73 }
74 }
75
76 /// get the key of the current entry
77 ///
78 /// ```
79 /// # use prefix_trie::*;
80 /// # #[cfg(feature = "ipnet")]
81 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
82 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
83 /// pm.insert("192.168.1.0/24".parse()?, 1);
84 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).key(), &"192.168.1.0/24".parse()?);
85 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).key(), &"192.168.2.0/24".parse()?);
86 /// # Ok(())
87 /// # }
88 /// # #[cfg(not(feature = "ipnet"))]
89 /// # fn main() {}
90 /// ```
91 pub fn key(&self) -> &P {
92 match self {
93 Entry::Vacant(e) => &e.prefix,
94 Entry::Occupied(e) => &e.node.prefix,
95 }
96 }
97}
98
99impl<'a, P, T> Entry<'a, P, T>
100where
101 P: Prefix,
102{
103 /// Replace the current entry, and return the entry that was stored before. This will also
104 /// replace the key with the one provided to the `entry` function.
105 ///
106 /// ```
107 /// # use prefix_trie::*;
108 /// # #[cfg(feature = "ipnet")]
109 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
110 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
111 /// pm.insert("192.168.1.0/24".parse()?, 1);
112 ///
113 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).insert(10), Some(1));
114 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).insert(20), None);
115 ///
116 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
117 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
118 /// # Ok(())
119 /// # }
120 /// # #[cfg(not(feature = "ipnet"))]
121 /// # fn main() {}
122 /// ```
123 #[inline(always)]
124 pub fn insert(self, v: T) -> Option<T> {
125 match self {
126 Entry::Vacant(e) => {
127 e._insert(v);
128 None
129 }
130 Entry::Occupied(e) => Some(e.insert(v)),
131 }
132 }
133
134 /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable
135 /// reference to the value in the entry.
136 ///
137 /// ```
138 /// # use prefix_trie::*;
139 /// # #[cfg(feature = "ipnet")]
140 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
141 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
142 /// pm.insert("192.168.1.0/24".parse()?, 1);
143 ///
144 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert(10), &1);
145 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert(20), &20);
146 ///
147 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
148 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
149 /// # Ok(())
150 /// # }
151 /// # #[cfg(not(feature = "ipnet"))]
152 /// # fn main() {}
153 /// ```
154 #[inline(always)]
155 pub fn or_insert(self, default: T) -> &'a mut T {
156 match self {
157 Entry::Vacant(e) => e._insert(default).value.as_mut().unwrap(),
158 Entry::Occupied(e) => e.node.value.get_or_insert(default),
159 }
160 }
161
162 /// Ensures a value is in the entry by inserting the result of the default function if empty,
163 /// and returns a mutable reference to the value in the entry.
164 ///
165 /// ```
166 /// # use prefix_trie::*;
167 /// # #[cfg(feature = "ipnet")]
168 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
169 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
170 /// pm.insert("192.168.1.0/24".parse()?, 1);
171 ///
172 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert_with(|| 10), &1);
173 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert_with(|| 20), &20);
174 ///
175 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
176 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
177 /// # Ok(())
178 /// # }
179 /// # #[cfg(not(feature = "ipnet"))]
180 /// # fn main() {}
181 /// ```
182 #[inline(always)]
183 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
184 match self {
185 Entry::Vacant(e) => e._insert(default()).value.as_mut().unwrap(),
186 Entry::Occupied(e) => e.node.value.get_or_insert_with(default),
187 }
188 }
189
190 /// Provides in-place mutable access to an occupied entry before any potential inserts into the
191 /// map.
192 ///
193 /// ```
194 /// # use prefix_trie::*;
195 /// # #[cfg(feature = "ipnet")]
196 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
197 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
198 /// pm.insert("192.168.1.0/24".parse()?, 1);
199 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).and_modify(|x| *x += 1).get(), Some(&2));
200 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).and_modify(|x| *x += 1).get(), None);
201 /// # Ok(())
202 /// # }
203 /// # #[cfg(not(feature = "ipnet"))]
204 /// # fn main() {}
205 /// ```
206 #[inline(always)]
207 pub fn and_modify<F: FnOnce(&mut T)>(self, f: F) -> Self {
208 match self {
209 Entry::Vacant(e) => Entry::Vacant(e),
210 Entry::Occupied(e) => {
211 e.node.value.as_mut().map(f);
212 Entry::Occupied(e)
213 }
214 }
215 }
216}
217
218impl<'a, P, T> Entry<'a, P, T>
219where
220 P: Prefix,
221 T: Default,
222{
223 /// Ensures a value is in the entry by inserting the default value if empty, and returns a
224 /// mutable reference to the value in the entry.
225 ///
226 /// ```
227 /// # use prefix_trie::*;
228 /// # #[cfg(feature = "ipnet")]
229 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
230 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
231 /// pm.insert("192.168.1.0/24".parse()?, 1);
232 ///
233 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_default(), &1);
234 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_default(), &0);
235 ///
236 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
237 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&0));
238 /// # Ok(())
239 /// # }
240 /// # #[cfg(not(feature = "ipnet"))]
241 /// # fn main() {}
242 /// ```
243 #[allow(clippy::unwrap_or_default)]
244 #[inline(always)]
245 pub fn or_default(self) -> &'a mut T {
246 self.or_insert_with(Default::default)
247 }
248}
249
250impl<'a, P, T> VacantEntry<'a, P, T>
251where
252 P: Prefix,
253{
254 fn _insert(self, v: T) -> &'a mut Node<P, T> {
255 match self.direction {
256 DirectionForInsert::Reached => {
257 // increment the count, as node.value will be `None`. We do it here as we borrow
258 // `map` mutably in the next line.
259 self.map.count += 1;
260 let node = &mut self.map.table[self.idx];
261 node.prefix = self.prefix;
262 debug_assert!(node.value.is_none());
263 node.value = Some(v);
264 node
265 }
266 DirectionForInsert::NewLeaf { right } => {
267 let new = self.map.new_node(self.prefix, Some(v));
268 self.map.table.set_child(self.idx, new, right);
269 &mut self.map.table[new]
270 }
271 DirectionForInsert::NewChild { right, child_right } => {
272 let new = self.map.new_node(self.prefix, Some(v));
273 let child = self.map.table.set_child(self.idx, new, right).unwrap();
274 self.map.table.set_child(new, child, child_right);
275 &mut self.map.table[new]
276 }
277 DirectionForInsert::NewBranch {
278 branch_prefix,
279 right,
280 prefix_right,
281 } => {
282 let branch = self.map.new_node(branch_prefix, None);
283 let new = self.map.new_node(self.prefix, Some(v));
284 let child = self.map.table.set_child(self.idx, branch, right).unwrap();
285 self.map.table.set_child(branch, new, prefix_right);
286 self.map.table.set_child(branch, child, !prefix_right);
287 &mut self.map.table[new]
288 }
289 DirectionForInsert::Enter { .. } => unreachable!(),
290 }
291 }
292}
293
294impl<P, T> OccupiedEntry<'_, P, T> {
295 /// Gets a reference to the key in the entry. This is the key that is currently stored, and not
296 /// the key that was used in the insert.
297 ///
298 /// ```
299 /// # use prefix_trie::*;
300 /// use prefix_trie::map::Entry;
301 /// # #[cfg(feature = "ipnet")]
302 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
303 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
304 /// pm.insert("192.168.1.0/24".parse()?, 1);
305 /// match pm.entry("192.168.1.1/24".parse()?) {
306 /// Entry::Occupied(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
307 /// Entry::Vacant(_) => unreachable!(),
308 /// }
309 /// # Ok(())
310 /// # }
311 /// # #[cfg(not(feature = "ipnet"))]
312 /// # fn main() {}
313 /// ```
314 pub fn key(&self) -> &P {
315 &self.node.prefix
316 }
317
318 /// Gets a reference to the value in the entry.
319 ///
320 /// ```
321 /// # use prefix_trie::*;
322 /// use prefix_trie::map::Entry;
323 /// # #[cfg(feature = "ipnet")]
324 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
325 ///
326 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
327 /// pm.insert("192.168.1.0/24".parse()?, 1);
328 /// match pm.entry("192.168.1.0/24".parse()?) {
329 /// Entry::Occupied(e) => assert_eq!(e.get(), &1),
330 /// Entry::Vacant(_) => unreachable!(),
331 /// }
332 /// # Ok(())
333 /// # }
334 /// # #[cfg(not(feature = "ipnet"))]
335 /// # fn main() {}
336 /// ```
337 pub fn get(&self) -> &T {
338 self.node.value.as_ref().unwrap()
339 }
340
341 /// Gets a mutable reference to the value in the entry.
342 ///
343 /// This call will not modify the prefix stored in the tree. In case the prefix used to create
344 /// the entry is different from the stored one (has additional information in the host part),
345 /// and you wish that prefix to be overwritten, use `insert`.
346 ///
347 /// ```
348 /// # use prefix_trie::*;
349 /// use prefix_trie::map::Entry;
350 /// # #[cfg(feature = "ipnet")]
351 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
352 ///
353 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
354 /// pm.insert("192.168.1.0/24".parse()?, 1);
355 /// match pm.entry("192.168.1.0/24".parse()?) {
356 /// Entry::Occupied(mut e) => *e.get_mut() += 1,
357 /// Entry::Vacant(_) => unreachable!(),
358 /// }
359 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
360 /// # Ok(())
361 /// # }
362 /// # #[cfg(not(feature = "ipnet"))]
363 /// # fn main() {}
364 /// ```
365 pub fn get_mut(&mut self) -> &mut T {
366 self.node.value.as_mut().unwrap()
367 }
368
369 /// Insert a new value into the entry, returning the old value. This operation will also replace
370 /// the prefix with the provided one.
371 ///
372 /// ```
373 /// # use prefix_trie::*;
374 /// use prefix_trie::map::Entry;
375 /// # #[cfg(feature = "ipnet")]
376 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
377 ///
378 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
379 /// pm.insert("192.168.1.0/24".parse()?, 1);
380 /// match pm.entry("192.168.1.0/24".parse()?) {
381 /// Entry::Occupied(mut e) => assert_eq!(e.insert(10), 1),
382 /// Entry::Vacant(_) => unreachable!(),
383 /// }
384 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
385 /// # Ok(())
386 /// # }
387 /// # #[cfg(not(feature = "ipnet"))]
388 /// # fn main() {}
389 /// ```
390 pub fn insert(self, value: T) -> T {
391 self.node.prefix = self.prefix;
392 self.node.value.replace(value).unwrap()
393 }
394
395 /// Remove the current value and return it. The tree will not be modified (the same effect as
396 /// `PrefixMap::remove_keep_tree`).
397 ///
398 /// ```
399 /// # use prefix_trie::*;
400 /// use prefix_trie::map::Entry;
401 /// # #[cfg(feature = "ipnet")]
402 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
403 ///
404 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
405 /// pm.insert("192.168.1.0/24".parse()?, 1);
406 /// match pm.entry("192.168.1.0/24".parse()?) {
407 /// Entry::Occupied(mut e) => assert_eq!(e.remove(), 1),
408 /// Entry::Vacant(_) => unreachable!(),
409 /// }
410 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), None);
411 /// # Ok(())
412 /// # }
413 /// # #[cfg(not(feature = "ipnet"))]
414 /// # fn main() {}
415 /// ```
416 pub fn remove(&mut self) -> T {
417 self.node.value.take().unwrap()
418 }
419}
420
421impl<P, T> VacantEntry<'_, P, T> {
422 /// Gets a reference to the key in the entry.
423 ///
424 /// ```
425 /// # use prefix_trie::*;
426 /// use prefix_trie::map::Entry;
427 /// # #[cfg(feature = "ipnet")]
428 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
429 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
430 /// match pm.entry("192.168.1.0/24".parse()?) {
431 /// Entry::Vacant(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
432 /// Entry::Occupied(_) => unreachable!(),
433 /// }
434 /// # Ok(())
435 /// # }
436 /// # #[cfg(not(feature = "ipnet"))]
437 /// # fn main() {}
438 /// ```
439 pub fn key(&self) -> &P {
440 &self.prefix
441 }
442}
443
444impl<'a, P, T> VacantEntry<'a, P, T>
445where
446 P: Prefix,
447{
448 /// Get a mutable reference to the value. If the value is yet empty, set it to the given default
449 /// value.
450 ///
451 /// ```
452 /// # use prefix_trie::*;
453 /// use prefix_trie::map::Entry;
454 /// # #[cfg(feature = "ipnet")]
455 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
456 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
457 /// match pm.entry("192.168.1.0/24".parse()?) {
458 /// Entry::Vacant(mut e) => assert_eq!(e.insert(10), &10),
459 /// Entry::Occupied(_) => unreachable!(),
460 /// }
461 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
462 /// # Ok(())
463 /// # }
464 /// # #[cfg(not(feature = "ipnet"))]
465 /// # fn main() {}
466 /// ```
467 pub fn insert(self, default: T) -> &'a mut T {
468 let node = self._insert(default);
469 node.value.as_mut().unwrap()
470 }
471
472 /// Get a mutable reference to the value. If the value is yet empty, set it to the return value
473 /// from the given function.
474 ///
475 /// ```
476 /// # use prefix_trie::*;
477 /// use prefix_trie::map::Entry;
478 /// # #[cfg(feature = "ipnet")]
479 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
480 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
481 /// match pm.entry("192.168.1.0/24".parse()?) {
482 /// Entry::Vacant(mut e) => assert_eq!(e.insert_with(|| 10), &10),
483 /// Entry::Occupied(_) => unreachable!(),
484 /// }
485 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
486 /// # Ok(())
487 /// # }
488 /// # #[cfg(not(feature = "ipnet"))]
489 /// # fn main() {}
490 /// ```
491 pub fn insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
492 let node = self._insert(default());
493 node.value.as_mut().unwrap()
494 }
495}
496
497impl<'a, P, T> VacantEntry<'a, P, T>
498where
499 P: Prefix,
500 T: Default,
501{
502 /// Get a mutable reference to the value. If the value is yet empty, set it to the default value
503 /// using `Default::default()`.
504 ///
505 /// ```
506 /// # use prefix_trie::*;
507 /// use prefix_trie::map::Entry;
508 /// # #[cfg(feature = "ipnet")]
509 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
510 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
511 /// match pm.entry("192.168.1.0/24".parse()?) {
512 /// Entry::Vacant(e) => assert_eq!(e.default(), &0),
513 /// Entry::Occupied(_) => unreachable!(),
514 /// }
515 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&0));
516 /// # Ok(())
517 /// # }
518 /// # #[cfg(not(feature = "ipnet"))]
519 /// # fn main() {}
520 /// ```
521 pub fn default(self) -> &'a mut T {
522 let node = self._insert(Default::default());
523 node.value.as_mut().unwrap()
524 }
525}