From 20bda25f19a57f592a4a83dde8c15fd24ac76581 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Sun, 5 Jul 2020 17:15:40 -0400 Subject: [PATCH 1/3] Test that conversion and serialization outputs are the same --- tests/convert.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 tests/convert.rs diff --git a/tests/convert.rs b/tests/convert.rs new file mode 100644 index 00000000..0377a57b --- /dev/null +++ b/tests/convert.rs @@ -0,0 +1,61 @@ +//! This set of tests confirms that the `From` conversions and `to_value()` +//! conversions produce the same output. + +#![cfg(feature = "std")] + +use serde_cbor::{value::to_value, Value}; +use std::collections::BTreeMap; + +#[test] +fn bool() { + assert_eq!(Value::from(true), to_value(true).unwrap()); + assert_eq!(Value::from(false), to_value(false).unwrap()); +} + +#[test] +fn integer() { + assert_eq!(Value::from(127u8), to_value(127u8).unwrap()); + assert_eq!(Value::from(127u16), to_value(127u16).unwrap()); + assert_eq!(Value::from(127u32), to_value(127u32).unwrap()); + assert_eq!(Value::from(127u64), to_value(127u64).unwrap()); + assert_eq!(Value::from(127i8), to_value(127i8).unwrap()); + assert_eq!(Value::from(127i16), to_value(127i16).unwrap()); + assert_eq!(Value::from(127i32), to_value(127i32).unwrap()); + assert_eq!(Value::from(127i64), to_value(127i64).unwrap()); +} + +#[test] +fn float() { + assert_eq!(Value::from(7.8f32), to_value(7.8f32).unwrap()); + assert_eq!(Value::from(7.8f64), to_value(7.8f64).unwrap()); +} + +#[test] +fn bytes() { + let bytes = vec![0u8, 1u8, 2u8]; + + assert_eq!(Value::from(bytes.clone()), to_value(bytes).unwrap()); +} + +#[test] +fn string() { + let string = "foo".to_owned(); + + assert_eq!(Value::from(string.clone()), to_value(string).unwrap()); +} + +#[test] +fn array() { + let array: Vec = vec![1.into(), 2.into(), 3.into()]; + + assert_eq!(Value::from(array.clone()), to_value(array).unwrap()); +} + +#[test] +fn map() { + let mut map = BTreeMap::new(); + + map.insert(Value::from(1), Value::from(2)); + + assert_eq!(Value::from(map.clone()), to_value(map).unwrap()); +} From 15338506f61a6269e661a72a975512c477eecc39 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Sun, 5 Jul 2020 17:42:13 -0400 Subject: [PATCH 2/3] Add blanket From conversions for Value containers Serde uses a blanket impl for serialization. This change fixes the From conversions to match serde's behavior. Without this, the user of serde_cbor could run into awkward bugs where values of the same type get serialized different ways; all hidden behind an innocent looking .into(). --- src/value/mod.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/value/mod.rs b/src/value/mod.rs index 7bd22553..3ad95e72 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -125,11 +125,32 @@ impl_from!(Value::Integer, u64); // u128 omitted because not all numbers fit in CBOR serialization impl_from!(Value::Float, f32); impl_from!(Value::Float, f64); -impl_from!(Value::Bytes, Vec); impl_from!(Value::Text, String); -// TODO: figure out if these impls should be more generic or removed. -impl_from!(Value::Array, Vec); -impl_from!(Value::Map, BTreeMap); + +impl From> for Value +where + Value: From, +{ + fn from(mut value: Vec) -> Self { + Value::Array(value.drain(..).map(Value::from).collect()) + } +} + +impl From> for Value +where + Value: From, + Value: From, +{ + fn from(value: BTreeMap) -> Self { + let mut map = BTreeMap::new(); + + for (key, val) in value { + map.insert(Value::from(key), Value::from(val)); + } + + Value::Map(map) + } +} impl Value { fn major_type(&self) -> u8 { From d1e815a33715468e0197b0f70a28af1f324e8a81 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Sun, 5 Jul 2020 17:51:54 -0400 Subject: [PATCH 3/3] Add &str and &[T] From conversions It made sense to avoid these in the past because they caused allocation. However, in order to fix conversion mismatches with serde, we had to adopt allocation. Since we have now accepted allocation, it now makes sense to add these conversions for ergonomics. --- src/value/mod.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/value/mod.rs b/src/value/mod.rs index 3ad95e72..92b07454 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -126,6 +126,16 @@ impl_from!(Value::Integer, u64); impl_from!(Value::Float, f32); impl_from!(Value::Float, f64); impl_from!(Value::Text, String); +impl_from!(Value::Text, &str); + +impl From<&[T]> for Value +where + Value: From, +{ + fn from(value: &[T]) -> Self { + Value::Array(value.iter().map(|x| Value::from(x.clone())).collect()) + } +} impl From> for Value where