minecraft_pinger/
config.rs1use std::net::IpAddr;
2use std::sync::Arc;
3use std::time::Duration;
4
5use crate::common::ip_filter::{IpFilter, is_public_ip};
6
7pub const DEFAULT_PROTOCOL_VERSION: i32 = 777;
8pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(1);
9
10#[derive(Clone)]
11pub struct PingConfig {
12 timeout: Duration,
13 ip_filter: Option<Arc<IpFilter>>,
14}
15
16impl PingConfig {
17 pub fn builder() -> PingConfigBuilder {
18 PingConfigBuilder::new()
19 }
20
21 pub fn to_builder(&self) -> PingConfigBuilder {
23 PingConfigBuilder {
24 timeout: self.timeout,
25 ip_filter: self.ip_filter.clone(),
26 }
27 }
28
29 pub fn timeout(&self) -> Duration {
30 self.timeout
31 }
32
33 pub fn ip_filter(&self) -> Option<&Arc<IpFilter>> {
34 self.ip_filter.as_ref()
35 }
36}
37
38impl Default for PingConfig {
39 fn default() -> Self {
40 Self::builder().build()
41 }
42}
43
44#[derive(Clone)]
45pub struct PingConfigBuilder {
46 timeout: Duration,
47 ip_filter: Option<Arc<IpFilter>>,
48}
49
50impl Default for PingConfigBuilder {
51 fn default() -> Self {
52 Self::new()
53 }
54}
55
56impl PingConfigBuilder {
57 pub fn new() -> PingConfigBuilder {
58 PingConfigBuilder {
59 timeout: DEFAULT_TIMEOUT,
60 ip_filter: None,
61 }
62 }
63
64 pub fn set_timeout(mut self, timeout: Duration) -> PingConfigBuilder {
65 self.timeout = timeout;
66 self
67 }
68
69 pub fn deny_non_public_ips(mut self) -> PingConfigBuilder {
70 self.ip_filter = Some(Arc::new(is_public_ip));
71 self
72 }
73
74 pub fn set_ip_filter<F>(mut self, filter: F) -> PingConfigBuilder
75 where
76 F: Fn(IpAddr) -> bool + Send + Sync + 'static,
77 {
78 self.ip_filter = Some(Arc::new(filter));
79 self
80 }
81
82 pub fn build(self) -> PingConfig {
83 PingConfig {
84 timeout: self.timeout,
85 ip_filter: self.ip_filter,
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93 use std::net::{IpAddr, Ipv4Addr};
94 use std::time::Duration;
95
96 #[test]
97 fn test_ping_config_builder_default() {
98 let config = PingConfigBuilder::new().build();
99 assert_eq!(config.timeout(), DEFAULT_TIMEOUT);
100 assert!(config.ip_filter().is_none());
101 }
102
103 #[test]
104 fn test_ping_config_builder_custom_timeout() {
105 let config = PingConfigBuilder::new()
106 .set_timeout(Duration::from_secs(5))
107 .build();
108 assert_eq!(config.timeout(), Duration::from_secs(5));
109 }
110
111 #[test]
112 fn test_ping_config_builder_deny_non_public_ips() {
113 let config = PingConfigBuilder::new().deny_non_public_ips().build();
114 assert!(config.ip_filter().is_some());
115
116 let filter = config.ip_filter().unwrap();
117 assert!(filter(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
118 assert!(!filter(IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))));
119 }
120
121 #[test]
122 fn test_ping_config_builder_custom_ip_filter() {
123 let config = PingConfigBuilder::new()
124 .set_ip_filter(|ip| matches!(ip, IpAddr::V4(_)))
125 .build();
126 assert!(config.ip_filter().is_some());
127
128 let filter = config.ip_filter().unwrap();
129 assert!(filter(IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8))));
130 assert!(!filter(IpAddr::V6(std::net::Ipv6Addr::new(
131 0, 0, 0, 0, 0, 0, 0, 1
132 ))));
133 }
134
135 #[test]
136 fn test_ping_config_builder_chaining() {
137 let config = PingConfigBuilder::new()
138 .set_timeout(Duration::from_millis(500))
139 .deny_non_public_ips()
140 .build();
141 assert_eq!(config.timeout(), Duration::from_millis(500));
142 assert!(config.ip_filter().is_some());
143 }
144
145 #[test]
146 fn test_ping_config_default() {
147 let config = PingConfig::default();
148 assert_eq!(config.timeout(), DEFAULT_TIMEOUT);
149 assert!(config.ip_filter().is_none());
150 }
151
152 #[test]
153 fn test_ping_config_to_builder() {
154 let original = PingConfigBuilder::new()
155 .set_timeout(Duration::from_secs(10))
156 .deny_non_public_ips()
157 .build();
158
159 let builder = original.to_builder();
160 let rebuilt = builder.build();
161
162 assert_eq!(rebuilt.timeout(), Duration::from_secs(10));
163 assert!(rebuilt.ip_filter().is_some());
164 }
165}