1use crate::{
2 BaseIndex, StrideOpsExt,
3 iptrie::util,
4 node::{Child, StrideOps},
5};
6
7#[inline]
9pub fn insert<N>(node: &mut N, prefix: ipnet::IpNet, val: N::T) -> Option<N::T>
10where
11 N: StrideOps,
12{
13 insert_inner(node, prefix.trunc(), val, 0)
15}
16
17pub fn insert_inner<N>(
18 mut node: &mut N,
19 prefix: ipnet::IpNet,
20 val: N::T,
21 depth: usize,
22) -> Option<N::T>
23where
24 N: StrideOps,
25{
26 let (pfx_full_strides, pfx_overflow_bits) = util::stride_count_and_overflow(&prefix);
27
28 for (depth, &octet) in util::ip_octets(&prefix.addr())
29 .iter()
30 .enumerate()
31 .skip(depth)
32 {
33 if depth == pfx_full_strides {
34 return node.insert_prefix(BaseIndex::from_prefix(octet, pfx_overflow_bits), val);
35 }
36
37 if !node.child_bitset().test(octet as _) {
38 let child = if util::is_fringe(depth, &prefix) {
39 Child::Fringe(val)
40 } else {
41 Child::Leaf { prefix, value: val }
42 };
43
44 return node.insert_child(octet, child)?.into_value();
45 }
46
47 let replace_child: bool = match node.get_child_mut(octet).unwrap() {
62 Child::Leaf {
63 prefix: leaf_pfx,
64 value: leaf_value,
65 } if prefix == leaf_pfx => {
66 return Some(core::mem::replace(leaf_value, val));
67 }
68 Child::Fringe(old) if util::is_fringe(depth, &prefix) => {
69 return Some(core::mem::replace(old, val));
70 }
71
72 Child::Leaf { .. } => true,
73 Child::Fringe(..) => true,
74
75 Child::Path(..) => false,
76 };
77
78 if replace_child {
79 let removed = node.insert_child(octet, N::default().into_child()).unwrap();
81
82 let Some(Child::Path(n)) = node.get_child_mut(octet) else {
83 unreachable!();
84 };
85
86 match removed {
87 Child::Fringe(old) => {
88 n.insert_prefix(BaseIndex::new(1), old);
89 }
90 Child::Leaf {
91 prefix: leaf_prefix,
92 value: leaf_value,
93 } => {
94 insert_inner(n, leaf_prefix, leaf_value, depth + 1);
97 }
98
99 _ => unreachable!(),
100 }
101 }
102
103 let next = node.get_child_mut(octet).unwrap().into_node().unwrap();
105 node = next;
106 }
107
108 None
109}