From d3deef1f53cd8af1c1bf4390e72a9d2e8c6a84ef Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Wed, 20 Mar 2019 17:22:14 +0200 Subject: [PATCH] Provide more methods for value conversions + Provide is_[type] for each value type + Provide as_[type] for each value type Related to #16 --- src/value/mod.rs | 81 ++++++++++++++++++++++++++++++++++++++++++-- tests/integration.rs | 33 ++++++++++++++---- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 891b203..0c35624 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -28,6 +28,13 @@ pub enum Value { } impl Value { + /// Returns true if `self` is a `Value::String`. + pub fn is_string(&self) -> bool { + match self { + Value::String(_) => true, + _ => false, + } + } /// Returns true if `self` is a `Value::Int`. pub fn is_int(&self) -> bool { match self { @@ -44,7 +51,31 @@ impl Value { } } - /// Returns `self` as a `IntType`, or `Err` if `self` is not a `Value::Int`. + /// Returns true if `self` is a `Value::Boolean`. + pub fn is_boolean(&self) -> bool { + match self { + Value::Boolean(_) => true, + _ => false, + } + } + + /// Returns true if `self` is a `Value::Tuple`. + pub fn is_tuple(&self) -> bool { + match self { + Value::Tuple(_) => true, + _ => false, + } + } + + /// Clones the value stored in `self` as `String`, or returns `Err` if `self` is not a `Value::String`. + pub fn as_string(&self) -> Result { + match self { + Value::String(string) => Ok(string.clone()), + value => Err(Error::expected_string(value.clone())), + } + } + + /// Clones the value stored in `self` as `IntType`, or returns `Err` if `self` is not a `Value::Int`. pub fn as_int(&self) -> Result { match self { Value::Int(i) => Ok(*i), @@ -52,7 +83,8 @@ impl Value { } } - /// Returns `self` as a `FloatType`, or `Err` if `self` is not a `Value::Float` or `Value::Int`. + /// Clones the value stored in `self` as `FloatType`, or returns `Err` if `self` is not a `Value::Float` or `Value::Int`. + /// Note that this method silently converts `IntType` to `FloatType`, if `self` is a `Value::Int`. pub fn as_float(&self) -> Result { match self { Value::Float(f) => Ok(*f), @@ -60,6 +92,22 @@ impl Value { value => Err(Error::expected_number(value.clone())), } } + + /// Clones the value stored in `self` as `bool`, or returns `Err` if `self` is not a `Value::Boolean`. + pub fn as_boolean(&self) -> Result { + match self { + Value::Boolean(boolean) => Ok(*boolean), + value => Err(Error::expected_boolean(value.clone())), + } + } + + /// Clones the value stored in `self` as `TupleType`, or returns`Err` if `self` is not a `Value::Tuple`. + pub fn as_tuple(&self) -> Result { + match self { + Value::Tuple(tuple) => Ok(tuple.clone()), + value => Err(Error::expected_tuple(value.clone())), + } + } } impl From for Value { @@ -103,3 +151,32 @@ impl From for Result { Ok(value) } } + +#[cfg(test)] +mod tests { + use value::{TupleType, Value}; + + #[test] + fn test_value_conversions() { + assert_eq!( + Value::from("string").as_string().unwrap(), + String::from("string") + ); + assert_eq!(Value::from(3).as_int().unwrap(), 3); + assert_eq!(Value::from(3.3).as_float().unwrap(), 3.3); + assert_eq!(Value::from(true).as_boolean().unwrap(), true); + assert_eq!( + Value::from(TupleType::new()).as_tuple().unwrap(), + TupleType::new() + ); + } + + #[test] + fn test_value_checks() { + assert!(Value::from("string").is_string()); + assert!(Value::from(3).is_int()); + assert!(Value::from(3.3).is_float()); + assert!(Value::from(true).is_boolean()); + assert!(Value::from(TupleType::new()).is_tuple()); + } +} diff --git a/tests/integration.rs b/tests/integration.rs index 62b20c3..f72f853 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -367,24 +367,43 @@ fn test_shortcut_functions() { // assert_eq!(build_operator_tree("???").unwrap().eval_string()); assert_eq!( - build_operator_tree("string").unwrap().eval_string_with_configuration(&configuration), + build_operator_tree("string") + .unwrap() + .eval_string_with_configuration(&configuration), Ok("a string".to_string()) ); assert_eq!(build_operator_tree("3.3").unwrap().eval_float(), Ok(3.3)); assert_eq!( - build_operator_tree("3.3").unwrap().eval_float_with_configuration(&configuration), + build_operator_tree("3.3") + .unwrap() + .eval_float_with_configuration(&configuration), Ok(3.3) ); assert_eq!(build_operator_tree("3").unwrap().eval_int(), Ok(3)); - assert_eq!(build_operator_tree("3").unwrap().eval_int_with_configuration(&configuration), Ok(3)); - assert_eq!(build_operator_tree("true").unwrap().eval_boolean(), Ok(true)); assert_eq!( - build_operator_tree("true").unwrap().eval_boolean_with_configuration(&configuration), + build_operator_tree("3") + .unwrap() + .eval_int_with_configuration(&configuration), + Ok(3) + ); + assert_eq!( + build_operator_tree("true").unwrap().eval_boolean(), Ok(true) ); - assert_eq!(build_operator_tree("3,3").unwrap().eval_tuple(), Ok(vec![Value::Int(3), Value::Int(3)])); assert_eq!( - build_operator_tree("3,3").unwrap().eval_tuple_with_configuration(&configuration), + build_operator_tree("true") + .unwrap() + .eval_boolean_with_configuration(&configuration), + Ok(true) + ); + assert_eq!( + build_operator_tree("3,3").unwrap().eval_tuple(), + Ok(vec![Value::Int(3), Value::Int(3)]) + ); + assert_eq!( + build_operator_tree("3,3") + .unwrap() + .eval_tuple_with_configuration(&configuration), Ok(vec![Value::Int(3), Value::Int(3)]) ); }