1use bitstring::BitString;
8pub use cidr::{AnyIpCidr, IpCidr};
9#[cfg(feature = "lua")]
10use config::{any_err, get_or_create_sub_module};
11#[cfg(feature = "lua")]
12use mlua::prelude::LuaUserData;
13#[cfg(feature = "lua")]
14use mlua::{FromLua, Lua, MetaMethod, UserDataMethods};
15#[cfg(feature = "lua")]
16use mod_memoize::CacheValue;
17use serde::de::{MapAccess, Visitor};
18use serde::ser::SerializeMap;
19use serde::{Deserialize, Deserializer, Serialize, Serializer};
20use std::fmt::Debug;
21use std::net::IpAddr;
22use std::str::FromStr;
23use std::sync::Arc;
24
25#[derive(Clone, PartialEq)]
26pub struct CidrMap<V>
27where
28 V: Clone,
29{
30 root: Arc<Option<Node<V>>>,
31}
32
33impl<V> Debug for CidrMap<V>
34where
35 V: Clone + Debug,
36{
37 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
38 use std::fmt::DebugMap;
39 let mut map = fmt.debug_map();
40
41 fn walk<V: Clone + Debug>(node: &Node<V>, map: &mut DebugMap) {
42 match node {
43 Node::InnerNode(inner) => {
44 walk(&inner.children.left, map);
45 walk(&inner.children.right, map);
46 }
47 Node::Leaf(leaf) => {
48 map.key(&leaf.key.to_string());
49 map.value(&leaf.value);
50 }
51 }
52 }
53
54 if let Some(root) = self.root() {
55 walk(root, &mut map);
56 }
57
58 map.finish()
59 }
60}
61
62struct MapVis<T>
63where
64 T: Clone + PartialEq,
65{
66 map: CidrMap<T>,
67}
68
69impl<'de, T> Visitor<'de> for MapVis<T>
70where
71 T: Clone + PartialEq + Deserialize<'de>,
72{
73 type Value = CidrMap<T>;
74
75 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
76 formatter.write_str("a CidrMap")
77 }
78
79 fn visit_map<M>(mut self, mut access: M) -> Result<Self::Value, M::Error>
80 where
81 M: MapAccess<'de>,
82 {
83 while let Some((key, value)) = access.next_entry()? {
84 self.map.insert(key, value);
85 }
86
87 Ok(self.map)
88 }
89}
90
91impl<'de, V> Deserialize<'de> for CidrMap<V>
92where
93 V: Clone + PartialEq + Deserialize<'de>,
94{
95 fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
96 where
97 D: Deserializer<'de>,
98 {
99 deserializer.deserialize_map(MapVis {
100 map: CidrMap::new(),
101 })
102 }
103}
104
105impl<V> Serialize for CidrMap<V>
106where
107 V: Clone + PartialEq + Serialize,
108{
109 fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
110 where
111 S: Serializer,
112 {
113 let mut map = serializer.serialize_map(None)?;
114 for (k, v) in self.iter() {
115 map.serialize_entry(k, v)?;
116 }
117 map.end()
118 }
119}
120
121#[derive(Debug, Clone, PartialEq)]
124pub enum Node<V>
125where
126 V: Clone,
127{
128 InnerNode(InnerNode<V>),
130 Leaf(Leaf<V>),
132}
133
134#[derive(Clone, Debug, PartialEq)]
136pub struct Leaf<V>
137where
138 V: Clone,
139{
140 pub key: AnyIpCidr,
141 pub value: V,
142}
143
144#[derive(Clone, Debug, PartialEq)]
146pub struct InnerNode<V>
147where
148 V: Clone,
149{
150 pub(crate) key: AnyIpCidr,
151 pub(crate) children: Box<Children<V>>,
152}
153
154#[derive(Clone, Debug, PartialEq)]
155pub(crate) struct Children<V>
156where
157 V: Clone,
158{
159 pub(crate) left: Node<V>,
160 pub(crate) right: Node<V>,
161}
162
163impl<V> InnerNode<V>
164where
165 V: Clone,
166{
167 pub fn key(&self) -> &AnyIpCidr {
168 &self.key
169 }
170
171 pub fn pick_side<'a>(&'a self, subkey: &AnyIpCidr) -> &'a Node<V> {
172 if subkey.get(self.key.len()) {
173 &self.children.right
174 } else {
175 &self.children.left
176 }
177 }
178
179 pub fn pick_side_mut<'a>(&'a mut self, subkey: &AnyIpCidr) -> &'a mut Node<V> {
180 if subkey.get(self.key.len()) {
181 &mut self.children.right
182 } else {
183 &mut self.children.left
184 }
185 }
186
187 pub fn left(&self) -> &Node<V> {
188 &self.children.left
189 }
190
191 pub fn right(&self) -> &Node<V> {
192 &self.children.right
193 }
194}
195
196impl<V> Node<V>
197where
198 V: Clone,
199{
200 fn new_leaf(key: AnyIpCidr, value: V) -> Self {
201 Self::Leaf(Leaf { key, value })
202 }
203
204 fn new_children_unknown_order(
205 shared_prefix_len: usize,
206 a: Node<V>,
207 b: Node<V>,
208 ) -> Box<Children<V>> {
209 let a_right = a.key().get(shared_prefix_len);
210 assert_eq!(!a_right, b.key().get(shared_prefix_len));
211 if a_right {
212 Box::new(Children { left: b, right: a })
213 } else {
214 Box::new(Children { left: a, right: b })
215 }
216 }
217
218 fn new_inner_unknown_order(shared_prefix_len: usize, a: Node<V>, b: Node<V>) -> Node<V> {
219 let mut key = *a.key();
220 key.clip(shared_prefix_len);
221 Node::InnerNode(InnerNode {
222 key,
223 children: Self::new_children_unknown_order(shared_prefix_len, a, b),
224 })
225 }
226
227 pub fn key(&self) -> &AnyIpCidr {
229 match *self {
230 Node::Leaf(ref leaf) => &leaf.key,
231 Node::InnerNode(ref inner) => &inner.key,
232 }
233 }
234
235 fn leaf_ref(&self) -> Option<&Leaf<V>> {
236 match *self {
237 Node::Leaf(ref leaf) => Some(leaf),
238 _ => None,
239 }
240 }
241
242 fn convert_leaf(&mut self, key_len: usize, value: V) {
245 *self = match self {
246 Node::Leaf(leaf) => {
247 let mut leaf = leaf.clone();
248 leaf.key.clip(key_len);
249 leaf.value = value;
250 Node::Leaf(leaf)
251 }
252 Node::InnerNode(inner) => {
253 let mut key = inner.key;
254 key.clip(key_len);
255 Self::new_leaf(key, value)
256 }
257 };
258 }
259
260 fn insert_uncompressed(&mut self, key: AnyIpCidr, value: V)
261 where
262 V: Clone,
263 {
264 let (self_key_len, shared_prefix_len) = {
265 let key_ref = self.key();
266 (key_ref.len(), key_ref.shared_prefix_len(&key))
267 };
268
269 if shared_prefix_len == key.len() {
270 self.convert_leaf(shared_prefix_len, value);
273 } else if shared_prefix_len < self_key_len {
274 debug_assert!(shared_prefix_len < key.len());
275 *self = Self::new_inner_unknown_order(
277 shared_prefix_len,
278 self.clone(),
279 Self::new_leaf(key, value),
280 );
281 } else {
282 debug_assert!(shared_prefix_len == self_key_len);
283 debug_assert!(shared_prefix_len < key.len());
284 match *self {
286 Node::Leaf(_) => {
287 let old_value = self.leaf_ref().unwrap().value.clone();
289 let mut new_node = Self::new_leaf(key, value);
290 for l in (shared_prefix_len..key.len()).rev() {
291 let mut other_key = key;
292 other_key.clip(l + 1);
293 other_key.flip(l);
294 new_node = Self::new_inner_unknown_order(
295 l,
296 new_node,
297 Self::new_leaf(other_key, old_value.clone()),
298 );
299 }
300 *self = new_node;
301 }
302 Node::InnerNode(ref mut inner) => {
303 inner.pick_side_mut(&key).insert_uncompressed(key, value);
304 }
305 }
306 }
307 }
308
309 fn insert(&mut self, key: AnyIpCidr, value: V)
310 where
311 V: Clone + PartialEq,
312 {
313 let (self_key_len, shared_prefix_len) = {
314 let key_ref = self.key();
315 (key_ref.len(), key_ref.shared_prefix_len(&key))
316 };
317
318 if shared_prefix_len == key.len() {
319 self.convert_leaf(shared_prefix_len, value);
322 } else if shared_prefix_len < self_key_len {
324 debug_assert!(shared_prefix_len < key.len());
325 if shared_prefix_len + 1 == self_key_len && shared_prefix_len + 1 == key.len() {
326 if let Node::Leaf(ref mut this) = *self {
327 if this.value == value {
328 this.key.clip(shared_prefix_len);
331 return; }
333 }
334 }
335
336 *self = Self::new_inner_unknown_order(
338 shared_prefix_len,
339 self.clone(),
340 Self::new_leaf(key, value),
341 );
342 } else {
345 debug_assert!(shared_prefix_len == self_key_len);
346 debug_assert!(shared_prefix_len < key.len());
347 match *self {
349 Node::Leaf(_) => {
350 let new_node = {
352 let old_value = &self.leaf_ref().unwrap().value;
353 if *old_value == value {
354 return;
356 }
357 let mut new_node = Self::new_leaf(key, value);
358 for l in (shared_prefix_len..key.len()).rev() {
359 let mut other_key = key;
360 other_key.clip(l + 1);
361 other_key.flip(l);
362 new_node = Self::new_inner_unknown_order(
363 l,
364 new_node,
365 Self::new_leaf(other_key, old_value.clone()),
366 );
367 }
368 new_node
369 };
370 *self = new_node;
371 return;
373 }
374 Node::InnerNode(ref mut inner) => {
375 inner.pick_side_mut(&key).insert(key, value);
376 }
377 }
378 self.compress();
380 }
381 }
382
383 fn compress(&mut self)
384 where
385 V: PartialEq,
386 {
387 let self_key_len = self.key().len();
388
389 let compress = match *self {
394 Node::InnerNode(ref inner) => {
395 let left_value = match inner.children.left {
396 Node::Leaf(ref leaf) if leaf.key.len() == self_key_len + 1 => &leaf.value,
397 _ => return, };
399 let right_value = match inner.children.right {
400 Node::Leaf(ref leaf) if leaf.key.len() == self_key_len + 1 => &leaf.value,
401 _ => return, };
403 left_value == right_value
404 }
405 Node::Leaf(_) => return, };
407 if compress {
408 *self = match self {
409 Node::InnerNode(inner) => match &inner.children.left {
411 Node::Leaf(leaf) => Node::Leaf(Leaf {
412 key: inner.key,
413 value: leaf.value.clone(),
414 }),
415 _ => unreachable!(),
416 },
417 _ => unreachable!(),
418 };
419 }
420 }
421}
422
423impl<V> Default for CidrMap<V>
424where
425 V: Clone,
426{
427 fn default() -> Self {
428 Self::new()
429 }
430}
431
432impl<V> CidrMap<V>
433where
434 V: Clone,
435{
436 pub fn new() -> Self {
437 Self {
438 root: Arc::new(None),
439 }
440 }
441
442 pub fn contains(&self, ip: IpAddr) -> bool {
443 self.get_prefix_match(ip).is_some()
444 }
445
446 pub fn get_prefix_match(&self, ip: IpAddr) -> Option<&V> {
447 let key: AnyIpCidr = IpCidr::new_host(ip).into();
448 self.get_prefix_match_cidr(&key)
449 }
450
451 pub fn get_prefix_match_cidr(&self, key: &AnyIpCidr) -> Option<&V> {
452 let node = self.root()?;
453 Self::find_item(node, key)
454 }
455
456 fn find_item<'a>(node: &'a Node<V>, ip: &AnyIpCidr) -> Option<&'a V> {
457 match node {
458 Node::Leaf(leaf) => {
459 if leaf.key.contains(&ip.first_address().unwrap()) {
460 Some(&leaf.value)
461 } else {
462 None
463 }
464 }
465 Node::InnerNode(inner) => Self::find_item(inner.pick_side(ip), ip),
466 }
467 }
468
469 pub fn insert_uncompressed(&mut self, key: AnyIpCidr, value: V)
474 where
475 V: Clone,
476 {
477 let root = Arc::make_mut(&mut self.root);
478 match root {
479 None => {
480 *root = Some(Node::new_leaf(key, value));
481 }
482 Some(node) => {
483 node.insert_uncompressed(key, value);
484 }
485 }
486 }
487
488 pub fn insert(&mut self, key: AnyIpCidr, value: V)
491 where
492 V: Clone + PartialEq,
493 {
494 let root = Arc::make_mut(&mut self.root);
495 match root {
496 None => {
497 *root = Some(Node::new_leaf(key, value));
498 }
499 Some(node) => {
500 node.insert(key, value);
501 }
502 }
503 }
504
505 pub fn root(&self) -> Option<&Node<V>> {
509 (*self.root).as_ref()
510 }
511
512 pub fn iter(&'_ self) -> Iter<'_, V> {
514 Iter::new(self)
515 }
516}
517
518#[derive(Clone, Copy, PartialEq, Eq)]
519enum Direction {
520 Left,
521 Right,
522 Up,
523}
524
525pub struct Iter<'a, V: 'a>
527where
528 V: Clone,
529{
530 stack: Vec<(Direction, &'a Node<V>)>,
531}
532
533impl<'a, V> Iter<'a, V>
534where
535 V: Clone,
536{
537 pub fn new(tree: &'a CidrMap<V>) -> Self {
539 match tree.root() {
540 None => Iter { stack: Vec::new() },
541 Some(node) => Iter {
542 stack: vec![(Direction::Left, node)],
543 },
544 }
545 }
546}
547
548impl<'a, V> Iterator for Iter<'a, V>
549where
550 V: Clone,
551{
552 type Item = (&'a AnyIpCidr, &'a V);
553
554 fn next(&mut self) -> Option<Self::Item> {
555 if self.stack.is_empty() {
556 return None;
557 }
558
559 while Direction::Up == self.stack[self.stack.len() - 1].0 {
561 if 1 == self.stack.len() {
562 self.stack.clear();
563 return None;
564 }
565
566 self.stack.pop();
567 debug_assert!(!self.stack.is_empty());
569 }
570
571 loop {
572 let top = self.stack.len() - 1;
573 let (dir, node) = self.stack[top];
574
575 debug_assert!(!self.stack.is_empty());
576 match dir {
578 Direction::Left => match *node {
579 Node::InnerNode(ref inner) => {
580 self.stack[top].0 = Direction::Right;
581 self.stack.push((Direction::Left, inner.left()));
582 }
583 Node::Leaf(ref leaf) => {
584 self.stack[top].0 = Direction::Up;
585 return Some((&leaf.key, &leaf.value));
586 }
587 },
588 Direction::Right => match *node {
589 Node::InnerNode(ref inner) => {
590 self.stack[top].0 = Direction::Up;
591 self.stack.push((Direction::Left, inner.right()));
592 }
593 Node::Leaf(_) => unreachable!(),
594 },
595 Direction::Up => unreachable!(),
596 }
597 }
598 }
599}
600
601impl<S, V: Clone + PartialEq> FromIterator<(S, V)> for CidrMap<V>
602where
603 S: Into<AnyIpCidr>,
604{
605 fn from_iter<I: IntoIterator<Item = (S, V)>>(iter: I) -> Self {
606 let mut map = CidrMap::new();
607 for (key, value) in iter {
608 map.insert(key.into(), value);
609 }
610 map
611 }
612}
613
614impl<T: Ord + Into<AnyIpCidr>, const N: usize, V: Clone + Ord> From<[(T, V); N]> for CidrMap<V> {
615 fn from(mut arr: [(T, V); N]) -> Self {
617 if N == 0 {
618 return CidrMap::new();
619 }
620
621 arr.sort();
623 let iter = IntoIterator::into_iter(arr);
624 iter.collect()
625 }
626}
627
628impl<V: Clone> From<CidrMap<V>> for Vec<(AnyIpCidr, V)> {
629 fn from(val: CidrMap<V>) -> Self {
630 let mut result = vec![];
631 for (key, value) in val.iter() {
632 result.push((*key, value.clone()));
633 }
634 result
635 }
636}
637
638#[cfg(feature = "lua")]
639impl LuaUserData for CidrMap<CacheValue> {
640 fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
641 mod_memoize::Memoized::impl_memoize(methods);
642 methods.add_meta_method(MetaMethod::Index, |lua, this, key: String| {
643 let key = parse_cidr_from_ip_and_or_port(&key).map_err(any_err)?;
644 if let Some(value) = this.get_prefix_match_cidr(&key) {
645 let value = value.as_lua(lua)?;
646 Ok(Some(value))
647 } else {
648 Ok(None)
649 }
650 });
651 methods.add_meta_method_mut(
652 MetaMethod::NewIndex,
653 |lua, this, (key, value): (String, mlua::Value)| {
654 let key = parse_cidr_from_ip_and_or_port(&key).map_err(any_err)?;
655 let value = CacheValue::from_lua(value, lua)?;
656 this.insert(key, value);
657 Ok(())
658 },
659 );
660 }
661}
662
663#[cfg(feature = "lua")]
664fn parse_cidr_from_ip_and_or_port(s: &str) -> anyhow::Result<AnyIpCidr> {
665 match parse_cidr(s) {
666 Ok(c) => Ok(c),
667 Err(err) => {
668 if s.starts_with('[') {
669 if let Some((ip, _port)) = s[1..].split_once(']') {
670 return parse_cidr(ip).map_err(|err| {
671 anyhow::anyhow!(
672 "failed to parse '{ip}', the \
673 []-enclosed portion of '{s}', as an IP address: {err:#}"
674 )
675 });
676 }
677 }
678 if let Some((ip, _port)) = s.rsplit_once(':') {
679 return parse_cidr(ip).map_err(|err| {
680 anyhow::anyhow!(
681 "failed to parse '{ip}', the \
682 :-delimited portion of '{s}', as an IP address: {err:#}"
683 )
684 });
685 }
686 Err(err)
687 }
688 }
689}
690
691pub fn parse_cidr(s: &str) -> anyhow::Result<AnyIpCidr> {
697 AnyIpCidr::from_str(s).map_err(|err| {
698 match cidr::parsers::parse_any_cidr_full_ignore_hostbits(
699 s,
700 std::str::FromStr::from_str,
701 std::str::FromStr::from_str,
702 ) {
703 Ok(loose) => {
704 anyhow::anyhow!("{s} is not a valid CIDR: {err:#}. Did you mean {loose}?")
705 }
706 Err(err) => {
707 anyhow::anyhow!("{s} is not a valid CIDR: {err:#}")
708 }
709 }
710 })
711}
712
713#[cfg(feature = "lua")]
714pub fn register(lua: &Lua) -> anyhow::Result<()> {
715 use std::collections::HashMap;
716 let cidr_mod = get_or_create_sub_module(lua, "cidr")?;
717
718 cidr_mod.set(
719 "make_map",
720 lua.create_function(|lua, value: Option<HashMap<String, mlua::Value>>| {
721 let mut cmap: CidrMap<mod_memoize::CacheValue> = CidrMap::new();
722
723 if let Some(value) = value {
724 for (k, v) in value {
725 let k = parse_cidr_from_ip_and_or_port(&k).map_err(any_err)?;
726 let v = CacheValue::from_lua(v, lua)?;
727 cmap.insert(k, v);
728 }
729 }
730
731 Ok(cmap)
732 })?,
733 )?;
734
735 Ok(())
736}
737
738#[cfg(test)]
739mod test {
740 use super::*;
741
742 #[test]
743 fn test_parse_error_message() {
744 assert_eq!(
745 parse_cidr("10.0.0.1/24").unwrap_err().to_string(),
746 "10.0.0.1/24 is not a valid CIDR: host part of address was not zero. Did you mean 10.0.0.0/24?"
747 );
748 }
749
750 #[test]
751 fn cidrmap() {
752 let set: CidrMap<&str> = [
753 (parse_cidr("127.0.0.1").unwrap(), "loopbackv4"),
754 (parse_cidr("::1").unwrap(), "loopbackv6"),
755 (parse_cidr("192.168.1.0/24").unwrap(), ".1"),
756 (parse_cidr("192.168.1.24").unwrap(), ".1"),
758 (parse_cidr("192.168.3.0/28").unwrap(), ".3"),
759 (parse_cidr("192.168.3.2").unwrap(), ".3.split"),
760 (parse_cidr("10.0.3.0/24").unwrap(), "10.3"),
761 (parse_cidr("10.0.4.0/24").unwrap(), "10.4"),
762 (parse_cidr("10.0.7.0/24").unwrap(), "10.7"),
763 ]
764 .into();
765
766 fn get<'a>(set: &'a CidrMap<&str>, key: &str) -> Option<&'a str> {
767 let key = key.parse().unwrap();
768 set.get_prefix_match(key).copied()
769 }
770
771 assert_eq!(get(&set, "127.0.0.1"), Some("loopbackv4"));
772 assert_eq!(get(&set, "127.0.0.2"), None);
773 assert_eq!(get(&set, "::1"), Some("loopbackv6"));
774
775 assert_eq!(get(&set, "192.168.2.1"), None);
776
777 assert_eq!(get(&set, "192.168.1.0"), Some(".1"));
778 assert_eq!(get(&set, "192.168.1.1"), Some(".1"));
779 assert_eq!(get(&set, "192.168.1.100"), Some(".1"));
780 assert_eq!(get(&set, "192.168.1.24"), Some(".1"));
781
782 assert_eq!(get(&set, "192.168.3.0"), Some(".3"));
783 assert_eq!(get(&set, "192.168.3.16"), None);
784 assert_eq!(get(&set, "192.168.3.2"), Some(".3.split"));
785
786 k9::snapshot!(
793 &set,
794 r#"
795{
796 "10.0.3.0/24": "10.3",
797 "10.0.4.0/24": "10.4",
798 "10.0.7.0/24": "10.7",
799 "127.0.0.1": "loopbackv4",
800 "192.168.1.0/24": ".1",
801 "192.168.3.0/31": ".3",
802 "192.168.3.2": ".3.split",
803 "192.168.3.3": ".3",
804 "192.168.3.4/30": ".3",
805 "192.168.3.8/29": ".3",
806 "::1": "loopbackv6",
807}
808"#
809 );
810 }
811
812 #[test]
813 fn clone_is_shared_until_written() {
814 let mut map: CidrMap<&str> = CidrMap::new();
815 map.insert(parse_cidr("10.0.0.0/8").unwrap(), "ten");
816
817 let mut copy = map.clone();
818 assert!(Arc::ptr_eq(&map.root, ©.root));
819
820 copy.insert(parse_cidr("192.168.0.0/16").unwrap(), "private");
821 assert!(!Arc::ptr_eq(&map.root, ©.root));
822 assert_eq!(map.get_prefix_match("192.168.1.1".parse().unwrap()), None);
823 assert_eq!(
824 copy.get_prefix_match("192.168.1.1".parse().unwrap()),
825 Some(&"private")
826 );
827 assert_eq!(
828 copy.get_prefix_match("10.1.1.1".parse().unwrap()),
829 Some(&"ten")
830 );
831 }
832}