1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use crate::Error;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct Config {
socks5: Option<Socks5Config>,
timeout: Option<Duration>,
retry: u8,
validate_domain: bool,
}
#[derive(Debug, Clone)]
pub struct Socks5Config {
pub addr: String,
pub credentials: Option<Socks5Credential>,
}
#[derive(Debug, Clone)]
pub struct Socks5Credential {
pub username: String,
pub password: String,
}
pub struct ConfigBuilder {
config: Config,
}
impl ConfigBuilder {
pub fn new() -> Self {
ConfigBuilder {
config: Config::default(),
}
}
pub fn socks5(mut self, socks5_config: Option<Socks5Config>) -> Result<Self, Error> {
if socks5_config.is_some() && self.config.timeout.is_some() {
return Err(Error::BothSocksAndTimeout);
}
self.config.socks5 = socks5_config;
Ok(self)
}
pub fn timeout(mut self, timeout: u8) -> Result<Self, Error> {
if self.config.socks5.is_some() {
return Err(Error::BothSocksAndTimeout);
}
self.config.timeout = Some(Duration::from_secs(timeout as u64));
Ok(self)
}
pub fn retry(mut self, retry: u8) -> Self {
self.config.retry = retry;
self
}
pub fn validate_domain(mut self, validate_domain: bool) -> Self {
self.config.validate_domain = validate_domain;
self
}
pub fn build(self) -> Config {
self.config
}
}
impl Default for ConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl Socks5Config {
pub fn new(addr: impl ToString) -> Self {
let addr = addr.to_string().replacen("socks5://", "", 1);
Socks5Config {
addr,
credentials: None,
}
}
pub fn with_credentials(addr: impl ToString, username: String, password: String) -> Self {
let mut config = Socks5Config::new(addr);
config.credentials = Some(Socks5Credential { username, password });
config
}
}
impl Config {
pub fn socks5(&self) -> &Option<Socks5Config> {
&self.socks5
}
pub fn retry(&self) -> u8 {
self.retry
}
pub fn timeout(&self) -> Option<Duration> {
self.timeout
}
pub fn validate_domain(&self) -> bool {
self.validate_domain
}
}
impl Default for Config {
fn default() -> Self {
Config {
socks5: None,
timeout: None,
retry: 1,
validate_domain: true,
}
}
}