1use serde::{Deserialize, Serialize};
2use std::{fmt::Display, net::SocketAddr};
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
6pub struct DnsRule {
7 pub domain: String,
8 pub target: SocketAddr,
9 pub https: bool,
11}
12
13impl DnsRule {
14 pub fn is_wildcard(&self) -> bool {
15 self.domain.strip_prefix("*.").is_some()
16 }
17
18 pub fn matches(&self, domain: &str) -> bool {
19 match self.domain.strip_prefix("*.") {
20 Some(suffix) => {
21 domain.ends_with(suffix)
22 && domain.len() > suffix.len()
23 && domain.as_bytes()[domain.len() - suffix.len() - 1] == b'.'
24 },
25 None => self.domain == domain,
26 }
27 }
28 pub fn new(domain: String, target: SocketAddr, https: bool) -> Self {
29 Self {
30 domain,
31 target,
32 https,
33 }
34 }
35 pub fn with_https(mut self, https: bool) -> Self {
36 self.https = https;
37 self
38 }
39}
40
41impl Display for DnsRule {
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 let scheme = if self.https { "https" } else { "http" };
44 write!(f, "{scheme}://{} → {}", self.domain, self.target)
45 }
46}