summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Leckey <leckey.ryan@gmail.com>2017-02-11 12:00:23 -0800
committerRyan Leckey <leckey.ryan@gmail.com>2017-02-11 12:00:23 -0800
commitbcd0737e15726f3ad324c3cf26c5d04fe5f75766 (patch)
tree804aa3d382baef5bb341eedfa341e79a981a3930
parent1fc094826fedc1924bc03b7ac21ff3518f8ef521 (diff)
Move to copy API instead of reference; fixes #9
-rw-r--r--src/config.rs51
-rw-r--r--src/lib.rs52
-rw-r--r--src/value.rs63
3 files changed, 72 insertions, 94 deletions
diff --git a/src/config.rs b/src/config.rs
index 4df5377..cdb241b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -5,7 +5,6 @@ use path;
use std::error::Error;
use std::fmt;
use std::str::FromStr;
-use std::borrow::Cow;
use std::collections::HashMap;
#[derive(Default, Debug)]
@@ -357,7 +356,7 @@ impl Config {
}
}
- pub fn get<'a>(&'a self, key_path: &str) -> Option<&'a Value> {
+ pub fn get(&self, key_path: &str) -> Option<Value> {
let key_expr: path::Expression = match key_path.to_lowercase().parse() {
Ok(expr) => expr,
Err(_) => {
@@ -366,31 +365,31 @@ impl Config {
}
};
- self.path_get(key_expr)
+ self.path_get(key_expr).cloned()
}
- pub fn get_str<'a>(&'a self, key: &str) -> Option<Cow<'a, str>> {
- self.get(key).and_then(Value::as_str)
+ pub fn get_str(&self, key: &str) -> Option<String> {
+ self.get(key).and_then(Value::into_str)
}
pub fn get_int(&self, key: &str) -> Option<i64> {
- self.get(key).and_then(Value::as_int)
+ self.get(key).and_then(Value::into_int)
}
pub fn get_float(&self, key: &str) -> Option<f64> {
- self.get(key).and_then(Value::as_float)
+ self.get(key).and_then(Value::into_float)
}
pub fn get_bool(&self, key: &str) -> Option<bool> {
- self.get(key).and_then(Value::as_bool)
+ self.get(key).and_then(Value::into_bool)
}
- pub fn get_map<'a>(&'a self, key: &str) -> Option<&'a HashMap<String, Value>> {
- self.get(key).and_then(Value::as_map)
+ pub fn get_table(&self, key: &str) -> Option<HashMap<String, Value>> {
+ self.get(key).and_then(Value::into_table)
}
- pub fn get_slice<'a>(&'a self, key: &str) -> Option<&'a [Value]> {
- self.get(key).and_then(Value::as_slice)
+ pub fn get_array(self, key: &str) -> Option<Vec<Value>> {
+ self.get(key).and_then(Value::into_array)
}
}
@@ -556,10 +555,10 @@ mod test {
vec![Value::Integer(10), Value::Integer(325), Value::Integer(12)])
.unwrap();
- let values = c.get_slice("values").unwrap();
+ let values = c.get_array("values").unwrap();
assert_eq!(values.len(), 3);
- assert_eq!(values[1].as_int(), Some(325));
+ assert_eq!(values[1].clone().into_int(), Some(325));
}
#[test]
@@ -569,10 +568,10 @@ mod test {
c.set("values", vec![10, 325, 12])
.unwrap();
- let values = c.get_slice("values").unwrap();
+ let values = c.get_array("values").unwrap();
assert_eq!(values.len(), 3);
- assert_eq!(values[1].as_int(), Some(325));
+ assert_eq!(values[1].clone().into_int(), Some(325));
}
@@ -589,10 +588,10 @@ mod test {
}
{
- let m = c.get_map("redis").unwrap();
+ let m = c.get_table("redis").unwrap();
- assert_eq!(m.get("port").unwrap().as_int().unwrap(), 6379);
- assert_eq!(m.get("address").unwrap().as_str().unwrap(), "::1");
+ assert_eq!(m.get("port").cloned().unwrap().into_int().unwrap(), 6379);
+ assert_eq!(m.get("address").cloned().unwrap().into_str().unwrap(), "::1");
}
{
@@ -604,11 +603,11 @@ mod test {
}
{
- let m = c.get_map("redis").unwrap();
+ let m = c.get_table("redis").unwrap();
- assert_eq!(m.get("port").unwrap().as_int().unwrap(), 6379);
- assert_eq!(m.get("address").unwrap().as_str().unwrap(), "::0");
- assert_eq!(m.get("db").unwrap().as_str().unwrap(), "1");
+ assert_eq!(m.get("port").cloned().unwrap().into_int().unwrap(), 6379);
+ assert_eq!(m.get("address").cloned().unwrap().into_str().unwrap(), "::0");
+ assert_eq!(m.get("db").cloned().unwrap().into_str().unwrap(), "1");
}
}
@@ -647,10 +646,10 @@ mod test {
}
{
- let m = c.get_map("redis").unwrap();
+ let m = c.get_table("redis").unwrap();
- assert_eq!(m.get("port").unwrap().as_int().unwrap(), 6379);
- assert_eq!(m.get("db").unwrap().as_int().unwrap(), 2);
+ assert_eq!(m.get("port").cloned().unwrap().into_int().unwrap(), 6379);
+ assert_eq!(m.get("db").cloned().unwrap().into_int().unwrap(), 2);
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 073815f..dae615c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,7 +30,7 @@
//! ```rust
//! // Get 'debug' and coerce to a boolean
//! if let Some(value) = config::get("debug") {
-//! println!("{:?}", value.as_bool());
+//! println!("{:?}", value.into_bool());
//! }
//!
//! // You can use a type suffix
@@ -62,7 +62,7 @@ mod config;
use std::error::Error;
use std::sync::{Once, ONCE_INIT, RwLock};
-use std::borrow::Cow;
+use std::collections::HashMap;
pub use source::{Source, SourceBuilder};
pub use file::{File, FileFormat};
@@ -105,52 +105,32 @@ pub fn set<T>(key: &str, value: T) -> Result<(), Box<Error>>
global().write().unwrap().set(key, value)
}
-pub fn get<'a>(key: &str) -> Option<&'a Value> {
+pub fn get(key: &str) -> Option<Value> {
// TODO(~): Should this panic! or return None with an error message?
// Make an issue if you think it should be an error message.
- let r = global().read().unwrap();
-
- let c = &*r;
-
- // TODO(@rust): Figure out how to not to use unsafe here
- unsafe {
- let c: &'static Config = std::mem::transmute(c);
- c.get(key)
- }
+ global().read().unwrap().get(key)
}
-pub fn get_str<'a>(key: &str) -> Option<Cow<'a, str>> {
- let r = global().read().unwrap();
-
- unsafe {
- let c: &'static Config = std::mem::transmute(&*r);
- c.get_str(key)
- }
+pub fn get_str(key: &str) -> Option<String> {
+ get(key).and_then(Value::into_str)
}
pub fn get_int(key: &str) -> Option<i64> {
- let r = global().read().unwrap();
-
- unsafe {
- let c: &'static Config = std::mem::transmute(&*r);
- c.get_int(key)
- }
+ get(key).and_then(Value::into_int)
}
pub fn get_float(key: &str) -> Option<f64> {
- let r = global().read().unwrap();
-
- unsafe {
- let c: &'static Config = std::mem::transmute(&*r);
- c.get_float(key)
- }
+ get(key).and_then(Value::into_float)
}
pub fn get_bool(key: &str) -> Option<bool> {
- let r = global().read().unwrap();
+ get(key).and_then(Value::into_bool)
+}
- unsafe {
- let c: &'static Config = std::mem::transmute(&*r);
- c.get_bool(key)
- }
+pub fn get_table(key: &str) -> Option<HashMap<String, Value>> {
+ get(key).and_then(Value::into_table)
+}
+
+pub fn get_array(key: &str) -> Option<Vec<Value>> {
+ get(key).and_then(Value::into_array)
}
diff --git a/src/value.rs b/src/value.rs
index bb88c34..5b5a838 100644
--- a/src/value.rs
+++ b/src/value.rs
@@ -1,6 +1,5 @@
use std::convert::From;
use std::collections::HashMap;
-use std::borrow::Cow;
/// A configuration value.
///
@@ -18,22 +17,23 @@ pub enum Value {
}
impl Value {
- /// Gets the underlying value as a string, performing a conversion only if neccessary.
- #[allow(needless_lifetimes)]
- pub fn as_str<'a>(&'a self) -> Option<Cow<'a, str>> {
- match *self {
- Value::String(ref value) => Some(Cow::Borrowed(value)),
- Value::Integer(value) => Some(Cow::Owned(value.to_string())),
- Value::Float(value) => Some(Cow::Owned(value.to_string())),
- Value::Boolean(value) => Some(Cow::Owned(value.to_string())),
+ /// Converts `self` into a string, if possible.
+ /// Returns None otherwise.
+ pub fn into_str(self) -> Option<String> {
+ match self {
+ Value::String(value) => Some(value),
+ Value::Integer(value) => Some(value.to_string()),
+ Value::Float(value) => Some(value.to_string()),
+ Value::Boolean(value) => Some(value.to_string()),
_ => None,
}
}
- /// Gets the underlying type as a boolean, performing a conversion only if neccessary.
- pub fn as_bool(&self) -> Option<bool> {
- match *self {
+ /// Converts `self` into a bool, if possible.
+ /// Returns None otherwise.
+ pub fn into_bool(self) -> Option<bool> {
+ match self {
Value::Boolean(value) => Some(value),
Value::Integer(value) => Some(value != 0),
Value::Float(value) => Some(value != 0.0),
@@ -50,9 +50,10 @@ impl Value {
}
}
- /// Gets the underlying type as an integer, performing a conversion only if neccessary.
- pub fn as_int(&self) -> Option<i64> {
- match *self {
+ /// Converts `self` into an i64, if possible.
+ /// Returns None otherwise.
+ pub fn into_int(self) -> Option<i64> {
+ match self {
Value::Integer(value) => Some(value),
Value::String(ref value) => value.parse().ok(),
Value::Boolean(value) => Some(if value { 1 } else { 0 }),
@@ -62,9 +63,10 @@ impl Value {
}
}
- /// Gets the underlying type as a floating-point, performing a conversion only if neccessary.
- pub fn as_float(&self) -> Option<f64> {
- match *self {
+ /// Converts `self` into a f64, if possible.
+ /// Returns None otherwise.
+ pub fn into_float(self) -> Option<f64> {
+ match self {
Value::Float(value) => Some(value),
Value::String(ref value) => value.parse().ok(),
Value::Integer(value) => Some(value as f64),
@@ -74,17 +76,20 @@ impl Value {
}
}
- /// Gets the underlying type as a map; only works if the type is actually a map.
- pub fn as_map(&self) -> Option<&HashMap<String, Value>> {
- match *self {
- Value::Table(ref value) => Some(value),
+ /// If the `Value` is a Table, returns the associated Map.
+ /// Returns None otherwise.
+ pub fn into_table(self) -> Option<HashMap<String, Value>> {
+ match self {
+ Value::Table(value) => Some(value),
_ => None,
}
}
- /// Gets the underlying type as a slice; only works if the type is actually a slice.
- pub fn as_slice(&self) -> Option<&[Value]> {
- match *self {
- Value::Array(ref value) => Some(value),
+
+ /// If the `Value` is an Array, returns the associated Vector.
+ /// Returns None otherwise.
+ pub fn into_array(self) -> Option<Vec<Value>> {
+ match self {
+ Value::Array(value) => Some(value),
_ => None,
}
}
@@ -123,12 +128,6 @@ impl From<bool> for Value {
}
}
-// impl From<HashMap<String, Value>> for Value {
-// fn from(value: HashMap<String, Value>) -> Value {
-// Value::Table(value)
-// }
-// }
-
impl<T> From<HashMap<String, T>> for Value
where T: Into<Value>
{