1extern crate yaml_rust;
2
3use super::constants::{APP_NAME, DIR_NAME};
4use std::collections::HashMap;
5
6use std::clone::Clone;
7use std::fs;
8use std::path::PathBuf;
9use std::result::Result;
10use yaml_rust::{Yaml, YamlLoader};
11
12use log::info;
13
14pub struct ServerConfig {
15 pub port: u16,
16 pub use_unix_domain_socket: bool,
17 pub use_ssl: bool,
18}
19
20impl ServerConfig {
21 fn new(port: u16, use_unix_domain_socket: bool, use_ssl: bool) -> ServerConfig {
22 ServerConfig {
23 port: port,
24 use_unix_domain_socket: use_unix_domain_socket,
25 use_ssl: use_ssl,
26 }
27 }
28}
29
30#[derive(Clone)]
31pub struct CacheConfig {
32 pub host: String,
34 pub origin: String,
36 pub expire: u32,
37 pub err_expire: u32,
38 pub keep_cache_after_shutdown: bool,
39}
40
41impl CacheConfig {
42 fn new(
43 host: &str,
44 origin: &str,
45 expire: u32,
46 err_expire: u32,
47 keep_cache_after_shutdown: bool,
48 ) -> CacheConfig {
49 CacheConfig {
50 host: host.to_string(),
51 origin: origin.to_string(),
52 expire: expire,
53 err_expire: err_expire,
54 keep_cache_after_shutdown: keep_cache_after_shutdown,
55 }
56 }
57}
58
59pub struct Config {
60 pub server: ServerConfig,
61 pub cache: HashMap<String, CacheConfig>,
62}
63
64fn i64tou32(i: i64) -> Result<u32, &'static str> {
65 if i <= u32::max_value() as i64 && i >= 0 {
66 Ok(i as u32)
67 } else {
68 Err("error!")
69 }
70}
71
72fn collect_config_path(home: &PathBuf) -> Result<PathBuf, String> {
73 let candidate = vec![
74 format!(".{}{}", APP_NAME, ".yml"),
75 format!(".{}{}", APP_NAME, ".yaml"),
76 format!("{}/{}{}", DIR_NAME, APP_NAME, ".yml"),
77 format!("{}/{}{}", DIR_NAME, APP_NAME, ".yaml"),
78 ];
79 for c in &candidate {
80 let config_path = home.join(c);
81 if config_path.exists() {
82 return Ok(config_path);
83 }
84 }
85 Err(format!("missing {:?}", candidate))
86}
87
88pub fn load_config_file(home: &PathBuf) -> Result<Config, String> {
89 let config_path = match collect_config_path(home) {
90 Ok(v) => v,
91 Err(err) => {
92 return Err(err.to_string());
93 }
94 };
95 info!(
96 "load config file: {}",
97 config_path
98 .to_str()
99 .expect("error: can't load config file")
100 );
101
102 let yaml_text = fs::read_to_string(config_path).unwrap();
103 let yaml = YamlLoader::load_from_str(yaml_text.as_str()).unwrap();
104 let hosts = &yaml[0]["hosts"];
105 let default = &hosts["default"];
106 let mut cache_config: HashMap<String, CacheConfig> = HashMap::new();
107 match hosts {
108 Yaml::Hash(hosts) => {
109 for (host, config) in hosts {
110 let host = host.as_str().unwrap();
111 if host != "default" {
112 let origin = match &config["origin"] {
113 Yaml::String(origin) => origin,
114 _ => {
115 return Err(format!("parse error:\n\thost:{}\n\tstep:origin", host));
116 }
117 };
118 let expire: u32 = match config["expire"] {
119 Yaml::Integer(expire) => match i64tou32(expire) {
120 Ok(v) => v,
121 Err(_) => {
122 return Err(format!(
123 "parse error:\n\thost:{}\n\tstep:expire",
124 host
125 ));
126 }
127 },
128 _ => match default["expire"] {
129 Yaml::Integer(expire) => match i64tou32(expire) {
130 Ok(v) => v,
131 Err(_) => {
132 return Err(format!(
133 "parse error:\n\thost:{}\n\tstep:expire",
134 host
135 ));
136 }
137 },
138 _ => 86400,
139 },
140 };
141 let err_expire: u32 = match config["err_expire"] {
142 Yaml::Integer(expire) => match i64tou32(expire) {
143 Ok(v) => v,
144 Err(_) => {
145 return Err(format!(
146 "parse error:\n\thost:{}\n\tstep:err_expire",
147 host
148 ));
149 }
150 },
151 _ => match default["err_expire"] {
152 Yaml::Integer(expire) => match i64tou32(expire) {
153 Ok(v) => v,
154 Err(_) => {
155 return Err(format!(
156 "parse error:\n\thost:{}\n\tstep:err_expire",
157 host
158 ));
159 }
160 },
161 _ => 300,
162 },
163 };
164 let keep_cache_after_shutdown = match config["keep_cache_after_shutdown"] {
165 Yaml::Boolean(keep_cache_after_shutdown) => keep_cache_after_shutdown,
166 _ => match default["keep_cache_after_shutdown"] {
167 Yaml::Boolean(keep_cache_after_shutdown) => keep_cache_after_shutdown,
168 _ => false,
169 },
170 };
171 let config = CacheConfig::new(
172 &host,
173 &origin,
174 expire,
175 err_expire,
176 keep_cache_after_shutdown,
177 );
178 cache_config.insert(host.to_string(), config);
179 }
180 }
181 }
182 _ => {}
183 }
184
185 let server_config = ServerConfig::new(0, false, false);
186 let config = Config {
187 server: server_config,
188 cache: cache_config,
189 };
190 Ok(config)
191}