1use serde::Deserialize;
4
5const fn default_timeout() -> u64 {
7 15
8}
9
10const fn default_retries() -> u32 {
12 3
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
20pub struct RemoteConfig {
21 pub name: String,
23 pub url: String,
25 #[serde(default)]
28 pub auth_env: Option<String>,
29 #[serde(default = "default_timeout")]
31 pub timeout_seconds: u64,
32 #[serde(default = "default_retries")]
34 pub max_retries: u32,
35}
36
37impl RemoteConfig {
38 #[cfg(any(test, feature = "test-support"))]
40 #[must_use]
41 pub fn fixture(name: &str) -> Self {
42 Self {
43 name: name.to_string(),
44 url: format!("https://{name}.example.com"),
45 auth_env: None,
46 timeout_seconds: 15,
47 max_retries: 3,
48 }
49 }
50}
51
52#[cfg(test)]
53#[allow(clippy::expect_used)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn deserialize_remote_with_defaults() {
59 let toml_str = r#"
60 name = "upstream"
61 url = "https://sashiko.dev"
62 "#;
63 let remote: RemoteConfig = toml::from_str(toml_str).expect("parse remote");
64 assert_eq!(remote.name, "upstream");
65 assert_eq!(remote.url, "https://sashiko.dev");
66 assert_eq!(remote.timeout_seconds, 15);
67 assert_eq!(remote.max_retries, 3);
68 assert!(remote.auth_env.is_none());
69 }
70
71 #[test]
72 fn deserialize_remote_with_overrides() {
73 let toml_str = r#"
74 name = "staging"
75 url = "https://staging.sashiko.dev"
76 auth_env = "SASHIKO_TOKEN"
77 timeout_seconds = 30
78 max_retries = 5
79 "#;
80 let remote: RemoteConfig = toml::from_str(toml_str).expect("parse remote overrides");
81 assert_eq!(remote.timeout_seconds, 30);
82 assert_eq!(remote.max_retries, 5);
83 assert_eq!(remote.auth_env.as_deref(), Some("SASHIKO_TOKEN"));
84 }
85}