diff --git a/src/bytes.rs b/src/bytes.rs new file mode 100644 index 00000000..495b2c4b --- /dev/null +++ b/src/bytes.rs @@ -0,0 +1,171 @@ +use std::ops; + +use ser; +use de; + +/////////////////////////////////////////////////////////////////////////////// + +/// `Bytes` wraps a `&[u8]` in order to serialize into a byte array. +pub struct Bytes<'a> { + bytes: &'a [u8], +} + +impl<'a, T> From for Bytes<'a> where T: Into<&'a [u8]> { + fn from(bytes: T) -> Self { + Bytes { + bytes: bytes.into(), + } + } +} + + +impl<'a> ops::Deref for Bytes<'a> { + type Target = [u8]; + + fn deref(&self) -> &[u8] { self.bytes } +} + +impl<'a> ser::Serialize for Bytes<'a> { + #[inline] + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: ser::Serializer + { + serializer.visit_bytes(self.bytes) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +/// `ByteBuf` wraps a `Vec` in order to hook into serialize and from deserialize a byte array. +#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +pub struct ByteBuf { + bytes: Vec, +} + +impl ByteBuf { + pub fn new() -> Self { + ByteBuf { + bytes: Vec::new(), + } + } + + pub fn with_capacity(cap: usize) -> Self { + ByteBuf { + bytes: Vec::with_capacity(cap) + } + } +} + +impl From for ByteBuf where T: Into> { + fn from(bytes: T) -> Self { + ByteBuf { + bytes: bytes.into(), + } + } +} + +impl AsRef> for ByteBuf { + fn as_ref(&self) -> &Vec { + &self.bytes + } +} + +impl AsRef<[u8]> for ByteBuf { + fn as_ref(&self) -> &[u8] { + &self.bytes + } +} + +impl AsMut> for ByteBuf { + fn as_mut(&mut self) -> &mut Vec { + &mut self.bytes + } +} + +impl AsMut<[u8]> for ByteBuf { + fn as_mut(&mut self) -> &mut [u8] { + &mut self.bytes + } +} + +impl Into> for ByteBuf { + fn into(self) -> Vec { + self.bytes + } +} + +impl ops::Deref for ByteBuf { + type Target = [u8]; + + fn deref(&self) -> &[u8] { &self.bytes[..] } +} + +impl ops::DerefMut for ByteBuf { + fn deref_mut(&mut self) -> &mut [u8] { &mut self.bytes[..] } +} + +impl ser::Serialize for ByteBuf { + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> + where S: ser::Serializer + { + serializer.visit_bytes(&self) + } +} + +pub struct ByteBufVisitor; + +impl de::Visitor for ByteBufVisitor { + type Value = ByteBuf; + + #[inline] + fn visit_unit(&mut self) -> Result + where E: de::Error, + { + Ok(ByteBuf { + bytes: Vec::new(), + }) + } + + #[inline] + fn visit_seq(&mut self, mut visitor: V) -> Result + where V: de::SeqVisitor, + { + let (len, _) = visitor.size_hint(); + let mut values = Vec::with_capacity(len); + + while let Some(value) = try!(visitor.visit()) { + values.push(value); + } + + try!(visitor.end()); + + Ok(ByteBuf { + bytes: values, + }) + } + + #[inline] + fn visit_bytes(&mut self, v: &[u8]) -> Result + where E: de::Error, + { + self.visit_byte_buf(v.to_vec()) + } + + #[inline] + fn visit_byte_buf(&mut self, v: Vec) -> Result + where E: de::Error, + { + Ok(ByteBuf { + bytes: v, + }) + } +} + +impl de::Deserialize for ByteBuf { + #[inline] + fn deserialize(deserializer: &mut D) -> Result + where D: de::Deserializer + { + deserializer.visit_bytes(ByteBufVisitor) + } +} diff --git a/src/de.rs b/src/de.rs index 5c4006f0..87d02f85 100644 --- a/src/de.rs +++ b/src/de.rs @@ -103,6 +103,16 @@ pub trait Deserializer { { Err(Error::syntax_error()) } + + /// The `visit_bytes` method allows a `Deserialize` type to inform the `Deserializer` that it's + /// expecting a `Vec`. This allows deserializers that provide a custom byte vector + /// serialization to properly deserialize the type. + #[inline] + fn visit_bytes(&mut self, visitor: V) -> Result + where V: Visitor, + { + self.visit(visitor) + } } /////////////////////////////////////////////////////////////////////////////// @@ -247,6 +257,18 @@ pub trait Visitor { { Err(Error::syntax_error()) } + + fn visit_bytes(&mut self, _v: &[u8]) -> Result + where E: Error, + { + Err(Error::syntax_error()) + } + + fn visit_byte_buf(&mut self, _v: Vec) -> Result + where E: Error, + { + Err(Error::syntax_error()) + } } /////////////////////////////////////////////////////////////////////////////// @@ -981,7 +1003,7 @@ impl Visitor for PathBufVisitor { fn visit_str(&mut self, v: &str) -> Result where E: Error, { - Ok(path::PathBuf::new(&v)) + Ok(From::from(v)) } fn visit_string(&mut self, v: String) -> Result diff --git a/src/lib.rs b/src/lib.rs index 60257b97..6dc36e14 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,4 @@ -#![feature(core, std_misc, unicode)] +#![feature(convert, core, std_misc, unicode)] extern crate unicode; @@ -8,3 +8,4 @@ pub use de::{Deserialize, Deserializer, Error}; pub mod ser; pub mod de; pub mod json; +pub mod bytes; diff --git a/src/ser.rs b/src/ser.rs index 80887812..a63dd783 100644 --- a/src/ser.rs +++ b/src/ser.rs @@ -73,6 +73,8 @@ pub trait Serializer { fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error>; + /// `visit_char` serializes a character. By default it serializes it as a `&str` containing a + /// single character. #[inline] fn visit_char(&mut self, v: char) -> Result<(), Self::Error> { // The unwraps in here should be safe. @@ -81,8 +83,16 @@ pub trait Serializer { self.visit_str(str::from_utf8(&s[..len]).unwrap()) } + /// `visit_str` serializes a `&str`. fn visit_str(&mut self, value: &str) -> Result<(), Self::Error>; + /// `visit_bytes` is a hook that enables those serialization formats that support serializing + /// byte slices separately from generic arrays. By default it serializes as a regular array. + #[inline] + fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> { + self.visit_seq(SeqIteratorVisitor::new(value.iter(), Some(value.len()))) + } + fn visit_unit(&mut self) -> Result<(), Self::Error>; #[inline] diff --git a/tests/test_bytes.rs b/tests/test_bytes.rs new file mode 100644 index 00000000..3b323069 --- /dev/null +++ b/tests/test_bytes.rs @@ -0,0 +1,210 @@ +#![feature(convert, custom_derive, plugin, test)] +#![plugin(serde_macros)] + +extern crate test; +extern crate serde; + +use serde::Serialize; +use serde::bytes::{ByteBuf, Bytes}; +use serde::json; + +/////////////////////////////////////////////////////////////////////////////// + +#[derive(Debug, PartialEq)] +struct Error; + +impl serde::de::Error for Error { + fn syntax_error() -> Error { Error } + + fn end_of_stream_error() -> Error { Error } + + fn missing_field_error(_field: &'static str) -> Error { Error } +} + +/////////////////////////////////////////////////////////////////////////////// + +struct BytesSerializer { + bytes: Vec, +} + +impl BytesSerializer { + fn new(bytes: Vec) -> Self { + BytesSerializer { + bytes: bytes, + } + } +} + +impl serde::Serializer for BytesSerializer { + type Error = Error; + + fn visit_unit(&mut self) -> Result<(), Error> { + Err(Error) + } + + fn visit_bool(&mut self, _v: bool) -> Result<(), Error> { + Err(Error) + } + + fn visit_i64(&mut self, _v: i64) -> Result<(), Error> { + Err(Error) + } + + fn visit_u64(&mut self, _v: u64) -> Result<(), Error> { + Err(Error) + } + + fn visit_f32(&mut self, _v: f32) -> Result<(), Error> { + Err(Error) + } + + fn visit_f64(&mut self, _v: f64) -> Result<(), Error> { + Err(Error) + } + + fn visit_char(&mut self, _v: char) -> Result<(), Error> { + Err(Error) + } + + fn visit_str(&mut self, _v: &str) -> Result<(), Error> { + Err(Error) + } + + fn visit_none(&mut self) -> Result<(), Error> { + Err(Error) + } + + fn visit_some(&mut self, _value: V) -> Result<(), Error> + where V: serde::Serialize, + { + Err(Error) + } + + fn visit_seq(&mut self, _visitor: V) -> Result<(), Error> + where V: serde::ser::SeqVisitor, + { + Err(Error) + } + + fn visit_seq_elt(&mut self, _value: T) -> Result<(), Error> + where T: serde::Serialize + { + Err(Error) + } + + fn visit_map(&mut self, _visitor: V) -> Result<(), Error> + where V: serde::ser::MapVisitor, + { + Err(Error) + } + + fn visit_map_elt(&mut self, _key: K, _value: V) -> Result<(), Error> + where K: serde::Serialize, + V: serde::Serialize, + { + Err(Error) + } + + fn visit_bytes(&mut self, bytes: &[u8]) -> Result<(), Error> { + assert_eq!(self.bytes, bytes); + Ok(()) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +struct BytesDeserializer { + bytes: Option>, +} + +impl BytesDeserializer { + fn new(bytes: Vec) -> Self { + BytesDeserializer { + bytes: Some(bytes), + } + } +} + +impl serde::Deserializer for BytesDeserializer { + type Error = Error; + + fn visit(&mut self, _visitor: V) -> Result + where V: serde::de::Visitor, + { + Err(Error) + } + + fn visit_bytes(&mut self, mut visitor: V) -> Result + where V: serde::de::Visitor, + { + visitor.visit_byte_buf(self.bytes.take().unwrap()) + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#[test] +fn test_bytes_ser_json() { + let buf = vec![]; + let bytes = Bytes::from(&buf); + assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string()); + + let buf = vec![1, 2, 3]; + let bytes = Bytes::from(&buf); + assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string()); +} + +#[test] +fn test_bytes_ser_bytes() { + let buf = vec![]; + let bytes = Bytes::from(&buf); + let mut ser = BytesSerializer::new(vec![]); + bytes.serialize(&mut ser).unwrap(); + + let buf = vec![1, 2, 3]; + let bytes = Bytes::from(&buf); + let mut ser = BytesSerializer::new(vec![1, 2, 3]); + bytes.serialize(&mut ser).unwrap(); +} + +#[test] +fn test_byte_buf_ser_json() { + let bytes = ByteBuf::new(); + assert_eq!(json::to_string(&bytes).unwrap(), "[]".to_string()); + + let bytes = ByteBuf::from(vec![1, 2, 3]); + assert_eq!(json::to_string(&bytes).unwrap(), "[1,2,3]".to_string()); +} + +#[test] +fn test_byte_buf_ser_bytes() { + let bytes = ByteBuf::new(); + let mut ser = BytesSerializer::new(vec![]); + bytes.serialize(&mut ser).unwrap(); + + let bytes = ByteBuf::from(vec![1, 2, 3]); + let mut ser = BytesSerializer::new(vec![1, 2, 3]); + bytes.serialize(&mut ser).unwrap(); +} + +/////////////////////////////////////////////////////////////////////////////// + +#[test] +fn test_byte_buf_de_json() { + let bytes = ByteBuf::new(); + assert_eq!(json::from_str("[]").unwrap(), bytes); + + let bytes = ByteBuf::from(vec![1, 2, 3]); + assert_eq!(json::from_str("[1, 2, 3]").unwrap(), bytes); +} + +#[test] +fn test_byte_buf_de_bytes() { + let mut de = BytesDeserializer::new(vec![]); + let bytes = serde::Deserialize::deserialize(&mut de); + assert_eq!(bytes, Ok(ByteBuf::new())); + + let mut de = BytesDeserializer::new(vec![1, 2, 3]); + let bytes = serde::Deserialize::deserialize(&mut de); + assert_eq!(bytes, Ok(ByteBuf::from(vec![1, 2, 3]))); +}