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 /// **Note**: For an occupied entry, this is the canonical stored prefix (host bits masked
112 /// out). For a vacant entry, the prefix is returned exactly as it was passed to
113 /// [`PrefixMap::entry`](crate::PrefixMap::entry), including any host bits.
114 ///
115 /// ```
116 /// # use prefix_trie::*;
117 /// # #[cfg(feature = "ipnet")]
118 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
119 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
120 /// pm.insert("192.168.1.0/24".parse()?, 1);
121 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).key(), &"192.168.1.0/24".parse()?);
122 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).key(), &"192.168.2.0/24".parse()?);
123 /// # Ok(())
124 /// # }
125 /// # #[cfg(not(feature = "ipnet"))]
126 /// # fn main() {}
127 /// ```
128 pub fn key(&self) -> &P {
129 match self {
130 Entry::Vacant(e) => &e.prefix,
131 Entry::Occupied(e) => e.key(),
132 }
133 }
134}
135
136impl<'a, P, T> Entry<'a, P, T>
137where
138 P: Prefix,
139{
140 /// Replace the current entry, and return the entry that was stored before.
141 ///
142 /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
143 /// bits masked out by the prefix length are not preserved.
144 ///
145 /// ```
146 /// # use prefix_trie::*;
147 /// # #[cfg(feature = "ipnet")]
148 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
149 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
150 /// pm.insert("192.168.1.0/24".parse()?, 1);
151 ///
152 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).insert(10), Some(1));
153 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).insert(20), None);
154 ///
155 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
156 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
157 /// # Ok(())
158 /// # }
159 /// # #[cfg(not(feature = "ipnet"))]
160 /// # fn main() {}
161 /// ```
162 ///
163 /// Host bits from the `entry` argument are not preserved:
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.1/24".parse()?, 1);
171 /// pm.entry("192.168.1.2/24".parse()?).insert(2);
172 /// assert_eq!(
173 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
174 /// Some(("192.168.1.0/24".parse()?, &2))
175 /// );
176 /// # Ok(())
177 /// # }
178 /// # #[cfg(not(feature = "ipnet"))]
179 /// # fn main() {}
180 /// ```
181 #[inline(always)]
182 pub fn insert(self, v: T) -> Option<T> {
183 match self {
184 Entry::Vacant(e) => {
185 e._insert(v);
186 None
187 }
188 Entry::Occupied(e) => Some(e.insert(v)),
189 }
190 }
191
192 /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable
193 /// reference to the value in the entry.
194 ///
195 /// ```
196 /// # use prefix_trie::*;
197 /// # #[cfg(feature = "ipnet")]
198 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
199 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
200 /// pm.insert("192.168.1.0/24".parse()?, 1);
201 ///
202 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert(10), &1);
203 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert(20), &20);
204 ///
205 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
206 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
207 /// # Ok(())
208 /// # }
209 /// # #[cfg(not(feature = "ipnet"))]
210 /// # fn main() {}
211 /// ```
212 ///
213 /// Host bits from an existing matching prefix are not preserved.
214 ///
215 /// ```
216 /// # use prefix_trie::*;
217 /// # #[cfg(feature = "ipnet")]
218 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
219 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
220 /// pm.insert("192.168.1.1/24".parse()?, 1);
221 /// pm.entry("192.168.1.2/24".parse()?).or_insert(2);
222 /// assert_eq!(
223 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
224 /// Some(("192.168.1.0/24".parse()?, &1))
225 /// );
226 /// # Ok(())
227 /// # }
228 /// # #[cfg(not(feature = "ipnet"))]
229 /// # fn main() {}
230 /// ```
231 #[inline(always)]
232 pub fn or_insert(self, default: T) -> &'a mut T {
233 match self {
234 Entry::Vacant(e) => e._insert(default).1,
235 Entry::Occupied(e) => e.into_mut(),
236 }
237 }
238
239 /// Ensures a value is in the entry by inserting the result of the default function if empty,
240 /// and returns a mutable reference to the value in the entry.
241 ///
242 /// ```
243 /// # use prefix_trie::*;
244 /// # #[cfg(feature = "ipnet")]
245 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
246 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
247 /// pm.insert("192.168.1.0/24".parse()?, 1);
248 ///
249 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_insert_with(|| 10), &1);
250 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_insert_with(|| 20), &20);
251 ///
252 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
253 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&20));
254 /// # Ok(())
255 /// # }
256 /// # #[cfg(not(feature = "ipnet"))]
257 /// # fn main() {}
258 /// ```
259 ///
260 /// Host bits from an existing matching prefix are not preserved.
261 ///
262 /// ```
263 /// # use prefix_trie::*;
264 /// # #[cfg(feature = "ipnet")]
265 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
266 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
267 /// pm.insert("192.168.1.1/24".parse()?, 1);
268 /// pm.entry("192.168.1.2/24".parse()?).or_insert_with(|| 2);
269 /// assert_eq!(
270 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
271 /// Some(("192.168.1.0/24".parse()?, &1))
272 /// );
273 /// # Ok(())
274 /// # }
275 /// # #[cfg(not(feature = "ipnet"))]
276 /// # fn main() {}
277 /// ```
278 #[inline(always)]
279 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
280 match self {
281 Entry::Vacant(e) => e._insert(default()).1,
282 Entry::Occupied(e) => e.into_mut(),
283 }
284 }
285
286 /// Provides in-place mutable access to an occupied entry before any potential inserts into the
287 /// map.
288 ///
289 /// ```
290 /// # use prefix_trie::*;
291 /// # #[cfg(feature = "ipnet")]
292 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
293 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
294 /// pm.insert("192.168.1.0/24".parse()?, 1);
295 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).and_modify(|x| *x += 1).get(), Some(&2));
296 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).and_modify(|x| *x += 1).get(), None);
297 /// # Ok(())
298 /// # }
299 /// # #[cfg(not(feature = "ipnet"))]
300 /// # fn main() {}
301 /// ```
302 ///
303 /// Host bits from an existing matching prefix are not preserved.
304 ///
305 /// ```
306 /// # use prefix_trie::*;
307 /// # #[cfg(feature = "ipnet")]
308 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
309 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
310 /// pm.insert("192.168.1.1/24".parse()?, 1);
311 /// pm.entry("192.168.1.2/24".parse()?).and_modify(|x| *x += 1);
312 /// assert_eq!(
313 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
314 /// Some(("192.168.1.0/24".parse()?, &2))
315 /// );
316 /// # Ok(())
317 /// # }
318 /// # #[cfg(not(feature = "ipnet"))]
319 /// # fn main() {}
320 /// ```
321 #[inline(always)]
322 pub fn and_modify<F: FnOnce(&mut T)>(self, f: F) -> Self {
323 match self {
324 Entry::Vacant(e) => Entry::Vacant(e),
325 Entry::Occupied(mut e) => {
326 f(e.get_mut());
327 Entry::Occupied(e)
328 }
329 }
330 }
331}
332
333impl<'a, P, T> Entry<'a, P, T>
334where
335 P: Prefix,
336 T: Default,
337{
338 /// Ensures a value is in the entry by inserting the default value if empty, and returns a
339 /// mutable reference to the value in the entry.
340 ///
341 /// ```
342 /// # use prefix_trie::*;
343 /// # #[cfg(feature = "ipnet")]
344 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
345 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
346 /// pm.insert("192.168.1.0/24".parse()?, 1);
347 ///
348 /// assert_eq!(pm.entry("192.168.1.0/24".parse()?).or_default(), &1);
349 /// assert_eq!(pm.entry("192.168.2.0/24".parse()?).or_default(), &0);
350 ///
351 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&1));
352 /// assert_eq!(pm.get(&"192.168.2.0/24".parse()?), Some(&0));
353 /// # Ok(())
354 /// # }
355 /// # #[cfg(not(feature = "ipnet"))]
356 /// # fn main() {}
357 /// ```
358 ///
359 /// Host bits from an existing matching prefix are not preserved.
360 ///
361 /// ```
362 /// # use prefix_trie::*;
363 /// # #[cfg(feature = "ipnet")]
364 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
365 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
366 /// pm.insert("192.168.1.1/24".parse()?, 1);
367 /// pm.entry("192.168.1.2/24".parse()?).or_default();
368 /// assert_eq!(
369 /// pm.get_key_value(&"192.168.1.0/24".parse()?),
370 /// Some(("192.168.1.0/24".parse()?, &1))
371 /// );
372 /// # Ok(())
373 /// # }
374 /// # #[cfg(not(feature = "ipnet"))]
375 /// # fn main() {}
376 /// ```
377 #[allow(clippy::unwrap_or_default)]
378 #[inline(always)]
379 pub fn or_default(self) -> &'a mut T {
380 self.or_insert_with(Default::default)
381 }
382}
383
384impl<'a, P, T> VacantEntry<'a, P, T>
385where
386 P: Prefix,
387{
388 fn _insert(self, v: T) -> (P, &'a mut T) {
389 let Self { loc, count, prefix } = self;
390 *count += 1;
391 let r = match loc {
392 Ok(empty_mut) => empty_mut.insert(v),
393 Err(no_node_mut) => {
394 no_node_mut.insert_path_and_data(prefix.repr(), prefix.prefix_len() as u32, v)
395 }
396 };
397 let computed_prefix = r.prefix(prefix.repr());
398 let val_ref = r.get_mut();
399 (computed_prefix, val_ref)
400 }
401}
402
403impl<P: Prefix, T> OccupiedEntry<'_, P, T> {
404 /// Gets a reference to the key in the entry. This is the key that is currently stored, and not
405 /// the key that was used in the insert.
406 ///
407 /// ```
408 /// # use prefix_trie::*;
409 /// use prefix_trie::map::Entry;
410 /// # #[cfg(feature = "ipnet")]
411 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
412 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
413 /// pm.insert("192.168.1.0/24".parse()?, 1);
414 /// match pm.entry("192.168.1.1/24".parse()?) {
415 /// Entry::Occupied(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
416 /// Entry::Vacant(_) => unreachable!(),
417 /// }
418 /// # Ok(())
419 /// # }
420 /// # #[cfg(not(feature = "ipnet"))]
421 /// # fn main() {}
422 /// ```
423 pub fn key(&self) -> &P {
424 &self.prefix
425 }
426
427 /// Gets a reference to the value in the entry.
428 ///
429 /// ```
430 /// # use prefix_trie::*;
431 /// use prefix_trie::map::Entry;
432 /// # #[cfg(feature = "ipnet")]
433 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
434 ///
435 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
436 /// pm.insert("192.168.1.0/24".parse()?, 1);
437 /// match pm.entry("192.168.1.0/24".parse()?) {
438 /// Entry::Occupied(e) => assert_eq!(e.get(), &1),
439 /// Entry::Vacant(_) => unreachable!(),
440 /// }
441 /// # Ok(())
442 /// # }
443 /// # #[cfg(not(feature = "ipnet"))]
444 /// # fn main() {}
445 /// ```
446 pub fn get(&self) -> &T {
447 self.loc.get()
448 }
449
450 /// Gets a mutable reference to the value in the entry.
451 ///
452 /// Prefixes are not stored verbatim. They are reconstructed from the trie position, so host
453 /// bits masked out by the prefix length are not preserved.
454 ///
455 /// ```
456 /// # use prefix_trie::*;
457 /// use prefix_trie::map::Entry;
458 /// # #[cfg(feature = "ipnet")]
459 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
460 ///
461 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
462 /// pm.insert("192.168.1.0/24".parse()?, 1);
463 /// match pm.entry("192.168.1.0/24".parse()?) {
464 /// Entry::Occupied(mut e) => *e.get_mut() += 1,
465 /// Entry::Vacant(_) => unreachable!(),
466 /// }
467 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&2));
468 /// # Ok(())
469 /// # }
470 /// # #[cfg(not(feature = "ipnet"))]
471 /// # fn main() {}
472 /// ```
473 pub fn get_mut(&mut self) -> &mut T {
474 self.loc.as_mut()
475 }
476
477 /// Insert a new value into the entry, returning the old value.
478 ///
479 /// ```
480 /// # use prefix_trie::*;
481 /// use prefix_trie::map::Entry;
482 /// # #[cfg(feature = "ipnet")]
483 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
484 ///
485 /// let mut pm: PrefixMap<ipnet::Ipv4Net, _> = PrefixMap::new();
486 /// pm.insert("192.168.1.0/24".parse()?, 1);
487 /// match pm.entry("192.168.1.0/24".parse()?) {
488 /// Entry::Occupied(mut e) => assert_eq!(e.insert(10), 1),
489 /// Entry::Vacant(_) => unreachable!(),
490 /// }
491 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
492 /// # Ok(())
493 /// # }
494 /// # #[cfg(not(feature = "ipnet"))]
495 /// # fn main() {}
496 /// ```
497 pub fn insert(self, v: T) -> T {
498 self.loc.replace(v)
499 }
500
501 /// Remove the current value and return it. Empty trie nodes may be left in place (the same
502 /// effect as `PrefixMap::remove_keep_tree`).
503 ///
504 /// ```
505 /// # use prefix_trie::*;
506 /// use prefix_trie::map::Entry;
507 /// # #[cfg(feature = "ipnet")]
508 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
509 ///
510 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
511 /// pm.insert("192.168.1.0/24".parse()?, 1);
512 /// match pm.entry("192.168.1.0/24".parse()?) {
513 /// Entry::Occupied(mut e) => assert_eq!(e.remove(), 1),
514 /// Entry::Vacant(_) => unreachable!(),
515 /// }
516 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), None);
517 /// # Ok(())
518 /// # }
519 /// # #[cfg(not(feature = "ipnet"))]
520 /// # fn main() {}
521 /// ```
522 pub fn remove(self) -> T {
523 *self.count -= 1;
524 self.loc.take()
525 }
526}
527
528impl<'a, P, T> OccupiedEntry<'a, P, T> {
529 /// Converts this occupied entry into a mutable reference to the stored value.
530 pub fn into_mut(self) -> &'a mut T {
531 self.loc.get_mut()
532 }
533}
534
535impl<P, T> VacantEntry<'_, P, T> {
536 /// Gets a reference to the key in the entry.
537 ///
538 /// **Note**: The prefix is returned exactly as it was passed to
539 /// [`PrefixMap::entry`](crate::PrefixMap::entry); host bits are not masked. This differs
540 /// from [`OccupiedEntry::key`], which returns the canonical stored prefix.
541 ///
542 /// ```
543 /// # use prefix_trie::*;
544 /// use prefix_trie::map::Entry;
545 /// # #[cfg(feature = "ipnet")]
546 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
547 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
548 /// match pm.entry("192.168.1.0/24".parse()?) {
549 /// Entry::Vacant(e) => assert_eq!(e.key(), &"192.168.1.0/24".parse()?),
550 /// Entry::Occupied(_) => unreachable!(),
551 /// }
552 /// # Ok(())
553 /// # }
554 /// # #[cfg(not(feature = "ipnet"))]
555 /// # fn main() {}
556 /// ```
557 pub fn key(&self) -> &P {
558 &self.prefix
559 }
560}
561
562impl<'a, P, T> VacantEntry<'a, P, T>
563where
564 P: Prefix,
565{
566 /// Get a mutable reference to the value. If the value is yet empty, set it to the given default
567 /// value.
568 ///
569 /// ```
570 /// # use prefix_trie::*;
571 /// use prefix_trie::map::Entry;
572 /// # #[cfg(feature = "ipnet")]
573 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
574 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
575 /// match pm.entry("192.168.1.0/24".parse()?) {
576 /// Entry::Vacant(mut e) => assert_eq!(e.insert(10), &10),
577 /// Entry::Occupied(_) => unreachable!(),
578 /// }
579 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
580 /// # Ok(())
581 /// # }
582 /// # #[cfg(not(feature = "ipnet"))]
583 /// # fn main() {}
584 /// ```
585 pub fn insert(self, default: T) -> &'a mut T {
586 self._insert(default).1
587 }
588
589 /// Get a mutable reference to the value. If the value is yet empty, set it to the return value
590 /// from the given function.
591 ///
592 /// ```
593 /// # use prefix_trie::*;
594 /// use prefix_trie::map::Entry;
595 /// # #[cfg(feature = "ipnet")]
596 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
597 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
598 /// match pm.entry("192.168.1.0/24".parse()?) {
599 /// Entry::Vacant(mut e) => assert_eq!(e.insert_with(|| 10), &10),
600 /// Entry::Occupied(_) => unreachable!(),
601 /// }
602 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&10));
603 /// # Ok(())
604 /// # }
605 /// # #[cfg(not(feature = "ipnet"))]
606 /// # fn main() {}
607 /// ```
608 pub fn insert_with<F: FnOnce() -> T>(self, default: F) -> &'a mut T {
609 self._insert(default()).1
610 }
611}
612
613impl<'a, P, T> VacantEntry<'a, P, T>
614where
615 P: Prefix,
616 T: Default,
617{
618 /// Get a mutable reference to the value. If the value is yet empty, set it to the default value
619 /// using `Default::default()`.
620 ///
621 /// ```
622 /// # use prefix_trie::*;
623 /// use prefix_trie::map::Entry;
624 /// # #[cfg(feature = "ipnet")]
625 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
626 /// let mut pm: PrefixMap<ipnet::Ipv4Net, i32> = PrefixMap::new();
627 /// match pm.entry("192.168.1.0/24".parse()?) {
628 /// Entry::Vacant(e) => assert_eq!(e.default(), &0),
629 /// Entry::Occupied(_) => unreachable!(),
630 /// }
631 /// assert_eq!(pm.get(&"192.168.1.0/24".parse()?), Some(&0));
632 /// # Ok(())
633 /// # }
634 /// # #[cfg(not(feature = "ipnet"))]
635 /// # fn main() {}
636 /// ```
637 pub fn default(self) -> &'a mut T {
638 self._insert(Default::default()).1
639 }
640}