Update toml to 0.4. Add Config::get_datetime.

This commit is contained in:
Sergio Benitez 2017-06-11 02:20:57 -07:00
parent 2bfb41d968
commit 8badc73c4b
5 changed files with 81 additions and 41 deletions

View File

@ -21,7 +21,7 @@ tls = ["rustls", "hyper-rustls"]
yansi = "0.3" yansi = "0.3"
log = "0.3" log = "0.3"
url = "1" url = "1"
toml = { version = "0.2", default-features = false } toml = "0.4"
num_cpus = "1" num_cpus = "1"
state = "0.2.2" state = "0.2.2"
time = "0.1" time = "0.1"

View File

@ -319,7 +319,7 @@ impl ConfigBuilder {
/// # Panics /// # Panics
/// ///
/// Panics if the current working directory cannot be retrieved or if the /// Panics if the current working directory cannot be retrieved or if the
/// supplied address or secret key fail to parse. /// supplied address, secret key, or TLS configuration fail to parse.
/// ///
/// # Example /// # Example
/// ///
@ -336,4 +336,29 @@ impl ConfigBuilder {
pub fn unwrap(self) -> Config { pub fn unwrap(self) -> Config {
self.finalize().expect("ConfigBuilder::unwrap() failed") self.finalize().expect("ConfigBuilder::unwrap() failed")
} }
///
/// Returns the `Config` structure that was being built by this builder.
///
/// # Panics
///
/// Panics if the current working directory cannot be retrieved or if the
/// supplied address, secret key, or TLS configuration fail to parse. If a
/// panic occurs, the error message `msg` is printed.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment};
///
/// let config = Config::build(Environment::Staging)
/// .address("127.0.0.1")
/// .expect("the configuration is bad!");
///
/// assert_eq!(config.address.as_str(), "127.0.0.1");
/// ```
#[inline(always)]
pub fn expect(self, msg: &str) -> Config {
self.finalize().expect(msg)
}
} }

View File

