From 09fc0f9177f44730b89e02a188b37b5e9b034ca1 Mon Sep 17 00:00:00 2001 From: Aleksey Kuznetsov Date: Sun, 20 Nov 2022 19:38:08 +0500 Subject: [PATCH] Introduce Data type to use with serde --- src/data.rs | 121 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 4 ++ src/serde_tests.rs | 6 ++- 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 src/data.rs diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..0c26c28 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,121 @@ +use std::fmt; + +/// A byte buffer used for serialization to and from the plist data type. +/// +/// You use it in types with derived `Serialize`/`Deserialize` traits. +/// +/// ## Examples +/// +/// ```rust +/// extern crate plist; +/// #[macro_use] +/// extern crate serde_derive; +/// +/// # fn main() { +/// #[derive(Deserialize, Serialize)] +/// struct Info { +/// blob: plist::Data, +/// } +/// +/// let actual = Info { blob: plist::Data::new(vec![1, 2, 3, 4]) }; +/// +/// let mut xml_byte_buffer: Vec = vec![]; +/// plist::to_writer_xml(&mut xml_byte_buffer, &actual) +/// .expect("serialize into xml"); +/// +/// let expected: Info = plist::from_reader_xml(xml_byte_buffer.as_slice()) +/// .expect("deserialize from xml"); +/// +/// assert_eq!(actual.blob, expected.blob); +/// # } +/// ``` +#[derive(Clone, PartialEq, Eq)] +pub struct Data { + inner: Vec, +} + +impl Data { + /// Creates a new `Data` from vec of bytes. + pub fn new(bytes: Vec) -> Self { + Data { inner: bytes } + } +} + +impl From> for Data { + fn from(from: Vec) -> Self { + Data { inner: from } + } +} + +impl From for Vec { + fn from(from: Data) -> Self { + from.inner + } +} + +impl AsRef<[u8]> for Data { + fn as_ref(&self) -> &[u8] { + self.inner.as_ref() + } +} + +impl AsMut<[u8]> for Data { + fn as_mut(&mut self) -> &mut [u8] { + self.inner.as_mut() + } +} + +impl fmt::Debug for Data { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +pub mod serde_impls { + use serde::{de, ser}; + use std::fmt; + + use crate::Data; + + impl ser::Serialize for Data { + fn serialize(&self, serializer: S) -> Result + where + S: ser::Serializer, + { + serializer.serialize_bytes(self.as_ref()) + } + } + + struct DataVisitor; + + impl<'de> de::Visitor<'de> for DataVisitor { + type Value = Data; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a byte array") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + self.visit_byte_buf(v.to_owned()) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: de::Error, + { + Ok(v.into()) + } + } + + impl<'de> de::Deserialize<'de> for Data { + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + deserializer.deserialize_byte_buf(DataVisitor) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index ba1d8cb..e2f3a21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,12 +82,16 @@ pub mod stream; #[cfg(not(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"))] mod stream; +#[cfg(feature = "serde")] +mod data; mod date; mod error; mod integer; mod uid; mod value; +#[cfg(feature = "serde")] +pub use data::Data; pub use date::{Date, InvalidXmlDate}; pub use dictionary::Dictionary; pub use error::Error; diff --git a/src/serde_tests.rs b/src/serde_tests.rs index 9a5b5d8..0e3b789 100644 --- a/src/serde_tests.rs +++ b/src/serde_tests.rs @@ -6,7 +6,7 @@ use std::{collections::BTreeMap, fmt::Debug, fs::File, io::Cursor}; use crate::{ stream::{private::Sealed, Event, OwnedEvent, Writer}, - Date, Deserializer, Dictionary, Error, Integer, Serializer, Uid, Value, + Data, Date, Deserializer, Dictionary, Error, Integer, Serializer, Uid, Value, }; struct VecWriter { @@ -130,6 +130,7 @@ struct DogInner { b: usize, c: Vec, d: Option, + e: Data, } #[test] @@ -149,6 +150,7 @@ fn dog() { b: 12, c: vec!["a".to_string(), "b".to_string()], d: Some(Uid::new(42)), + e: Data::new(vec![20, 22]), }], }); @@ -170,6 +172,8 @@ fn dog() { Event::EndCollection, Event::String("d".into()), Event::Uid(Uid::new(42)), + Event::String("e".into()), + Event::Data(vec![20, 22].into()), Event::EndCollection, Event::EndCollection, Event::EndCollection,