huawei_dongle_api/
config.rs1use crate::error::{Error, Result};
41use std::time::Duration;
42use url::Url;
43
44#[derive(Debug, Clone)]
48pub struct Config {
49 pub base_url: Url,
51 pub timeout: Duration,
53 pub max_retries: usize,
55 pub retry_delay: Duration,
57 pub max_retry_delay: Duration,
59 pub user_agent: String,
61}
62
63impl Default for Config {
64 fn default() -> Self {
65 Self {
66 base_url: Url::parse("http://192.168.8.1").unwrap(),
67 timeout: Duration::from_secs(30),
68 max_retries: 3,
69 retry_delay: Duration::from_millis(500),
70 max_retry_delay: Duration::from_secs(30),
71 user_agent: format!("huawei-dongle-api/{}", env!("CARGO_PKG_VERSION")),
72 }
73 }
74}
75
76impl Config {
77 pub fn builder() -> ConfigBuilder {
79 ConfigBuilder::default()
80 }
81
82 pub fn for_url<S: AsRef<str>>(url: S) -> Result<Self> {
84 Ok(Self {
85 base_url: Url::parse(url.as_ref())?,
86 ..Default::default()
87 })
88 }
89}
90
91#[derive(Debug, Default)]
93pub struct ConfigBuilder {
94 base_url: Option<String>,
95 timeout: Option<Duration>,
96 max_retries: Option<usize>,
97 retry_delay: Option<Duration>,
98 max_retry_delay: Option<Duration>,
99 user_agent: Option<String>,
100}
101
102impl ConfigBuilder {
103 pub fn base_url<S: Into<String>>(mut self, url: S) -> Self {
104 self.base_url = Some(url.into());
105 self
106 }
107
108 pub fn timeout(mut self, timeout: Duration) -> Self {
109 self.timeout = Some(timeout);
110 self
111 }
112
113 pub fn max_retries(mut self, max_retries: usize) -> Self {
114 self.max_retries = Some(max_retries);
115 self
116 }
117
118 pub fn retry_delay(mut self, delay: Duration) -> Self {
119 self.retry_delay = Some(delay);
120 self
121 }
122
123 pub fn max_retry_delay(mut self, delay: Duration) -> Self {
124 self.max_retry_delay = Some(delay);
125 self
126 }
127
128 pub fn user_agent<S: Into<String>>(mut self, user_agent: S) -> Self {
129 self.user_agent = Some(user_agent.into());
130 self
131 }
132
133 pub fn build(self) -> Result<Config> {
134 let default = Config::default();
135
136 let base_url = if let Some(url) = self.base_url {
137 Url::parse(&url).map_err(|e| Error::config(format!("Invalid base URL: {e}")))?
138 } else {
139 default.base_url
140 };
141
142 Ok(Config {
143 base_url,
144 timeout: self.timeout.unwrap_or(default.timeout),
145 max_retries: self.max_retries.unwrap_or(default.max_retries),
146 retry_delay: self.retry_delay.unwrap_or(default.retry_delay),
147 max_retry_delay: self.max_retry_delay.unwrap_or(default.max_retry_delay),
148 user_agent: self.user_agent.unwrap_or(default.user_agent),
149 })
150 }
151}
152
153#[cfg(test)]
154mod tests {
155 use super::*;
156
157 #[test]
158 fn test_default_config() {
159 let config = Config::default();
160 assert_eq!(config.base_url.as_str(), "http://192.168.8.1/");
161 assert_eq!(config.timeout, Duration::from_secs(30));
162 assert_eq!(config.max_retries, 3);
163 }
164
165 #[test]
166 fn test_config_builder() {
167 let config = Config::builder()
168 .base_url("http://192.168.62.1")
169 .timeout(Duration::from_secs(60))
170 .max_retries(5)
171 .build()
172 .unwrap();
173
174 assert_eq!(config.base_url.as_str(), "http://192.168.62.1/");
175 assert_eq!(config.timeout, Duration::from_secs(60));
176 assert_eq!(config.max_retries, 5);
177 }
178
179 #[test]
180 fn test_for_url() {
181 let config = Config::for_url("http://192.168.62.1").unwrap();
182 assert_eq!(config.base_url.as_str(), "http://192.168.62.1/");
183 }
184}