cfx_config/
config_macro.rs1macro_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 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 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}