From e11922c03e29c984fcdaadb6323270991ec1d250 Mon Sep 17 00:00:00 2001 From: Caio Rossi Date: Wed, 18 Sep 2019 16:21:56 +0200 Subject: [PATCH 1/2] feat: Implemented Tagged Strings support --- src/lib.rs | 1 + src/tag.rs | 36 ++++++++++++++++++++++++++++++++++++ src/value/mod.rs | 4 ++++ src/value/ser.rs | 8 ++++++++ 4 files changed, 49 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 91efc91d..e3b1008d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -317,3 +317,4 @@ pub use crate::value::Value; #[cfg(feature = "tags")] pub use tag::EncodeCborTag; +pub use tag::TaggedString; diff --git a/src/tag.rs b/src/tag.rs index cfb41552..6675d63f 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -1,4 +1,5 @@ use serde::ser::{Serialize, SerializeStruct, Serializer}; +use serde::de::{Deserialize, Deserializer}; /// Wrapper struct to handle encoding Cbor semantic tags. #[derive(Deserialize)] @@ -38,3 +39,38 @@ impl Serialize for EncodeCborTag { state.end() } } + +/// TaggedString +#[derive(Clone, Debug, PartialEq)] +pub struct TaggedString { + /// Tag + pub tag: u64, + /// Raw String to be tagged + pub data: String, +} + +impl TaggedString { + /// Returns tag + pub fn tag(&self) -> u64 { + return self.tag; + } +} + +impl Serialize for TaggedString { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + EncodeCborTag::new(self.tag, &self.data).serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for TaggedString { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let wrapper = EncodeCborTag::deserialize(deserializer)?; + Ok(TaggedString {tag: wrapper.tag(), data: wrapper.value() }) + } +} diff --git a/src/value/mod.rs b/src/value/mod.rs index 040a522e..f9292f24 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -5,6 +5,7 @@ mod ser; use std::cmp::{Ord, Ordering, PartialOrd}; use std::collections::BTreeMap; +use crate::tag::TaggedString; #[doc(inline)] pub use self::de::from_value; @@ -53,6 +54,8 @@ pub enum Value { Map(BTreeMap), /// Semantic Tag Tag(u64), + /// Tagged String + TaggedString(TaggedString), // The hidden variant allows the enum to be extended // with variants for tags and simple values. #[doc(hidden)] @@ -150,6 +153,7 @@ impl Value { Array(_) => 4, Map(_) => 5, Tag(_) => 6, + TaggedString(_) => 8, __Hidden => unreachable!(), } } diff --git a/src/value/ser.rs b/src/value/ser.rs index 930dd7ad..2c4c7e83 100644 --- a/src/value/ser.rs +++ b/src/value/ser.rs @@ -25,6 +25,14 @@ impl serde::Serialize for Value { Value::Text(ref v) => serializer.serialize_str(&v), Value::Array(ref v) => v.serialize(serializer), Value::Tag(v) => serializer.serialize_u64(v), + Value::TaggedString(ref v) => { + use serde::ser::SerializeStruct; + + let mut s = serializer.serialize_struct("EncodeCborTag", 2)?; + s.serialize_field("__cbor_tag_ser_tag", &Value::Tag(v.tag))?; + s.serialize_field("__cbor_tag_ser_data", &v.data.to_owned())?; + return s.end(); + }, Value::Map(ref v) => { if v.len() == 2 { use serde::ser::SerializeStruct; From f51e3c58d862583b02d46693cae9b1ceae21d710 Mon Sep 17 00:00:00 2001 From: Caio Rossi Date: Sun, 29 Sep 2019 00:04:56 -0300 Subject: [PATCH 2/2] feat: Added tests for Tagged Strings --- tests/ser.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/ser.rs b/tests/ser.rs index 60a21d58..5e8aecb5 100644 --- a/tests/ser.rs +++ b/tests/ser.rs @@ -323,4 +323,31 @@ mod std_tests { serde_cbor::de::from_slice(&[0xd9, 0xd9, 0xf6, 0x83, 0x01, 0x02, 0x03]).unwrap(); assert_eq!(value, (55798, (1, 2, 3))); } + + +#[cfg(feature = "tags")] + #[test] + fn test_tagged_string() { + /* D8 20 # tag(32) + 67 # text(7) + 6578616D706C65 # "example" */ + use serde_cbor::TaggedString; + const CBOR_ENCODED: [u8;10] = [0xd8,0x20,0x67,0x65,0x78,0x61,0x6d,0x70,0x6c,0x65]; + + let tagged_string = TaggedString {tag: 32, data: String::from("example")}; + + // Serialize tagged string (CBOR encode) + let ser_result = serde_cbor::to_vec(&tagged_string).unwrap(); + assert_eq!(ser_result, CBOR_ENCODED); + println!("{:?}", ser_result); + + + // Deserialize tagged string (CBOR decode) + let de_result: (TaggedString) = + serde_cbor::de::from_slice_with_scratch(&CBOR_ENCODED, &mut []).unwrap(); + assert_eq!(32, de_result.tag); + assert_eq!(String::from("example"), de_result.data); + println!("{:?}", de_result); + } + }