1use std::fmt;
6
7use wildmatch::WildMatch;
8
9use super::HostParams;
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Host {
14 pub pattern: Vec<HostClause>,
16 pub params: HostParams,
17}
18
19impl Host {
20 pub fn new(pattern: Vec<HostClause>, params: HostParams) -> Self {
21 Self { pattern, params }
22 }
23
24 pub fn intersects(&self, host: &str) -> bool {
26 let mut has_matched = false;
27 for entry in self.pattern.iter() {
28 let matches = entry.intersects(host);
29 if matches && entry.negated {
31 return false;
32 }
33 has_matched |= matches;
34 }
35 has_matched
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct HostClause {
42 pub pattern: String,
43 pub negated: bool,
44}
45
46impl fmt::Display for HostClause {
47 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48 if self.negated {
49 write!(f, "!{}", self.pattern)
50 } else {
51 write!(f, "{}", self.pattern)
52 }
53 }
54}
55
56impl HostClause {
57 pub fn new(pattern: String, negated: bool) -> Self {
59 Self { pattern, negated }
60 }
61
62 pub fn intersects(&self, host: &str) -> bool {
64 WildMatch::new(self.pattern.as_str()).matches(host)
65 }
66}
67
68#[cfg(test)]
69mod test {
70
71 use pretty_assertions::assert_eq;
72
73 use super::*;
74
75 #[test]
76 fn should_build_host_clause() {
77 let clause = HostClause::new("192.168.1.1".to_string(), false);
78 assert_eq!(clause.pattern.as_str(), "192.168.1.1");
79 assert_eq!(clause.negated, false);
80 }
81
82 #[test]
83 fn should_intersect_host_clause() {
84 let clause = HostClause::new("192.168.*.*".to_string(), false);
85 assert!(clause.intersects("192.168.2.30"));
86 let clause = HostClause::new("192.168.?0.*".to_string(), false);
87 assert!(clause.intersects("192.168.40.28"));
88 }
89
90 #[test]
91 fn should_not_intersect_host_clause() {
92 let clause = HostClause::new("192.168.*.*".to_string(), false);
93 assert_eq!(clause.intersects("172.26.104.4"), false);
94 }
95
96 #[test]
97 fn should_init_host() {
98 let host = Host::new(
99 vec![HostClause::new("192.168.*.*".to_string(), false)],
100 HostParams::default(),
101 );
102 assert_eq!(host.pattern.len(), 1);
103 }
104
105 #[test]
106 fn should_intersect_clause() {
107 let host = Host::new(
108 vec![
109 HostClause::new("192.168.*.*".to_string(), false),
110 HostClause::new("172.26.*.*".to_string(), false),
111 HostClause::new("10.8.*.*".to_string(), false),
112 HostClause::new("10.8.0.8".to_string(), true),
113 ],
114 HostParams::default(),
115 );
116 assert!(host.intersects("192.168.1.32"));
117 assert!(host.intersects("172.26.104.4"));
118 assert!(host.intersects("10.8.0.10"));
119 }
120
121 #[test]
122 fn should_not_intersect_clause() {
123 let host = Host::new(
124 vec![
125 HostClause::new("192.168.*.*".to_string(), false),
126 HostClause::new("172.26.*.*".to_string(), false),
127 HostClause::new("10.8.*.*".to_string(), false),
128 HostClause::new("10.8.0.8".to_string(), true),
129 ],
130 HostParams::default(),
131 );
132 assert_eq!(host.intersects("192.169.1.32"), false);
133 assert_eq!(host.intersects("172.28.104.4"), false);
134 assert_eq!(host.intersects("10.9.0.8"), false);
135 assert_eq!(host.intersects("10.8.0.8"), false);
136 }
137}