cfx_config/
config_macro.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5macro_rules! if_option {
6	(Option<$type:ty>, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
7		$($then)*
8	);
9	($type:ty, THEN {$($then:tt)*} ELSE {$($otherwise:tt)*}) => (
10		$($otherwise)*
11	);
12}
13
14macro_rules! underscore_to_hyphen {
15    ($e:expr) => {
16        str::replace($e, "_", "-")
17    };
18}
19
20#[macro_export]
21macro_rules! build_config{
22    (
23        {
24            $(($name:ident, ($($type:tt)+), $default:expr))*
25        }
26        {
27            $(($c_name:ident, ($($c_type:tt)+), $c_default:expr, $converter:expr))*
28        }
29    ) => {
30        use cfxcore::pow::ProofOfWorkConfig;
31        use cfxcore::verification::VerificationConfig;
32        use cfxcore::cache_config::CacheConfig;
33        use clap;
34        use cfxcore::db::NUM_COLUMNS;
35        use db;
36        use kvdb_rocksdb::DatabaseConfig;
37        use log::LevelFilter;
38        use network::{node_table::validate_node_url, NetworkConfiguration};
39        use std::{
40            fs::{self, File},
41            io::prelude::*,
42            net::ToSocketAddrs,
43            path::Path,
44            str::FromStr,
45            time::Duration,
46        };
47        use toml;
48
49        #[derive(Debug, PartialEq, Clone)]
50        pub struct RawConfiguration {
51            $(pub $name: $($type)+,)*
52            $(pub $c_name: $($c_type)+,)*
53        }
54
55        impl Default for RawConfiguration {
56            fn default() -> Self {
57                RawConfiguration {
58                    $($name: $default,)*
59                    $($c_name: $c_default,)*
60                }
61            }
62        }
63        impl RawConfiguration {
64            // First parse arguments from config file,
65            // and then parse them from commandline.
66            // Replace the ones from config file with the ones
67            // from commandline if duplicates.
68            pub fn parse(matches: &clap::ArgMatches) -> Result<RawConfiguration, String> {
69                let mut config = if let Ok(Some(config_filename)) = matches.try_get_one::<String>("config")  {
70                    RawConfiguration::from_file(config_filename)?
71
72                } else {
73                    RawConfiguration::default()
74                };
75                $(
76                    if let Ok(Some(value)) = matches.try_get_one::<String>(underscore_to_hyphen!(stringify!($name)).as_str()) {
77                        config.$name = if_option!(
78                                $($type)+,
79                                THEN{ Some(value.parse().map_err(|_| concat!("Invalid ", stringify!($name)).to_owned())?) }
80                                ELSE{ value.parse().map_err(|_| concat!("Invalid ", stringify!($name)).to_owned())? }
81                            );
82                    }
83                )*
84                $(
85                    if let Ok(Some(value)) = matches.try_get_one::<String>(underscore_to_hyphen!(stringify!($c_name)).as_str()) {
86                        config.$c_name = if_option!(
87                                $($c_type)+,
88                                THEN{ Some($converter(value)?) }
89                                ELSE{ $converter(value)? }
90                            )
91                    }
92                )*
93                Ok(config)
94            }
95            // The hyphenated keys `parse` looks up (one per config field). A
96            // CLI option whose clap `id` is not in this set is silently
97            // ignored — the bug class exercised by the exhaustiveness test in
98            // the `conflux` binary.
99            pub fn cli_lookup_keys() -> Vec<String> {
100                let mut keys = Vec::new();
101                $( keys.push(underscore_to_hyphen!(stringify!($name))); )*
102                $( keys.push(underscore_to_hyphen!(stringify!($c_name))); )*
103                keys
104            }
105            pub fn from_file(config_path: &str) ->  Result<RawConfiguration, String> {
106
107                let mut config = RawConfiguration::default();
108
109                let mut config_file = File::open(config_path)
110                .map_err(|e| format!("failed to open configuration file: {:?}", e))?;
111
112                let mut config_str = String::new();
113                config_file
114                    .read_to_string(&mut config_str)
115                    .map_err(|e| format!("failed to read configuration file: {:?}", e))?;
116
117                let config_value = config_str.parse::<toml::Value>()
118                    .map_err(|e| format!("failed to parse configuration file: {:?}", e))?;
119                $(
120                    if let Some(value) = config_value.get(stringify!($name)) {
121                        config.$name = if_option!(
122                            $($type)+,
123                            THEN{ Some(value.clone().try_into().map_err(|e| format!("Invalid {}: err={:?}", stringify!($name), e).to_owned())?) }
124                            ELSE{ value.clone().try_into().map_err(|e| format!("Invalid {}: err={:?}", stringify!($name), e).to_owned())? }
125                        );
126                    }
127                )*
128
129                $(
130                  if let Some(value) = config_value.get(stringify!($c_name)) {
131                        config.$c_name = if_option!(
132                            $($c_type)+,
133                            THEN{ Some($converter(value.as_str().unwrap())?) }
134                            ELSE{ $converter(value.as_str().unwrap())? }
135                        )
136                    }
137                )*
138                Ok(config)
139         }
140        }
141    }
142}
143
144#[macro_export]
145macro_rules! set_conf {
146    ($src: expr; $dst: expr => {$($field: tt),* }) => {
147        {
148            let number = $src;
149            $($dst.$field = number;)*
150        }
151    };
152}