diff --git a/edn/src/types.rs b/edn/src/types.rs index 6f5f0c60..7ef5a4ac 100644 --- a/edn/src/types.rs +++ b/edn/src/types.rs @@ -119,16 +119,16 @@ macro_rules! def_is { /// which returns the underlying value representing this Value wrapped /// in an Option, like ``. macro_rules! def_as { - ($name: ident, $kind: path, $t: ty) => { + ($name: ident, $kind: path, $t: ty, $( $transform: expr ),* ) => { pub fn $name(&self) -> Option<$t> { - match *self { $kind(v) => Some(v), _ => None } + match *self { $kind(v) => { $( let v = $transform(v) )*; Some(v) }, _ => None } } } } /// Creates `as_$TYPE` helper functions for Value, like `as_big_integer()`, -/// which returns the underlying value representing this Value wrapped -/// in an Option, like ``. +/// which returns a reference to the underlying value representing this Value +/// wrapped in an Option, like ``. macro_rules! def_as_ref { ($name: ident, $kind: path, $t: ty) => { pub fn $name(&self) -> Option<&$t> { @@ -137,6 +137,17 @@ macro_rules! def_as_ref { } } +/// Creates `into_$TYPE` helper functions for Value, like `into_big_integer()`, +/// which consumes it, returning underlying value representing this Value +/// wrapped in an Option, like ``. +macro_rules! def_into { + ($name: ident, $kind: path, $t: ty, $( $transform: expr ),* ) => { + pub fn $name(self) -> Option<$t> { + match self { $kind(v) => { $( let v = $transform(v) )*; Some(v) }, _ => None } + } + } +} + impl Value { def_is!(is_nil, Nil); def_is!(is_boolean, Boolean(_)); @@ -159,12 +170,10 @@ impl Value { match *self { Nil => Some(()), _ => None } } - pub fn as_float(&self) -> Option { - self.as_ordered_float().map(|x| (*x).into()) - } + def_as!(as_boolean, Boolean, bool,); + def_as!(as_integer, Integer, i64,); + def_as!(as_float, Float, f64, |v: OrderedFloat| v.into_inner()); - def_as!(as_boolean, Boolean, bool); - def_as!(as_integer, Integer, i64); def_as_ref!(as_big_integer, BigInteger, BigInt); def_as_ref!(as_ordered_float, Float, OrderedFloat); def_as_ref!(as_text, Text, String); @@ -177,6 +186,21 @@ impl Value { def_as_ref!(as_set, Set, BTreeSet); def_as_ref!(as_map, Map, BTreeMap); + def_into!(into_boolean, Boolean, bool,); + def_into!(into_integer, Integer, i64,); + def_into!(into_big_integer, BigInteger, BigInt,); + def_into!(into_ordered_float, Float, OrderedFloat,); + def_into!(into_float, Float, f64, |v: OrderedFloat| v.into_inner()); + def_into!(into_text, Text, String,); + def_into!(into_symbol, PlainSymbol, symbols::PlainSymbol,); + def_into!(into_namespaced_symbol, NamespacedSymbol, symbols::NamespacedSymbol,); + def_into!(into_keyword, Keyword, symbols::Keyword,); + def_into!(into_namespaced_keyword, NamespacedKeyword, symbols::NamespacedKeyword,); + def_into!(into_vector, Vector, Vec,); + def_into!(into_list, List, LinkedList,); + def_into!(into_set, Set, BTreeSet,); + def_into!(into_map, Map, BTreeMap,); + pub fn from_bigint(src: &str) -> Option { src.parse::().map(Value::BigInteger).ok() } diff --git a/edn/tests/tests.rs b/edn/tests/tests.rs index 74dbde63..04b4ac72 100644 --- a/edn/tests/tests.rs +++ b/edn/tests/tests.rs @@ -1020,6 +1020,15 @@ macro_rules! def_test_as_type { } } +macro_rules! def_test_into_type { + ($value: ident, $method: ident, $is_some: expr, $expected: expr) => { + if $is_some { + assert_eq!($value.clone().$method().unwrap(), $expected) + } + assert_eq!($value.clone().$method().is_some(), $is_some); + } +} + #[test] fn test_is_and_as_type_helper_functions() { let max_i64 = i64::max_value().to_bigint().unwrap(); @@ -1083,17 +1092,33 @@ fn test_is_and_as_type_helper_functions() { def_test_as_type!(value, as_ordered_float, i == 4, OrderedFloat(22.22f64)); def_test_as_type!(value, as_text, i == 5, "hello world".to_string()); def_test_as_type!(value, as_symbol, i == 6, symbols::PlainSymbol::new("$symbol")); - def_test_as_type!(value, as_namespaced_symbol, i == 7, - symbols::NamespacedSymbol::new("$ns", "$symbol")); + def_test_as_type!(value, as_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol")); def_test_as_type!(value, as_keyword, i == 8, symbols::Keyword::new("hello")); - def_test_as_type!(value, as_namespaced_keyword, i == 9, - symbols::NamespacedKeyword::new("hello", "world")); + def_test_as_type!(value, as_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world")); def_test_as_type!(value, as_vector, i == 10, vec![Integer(1)]); def_test_as_type!(value, as_list, i == 11, LinkedList::from_iter(vec![])); def_test_as_type!(value, as_set, i == 12, BTreeSet::from_iter(vec![])); def_test_as_type!(value, as_map, i == 13, BTreeMap::from_iter(vec![ (Value::Text("a".to_string()), Value::Integer(1)), ])); + + def_test_into_type!(value, into_boolean, i == 1, false); + def_test_into_type!(value, into_integer, i == 2, 1i64); + def_test_into_type!(value, into_float, i == 4, 22.22f64); + + def_test_into_type!(value, into_big_integer, i == 3, &max_i64 * &max_i64); + def_test_into_type!(value, into_ordered_float, i == 4, OrderedFloat(22.22f64)); + def_test_into_type!(value, into_text, i == 5, "hello world".to_string()); + def_test_into_type!(value, into_symbol, i == 6, symbols::PlainSymbol::new("$symbol")); + def_test_into_type!(value, into_namespaced_symbol, i == 7, symbols::NamespacedSymbol::new("$ns", "$symbol")); + def_test_into_type!(value, into_keyword, i == 8, symbols::Keyword::new("hello")); + def_test_into_type!(value, into_namespaced_keyword, i == 9, symbols::NamespacedKeyword::new("hello", "world")); + def_test_into_type!(value, into_vector, i == 10, vec![Integer(1)]); + def_test_into_type!(value, into_list, i == 11, LinkedList::from_iter(vec![])); + def_test_into_type!(value, into_set, i == 12, BTreeSet::from_iter(vec![])); + def_test_into_type!(value, into_map, i == 13, BTreeMap::from_iter(vec![ + (Value::Text("a".to_string()), Value::Integer(1)), + ])); } }