Use serde to parse config file
This commit is contained in:
parent
42ca66e52a
commit
5866076b21
6 changed files with 51 additions and 163 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
@ -25,7 +25,7 @@ dependencies = [
|
|||
"shell32-sys 0.1.1 (git+https://github.com/retep998/winapi-rs?branch=0.2)",
|
||||
"sqlite 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"staticfile 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"user32-sys 0.2.0 (git+https://github.com/retep998/winapi-rs?branch=0.2)",
|
||||
"uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1070,10 +1070,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.2.1"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1334,7 +1334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
|
||||
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
|
||||
"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
|
||||
"checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
|
||||
"checksum toml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3063405db158de3dce8efad5fc89cf1baffb9501a3647dc9505ba109694ce31f"
|
||||
"checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
|
||||
"checksum traitobject 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9dc23794ff47c95882da6f9d15de9a6be14987760a28cc0aafb40b7675ef09d8"
|
||||
"checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
|
||||
|
|
|
@ -28,7 +28,7 @@ serde_derive = "1.0.2"
|
|||
serde_json = "1.0.2"
|
||||
sqlite = "0.23.0"
|
||||
staticfile = "0.3.0"
|
||||
toml = "0.2"
|
||||
toml = "0.4"
|
||||
url = "1.2.0"
|
||||
|
||||
winapi = { git = "https://github.com/retep998/winapi-rs", branch="0.2" }
|
||||
|
|
|
@ -9,21 +9,12 @@ use index::*;
|
|||
use vfs::*;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct User {
|
||||
name: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn new(name: String, password: String) -> User {
|
||||
User {
|
||||
name: name,
|
||||
password: password,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Collection {
|
||||
vfs: Arc<Vfs>,
|
||||
users: Vec<User>,
|
||||
|
|
189
src/config.rs
189
src/config.rs
|
@ -1,4 +1,4 @@
|
|||
use regex;
|
||||
use regex::Regex;
|
||||
use std::fs;
|
||||
use std::io::Read;
|
||||
use std::path;
|
||||
|
@ -13,19 +13,22 @@ use vfs::VfsConfig;
|
|||
|
||||
const DEFAULT_CONFIG_FILE_NAME: &'static str = "polaris.toml";
|
||||
const INDEX_FILE_NAME: &'static str = "index.sqlite";
|
||||
const CONFIG_SECRET: &'static str = "auth_secret";
|
||||
const CONFIG_MOUNT_DIRS: &'static str = "mount_dirs";
|
||||
const CONFIG_MOUNT_DIR_NAME: &'static str = "name";
|
||||
const CONFIG_MOUNT_DIR_SOURCE: &'static str = "source";
|
||||
const CONFIG_USERS: &'static str = "users";
|
||||
const CONFIG_USER_NAME: &'static str = "name";
|
||||
const CONFIG_USER_PASSWORD: &'static str = "password";
|
||||
const CONFIG_ALBUM_ART_PATTERN: &'static str = "album_art_pattern";
|
||||
const CONFIG_INDEX_SLEEP_DURATION: &'static str = "reindex_every_n_seconds";
|
||||
const CONFIG_DDNS: &'static str = "ydns";
|
||||
const CONFIG_DDNS_HOST: &'static str = "host";
|
||||
const CONFIG_DDNS_USERNAME: &'static str = "username";
|
||||
const CONFIG_DDNS_PASSWORD: &'static str = "password";
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct MountDir {
|
||||
pub name: String,
|
||||
pub source: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct UserConfig {
|
||||
pub auth_secret: String,
|
||||
pub album_art_pattern: Option<String>,
|
||||
pub reindex_every_n_seconds: Option<u64>,
|
||||
pub mount_dirs: Vec<MountDir>,
|
||||
pub users: Vec<User>,
|
||||
pub ydns: Option<DDNSConfig>,
|
||||
}
|
||||
|
||||
pub struct Config {
|
||||
pub secret: String,
|
||||
|
@ -48,154 +51,46 @@ impl Config {
|
|||
};
|
||||
println!("Config file path: {}", config_path.to_string_lossy());
|
||||
|
||||
// Parse user config
|
||||
let mut config_file = fs::File::open(config_path)?;
|
||||
let mut config_file_content = String::new();
|
||||
config_file.read_to_string(&mut config_file_content)?;
|
||||
let parsed_config = toml::Parser::new(config_file_content.as_str()).parse();
|
||||
let parsed_config = parsed_config
|
||||
.ok_or("Could not parse config as valid TOML")?;
|
||||
let user_config = toml::de::from_str::<UserConfig>(config_file_content.as_str())?;
|
||||
|
||||
let mut config = Config {
|
||||
secret: String::new(),
|
||||
vfs: VfsConfig::new(),
|
||||
users: Vec::new(),
|
||||
index: IndexConfig::new(),
|
||||
ddns: None,
|
||||
};
|
||||
|
||||
config.parse_secret(&parsed_config)?;
|
||||
config.parse_index_sleep_duration(&parsed_config)?;
|
||||
config.parse_mount_points(&parsed_config)?;
|
||||
config.parse_users(&parsed_config)?;
|
||||
config.parse_album_art_pattern(&parsed_config)?;
|
||||
config.parse_ddns(&parsed_config)?;
|
||||
|
||||
let mut index_path = utils::get_cache_root()?;
|
||||
index_path.push(INDEX_FILE_NAME);
|
||||
config.index.path = index_path;
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn parse_secret(&mut self, source: &toml::Table) -> Result<()> {
|
||||
self.secret = source
|
||||
.get(CONFIG_SECRET)
|
||||
.and_then(|s| s.as_str())
|
||||
.map(|s| s.to_owned())
|
||||
.ok_or("Could not parse config secret")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_index_sleep_duration(&mut self, source: &toml::Table) -> Result<()> {
|
||||
let sleep_duration = match source.get(CONFIG_INDEX_SLEEP_DURATION) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let sleep_duration = match sleep_duration {
|
||||
&toml::Value::Integer(s) => s as u64,
|
||||
_ => bail!("Could not parse index sleep duration"),
|
||||
};
|
||||
self.index.sleep_duration = sleep_duration;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_album_art_pattern(&mut self, source: &toml::Table) -> Result<()> {
|
||||
let pattern = match source.get(CONFIG_ALBUM_ART_PATTERN) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let pattern = match pattern {
|
||||
&toml::Value::String(ref s) => s,
|
||||
_ => bail!("Could not parse album art pattern"),
|
||||
};
|
||||
self.index.album_art_pattern = Some(regex::Regex::new(pattern)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_users(&mut self, source: &toml::Table) -> Result<()> {
|
||||
let users = match source.get(CONFIG_USERS) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let users = match users {
|
||||
&toml::Value::Array(ref a) => a,
|
||||
_ => bail!("Could not parse users array"),
|
||||
};
|
||||
|
||||
for user in users {
|
||||
let name = user.lookup(CONFIG_USER_NAME)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse username")?;
|
||||
let password = user.lookup(CONFIG_USER_PASSWORD)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse user password")?;
|
||||
let user = User::new(name.to_owned(), password.to_owned());
|
||||
self.users.push(user);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_mount_points(&mut self, source: &toml::Table) -> Result<()> {
|
||||
let mount_dirs = match source.get(CONFIG_MOUNT_DIRS) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let mount_dirs = match mount_dirs {
|
||||
&toml::Value::Array(ref a) => a,
|
||||
_ => bail!("Could not parse mount directories array"),
|
||||
};
|
||||
|
||||
for dir in mount_dirs {
|
||||
let name = dir.lookup(CONFIG_MOUNT_DIR_NAME)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse mount directory name")?;
|
||||
let source = dir.lookup(CONFIG_MOUNT_DIR_SOURCE)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse mount directory source")?;
|
||||
let source = clean_path_string(source);
|
||||
if self.vfs.mount_points.contains_key(name) {
|
||||
// Init VFS config
|
||||
let mut vfs_config = VfsConfig::new();
|
||||
for dir in user_config.mount_dirs {
|
||||
if vfs_config.mount_points.contains_key(&dir.name) {
|
||||
bail!("Conflicting mount directories");
|
||||
}
|
||||
self.vfs.mount_points.insert(name.to_owned(), source);
|
||||
vfs_config.mount_points.insert(dir.name.to_owned(), clean_path_string(dir.source.as_str()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
// Init Index config
|
||||
let mut index_config = IndexConfig::new();
|
||||
index_config.album_art_pattern = user_config.album_art_pattern.and_then(|s| Regex::new(s.as_str()).ok());
|
||||
if let Some(duration) = user_config.reindex_every_n_seconds {
|
||||
index_config.sleep_duration = duration;
|
||||
}
|
||||
let mut index_path = utils::get_cache_root()?;
|
||||
index_path.push(INDEX_FILE_NAME);
|
||||
index_config.path = index_path;
|
||||
|
||||
fn parse_ddns(&mut self, source: &toml::Table) -> Result<()> {
|
||||
let ddns = match source.get(CONFIG_DDNS) {
|
||||
Some(s) => s,
|
||||
None => return Ok(()),
|
||||
};
|
||||
let ddns = match ddns {
|
||||
&toml::Value::Table(ref a) => a,
|
||||
_ => bail!("Could not parse DDNS settings table"),
|
||||
// Init master config
|
||||
let config = Config {
|
||||
secret: user_config.auth_secret,
|
||||
vfs: vfs_config,
|
||||
users: user_config.users,
|
||||
index: index_config,
|
||||
ddns: user_config.ydns,
|
||||
};
|
||||
|
||||
let host = ddns.get(CONFIG_DDNS_HOST)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse DDNS host")?;
|
||||
let username = ddns.get(CONFIG_DDNS_USERNAME)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse DDNS username")?;
|
||||
let password = ddns.get(CONFIG_DDNS_PASSWORD)
|
||||
.and_then(|n| n.as_str())
|
||||
.ok_or("Could not parse DDNS password")?;
|
||||
|
||||
self.ddns = Some(DDNSConfig {
|
||||
host: host.to_owned(),
|
||||
username: username.to_owned(),
|
||||
password: password.to_owned(),
|
||||
});
|
||||
Ok(())
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_path_string(path_string: &str) -> path::PathBuf {
|
||||
let separator_regex = regex::Regex::new(r"\\|/").unwrap();
|
||||
let separator_regex = Regex::new(r"\\|/").unwrap();
|
||||
let mut correct_separator = String::new();
|
||||
correct_separator.push(path::MAIN_SEPARATOR);
|
||||
let path_string = separator_regex.replace_all(path_string, correct_separator.as_str());
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::io::Read;
|
|||
use std::thread;
|
||||
use std::time;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct DDNSConfig {
|
||||
pub host: String,
|
||||
pub username: String,
|
||||
|
|
|
@ -10,6 +10,7 @@ use metaflac;
|
|||
use regex;
|
||||
use sqlite;
|
||||
use std;
|
||||
use toml;
|
||||
|
||||
error_chain! {
|
||||
foreign_links {
|
||||
|
@ -21,6 +22,7 @@ error_chain! {
|
|||
Image(image::ImageError);
|
||||
Io(std::io::Error);
|
||||
Time(std::time::SystemTimeError);
|
||||
Toml(toml::de::Error);
|
||||
Regex(regex::Error);
|
||||
SQLite(sqlite::Error);
|
||||
Vorbis(lewton::VorbisError);
|
||||
|
|
Loading…
Add table
Reference in a new issue