prefix_trie/map/entry.rs
1//! Code for inserting elements and the entry pattern.
2
3use crate::{
4 table::{EmptyMut, NoNodeMut, PresentMut},
5 Prefix,
6};
7
8/// A mutable view into a single entry in a map, which may either be vacant or occupied.
9pub enum Entry<'a, P, T> {
10 /// The entry is not present in the tree.
11 Vacant(VacantEntry<'a, P, T>),
12 /// The entry is already present in the tree.
13 Occupied(OccupiedEntry<'a, P, T>),
14}
15
16/// A mutable view into a missing entry. The information within this structure describes a path
17/// towards that missing node, and how to insert it.
18pub struct VacantEntry<'a, P, T> {
19 loc: Result<EmptyMut<'a, T>, NoNodeMut<'a, T>>,
20 count: &'a mut usize,
21 prefix: P,
22}
23
24impl<'a, P, T> VacantEntry<'a, P, T> {
25 pub(super) fn empty(loc: EmptyMut<'a, T>, count: &'a mut usize, prefix: P) -> Self {
26 Self {
27 loc: Ok(loc),
28 count,
29 prefix,
30 }
31 }
32 pub(super) fn no_node(loc: NoNodeMut<'a, T>, count: &'a mut usize, prefix: P) -> Self {
33 Self {
34 loc: Err(loc),
35 count,
36 prefix,
37 }
38 }
39}
40
41/// A mutable view into an occupied entry. An occupied entry represents a node that is already
42/// present on the tree.
43pub struct OccupiedEntry<'a, P, T> {
44 loc: PresentMut<'a, T>,
45 count: &'a mut usize,
46 prefix: P,
47}
48
49impl<'a, P, T> OccupiedEntry<'a, P, T>
50where
51 P: Prefix,
52{
53 pub(super) fn new(loc: PresentMut<'a, T>, count: &'a mut usize, prefix: P) -> Self {
54 let prefix = P::from_repr_len(prefix.mask(), prefix.prefix_len());
55 Self { loc, count, prefix }
56 }
57}
58
59impl<P: Prefix, T> Entry<'_, P, T> {
60 /// Get the value if it exists
61 ///
62 /// ```
63 /// # use prefix_trie::*;
64 /// # #[cfg(feature = "ipnet")]
65 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
66 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
67 /// pm.insert("192.168.1.0/24".parse()?, 1);
68 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).get(), Some(&1));
69 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).get(), None);
70 /// # Ok(())
71 /// # }
72 /// # #[cfg(not(feature = "ipnet"))]
73 /// # fn main() {}
74 /// ```
75 pub fn get(&self) -> Option<&T> {
76 match self {
77 Entry::Vacant(_) => None,
78 Entry::Occupied(e) => Some(e.get()),
79 }
80 }
81
82 /// Get the value if it exists
83 ///
84 /// ```
85 /// # use prefix_trie::*;
86 /// # #[cfg(feature = "ipnet")]
87 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
88 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
89 /// pm.insert("192.168.1.0/24".parse()?, 1);
90 /// pm.entry("192.168.1.0/24".parse()?).get_mut().map(|x| *x += 1);
91 /// pm.entry("192.168.2.0/24".parse()?).get_mut().map(|x| *x += 1);
92 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
93 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), None);
94 /// # Ok(())
95 /// # }
96 /// # #[cfg(not(feature = "ipnet"))]
97 /// # fn main() {}
98 /// ```
99 pub fn get_mut(&mut self) -> Option<&mut T> {
100 match self {
101 Entry::Vacant(_) => None,
102 Entry::Occupied(e) => {
103 // Safety: internal_idx points to an initialized cell (see OccupiedEntry::new)
104 Some(e.get_mut())
105 }
106 }
107 }
108
109 /// get the key of the current entry
110 ///
111 /// ```
112 /// # use prefix_trie::*;
113 /// # #[cfg(feature = "ipnet")]
114 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
115 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
116 /// pm.insert("192.168.1.0/24".parse()?, 1);
117 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).key(), &"192.168.1.0/24".parse()?);
118 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).key(), &"192.168.2.0/24".parse()?);
119 /// # Ok(())
120 /// # }
121 /// # #[cfg(not(feature = "ipnet"))]
122 /// # fn main() {}
123 /// ```
124 pub fn key(&self) -> &P {
125 match self {
126 Entry::Vacant(e) => &e.prefix,
127 Entry::Occupied(e) => e.key(),
128 }
129 }
130}
131
132impl<'a, P, T> Entry<'a, P, T>
133where
134 P: Prefix,
135{
136 /// Replace the current entry, and return the entry that was stored before.
137 ///
138 /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
139 /// bits masked out by the prefix length are not preserved.
140 ///
141 /// ```
142 /// # use prefix_trie::*;
143 /// # #[cfg(feature = "ipnet")]
144 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
145 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
146 /// pm.insert("192.168.1.0/24".parse()?, 1);
147 ///
148 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).insert(10), Some(1));
149 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).insert(20), None);
150 ///
151 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
152 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
153 /// # Ok(())
154 /// # }
155 /// # #[cfg(not(feature = "ipnet"))]
156 /// # fn main() {}
157 /// ```
158 ///
159 /// Host bits from the `entry` argument are not preserved:
160 ///
161 /// ```
162 /// # use prefix_trie::*;
163 /// # #[cfg(feature = "ipnet")]
164 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
165 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
166 /// pm.insert("192.168.1.1/24".parse()?, 1);
167 /// pm.entry("192.168.1.2/24".parse()?).insert(2);
168 /// assert_eq!(
169 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
170 /// Some(("192.168.1.0/24".parse()?, &2))
171 /// );
172 /// # Ok(())
173 /// # }
174 /// # #[cfg(not(feature = "ipnet"))]
175 /// # fn main() {}
176 /// ```
177 #[inline(always)]
178 pub fn insert(self, v: T) -> Option<T> {
179 match self {
180 Entry::Vacant(e) => {
181 e._insert(v);
182 None
183 }
184 Entry::Occupied(e) => Some(e.insert(v)),
185 }
186 }
187
188 /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable
189 /// reference to the value in the entry.
190 ///
191 /// ```
192 /// # use prefix_trie::*;
193 /// # #[cfg(feature = "ipnet")]
194 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
195 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
196 /// pm.insert("192.168.1.0/24".parse()?, 1);
197 ///
198 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert(10), &1);
199 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert(20), &20);
200 ///
201 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
202 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
203 /// # Ok(())
204 /// # }
205 /// # #[cfg(not(feature = "ipnet"))]
206 /// # fn main() {}
207 /// ```
208 ///
209 /// Host bits from an existing matching prefix are not preserved.
210 ///
211 /// ```
212 /// # use prefix_trie::*;
213 /// # #[cfg(feature = "ipnet")]
214 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
215 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
216 /// pm.insert("192.168.1.1/24".parse()?, 1);
217 /// pm.entry("192.168.1.2/24".parse()?).or_insert(2);
218 /// assert_eq!(
219 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
220 /// Some(("192.168.1.0/24".parse()?, &1))
221 /// );
222 /// # Ok(())
223 /// # }
224 /// # #[cfg(not(feature = "ipnet"))]
225 /// # fn main() {}
226 /// ```
227 #[inline(always)]
228 pub fn or_insert(self, default: T) -> &'a mut T {
229 match self {
230 Entry::Vacant(e) => e._insert(default).1,
231 Entry::Occupied(e) => e.into_mut(),
232 }
233 }
234
235 /// Ensures a value is in the entry by inserting the result of the default function if empty,
236 /// and returns a mutable reference to the value in the entry.
237 ///
238 /// ```
239 /// # use prefix_trie::*;
240 /// # #[cfg(feature = "ipnet")]
241 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
242 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
243 /// pm.insert("192.168.1.0/24".parse()?, 1);
244 ///
245 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert_with(|| 10), &1);
246 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert_with(|| 20), &20);
247 ///
248 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
249 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
250 /// # Ok(())
251 /// # }
252 /// # #[cfg(not(feature = "ipnet"))]
253 /// # fn main() {}
254 /// ```
255 ///
256 /// Host bits from an existing matching prefix are not preserved.
257 ///
258 /// ```
259 /// # use prefix_trie::*;
260 /// # #[cfg(feature = "ipnet")]
261 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
262 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
263 /// pm.insert("192.168.1.1/24".parse()?, 1);
264 /// pm.entry("192.168.1.2/24".parse()?).or_insert_with(|| 2);
265 /// assert_eq!(
266 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
267 /// Some(("192.168.1.0/24".parse()?, &1))
268 /// );
269 /// # Ok(())
270 /// # }
271 /// # #[cfg(not(feature = "ipnet"))]
272 /// # fn main() {}
273 /// ```
274 #[inline(always)]
275 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
276 match self {
277 Entry::Vacant(e) => e._insert(default()).1,
278 Entry::Occupied(e) => e.into_mut(),
279 }
280 }
281
282 /// Provides in-place mutable access to an occupied entry before any potential inserts into the
283 /// map.
284 ///
285 /// ```
286 /// # use prefix_trie::*;
287 /// # #[cfg(feature = "ipnet")]
288 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
289 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
290 /// pm.insert("192.168.1.0/24".parse()?, 1);
291 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).and_modify(|x| *x += 1).get(), Some(&2));
292 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).and_modify(|x| *x += 1).get(), None);
293 /// # Ok(())
294 /// # }
295 /// # #[cfg(not(feature = "ipnet"))]
296 /// # fn main() {}
297 /// ```
298 ///
299 /// Host bits from an existing matching prefix are not preserved.
300 ///
301 /// ```
302 /// # use prefix_trie::*;
303 /// # #[cfg(feature = "ipnet")]
304 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
305 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
306 /// pm.insert("192.168.1.1/24".parse()?, 1);
307 /// pm.entry("192.168.1.2/24".parse()?).and_modify(|x| *x += 1);
308 /// assert_eq!(
309 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
310 /// Some(("192.168.1.0/24".parse()?, &2))
311 /// );
312 /// # Ok(())
313 /// # }
314 /// # #[cfg(not(feature = "ipnet"))]
315 /// # fn main() {}
316 /// ```
317 #[inline(always)]
318 pub fn and_modify<F: FnOnce(&mut T)>(self, f: F) -> Self {
319 match self {
320 Entry::Vacant(e) => Entry::Vacant(e),
321 Entry::Occupied(mut e) => {
322 f(e.get_mut());
323 Entry::Occupied(e)
324 }
325 }
326 }
327}
328
329impl<'a, P, T> Entry<'a, P, T>
330where
331 P: Prefix,
332 T: Default,
333{
334 /// Ensures a value is in the entry by inserting the default value if empty, and returns a
335 /// mutable reference to the value in the entry.
336 ///
337 /// ```
338 /// # use prefix_trie::*;
339 /// # #[cfg(feature = "ipnet")]
340 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
341 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
342 /// pm.insert("192.168.1.0/24".parse()?, 1);
343 ///
344 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_default(), &1);
345 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_default(), &0);
346 ///
347 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
348 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&0));
349 /// # Ok(())
350 /// # }
351 /// # #[cfg(not(feature = "ipnet"))]
352 /// # fn main() {}
353 /// ```
354 ///
355 /// Host bits from an existing matching prefix are not preserved.
356 ///
357 /// ```
358 /// # use prefix_trie::*;
359 /// # #[cfg(feature = "ipnet")]
360 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
361 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
362 /// pm.insert("192.168.1.1/24".parse()?, 1);
363 /// pm.entry("192.168.1.2/24".parse()?).or_default();
364 /// assert_eq!(
365 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
366 /// Some(("192.168.1.0/24".parse()?, &1))
367 /// );
368 /// # Ok(())
369 /// # }
370 /// # #[cfg(not(feature = "ipnet"))]
371 /// # fn main() {}
372 /// ```
373 #[allow(clippy::unwrap_or_default)]
374 #[inline(always)]
375 pub fn or_default(self) -> &'a mut T {
376 self.or_insert_with(Default::default)
377 }
378}
379
380impl<'a, P, T> VacantEntry<'a, P, T>
381where
382 P: Prefix,
383{
384 fn _insert(self, v: T) -> (P, &'a mut T) {
385 let Self { loc, count, prefix } = self;
386 *count += 1;
387 let r = match loc {
388 Ok(empty_mut) => empty_mut.insert(v),
389 Err(no_node_mut) => {
390 no_node_mut.insert_path_and_data(prefix.repr(), prefix.prefix_len() as u32, v)
391 }
392 };
393 let computed_prefix = r.prefix(prefix.repr());
394 let val_ref = r.get_mut();
395 (computed_prefix, val_ref)
396 }
397}
398
399impl<P: Prefix, T> OccupiedEntry<'_, P, T> {
400 /// Gets a reference to the key in the entry. This is the key that is currently stored, and not
401 /// the key that was used in the insert.
402 ///
403 /// ```
404 /// # use prefix_trie::*;
405 /// use prefix_trie::map::Entry;
406 /// # #[cfg(feature = "ipnet")]
407 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
408 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
409 /// pm.insert("192.168.1.0/24".parse()?, 1);
410 /// match pm.entry("192.168.1.1/24".parse()?) {
411 /// Entry::Occupied(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
412 /// Entry::Vacant(_) => unreachable!(),
413 /// }
414 /// # Ok(())
415 /// # }
416 /// # #[cfg(not(feature = "ipnet"))]
417 /// # fn main() {}
418 /// ```
419 pub fn key(&self) -> &P {
420 &self.prefix
421 }
422
423 /// Gets a reference to the value in the entry.
424 ///
425 /// ```
426 /// # use prefix_trie::*;
427 /// use prefix_trie::map::Entry;
428 /// # #[cfg(feature = "ipnet")]
429 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
430 ///
431 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
432 /// pm.insert("192.168.1.0/24".parse()?, 1);
433 /// match pm.entry("192.168.1.0/24".parse()?) {
434 /// Entry::Occupied(e) => assert_eq!(e.get(), &1),
435 /// Entry::Vacant(_) => unreachable!(),
436 /// }
437 /// # Ok(())
438 /// # }
439 /// # #[cfg(not(feature = "ipnet"))]
440 /// # fn main() {}
441 /// ```
442 pub fn get(&self) -> &T {
443 self.loc.get()
444 }
445
446 /// Gets a mutable reference to the value in the entry.
447 ///
448 /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
449 /// bits masked out by the prefix length are not preserved.
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 ///
457 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
458 /// pm.insert("192.168.1.0/24".parse()?, 1);
459 /// match pm.entry("192.168.1.0/24".parse()?) {
460 /// Entry::Occupied(mut e) => *e.get_mut() += 1,
461 /// Entry::Vacant(_) => unreachable!(),
462 /// }
463 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
464 /// # Ok(())
465 /// # }
466 /// # #[cfg(not(feature = "ipnet"))]
467 /// # fn main() {}
468 /// ```
469 pub fn get_mut(&mut self) -> &mut T {
470 self.loc.as_mut()
471 }
472
473 /// Insert a new value into the entry, returning the old value.
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 ///
481 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
482 /// pm.insert("192.168.1.0/24".parse()?, 1);
483 /// match pm.entry("192.168.1.0/24".parse()?) {
484 /// Entry::Occupied(mut e) => assert_eq!(e.insert(10), 1),
485 /// Entry::Vacant(_) => unreachable!(),
486 /// }
487 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
488 /// # Ok(())
489 /// # }
490 /// # #[cfg(not(feature = "ipnet"))]
491 /// # fn main() {}
492 /// ```
493 pub fn insert(self, v: T) -> T {
494 self.loc.replace(v)
495 }
496
497 /// Remove the current value and return it. Empty trie nodes may be left in place (the same
498 /// effect as `PrefixMap::remove_keep_tree`).
499 ///
500 /// ```
501 /// # use prefix_trie::*;
502 /// use prefix_trie::map::Entry;
503 /// # #[cfg(feature = "ipnet")]
504 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
505 ///
506 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
507 /// pm.insert("192.168.1.0/24".parse()?, 1);
508 /// match pm.entry("192.168.1.0/24".parse()?) {
509 /// Entry::Occupied(mut e) => assert_eq!(e.remove(), 1),
510 /// Entry::Vacant(_) => unreachable!(),
511 /// }
512 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), None);
513 /// # Ok(())
514 /// # }
515 /// # #[cfg(not(feature = "ipnet"))]
516 /// # fn main() {}
517 /// ```
518 pub fn remove(self) -> T {
519 *self.count -= 1;
520 self.loc.take()
521 }
522}
523
524impl<'a, P, T> OccupiedEntry<'a, P, T> {
525 /// Converts this occupied entry into a mutable reference to the stored value.
526 pub fn into_mut(self) -> &'a mut T {
527 self.loc.get_mut()
528 }
529}
530
531impl<P, T> VacantEntry<'_, P, T> {
532 /// Gets a reference to the key in the entry.
533 ///
534 /// ```
535 /// # use prefix_trie::*;
536 /// use prefix_trie::map::Entry;
537 /// # #[cfg(feature = "ipnet")]
538 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
539 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
540 /// match pm.entry("192.168.1.0/24".parse()?) {
541 /// Entry::Vacant(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
542 /// Entry::Occupied(_) => unreachable!(),
543 /// }
544 /// # Ok(())
545 /// # }
546 /// # #[cfg(not(feature = "ipnet"))]
547 /// # fn main() {}
548 /// ```
549 pub fn key(&self) -> &P {
550 &self.prefix
551 }
552}
553
554impl<'a, P, T> VacantEntry<'a, P, T>
555where
556 P: Prefix,
557{
558 /// Get a mutable reference to the value. If the value is yet empty, set it to the given default
559 /// value.
560 ///
561 /// ```
562 /// # use prefix_trie::*;
563 /// use prefix_trie::map::Entry;
564 /// # #[cfg(feature = "ipnet")]
565 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
566 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
567 /// match pm.entry("192.168.1.0/24".parse()?) {
568 /// Entry::Vacant(mut e) => assert_eq!(e.insert(10), &10),
569 /// Entry::Occupied(_) => unreachable!(),
570 /// }
571 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
572 /// # Ok(())
573 /// # }
574 /// # #[cfg(not(feature = "ipnet"))]
575 /// # fn main() {}
576 /// ```
577 pub fn insert(self, default: T) -> &'a mut T {
578 self._insert(default).1
579 }
580
581 /// Get a mutable reference to the value. If the value is yet empty, set it to the return value
582 /// from the given function.
583 ///
584 /// ```
585 /// # use prefix_trie::*;
586 /// use prefix_trie::map::Entry;
587 /// # #[cfg(feature = "ipnet")]
588 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
589 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
590 /// match pm.entry("192.168.1.0/24".parse()?) {
591 /// Entry::Vacant(mut e) => assert_eq!(e.insert_with(|| 10), &10),
592 /// Entry::Occupied(_) => unreachable!(),
593 /// }
594 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
595 /// # Ok(())
596 /// # }
597 /// # #[cfg(not(feature = "ipnet"))]
598 /// # fn main() {}
599 /// ```
600 pub fn insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
601 self._insert(default()).1
602 }
603}
604
605impl<'a, P, T> VacantEntry<'a, P, T>
606where
607 P: Prefix,
608 T: Default,
609{
610 /// Get a mutable reference to the value. If the value is yet empty, set it to the default value
611 /// using `Default::default()`.
612 ///
613 /// ```
614 /// # use prefix_trie::*;
615 /// use prefix_trie::map::Entry;
616 /// # #[cfg(feature = "ipnet")]
617 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
618 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
619 /// match pm.entry("192.168.1.0/24".parse()?) {
620 /// Entry::Vacant(e) => assert_eq!(e.default(), &0),
621 /// Entry::Occupied(_) => unreachable!(),
622 /// }
623 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&0));
624 /// # Ok(())
625 /// # }
626 /// # #[cfg(not(feature = "ipnet"))]
627 /// # fn main() {}
628 /// ```
629 pub fn default(self) -> &'a mut T {
630 self._insert(Default::default()).1
631 }
632}