From f73649f70374c7baeb7b947607068b9fa426af2e Mon Sep 17 00:00:00 2001 From: Ryan Leckey Date: Fri, 16 Jun 2017 14:09:01 -0700 Subject: [PATCH] Implement Deserialize for rocket::Config --- lib/Cargo.toml | 2 + lib/src/config/config.rs | 121 ++++++++++++++++++++++++++++++++ lib/src/config/custom_values.rs | 2 +- lib/src/lib.rs | 2 + lib/src/logger.rs | 2 +- 5 files changed, 127 insertions(+), 2 deletions(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index a756ad19..31b6afea 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -34,6 +34,8 @@ rustls = { version = "0.8.0", optional = true } cookie = { version = "0.8.1", features = ["percent-encode", "secure"] } hyper = { version = "0.10.11", default-features = false } ordermap = "0.2" +serde = "^1.0.8" +serde_derive = "^1.0.8" [dependencies.hyper-rustls] git = "https://github.com/SergioBenitez/hyper-rustls" diff --git a/lib/src/config/config.rs b/lib/src/config/config.rs index 9a5c6601..eaf33f78 100644 --- a/lib/src/config/config.rs +++ b/lib/src/config/config.rs @@ -770,3 +770,124 @@ impl PartialEq for Config { && self.extras == other.extras } } + +impl<'de> ::serde::de::Deserialize<'de> for Config { + fn deserialize(deserializer: D) -> ::std::result::Result + where D: ::serde::de::Deserializer<'de> + { + struct ConfigVisitor; + + #[derive(Deserialize)] + struct TlsRawConfig { + certs: String, + key: String, + } + + impl<'de> ::serde::de::Visitor<'de> for ConfigVisitor { + type Value = Config; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct Config") + } + + fn visit_map(self, mut map: V) -> ::std::result::Result + where V: ::serde::de::MapAccess<'de> + { + let mut environment: Option = None; + let mut address: Option = None; + let mut port: Option = None; + let mut workers: Option = None; + let mut log_level: Option = None; + let mut secret_key: Option = None; + let mut tls: Option = None; + let mut limits: Option = None; + let mut extras = HashMap::::new(); + + while let Some(key) = map.next_key::()?.as_ref() { + let key: &str = &*key; + match key { + "environment" => { + let env_str: String = map.next_value()?; + environment = Some(env_str.parse().map_err(|_| { + ::serde::de::Error::invalid_value(::serde::de::Unexpected::Str(&env_str), &self) + })?); + }, + + "address" => { + address = map.next_value()?; + }, + + "port" => { + port = map.next_value()?; + }, + + "workers" => { + workers = map.next_value()?; + } + + "log_level" => { + log_level = map.next_value()?; + } + + "secret_key" => { + secret_key = map.next_value()?; + } + + "tls" => { + tls = map.next_value()?; + } + + "limits" => { + limits = map.next_value()?; + } + + _ => { + extras.insert(key.into(), map.next_value()?); + } + } + } + + // FIXME: Remove unwrap + let mut config = Config::new( + environment.unwrap_or_else(|| Environment::active().unwrap())).unwrap(); + + config.set_extras(extras); + + if let Some(address) = address { + // FIXME: Remove unwrap + config.set_address(address).unwrap(); + } + + if let Some(port) = port { + config.set_port(port); + } + + if let Some(workers) = workers { + config.set_workers(workers); + } + + if let Some(log_level) = log_level { + config.set_log_level(log_level); + } + + if let Some(secret_key) = secret_key { + // FIXME: Remove unwrap + config.set_secret_key(secret_key).unwrap(); + } + + if let Some(tls) = tls { + // FIXME: Remove unwrap + config.set_tls(&tls.certs, &tls.key).unwrap(); + } + + if let Some(limits) = limits { + config.set_limits(limits); + } + + Ok(config) + } + } + + deserializer.deserialize_map(ConfigVisitor) + } +} diff --git a/lib/src/config/custom_values.rs b/lib/src/config/custom_values.rs index 5c590590..a330f663 100644 --- a/lib/src/config/custom_values.rs +++ b/lib/src/config/custom_values.rs @@ -76,7 +76,7 @@ pub struct TlsConfig; /// .limit("forms", 64 * 1024) /// .limit("json", 3 * 1024 * 1024); /// ``` -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize)] pub struct Limits { // We cache this internally but don't share that fact in the API. pub(crate) forms: u64, diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 66c29179..3f72c97b 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -116,6 +116,8 @@ extern crate memchr; extern crate base64; extern crate smallvec; extern crate ordermap; +extern crate serde; +#[macro_use] extern crate serde_derive; #[cfg(test)] #[macro_use] extern crate lazy_static; diff --git a/lib/src/logger.rs b/lib/src/logger.rs index 8e6d88ff..3ad50191 100644 --- a/lib/src/logger.rs +++ b/lib/src/logger.rs @@ -9,7 +9,7 @@ use yansi::Color::*; struct RocketLogger(LoggingLevel); /// Defines the different levels for log messages. -#[derive(PartialEq, Eq, Debug, Clone, Copy)] +#[derive(PartialEq, Eq, Debug, Clone, Copy, Deserialize)] pub enum LoggingLevel { /// Only shows errors and warning. Critical,