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 from_file(config_path: &str) -> Result<RawConfiguration, String> {
96
97 let mut config = RawConfiguration::default();
98
99 let mut config_file = File::open(config_path)
100 .map_err(|e| format!("failed to open configuration file: {:?}", e))?;
101
102 let mut config_str = String::new();
103 config_file
104 .read_to_string(&mut config_str)
105 .map_err(|e| format!("failed to read configuration file: {:?}", e))?;
106
107 let config_value = config_str.parse::<toml::Value>()
108 .map_err(|e| format!("failed to parse configuration file: {:?}", e))?;
109 $(
110 if let Some(value) = config_value.get(stringify!($name)) {
111 config.$name = if_option!(
112 $($type)+,
113 THEN{ Some(value.clone().try_into().map_err(|e| format!("Invalid {}: err={:?}", stringify!($name), e).to_owned())?) }
114 ELSE{ value.clone().try_into().map_err(|e| format!("Invalid {}: err={:?}", stringify!($name), e).to_owned())? }
115 );
116 }
117 )*
118
119 $(
120 if let Some(value) = config_value.get(stringify!($c_name)) {
121 config.$c_name = if_option!(
122 $($c_type)+,
123 THEN{ Some($converter(value.as_str().unwrap())?) }
124 ELSE{ $converter(value.as_str().unwrap())? }
125 )
126 }
127 )*
128 Ok(config)
129 }
130 }
131 }
132}
133
134#[macro_export]
135macro_rules! set_conf {
136 ($src: expr; $dst: expr => {$($field: tt),* }) => {
137 {
138 let number = $src;
139 $($dst.$field = number;)*
140 }
141 };
142}