1use std::{collections::HashMap, sync::Arc};
2
3use arc_swap::ArcSwap;
4
5use crate::rule::DnsRule;
6
7#[derive(Debug, Default, Clone)]
17pub struct InnerRuleStore {
18 ephemeral_exact: HashMap<String, DnsRule>,
19 persistent_exact: HashMap<String, DnsRule>,
20 ephemeral_wildcard: Vec<DnsRule>,
21 persistent_wildcard: Vec<DnsRule>,
22}
23
24impl InnerRuleStore {
25 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn resolve(&self, domain: &str) -> Option<&DnsRule> {
33 if let Some(r) = self.ephemeral_exact.get(domain) {
34 return Some(r);
35 }
36 if let Some(r) = self.find_wildcard(&self.ephemeral_wildcard, domain) {
37 return Some(r);
38 }
39 if let Some(r) = self.persistent_exact.get(domain) {
40 return Some(r);
41 }
42 if let Some(r) = self.find_wildcard(&self.persistent_wildcard, domain) {
43 return Some(r);
44 }
45 None
46 }
47
48 pub fn add(&mut self, rule: DnsRule) {
50 if rule.is_wildcard() {
51 self.persistent_wildcard.retain(|r| r.domain != rule.domain);
52 self.persistent_wildcard.push(rule);
53 } else {
54 self.persistent_exact.insert(rule.domain.clone(), rule);
55 }
56 }
57
58 pub fn add_all(&mut self, rules: Vec<DnsRule>) {
60 rules.into_iter().for_each(|rule| self.add(rule));
61 }
62
63 pub fn add_ephemeral(&mut self, rule: DnsRule) {
65 if rule.is_wildcard() {
66 self.ephemeral_wildcard.retain(|r| r.domain != rule.domain);
67 self.ephemeral_wildcard.push(rule);
68 } else {
69 self.ephemeral_exact.insert(rule.domain.clone(), rule);
70 }
71 }
72
73 pub fn remove(&mut self, domain: &str) -> Option<DnsRule> {
75 let rule = self.persistent_exact.remove(domain);
76 if let Some(pos) = self
77 .persistent_wildcard
78 .iter()
79 .position(|x| x.domain == domain)
80 {
81 let item = self.persistent_wildcard.swap_remove(pos);
82 return Some(item);
83 }
84 rule
85 }
86
87 pub fn remove_ephemeral(&mut self, domain: &str) -> Option<DnsRule> {
89 let rule = self.ephemeral_exact.remove(domain);
90 if let Some(pos) = self
91 .ephemeral_wildcard
92 .iter()
93 .position(|x| x.domain == domain)
94 {
95 let item = self.ephemeral_wildcard.swap_remove(pos);
96 return Some(item);
97 }
98 rule
99 }
100
101 pub fn persistent_rules(&self) -> impl Iterator<Item = &DnsRule> {
103 self.persistent_exact
104 .values()
105 .chain(self.persistent_wildcard.iter())
106 }
107
108 pub fn all_rules(&self) -> impl Iterator<Item = &DnsRule> {
110 self.ephemeral_exact
111 .values()
112 .chain(self.ephemeral_wildcard.iter())
113 .chain(self.persistent_exact.values())
114 .chain(self.persistent_wildcard.iter())
115 }
116
117 pub fn len(&self) -> usize {
118 self.ephemeral_exact.len()
119 + self.ephemeral_wildcard.len()
120 + self.persistent_exact.len()
121 + self.persistent_wildcard.len()
122 }
123
124 pub fn is_empty(&self) -> bool {
125 self.len() == 0
126 }
127
128 fn find_wildcard<'a>(&self, list: &'a [DnsRule], domain: &str) -> Option<&'a DnsRule> {
129 list.iter().find(|r| r.matches(domain))
130 }
131}
132
133#[derive(Clone, Debug)]
147pub struct RuleStore {
148 inner: Arc<ArcSwap<InnerRuleStore>>,
149}
150
151impl Default for RuleStore {
152 fn default() -> Self {
153 Self {
154 inner: Arc::new(ArcSwap::from_pointee(InnerRuleStore::new())),
155 }
156 }
157}
158
159impl RuleStore {
160 pub fn new() -> Self {
161 Self::default()
162 }
163
164 pub fn resolve(&self, domain: &str) -> Option<DnsRule> {
168 self.inner.load().resolve(domain).cloned()
169 }
170
171 pub fn add(&self, rule: DnsRule) -> DnsRule {
173 self.inner.rcu(|current| {
174 let mut next = (**current).clone();
175 next.add(rule.clone());
176 next
177 });
178 rule
179 }
180
181 pub fn add_all(&self, rules: Vec<DnsRule>) -> usize {
183 self.inner.rcu(|current| {
184 let mut next = (**current).clone();
185 next.add_all(rules.clone());
186 next
187 });
188 rules.len()
189 }
190
191 pub fn add_ephemeral(&self, rule: DnsRule) -> DnsRule {
193 self.inner.rcu(|current| {
194 let mut next = (**current).clone();
195 next.add_ephemeral(rule.clone());
196 next
197 });
198 rule
199 }
200
201 pub fn remove(&self, domain: &str) -> Option<DnsRule> {
205 let mut removed = None;
206 self.inner.rcu(|current| {
207 let mut next = (**current).clone();
208 removed = next.remove(domain);
209 next
210 });
211 removed
212 }
213
214 pub fn remove_ephemeral(&self, domain: &str) -> Option<DnsRule> {
218 let mut removed = None;
219 self.inner.rcu(|current| {
220 let mut next = (**current).clone();
221 removed = next.remove_ephemeral(domain);
222 next
223 });
224 removed
225 }
226
227 pub fn snapshot_persistent(&self) -> Vec<DnsRule> {
232 self.inner.load().persistent_rules().cloned().collect()
233 }
234
235 pub fn snapshot_all(&self) -> Vec<DnsRule> {
237 self.inner.load().all_rules().cloned().collect()
238 }
239
240 pub fn len(&self) -> usize {
241 self.inner.load().len()
242 }
243
244 pub fn is_empty(&self) -> bool {
245 self.inner.load().is_empty()
246 }
247}