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