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
use config::{ConfigError, Map, Source, Value};
use iroh_rpc_types::{gateway::GatewayAddr, p2p::P2pAddr, store::StoreAddr};
use iroh_util::insert_into_config_map;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default)]
/// Config for the rpc Client.
pub struct Config {
    /// Gateway rpc address.
    pub gateway_addr: Option<GatewayAddr>,
    /// P2p rpc address.
    pub p2p_addr: Option<P2pAddr>,
    /// Store rpc address.
    pub store_addr: Option<StoreAddr>,
    /// Number of concurent channels.
    pub channels: Option<usize>,
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new(self.clone())
    }

    fn collect(&self) -> Result<Map<String, Value>, ConfigError> {
        let mut map: Map<String, Value> = Map::new();
        if let Some(addr) = &self.gateway_addr {
            insert_into_config_map(&mut map, "gateway_addr", addr.to_string());
        }
        if let Some(addr) = &self.p2p_addr {
            insert_into_config_map(&mut map, "p2p_addr", addr.to_string());
        }
        if let Some(addr) = &self.store_addr {
            insert_into_config_map(&mut map, "store_addr", addr.to_string());
        }
        if let Some(channels) = &self.channels {
            insert_into_config_map(&mut map, "channels", channels.to_string());
        }
        Ok(map)
    }
}

impl Config {
    pub fn default_network() -> Self {
        Self {
            gateway_addr: Some("irpc://127.0.0.1:4400".parse().unwrap()),
            p2p_addr: Some("irpc://127.0.0.1:4401".parse().unwrap()),
            store_addr: Some("irpc://127.0.0.1:4402".parse().unwrap()),
            /// disable load balancing by default by just having 1 channel
            channels: Some(1),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use config::Config as ConfigBuilder;

    #[test]
    fn test_collect() {
        let default = Config::default_network();
        let mut expect: Map<String, Value> = Map::new();
        expect.insert(
            "gateway_addr".to_string(),
            Value::new(None, default.gateway_addr.unwrap().to_string()),
        );
        expect.insert(
            "p2p_addr".to_string(),
            Value::new(None, default.p2p_addr.unwrap().to_string()),
        );
        expect.insert(
            "store_addr".to_string(),
            Value::new(None, default.store_addr.unwrap().to_string()),
        );
        expect.insert(
            "channels".to_string(),
            Value::new(None, default.channels.unwrap().to_string()),
        );
        let got = Config::default().collect().unwrap();
        for key in got.keys() {
            let left = expect.get(key).unwrap();
            let right = got.get(key).unwrap();
            assert_eq!(left, right);
        }
    }

    #[test]
    fn test_build_config_from_struct() {
        let expect = Config::default();
        let got: Config = ConfigBuilder::builder()
            .add_source(Config::default())
            .build()
            .unwrap()
            .try_deserialize()
            .unwrap();

        assert_eq!(expect, got);
    }
}