@ -8,7 +8,8 @@ use std::env;
use super::custom_values::*; use super::custom_values::*;
use {num_cpus, base64}; use {num_cpus, base64};
use config::Environment::*; use config::Environment::*;
use config::{Result, Table, Value, ConfigBuilder, Environment, ConfigError}; use config::{Result, ConfigBuilder, Environment, ConfigError};
use config::{Table, Value, Array, Datetime};
use logger::LoggingLevel; use logger::LoggingLevel;
use http::Key; use http::Key;
@ -662,9 +663,9 @@ impl Config {
/// ///
/// assert!(config.get_slice("numbers").is_ok()); /// assert!(config.get_slice("numbers").is_ok());
/// ``` /// ```
pub fn get_slice(&self, name: &str) -> Result<&[Value]> { pub fn get_slice(&self, name: &str) -> Result<&Array> {
let val = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?; let val = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
val.as_slice().ok_or_else(|| self.bad_type(name, val.type_str(), "a slice")) val.as_array().ok_or_else(|| self.bad_type(name, val.type_str(), "an array"))
} }
/// Attempts to retrieve the extra named `name` as a table. /// Attempts to retrieve the extra named `name` as a table.
@ -695,6 +696,32 @@ impl Config {
val.as_table().ok_or_else(|| self.bad_type(name, val.type_str(), "a table")) val.as_table().ok_or_else(|| self.bad_type(name, val.type_str(), "a table"))
} }
/// Attempts to retrieve the extra named `name` as a datetime value.
///
/// # Errors
///
/// If an extra with `name` doesn't exist, returns an `Err` of `NotFound`.
/// If an extra with `name` _does_ exist but is not a datetime, returns a
/// `BadType` error.
///
/// # Example
///
/// ```rust
/// use rocket::config::{Config, Environment, Value, Datetime};
///
/// let date = "1979-05-27T00:32:00-07:00".parse::<Datetime>().unwrap();
///
/// let config = Config::build(Environment::Staging)
/// .extra("my_date", Value::Datetime(date.clone()))
/// .unwrap();
///
/// assert_eq!(config.get_datetime("my_date"), Ok(&date));
/// ```
pub fn get_datetime(&self, name: &str) -> Result<&Datetime> {
let v = self.extras.get(name).ok_or_else(|| ConfigError::NotFound)?;
v.as_datetime().ok_or_else(|| self.bad_type(name, v.type_str(), "a datetime"))
}
/// Returns the path at which the configuration file for `self` is stored. /// Returns the path at which the configuration file for `self` is stored.
/// For instance, if the configuration file is at `/tmp/Rocket.toml`, the /// For instance, if the configuration file is at `/tmp/Rocket.toml`, the
/// path `/tmp` is returned. /// path `/tmp` is returned.
@ -721,7 +748,8 @@ impl Config {
impl fmt::Debug for Config { impl fmt::Debug for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Config[{}] {{ address: {}, port: {}, workers: {}, log: {:?}", write!(f, "Config[{}] {{ address: {}, port: {}, workers: {}, log: {:?}",
self.environment, self.address, self.port, self.workers, self.log_level)?; self.environment, self.address, self.port, self.workers,
self.log_level)?;
for (key, value) in self.extras() { for (key, value) in self.extras() {
write!(f, ", {}: {}", key, value)?; write!(f, ", {}: {}", key, value)?;

View File

@ -47,8 +47,8 @@ pub enum ConfigError {
BadType(String, &'static str, &'static str, PathBuf), BadType(String, &'static str, &'static str, PathBuf),
/// There was a TOML parsing error. /// There was a TOML parsing error.
/// ///
/// Parameters: (toml_source_string, filename, error_list) /// Parameters: (toml_source_string, filename, error_description, line/col)
ParseError(String, PathBuf, Vec<ParsingError>), ParseError(String, PathBuf, String, Option<(usize, usize)>),
/// There was a TOML parsing error in a config environment variable. /// There was a TOML parsing error in a config environment variable.
/// ///
/// Parameters: (env_key, env_value, error) /// Parameters: (env_key, env_value, error)
@ -87,15 +87,14 @@ impl ConfigError {
info_!("expected value to be {}, but found {}", info_!("expected value to be {}, but found {}",
White.paint(expected), White.paint(actual)); White.paint(expected), White.paint(actual));
} }
ParseError(ref source, ref filename, ref errors) => { ParseError(_, ref filename, ref desc, line_col) => {
for error in errors { error!("config file failed to parse due to invalid TOML");
let (lo, hi) = error.byte_range; info_!("{}", desc);
let (line, col) = error.start; if let Some((line, col)) = line_col {
let error_source = &source[lo..hi]; info_!("at {:?}:{}:{}", White.paint(filename),
White.paint(line + 1), White.paint(col + 1));
error!("config file failed to parse due to invalid TOML"); } else {
info_!("at {:?}:{}:{}", White.paint(filename), line + 1, col + 1); info_!("in {:?}", White.paint(filename));
trace_!("{:?} - {}", error_source, White.paint(&error.desc));
} }
} }
BadEnvVal(ref key, ref value, ref error) => { BadEnvVal(ref key, ref value, ref error) => {

View File

@ -203,7 +203,7 @@ use std::env;
use toml; use toml;
pub use self::custom_values::Limits; pub use self::custom_values::Limits;
pub use toml::{Array, Table, Value}; pub use toml::value::{Array, Table, Value, Datetime};
pub use self::error::{ConfigError, ParsingError}; pub use self::error::{ConfigError, ParsingError};
pub use self::environment::Environment; pub use self::environment::Environment;
pub use self::config::Config; pub use self::config::Config;
@ -391,30 +391,18 @@ impl RocketConfig {
/// Parses the configuration from the Rocket.toml file. Also overrides any /// Parses the configuration from the Rocket.toml file. Also overrides any
/// values there with values from the environment. /// values there with values from the environment.
fn parse<P: AsRef<Path>>(src: String, filename: P) -> Result<RocketConfig> { fn parse<P: AsRef<Path>>(src: String, filename: P) -> Result<RocketConfig> {
// Get a PathBuf version of the filename. use self::ConfigError::ParseError;
let path = filename.as_ref().to_path_buf();
// Parse the source as TOML, if possible. // Parse the source as TOML, if possible.
let mut parser = toml::Parser::new(&src); let path = filename.as_ref().to_path_buf();
let toml = parser.parse().ok_or_else(|| { let table = match src.parse::<toml::Value>() {
let source = src.clone(); Ok(toml::Value::Table(table)) => table,
let errors = parser.errors.iter() Ok(value) => {
.map(|error| { let err = format!("expected a table, found {}", value.type_str());
// workaround for poor error messages `toml` return Err(ConfigError::ParseError(src, path, err, Some((1, 1))));
let debug_desc = format!("{:?}", error.desc); }
// strip the leading " and trailing " from debug formatting Err(e) => return Err(ParseError(src, path, e.to_string(), e.line_col()))
let desc = debug_desc[1..debug_desc.len() - 1].to_string(); };
ParsingError {
byte_range: (error.lo, error.hi),
start: parser.to_linecol(error.lo),
end: parser.to_linecol(error.hi),
desc: desc
}
});
ConfigError::ParseError(source, path.clone(), errors.collect())
})?;
// Create a config with the defaults; set the env to the active one. // Create a config with the defaults; set the env to the active one.
let mut config = RocketConfig::active_default(filename)?; let mut config = RocketConfig::active_default(filename)?;
@ -423,7 +411,7 @@ impl RocketConfig {
let mut global = None; let mut global = None;
// Parse the values from the TOML file. // Parse the values from the TOML file.
for (entry, value) in toml { for (entry, value) in table {
// Each environment must be a table. // Each environment must be a table.
let kv_pairs = match value.as_table() { let kv_pairs = match value.as_table() {
Some(table) => table, Some(table) => table,