Skip to main content

minecraft_pinger/
config.rs

1use 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    // Remove it ?
22    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}